|
|
1.1 root 1: 0707071010112043441004440001630000160000010075200466055374000001000000013411alloc.c /*ident "@(#)ctrans:src/alloc.c 1.4" */
2: /**************************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: alloc.c:
11:
12: *****************************************************************************/
13: #include "cfront.h"
14: #include "size.h"
15: #include "sysent.h"
16:
17: const int NBITE = (CHUNK-8)/sizeof(name)-1;
18: const int EBITE = (CHUNK-8)/sizeof(expr)-1;
19: const int SBITE = (CHUNK-8)/sizeof(stmt)-1;
20: const int TBITE = (CHUNK-8)/sizeof(table)-1;
21: const int VBITE = (CHUNK-8)/sizeof(vec)-1;
22: const int FBITE = (CHUNK-8)/sizeof(fct)-1;
23: const int PBITE = (CHUNK-8)/sizeof(ptr)-1;
24:
25: #define mzero(p,l) memset(p,0,l)
26:
27: void* chunk(int i) // get memory that is not to be freed
28: {
29: register char* cp = malloc(i*CHUNK-8);
30: if (cp == 0) { // no space
31: free((char*)gtbl); // get space for error message
32: error('i',"free store exhausted");
33: }
34: return cp;
35: }
36:
37: #ifdef __HAVE_SIZE_T
38: #include <new.h>
39: #define NEW_SIZE size_t
40: #else
41: #define NEW_SIZE long
42: #endif
43:
44: void* operator new(NEW_SIZE sz) // get memory that might be freed
45: {
46: char* p = calloc((unsigned)sz,1);
47:
48: //fprintf(stderr,"alloc(%d)->%d\n",sz,p);
49:
50: if (p == 0) { // no space
51: free((char*)gtbl); // get space for error message
52: error('i',"free store exhausted");
53: }
54: return p;
55: }
56:
57: void operator delete (void* p)
58: {
59: if (p == 0) return;
60:
61: //fprintf(stderr,"free(%d) %d\n",p,((int*)p)[-1]-(int)p-1+sizeof(int*));
62:
63: free((char*)p);
64: }
65:
66: // class new and delete operators
67:
68: void*
69: expr::operator new(size_t sz)
70: {
71: register Pexpr p;
72:
73: if ( (p=expr_free) == 0 ) {
74: register Pexpr q = (Pexpr) chunk(1);
75: for (p=expr_free=&q[EBITE-1]; q<p; p--) {
76: p->e1 = p-1;
77: DB(p->node::allocated=0);
78: }
79: (p+1)->e1 = 0;
80: DB(p->node::allocated=0);
81: }
82: else
83: expr_free = p->e1;
84:
85: mzero(p,sz);
86: return p;
87: }
88:
89: void
90: expr::operator delete(void* vp, size_t)
91: {
92: Pexpr p = (Pexpr)vp;
93:
94: DB( if(!p->node::allocated) error('i',"deleting unallocated expr:%k! -- id==%d",p->base,p->node::id);
95: p->node::allocated = 0;
96: );
97: p->e1 = expr_free;
98: expr_free = p;
99: vp = 0;
100: }
101:
102: void*
103: stmt::operator new(size_t sz)
104: {
105: register Pstmt p;
106: if ( (p=stmt_free) == 0 ) {
107: register Pstmt q = (Pstmt) chunk(1);
108: for (p=stmt_free=&q[SBITE-1]; q<p; p--) {
109: p->s_list = p-1;
110: DB(p->node::allocated=0);
111: }
112: (p+1)->s_list = 0;
113: DB(p->node::allocated=0);
114: }
115: else
116: stmt_free = p->s_list;
117:
118: mzero(p,sz);
119: return p;
120: }
121:
122: void
123: stmt::operator delete(void* vp,size_t)
124: {
125: Pstmt p = (Pstmt)vp;
126: DB( if(!p->node::allocated) error('i',"deleting unallocated stmt:%k! -- id==%d",p->base,p->node::id);
127: p->node::allocated = 0;
128: );
129: p->s_list = stmt_free;
130: stmt_free = p;
131: vp = 0;
132: }
133:
134: void*
135: name::operator new(size_t sz)
136: {
137: register Pname p;
138:
139: if ( (p=name_free) == 0 ) {
140: register Pname q = (Pname) chunk(1);
141: for (p=name_free=&q[NBITE-1]; q<p; p--) {
142: p->n_tbl_list = p-1;
143: DB(p->node::allocated=0);
144: }
145: (p+1)->n_tbl_list = 0;
146: DB(p->node::allocated=0);
147: }
148: else
149: name_free = p->n_tbl_list;
150:
151: mzero(p,sz);
152: return p;
153: }
154:
155: void
156: name::operator delete(void* vp,size_t)
157: {
158: Pname p = (Pname)vp;
159: DB( if(!p->node::allocated) error('i',"deleting unallocated name %s! -- id==%d",p->string?p->string:"???",p->node::id);
160: p->node::allocated = 0;
161: );
162: p->n_tbl_list = name_free;
163: name_free = p;
164: vp = 0;
165: }
166:
167: void*
168: table::operator new(size_t sz)
169: {
170: register Ptable p;
171:
172: if ( (p=table_free) == 0 ) {
173: register Ptable q = (Ptable) chunk(1);
174: for (p=table_free=&q[TBITE-1]; q<p; p--) {
175: p->next = p-1;
176: DB(p->node::allocated=0);
177: }
178: (p+1)->next = 0;
179: DB(p->node::allocated=0);
180: }
181: else
182: table_free = p->next;
183:
184: mzero(p, sz);
185: return p;
186: }
187:
188: void
189: table::operator delete(void* vp,size_t)
190: {
191: Ptable p = (Ptable)vp;
192: DB( if(!p->node::allocated) error('i',"deleting unallocated table %d! -- id==%d",p->base,p->node::id);
193: p->node::allocated = 0;
194: );
195: p->next = table_free;
196: table_free = p;
197: vp = 0;
198: }
199:
200: void*
201: vec::operator new(size_t sz)
202: {
203: register Pvec p;
204:
205: if ( (p=vec_free) == 0 ) {
206: register Pvec q = (Pvec) chunk(1);
207: for (p=vec_free=&q[VBITE-1]; q<p; p--) {
208: p->tlist = p-1;
209: DB(p->node::allocated=0);
210: }
211: (p+1)->tlist = 0;
212: DB(p->node::allocated=0);
213: }
214: else
215: vec_free = (Pvec) p->tlist;
216:
217: mzero(p, sz);
218: return p;
219: }
220:
221: void
222: vec::operator delete(void* vp,size_t)
223: {
224: Pvec p = (Pvec)vp;
225: DB( if(!p->node::allocated) error('i',"deleting unallocated vec %d! -- id==%d",p->base,p->node::id);
226: p->node::allocated = 0;
227: );
228: p->tlist = vec_free;
229: vec_free = p;
230: vp = 0;
231: }
232:
233: void*
234: fct::operator new(size_t sz)
235: {
236: register Pfct p;
237:
238: if ( (p=fct_free) == 0 ) {
239: register Pfct q = (Pfct) chunk(1);
240: for (p=fct_free=&q[FBITE-1]; q<p; p--) {
241: p->tlist = p-1;
242: DB(p->node::allocated=0);
243: }
244: (p+1)->tlist = 0;
245: DB(p->node::allocated=0);
246: }
247: else
248: fct_free = (Pfct) p->tlist;
249:
250: mzero(p, sz);
251: return p;
252: }
253:
254: void
255: fct::operator delete(void* vp,size_t)
256: {
257: Pfct p = (Pfct)vp;
258: DB( if(!p->node::allocated) error('i',"deleting unallocated fct %d! -- id==%d",p->base,p->node::id);
259: p->node::allocated = 0;
260: );
261: p->tlist = fct_free;
262: fct_free = p;
263: vp = 0;
264: }
265:
266: void*
267: ptr::operator new(size_t sz)
268: {
269: register Pptr p;
270:
271: //error('d',"ptr new");
272: if ( (p=ptr_free) == 0 ) {
273: register Pptr q = (Pptr) chunk(1);
274: for (p=ptr_free=&q[PBITE-1]; q<p; p--) {
275: p->tlist = p-1;
276: DB(p->node::allocated=0);
277: }
278: (p+1)->tlist = 0;
279: DB(p->node::allocated=0);
280: }
281: else
282: ptr_free = (Pptr) p->tlist;
283:
284: mzero(p, sz);
285: return p;
286: }
287:
288: void
289: ptr::operator delete(void* vp,size_t)
290: {
291: Pptr p = (Pptr)vp;
292: DB( if(!p->node::allocated) error('i',"deleting unallocated ptr %d! -- id==%d",p->base,p->node::id);
293: p->node::allocated = 0;
294: );
295: p->tlist = ptr_free;
296: ptr_free = p;
297: vp = 0;
298: }
299: 0707071010112043451004440001630000160000010070500466055374500001100000070343cfront.h /*ident "@(#)ctrans:src/cfront.h 1.12" */
300: /***********************************************************************
301:
302: C++ source for cfront, the C++ compiler front-end
303: written in the computer science research center of Bell Labs
304:
305: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
306: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
307:
308: When reading cfront code please remember that C++ was not available
309: when it was originally written. Out of necessity cfront is written
310: in a style that takes advantage of only few of C++'s features.
311:
312: WARNING: This program relies on non-initialized class members being ZERO.
313: This will be true as long as they are allocated using the "new" operator
314: from alloc.c
315:
316: cfront.h:
317:
318: Here is all the class definitions for cfront, and most of the externs
319:
320: ***********************************************************************/
321:
322: #ifndef _CFRONT_H
323: #define _CFRONT_H
324:
325: #include "token.h"
326: #include "typedef.h"
327:
328: #ifndef GRAM
329: extern char* prog_name; // compiler name and version
330: extern int inline_restr; // inline expansion restrictions
331: #endif
332:
333: extern TOK tlex();
334: extern Pname syn();
335:
336: extern void ext(int);
337:
338: extern char* make_name(TOK);
339: extern void make_dummy();
340: extern Pname dummy_fct;
341: extern Pname really_dominate(Pname, Pname, bit);
342: extern int exact1(Pname, Ptype);
343:
344: extern int friend_check(Pclass start,Pclass stop, Pfct f);
345:
346: struct loc // a source file location
347: {
348: short file; // index into file_name[], or zero
349: short line;
350: #ifndef GRAM
351: void put(FILE*);
352: void putline();
353: #endif
354: };
355:
356: extern Loc curloc;
357: extern int curr_file;
358: extern char* src_file_name;
359: extern loc noloc; // dummy null location
360: extern bit binary_val;
361: extern bit stmtno;
362:
363: struct ea { // fudge portable printf-like formatting for error()
364: union {
365: void* p;
366: long i;
367: };
368:
369: ea(const void* pp) { p = pp; }
370: ea(long ii) { i = ii; }
371: ea() {}
372: };
373:
374: extern ea* ea0;
375:
376: overload error;
377: int error(const char*);
378: int error(const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
379: int error(int, const char*);
380: int error(int, const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
381: int error(loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
382: int error(int, loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
383: extern char emode;
384:
385: extern int error_count;
386: extern int vtbl_opt;
387: extern int debug_opt;
388: extern int warning_opt;
389: extern int ansi_opt;
390: extern int strict_opt;
391: extern FILE* out_file;
392: extern FILE* in_file;
393: extern char scan_started;
394:
395: extern int bl_level;
396: extern Ptable ktbl; // keywords and typedef names
397: extern Ptable gtbl; // global names
398: extern Ptable ptbl;
399: extern Ptable lcl_tbl;
400: extern char* oper_name(TOK);
401: extern Pname def_name;
402: extern Pname pdef_name;
403: extern Pclass ccl;
404: extern Pbase defa_type;
405: extern Pbase moe_type;
406: extern Pbase mptr_type;
407:
408: #ifndef GRAM
409: extern Pstmt Cstmt; // current statement, or 0
410: extern Pname Cdcl; // name currently being declared, or 0
411:
412: extern Pbase any_type;
413: extern int largest_int;
414: #endif
415:
416: extern Pbase int_type;
417: extern Pbase char_type;
418: extern Pbase short_type;
419: extern Pbase long_type;
420: extern Pbase uint_type;
421: extern Pbase float_type;
422: extern Pbase double_type;
423: extern Pbase ldouble_type;
424: extern Pbase void_type;
425:
426: #ifndef GRAM
427: extern Pbase uchar_type;
428: extern Pbase ushort_type;
429: extern Pbase ulong_type;
430: extern Ptype Pchar_type;
431: extern Ptype Pint_type;
432: extern Ptype Pvptr_type;
433: extern Ptype Pfctvec_type;
434: extern Ptype Pvoid_type;
435: extern Pbase zero_type;
436: extern Ptype size_t_type;
437:
438: extern int byte_offset;
439: extern int bit_offset;
440: extern int max_align;
441: extern int const_save;
442: extern int const_ptr;
443: extern int cm_const_save;
444: extern bit const_problem;
445: #endif
446:
447: extern Pexpr dummy; /* the empty expression */
448: extern Pexpr zero;
449: extern Pexpr one;
450: extern Pname sta_name; /* qualifier for unary :: */
451:
452: #define DEL(p) if (p && (p->permanent==0)) p->del()
453: #define PERM(p) p->permanent=1
454: #define UNPERM(p) p->permanent=0
455:
456: struct node {
457: TOK base;
458: bit permanent;
459: bit baseclass; // base classes have NAME in their base ...
460: #ifdef DBG
461: bit displayed; // avoid infinite recursion in display functions
462: bit allocated; // set when not on free list
463: long id;
464: #endif
465: };
466: #ifdef DBG
467: extern long node_id;
468: extern int Adebug;
469: #define DBID() { node::id = ++::node_id; node::allocated=1; displayed=0; \
470: if(Adebug>=1)fprintf(stderr,"\n*** allocated %d base %d\n",id,base); }
471: #else
472: #define DBID() /**/
473: #endif
474:
475: struct table : node {
476: /* a table is a node only to give it a "base" for debugging */
477: bit init_stat; /* ==0 if block(s) of table not simplified,
478: ==1 if simplified but had no initializers,
479: ==2 if simplified and had initializers.
480: */
481: short size;
482: short hashsize;
483: short free_slot; /* next free slot in entries */
484: Pname* entries;
485: short* hashtbl;
486: Pstmt real_block; /* the last block the user wrote,
487: not one of the ones cfront created
488: */
489: Ptable next; /* table for enclosing scope */
490: Pname t_name; /* name of the table */
491:
492: static Ptable table_free;
493: void* operator new(size_t);
494: void operator delete(void*,size_t);
495:
496: table(short, Ptable, Pname);
497: ~table();
498:
499: Pname look(char*, TOK);
500: Pname insert(Pname, TOK);
501: #ifndef GRAM
502: void grow(int);
503: void set_name(Pname n) { t_name = n; };
504: Pname get_mem(int);
505: int max() { return free_slot-1; };
506: void dcl_print(TOK,TOK);
507: #endif
508: void del();
509: };
510:
511: #ifndef GRAM
512: extern bit Nold;
513: extern bit vec_const, fct_const;
514: #endif
515:
516: extern void restore();
517: extern void set_scope(Pname);
518: extern Plist modified_tn;
519:
520: // local class
521: extern Plist local_tn;
522: extern Plist local_blk;
523: extern Plist local_class;
524: extern void local_hide( Pname );
525: extern char *make_local_name(Pclass, int=0);
526:
527: // nested type
528: extern Plist nested_tn;
529: extern Plist nested_type;
530: extern Pname curr_scope;
531: extern Pname curr_fct;
532: extern void nested_hide(Pname);
533: extern int is_empty(Pclass,bit=0);
534:
535: extern Pbase start_cl(TOK, Pname, Pbcl);
536: extern void end_cl();
537: extern Pbase end_enum(Pname, nlist*);
538:
539: /************ types : basic types, aggregates, declarators ************/
540:
541: #ifndef GRAM
542: extern bit new_type;
543: extern Pname cl_obj_vec;
544: extern Pname eobj;
545: #endif
546:
547:
548: #define DEFINED 01 /* definition fed through ?::dcl() */
549: #define SIMPLIFIED 02 /* in ?::simpl() */
550: #define DEF_SEEN 04 /* definition seen, but not processed */
551: #define REF_SEEN 010 /* reference seen (classdef) */
552: /* used for class members in norm.c */
553: #define IN_ERROR 010
554:
555: struct type : node {
556: bit defined; /* flags DEF_SEEN, DEFINED, SIMPLIFIED, IN_ERROR
557: not used systematically yet
558: */
559: bit lex_level;
560: Pclass in_class; // nested type
561: Pname in_fct; // local type
562: char *lcl;
563: char *nested_sig;
564: char *signature(char*);
565: Ptype tlist;
566: bit check(Ptype, TOK);
567: #ifndef GRAM
568: void print();
569: void dcl_print(Pname);
570: void base_print();
571:
572: Pname is_cl_obj(); /* sets cl_obj_vec */
573: Pptr is_ref();
574: Pptr is_ptr();
575: Pptr is_ptr_or_ref();
576: bit is_unsigned();
577: void dcl(Ptable);
578: int tsizeof(int = 0);
579: bit tconst();
580: TOK set_const(bit);
581: int align();
582: TOK kind(TOK,TOK);
583: TOK integral(TOK oo) { return kind(oo,'I'); };
584: TOK numeric(TOK oo) { return kind(oo,'N'); };
585: TOK num_ptr(TOK oo) { return kind(oo,'P'); };
586: bit vec_type();
587: Ptype deref();
588: inline Pptr addrof();
589: Pfct memptr();
590: #endif
591: void del();
592: };
593:
594: struct enumdef : type { /* ENUM */
595: bit e_body;
596: short no_of_enumerators;
597: unsigned char strlen; // strlen(string)
598: char* string; // name of enum
599: Pname mem;
600: Pbase e_type; // type representing the enum
601: enumdef(Pname n) { base=ENUM; mem=n; };
602: #ifndef GRAM
603: void print();
604: void dcl_print(Pname);
605: void dcl(Pname, Ptable);
606: void simpl();
607: #endif
608: };
609:
610: struct velem {
611: Pname n;
612: int offset;
613: };
614:
615: struct virt : node {
616: Pvirt next;
617: int n_init;
618: velem* virt_init; // vector of vtbl initializers (zero-terminated)
619: Pclass vclass; // for class vclass
620: char* string;
621: bit is_vbase; // vtable for virtual base
622: bit printed;
623: virt(Pclass cl, velem* v, char* s, bit flag, int ni) {base = XVIRT; vclass=cl; virt_init=v; string=s; is_vbase=flag; next=0; n_init = ni;}
624: };
625:
626: enum { C_VPTR=1, C_XREF=2, C_ASS=4, C_VBASE=8 };
627:
628: // An enumeration of the types of classes for Objectstore
629: enum class_type_enum { vanilla_class, // A regular class
630: template_class,
631: instantiated_template_class,
632: uninstantiated_template_class,
633: relationship_class,
634: defining_class
635: };
636: class type_extension;
637:
638: struct classdef : type { /* CLASS */
639: class_type_enum class_base; // An extension of "base" to further define
640: // the real subtype of the class
641: bit c_body; /* print definition only once */
642: TOK csu; /* CLASS, STRUCT, UNION, or ANON */
643: bit obj_align;
644: bit c_xref;
645: // 1 set: has vptr(s)
646: // 2 set: X(X&) exists
647: // 4 set: operator=(X&) exists
648: // 8 set: has vbaseptr(s)
649:
650: bit virt_count; // number of virtual functions
651: // starting at max base class virt_count in
652: bit virt_merge; // set when no virtual functions, but
653: // need to merge virtual base classes
654: bit c_abstract; // abstract class: don't instantiate
655: bit has_vvtab; // set if class has vtable from virtual base
656: unsigned char strlen; // strlen(string)
657: Pbcl baselist; // list of base classes
658: char* string; /* name of class */
659: Pname mem_list;
660: Ptable memtbl;
661: int obj_size;
662: int real_size; /* obj_size - alignment waste */
663: Plist friend_list;
664: Pname pubdef;
665: Plist tn_list; // list of member names hiding type names
666: Plist nest_list; // list of nested types
667: Ptype this_type;
668: Pvirt virt_list; // vtbl initializers
669: Pname c_ctor; // constuctor:
670: // possibly overloaded, possibly inherited
671: Pname c_dtor; // destructor
672: Pname c_itor; /* constructor X(X&) */
673: Pname conv; /* operator T() chain */
674: struct toknode *c_funqf, *c_funqr; // token Q for parsing function defs after class def
675:
676: classdef(TOK);
677: ~classdef();
678: TOK is_simple() { return (csu==CLASS)?0:csu; };
679: #ifndef GRAM
680: void print();
681: void dcl_print(Pname);
682: void simpl();
683:
684: void print_members();
685: void dcl(Pname, Ptable);
686:
687: // bit has_friend(Pname);
688: bit has_friend(Pclass);
689: bit has_friend(Pfct);
690:
691: bit has_base(Pclass cl);
692: bit baseof(Pname);
693: bit baseof(Pclass);
694: Pclass is_base(char*);
695:
696: Pname has_oper(TOK);
697: Pname has_ctor() { return c_ctor; }
698: Pname has_dtor() { return c_dtor; }
699: Pname has_itor() { return c_itor; }
700: Pname has_ictor();
701: Pname make_itor(int);
702: Pexpr find_name(char*, Pclass, int=0);
703: int do_virtuals(Pvirt, char*, int, bit);
704: int all_virt(Pclass, char*, int, bit);
705: void add_vtbl(velem*, char*, bit, int);
706: void print_all_vtbls(Pclass);
707: void print_vtbl(Pvirt);
708: void really_print(Pvirt);
709: int check_dup(Pclass, TOK);
710: int has_allocated_base(Pclass);
711: char *has_allocated_base(char*);
712: int get_offset(char*);
713: Pbcl get_base(char*);
714: Pexpr get_vptr_exp(char*);
715: Pexpr find_in_base(char*, Pclass);
716: void modify_inst_names(char *s); // Adjust ctor names for instantiation
717: bit parametrized_class();
718: bit same_class(Pclass p);
719: #endif
720: };
721:
722: #ifndef GRAM
723:
724: class clist {
725: Pclass cl;
726: clist* next;
727: public:
728: clist(Pclass c, clist* n) { cl=c; next=n; }
729: int onlist(Pclass);
730: void clear();
731: };
732:
733: extern clist * vcllist;
734:
735: struct vl {
736: struct vl* next;
737: Pvirt vt;
738: classdef* cl;
739:
740: vl(classdef* c, Pvirt v, struct vl* n)
741: { cl = c; vt = v; next = n; }
742: };
743:
744: extern vl* vlist;
745:
746: extern int nin;
747: extern int Nvis;
748: extern int Noffset;
749: extern TOK Nvirt;
750: extern Pexpr Nptr;
751: extern Pbcl Nvbc_alloc;
752: extern char *Nalloc_base;
753: extern Pexpr rptr(Ptype,Pexpr,int);
754: extern Pexpr vbase_args(Pfct, Pname);
755: extern Pexpr cdvec(Pname,Pexpr,Pclass,Pname,int,Pexpr,Pexpr=0);
756:
757: extern Pexpr find(char*, Pclass, int);
758: extern Pexpr find_name(Pname, Pclass, Ptable, int, Pname);
759: extern Pname find_virtual(Pclass,Pname);
760: extern Pname vfct(Pclass, char*);
761: extern int Vcheckerror;
762: extern int ignore_const;
763:
764: extern int mex;
765: extern Pclass mec;
766: extern Pclass tcl;
767: #endif
768:
769: struct basetype : type
770: /* ZTYPE CHAR SHORT INT LONG FLOAT DOUBLE
771: FIELD EOBJ COBJ TYPE ANY
772: */
773: /* used for gathering all the attributes
774: for a list of declarators
775:
776: ZTYPE is the (generic) type of ZERO
777: ANY is the generic type of an undeclared name
778: */
779: {
780: bit b_unsigned;
781: bit b_signed;
782: bit b_volatile;
783: bit b_const;
784: bit b_typedef;
785: bit b_inline;
786: bit b_virtual;
787: bit b_short;
788: bit b_long;
789: bit b_bits; /* number of bits in field */
790: bit b_offset; // bit offset of field
791: TOK b_sto; /* AUTO STATIC EXTERN REGISTER 0 */
792: Pname b_name; /* name of non-basic type */
793: Ptable b_table; /* memtbl for b_name, or 0 */
794: Pname b_xname; /* extra name */
795: union {
796: Ptype b_fieldtype;
797: char* b_linkage;
798: };
799:
800: basetype(TOK, Pname);
801:
802: Pbase type_adj(TOK);
803: Pbase base_adj(Pbase);
804: Pbase name_adj(Pname);
805: Pname aggr();
806: Pbase check(Pname);
807: #ifndef GRAM
808: void dcl_print();
809: Pbase arit_conv(Pbase);
810: bit parametrized_class();
811: #endif
812: int discriminator(int); // union discriminator fcn
813: };
814:
815: enum Linkage { linkage_default, linkage_C, linkage_Cplusplus };
816: extern Linkage linkage;
817: void set_linkage(char*);
818:
819: struct fct : type // FCT
820: {
821: TOK nargs;
822: TOK nargs_known; // 0 if unknown, 1 if known, or ELLIPSIS
823: bit last_stmt;
824: bit f_vdef; // 1 if this is the first virtual definition
825: // of this function
826: bit f_inline; // 1 if inline, 2 if being expanded, else 0
827: bit f_const; // one if member function that may be called for
828: // a const object, else 0
829: bit f_static; // 1 if static member function, else 0
830: short f_virtual; // index in virtual table, or 0 meaning non-virtual
831: short f_imeasure; // some measure of the size of an inline function
832: Ptype returns;
833: Pname argtype;
834: Ptype s_returns;
835: Pname f_this;
836: Pclass memof; // member of class memof
837: Pblock body;
838: Pname f_init; // base and member initializers
839: Pexpr f_expr; // body expanded into an expression
840: Pexpr last_expanded;
841: Pname f_result; // extra second argument of type X&
842: Pname f_args; // argument list including args added by cfront
843: Linkage f_linkage;
844: char* f_signature; // character encoding of function type
845: Plist local_class; // list of local classes
846: static Pfct fct_free;
847: void* operator new(size_t);
848: void operator delete(void*,size_t);
849:
850: fct(Ptype, Pname, TOK);
851: void argdcl(Pname,Pname);
852: #ifndef GRAM
853: Ptype normalize(Ptype);
854: void dcl_print();
855: void dcl(Pname);
856: Pexpr base_init(Pclass, Pexpr, Ptable, int);
857: Pexpr mem_init(Pname, Pexpr, Ptable);
858: void init_bases(Pclass, Pexpr);
859: bit declared() { return nargs_known; };
860: void simpl();
861: int ctor_simpl(Pclass, Pexpr);
862: Pstmt dtor_simpl(Pclass, Pexpr);
863: Pexpr expand(Pname,Ptable,Pexpr);
864: void sign();
865: #endif
866: int discriminator(int); // union discriminator fcn
867: };
868:
869: struct name_list : node {
870: Pname f;
871: Plist l;
872: name_list(Pname ff, Plist ll) { base = XNLIST; f=ff; l=ll; };
873: };
874:
875: #ifndef GRAM
876: struct gen : type { // OVERLOAD
877: Plist fct_list;
878:
879: gen() { base = OVERLOAD; }
880: Pname add(Pname);
881: Pname find(Pfct, bit);
882: Pname match(Pname, Pfct, bit);
883: };
884: #endif
885:
886: struct pvtyp : type {
887: Ptype typ;
888: };
889:
890: struct vec : pvtyp // VEC
891: // typ [ dim ]
892: {
893: Pexpr dim;
894: int size;
895:
896: static Pvec vec_free;
897: void* operator new(size_t);
898: void operator delete(void*,size_t);
899:
900: vec(Ptype t, Pexpr e) { base=VEC; typ=t; dim=e; DBID(); }
901: #ifndef GRAM
902: Ptype normalize(Ptype);
903: #endif
904: };
905:
906: struct ptr : pvtyp // PTR, RPTR i.e. reference
907: {
908: Pclass memof; // pointer to member of memof: memof::*
909: bit rdo; // "*const"
910:
911: static Pptr ptr_free;
912: void* operator new(size_t);
913: void operator delete(void*,size_t);
914:
915: ptr(TOK b, Ptype t) { base=b; typ=t; DBID(); }
916: #ifndef GRAM
917: Ptype normalize(Ptype);
918: #endif
919: };
920:
921: #ifndef GRAM
922: inline Pptr type::addrof() { return new ptr(PTR,this); }
923:
924: extern bit vrp_equiv;
925: #endif
926:
927:
928: /****************************** constants ********************************/
929:
930: /* STRING ZERO ICON FCON CCON ID */
931: /* IVAL FVAL LVAL */
932:
933: /***************************** expressions ********************************/
934:
935: #ifndef GRAM
936: extern Pexpr next_elem();
937: extern void new_list(Pexpr);
938: extern void list_check(Pname, Ptype, Pexpr, Ptable=0);
939: extern Pexpr ref_init(Pptr,Pexpr,Ptable);
940: extern Pexpr class_init(Pexpr,Ptype,Pexpr,Ptable);
941: extern Pexpr check_cond(Pexpr, TOK, Ptable);
942: extern Pexpr ptof(Pfct,Pexpr,Ptable);
943: extern void dosimpl(Pexpr, Pname);
944: extern int ref_initializer;
945: extern int ntok;
946:
947: extern void ptbl_init(int);
948: extern void ptbl_add_pair(char*,char*);
949: extern char *ptbl_lookup(char*);
950: extern char *st_name(char*);
951: #endif
952:
953: struct expr : node /* PLUS, MINUS, etc. */
954: /* IMPORTANT: all expressions are of sizeof(expr) */
955: /* DEREF => *e1 (e2==0) OR e1[e2]
956: UMINUS => -e2
957: INCR (e1==0) => ++e2
958: INCR (e2==0) => e1++
959: CM => e1 , e2
960: ILIST => LC e1 RC (an initializer list)
961: a Pexpr may denote a name
962: */
963: {
964: union {
965: Ptype tp;
966: char *string4;
967: };
968: union {
969: Pexpr e1;
970: long i1;
971: char* string;
972: };
973: union {
974: Pexpr e2;
975: int i2;
976: char* string2;
977: Pexpr n_initializer;
978: Ptype tpdef; // local and nested typedef info
979: };
980: union { /* used by the derived classes */
981: Ptype tp2;
982: Pname fct_name;
983: Pexpr cond;
984: Pexpr mem;
985: Ptype as_type;
986: Ptable n_table;
987: Pin il;
988: Pname query_this;
989: };
990:
991: static Pexpr expr_free;
992: void* operator new(size_t);
993: void operator delete(void*,size_t);
994: expr(TOK, Pexpr, Pexpr);
995: void del();
996: #ifndef GRAM
997: void print();
998: Pexpr typ0(Ptable);
999: Pexpr typ(Ptable);
1000: long eval();
1001: unsigned long ueval(long,long);
1002: int lval(TOK);
1003: Ptype call_fct(Ptable);
1004: Pexpr address();
1005: Pexpr contents();
1006: void simpl();
1007: Pexpr expand();
1008: bit not_simple();
1009: Pexpr try_to_overload(Ptable);
1010: Pexpr docast(Ptable);
1011: Pexpr dovalue(Ptable);
1012: Pexpr donew(Ptable);
1013: void simpl_new();
1014: void simpl_delete();
1015: #endif
1016: int discriminator(int); // union discriminator fcn
1017: };
1018:
1019: struct texpr : expr { // CAST NEW VALUE (also ICALL)
1020: texpr(TOK bb, Ptype tt, Pexpr ee) : expr (bb,ee,0) { tp2=tt; }
1021: };
1022:
1023: struct cast : expr { // CAST
1024: cast(Ptype tt, Pexpr ee) : expr (CAST,ee,0) { tp=tp2=tt; }
1025: };
1026:
1027: struct ival : expr { // IVAL
1028: ival(long ii) : expr (IVAL,0,0) { i1 = ii;}
1029: };
1030:
1031: struct call : expr { // CALL
1032: call(Pexpr aa, Pexpr bb) : expr (CALL,aa,bb) { }
1033: #ifndef GRAM
1034: void simpl();
1035: Pexpr expand(Ptable);
1036: #endif
1037: };
1038:
1039: struct qexpr : expr { // QUEST cond ? e1 : e2
1040: qexpr(Pexpr ee, Pexpr ee1, Pexpr ee2) : expr (QUEST,ee1,ee2) { cond=ee; }
1041: };
1042:
1043: struct ref : expr { // REF DOT e1->mem OR e1.mem
1044: ref(TOK ba, Pexpr a, Pexpr b) : expr (ba,a,0) { mem=b; }
1045: };
1046:
1047: struct mdot : expr { // MDOT a.b
1048: mdot(char* a, Pexpr b) : expr (MDOT,0,0) { string2=a; mem=b; }
1049: };
1050:
1051: struct text_expr : expr { // TEXT (vtbl_name)
1052: text_expr(char* a, char* b) : expr (TEXT,0,0)
1053: { string=a; string2=b; }
1054: };
1055: char* vtbl_name(char*,char*);
1056: /************************* names (are expressions) ****************************/
1057:
1058: struct basecl : node { // NAME => base class
1059: // VIRTUAL => virtual base class
1060: TOK ppp; // private / public / protected
1061: bit allocated; // allocated virtual base
1062: bit promoted; // non-explicit, promoted virtual base
1063: Pclass bclass;
1064: Pexpr init; // base class initializers for ctors
1065: int ptr_offset; // pointer's relative position in derived class
1066: int obj_offset; // object's relative position in derived class
1067: Pname* virt_init; // vector of vtbl table initializers
1068: basecl* next;
1069:
1070: basecl(Pclass cl, basecl* n) { baseclass=1; bclass=cl; next=n; promoted=0; init=0;}
1071: };
1072:
1073: enum template_formal_types {
1074: template_type_formal =1 , template_expr_formal,
1075: template_stmt_tree_formal, template_expr_tree_formal,
1076: template_actual_arg_dummy // used during the parse
1077: };
1078: extern TOK ppbase;
1079:
1080: struct name : expr { // NAME TNAME and the keywords in the ktbl
1081: TOK n_oper; // name of operator or 0
1082: TOK n_sto; // EXTERN STATIC AUTO REGISTER ENUM 0
1083: TOK n_stclass; // STATIC AUTO REGISTER 0
1084: TOK n_scope; // EXTERN STATIC FCT ARG PUBLIC 0
1085: TOK n_key; /* for names in table: class */
1086: bit n_evaluated; // 0 or n_val holds the value
1087: bit n_xref; // argument of type X(X&)
1088: unsigned char lex_level;
1089: TOK n_protect; // PROTECTED (<=>n_scope==0) or 0
1090: bit n_dcl_printed; // 1: declaration printed
1091: // 2: definition printed
1092: // 0: declaration not printed
1093:
1094: // if this is set it implies that n_template_arg == template_type_formal
1095: char n_template_arg; // One of template_formal_types for template arguments
1096: bit n_template_formal_must_be_class ;
1097: bit n_redefined ; // set only for PT function names where an explict
1098: // definition was provided.
1099: char *n_anon; // nested anonymous unions
1100: short n_union; // 0, or union index
1101: short n_addr_taken;
1102: short n_used;
1103: short n_assigned_to;
1104: Loc where;
1105: int n_offset; // byte offset in frame or struct
1106: Pname n_list;
1107: Pname n_tbl_list;
1108: char *n_gen_fct_name; // used to be punned with n_tbl_list.
1109: char *n_template_arg_string ; // the mangled string name
1110: union {
1111: /*
1112: * n_qualifier: name of containing class
1113: * n_realscope: for labels (always entered in function table)
1114: * the table for the actual scope in which label occurred.
1115: * syn_class: lex table only
1116: */
1117: Pname n_qualifier;
1118: Ptable n_realscope;
1119: int syn_class;
1120: };
1121:
1122: /* n_val: the value of n_initializer; also the argument
1123: * number for inline arguments (when base == ANAME) */
1124: long n_val;
1125: static Pname name_free;
1126: void* operator new(size_t);
1127: void operator delete(void*,size_t);
1128: name(char* =0);
1129:
1130:
1131: Pname normalize(Pbase, Pblock, bit);
1132: Pname tdef();
1133: Pname tname(TOK);
1134: void hide();
1135: void unhide() { n_key=0; n_list=0; };
1136: #ifndef GRAM
1137: Pname dcl(Ptable,TOK);
1138: int no_of_names();
1139: void use() { n_used++; };
1140: void assign();
1141: void take_addr();
1142: void check_oper(Pname);
1143: void simpl();
1144: void print();
1145: void dcl_print(TOK);
1146: void field_align();
1147: Pname dofct(Ptable,TOK);
1148: #endif
1149: void del();
1150: int discriminator(int); // union discriminator fcn
1151: };
1152:
1153: extern int friend_in_class;
1154: extern int in_class_dcl;
1155:
1156: // from parser
1157: extern int in_class_decl;
1158: extern int parsing_class_members;
1159: extern int in_mem_fct;
1160: extern int in_arg_list;
1161: extern Ptype in_typedef;
1162: extern int defer_check; // redefinition typedef check delay
1163: extern int declTag; // !1: inline, virtual mod permitted
1164: extern Pname in_tag;
1165: extern Pname statStat;
1166: extern int DECL_TYPE;
1167:
1168: /******************** statements *********************************/
1169:
1170: struct stmt : node { /* BREAK CONTINUE DEFAULT */
1171: /* IMPORTANT: all statement nodes have sizeof(stmt) */
1172: Pstmt s;
1173: Pstmt s_list;
1174: Loc where;
1175: union {
1176: Pname d; // goto/block -- destination
1177: Pexpr e2; // for iteration
1178: Pstmt has_default; // switch statement default
1179: int case_value;
1180: Ptype ret_tp; // pair
1181: };
1182: union {
1183: Pexpr e;
1184: bit own_tbl;
1185: Pstmt s2;
1186: };
1187: Ptable memtbl;
1188: union {
1189: Pstmt for_init;
1190: Pstmt else_stmt;
1191: Pstmt case_list;
1192: Loc where2; // location of } at end of block
1193: };
1194:
1195: static Pstmt stmt_free;
1196: void* operator new(size_t);
1197: void operator delete(void*,size_t);
1198: stmt(TOK, loc, Pstmt);
1199: void del();
1200: #ifndef GRAM
1201: void print();
1202: void dcl();
1203: void dcl1(Pstmt&);
1204: void reached();
1205: Pstmt simpl();
1206: Pstmt expand();
1207: Pstmt copy();
1208: #endif
1209: int discriminator(int); // union discriminator fcn
1210: };
1211:
1212: #ifndef GRAM
1213: extern char* Neval;
1214: extern Ptable scope;
1215: extern Ptable expand_tbl;
1216: extern Pname expand_fn;
1217: #endif
1218:
1219: struct estmt : stmt /* SM WHILE DO SWITCH RETURN CASE */
1220: /* SM (e!=0) => e;
1221: in particular assignments and function calls
1222: SM (e==0) => ; (the null statement)
1223: CASE => case e : s ;
1224: SM_PARAM => e is the template_statement_tree_formal name
1225: */
1226: {
1227: estmt(TOK t, loc ll, Pexpr ee, Pstmt ss) : stmt (t,ll,ss) { e=ee; }
1228: };
1229:
1230: struct ifstmt : stmt /* IF */
1231: // else_stme==0 => if (e) s
1232: // else_stmt!=0 => if (e) s else else_stmt
1233: {
1234: ifstmt(loc ll, Pexpr ee, Pstmt ss1, Pstmt ss2)
1235: : stmt (IF,ll,ss1) { e=ee; else_stmt=ss2; };
1236: };
1237:
1238: struct lstmt : stmt /* LABEL GOTO */
1239: /*
1240: d : s
1241: goto d
1242: */
1243: {
1244: lstmt(TOK bb, loc ll, Pname nn, Pstmt ss) : stmt (bb,ll,ss) { d=nn; }
1245: };
1246:
1247: struct forstmt : stmt { // FOR
1248: forstmt(loc ll, Pstmt fss, Pexpr ee1, Pexpr ee2, Pstmt ss)
1249: : stmt (FOR,ll,ss) { for_init=fss; e=ee1; e2=ee2; }
1250: };
1251:
1252: struct block : stmt { // BLOCK { d s }
1253: block(loc ll, Pname nn, Pstmt ss, loc rr = noloc ) : stmt (BLOCK,ll,ss)
1254: { d=nn; where2=rr; }
1255: #ifndef GRAM
1256: void dcl(Ptable);
1257: Pstmt simpl();
1258: #endif
1259: };
1260:
1261: #ifndef GRAM
1262: struct pair : public stmt { // PAIR
1263: pair(loc ll, Pstmt a, Pstmt b) : stmt (PAIR,ll,a) { s2 = b; }
1264: };
1265: #endif
1266:
1267: struct nlist {
1268: Pname head;
1269: Pname tail;
1270: nlist(Pname);
1271: void add(Pname n) { tail->n_list = n; tail = n; };
1272: void add_list(Pname);
1273: };
1274:
1275: extern Pname name_unlist(nlist*);
1276:
1277: struct slist {
1278: Pstmt head;
1279: Pstmt tail;
1280: slist(Pstmt s) { /*Nl++;*/ head = tail = s; };
1281: void add(Pstmt s) { tail->s_list = s; tail = s; };
1282: };
1283:
1284: extern Pstmt stmt_unlist(slist*);
1285:
1286: struct elist {
1287: Pexpr head;
1288: Pexpr tail;
1289: elist(Pexpr e) { /*Nl++;*/ head = tail = e; };
1290: void add(Pexpr e) { tail->e2 = e; tail = e; };
1291: };
1292:
1293: extern Pexpr expr_unlist(elist*);
1294:
1295: #ifndef GRAM
1296: extern class dcl_context * cc;
1297:
1298: struct dcl_context {
1299: Pname c_this; /* current fct's "this" */
1300: Ptype tot; /* type of "this" or 0 */
1301: Pname not; /* name of "this"'s class or 0 */
1302: Pclass cot; /* the definition of "this"'s class */
1303: Ptable ftbl; /* current fct's symbol table */
1304: Pname nof; /* current fct's name */
1305:
1306: void stack() { cc++; *cc = *(cc-1); };
1307: void unstack() { cc--; };
1308: };
1309:
1310: #define MAXCONT 20
1311: extern dcl_context ccvec[MAXCONT];
1312: #endif
1313:
1314: extern void yyerror(char*);
1315:
1316:
1317: #ifndef GRAM
1318: extern char* line_format;
1319:
1320: extern Plist stat_mem_list;
1321: extern Plist isf_list;
1322: extern Pstmt st_ilist;
1323: extern Pstmt st_dlist;
1324: extern Ptable sti_tbl;
1325: extern Ptable std_tbl;
1326: extern int need_sti( Pexpr e, Ptable tbl = 0, bit is_static_ok = 0 );
1327: Pexpr try_to_coerce(Ptype, Pexpr, char*, Ptable);
1328: extern bit can_coerce(Ptype, Ptype);
1329: extern Ptype np_promote(TOK, TOK, TOK, Ptype, Ptype, TOK);
1330: extern bit enum_promote;
1331: extern int suppress_error;
1332: extern void delete_local();
1333:
1334: extern int over_call(Pname, Pexpr);
1335: extern Pname overFound;
1336: extern Pname Nover;
1337: extern Pname Ncoerce;
1338: extern Nover_coerce;
1339: struct ia : node {
1340: Pname local; // local variable for argument
1341: Pexpr arg; // actual arguments for call
1342: Ptype tp; // type of formal argument
1343: ia() { base = XIA; };
1344: };
1345:
1346: struct iline : node {
1347: Pname fct_name; /* fct called */
1348: Pin i_next;
1349: Ptable i_table;
1350: int i_slots; // no of arg slots pointer to by i_args
1351: ia* i_args;
1352: iline() { base = XILINE; };
1353: };
1354:
1355: extern Pexpr curr_expr;
1356: extern Pin curr_icall;
1357: #define FUDGE111 11111
1358: #define VTOK 22222
1359: #define ITOR 77
1360:
1361: extern Pstmt curr_loop;
1362: extern Pblock curr_block;
1363: extern Pstmt curr_switch;
1364: extern loc last_line; // last #line + number of '\n's output since
1365: extern int last_ll; // 0 or line of current stmt/dcl being printed
1366: extern FILE* out_file; // output file descriptor
1367: extern bit Cast;
1368: extern loc no_where;
1369:
1370: extern no_of_undcl;
1371: extern no_of_badcall;
1372: extern Pname undcl, badcall;
1373:
1374: extern long str_to_long(const char*);
1375: extern int c_strlen(const char* s);
1376: #endif
1377:
1378: #ifndef GRAM
1379: extern Pname vec_new_fct;
1380: extern Pname new_fct;
1381: extern Pname del_fct;
1382: extern Pname vec_del_fct;
1383:
1384: extern int Nstd; // standard coercion used (derived* =>base* or int=>long or ...)
1385:
1386: extern int stcount; // number of names generated using make_name()
1387:
1388: Pexpr replace_temp(Pexpr,Pexpr);
1389: void make_res(Pfct);
1390:
1391: extern int Pchecked;
1392: Pexpr ptr_init(Pptr,Pexpr,Ptable);
1393: Pexpr call_ctor(Ptable, Pexpr p, Pexpr ctor, Pexpr args, int d = REF, Pexpr vb_args = 0);
1394: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg = 0, int d = DOT, Pexpr vb_args = 0);
1395: void check_visibility(Pname, Pname, Pclass, Ptable, Pname);
1396:
1397: int make_assignment(Pname);
1398:
1399: extern Pname make_tmp(char, Ptype, Ptable);
1400: Pexpr init_tmp(Pname, Pexpr, Ptable);
1401:
1402: extern int is_unique_base(Pclass, char*, int, int = 0);
1403: extern Pexpr rptr(Ptype, Pexpr, int);
1404:
1405: extern int read_align(char*);
1406: extern void new_init();
1407:
1408: extern void Eprint(Pexpr);
1409: extern Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast);
1410: extern Pexpr mptr_assign(Pexpr,Pexpr);
1411: extern Pclass Mptr;
1412:
1413: #endif
1414:
1415: extern bit fake_sizeof; // suppress error message for ``int v[];''
1416:
1417: extern TOK lalex();
1418:
1419:
1420: #ifdef DBG
1421: extern void display_expr( Pexpr, char* = 0, int = 0 );
1422: extern void display_stmt( Pstmt, char* = 0, int = 0 );
1423: extern void display_type( Ptype );
1424: extern void display_namelist( Plist, char* = 0, int = 0 );
1425:
1426: extern fprintf(const FILE*, const char* ...);
1427: extern void process_debug_flags( char* );
1428: #define DB(a) if(scan_started){a;}
1429: extern int Adebug; // allocation (ctor/del) debugging
1430: extern int Ddebug; // dcl debugging
1431: extern int Edebug; // expr debugging
1432: extern int Ldebug; // lex/lalex debugging
1433: extern int Mdebug; // trace function matching
1434: extern int Ndebug; // norm debugging
1435: extern int Pdebug; // print debugging
1436: extern int Rdebug; // run() debugging
1437: extern int Sdebug; // simpl debugging
1438: extern int Tdebug; // typ debugging
1439: #define Ydebug yydebug
1440: extern int Ydebug; // yacc debugging
1441:
1442: #else
1443:
1444: #define DB(a) /**/
1445:
1446: #endif
1447:
1448: #endif
1449: /* end */
1450: 0707071010112043661004440001630000160000010071100466055375100000600000112027dcl.c /*ident "@(#)ctrans:src/dcl.c 1.5" */
1451: /**************************************************************************
1452:
1453: C++ source for cfront, the C++ compiler front-end
1454: written in the computer science research center of Bell Labs
1455:
1456: Copyright (c) 1984 AT&T, Inc. All rights Reserved
1457: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
1458:
1459: dcl.c:
1460:
1461: ``declare'' all names, that is insert them in the appropriate symbol tables.
1462:
1463: Calculate the size for all objects (incl. stack frames),
1464: and find store the offsets for all members (incl. auto variables).
1465: "size.h" holds the constants needed for calculating sizes.
1466:
1467: Note that (due to errors) functions may nest
1468:
1469: *****************************************************************************/
1470:
1471:
1472: #include "cfront.h"
1473: #include "size.h"
1474:
1475: class dcl_context ccvec[MAXCONT], * cc = ccvec;
1476: int byte_offset;
1477: int bit_offset;
1478: int max_align;
1479: int friend_in_class;
1480: static Pstmt itail;
1481:
1482: Pname dclass(Pname, Ptable);
1483: Pname denum(Pname, Ptable);
1484: void merge_init(Pname, Pfct, Pfct);
1485:
1486: void dosimpl(Pexpr e, Pname n)
1487: {
1488: //error('d',"dosimpl %k %n",e?e->base:0,n);
1489: if (n==0) {
1490: if (dummy_fct == 0) make_dummy();
1491: n = dummy_fct;
1492: }
1493: Pname cf = curr_fct;
1494: curr_fct = n;
1495: e->simpl();
1496: curr_fct = cf;
1497: }
1498:
1499: static Pexpr co_array_init(Pname n, Ptable tbl)
1500: /*
1501: handle simple arrays only. To be done well list_check() must
1502: be rewritten to handle dynamic initialization.
1503: */
1504: {
1505: // error('d',"Ir forCO%n\[\]",n);
1506: Pexpr init = n->n_initializer;
1507:
1508: if (init->base != ILIST) {
1509: error("badIr for array ofCOs %n",n);
1510: return 0;
1511: }
1512:
1513: Pexpr el = 0;
1514: Pvec v = Pvec(n->tp);
1515: while (v->base==TYPE) v = Pvec(Pbase(v)->b_name->tp);
1516: Pname cn = v->typ->is_cl_obj();
1517: Pclass cl = cn ? Pclass(cn->tp) : 0;
1518: //error('d',"v %t cl %d %t",v,cl,cl);
1519: int i = v->size;
1520:
1521: int count = 0;
1522: Pexpr il2;
1523: for (Pexpr il = init->e1; il; il = il2) {
1524: // generate n[0].cl(initializer),
1525: // ...
1526: // n[max].cl(initializer),
1527: Pexpr e = il->e1;
1528: il2 = il->e2;
1529: il->e2 = 0;
1530: if (e == dummy) break;
1531: //error('d',"il %k e %k",il->base,e?e->base:0);
1532: if (e->base == VALUE) {
1533: switch (e->tp2->base) {
1534: case CLASS:
1535: if (Pclass(e->tp2)!=cl) e = new texpr(VALUE,cl,il);
1536: break;
1537: default:
1538: Pname n2 = e->tp2->is_cl_obj();
1539: if (n2==0 || Pclass(n2->tp)!=cl) e = new texpr(VALUE,cl,il);
1540: }
1541: }
1542: else
1543: e = new texpr(VALUE,cl,il);
1544: e->e2 = new expr(DEREF,n,new ival(count++));
1545: e = e->typ(tbl);
1546: dosimpl(e,cc->nof);
1547: // e->simpl();
1548: if (sti_tbl == tbl) {
1549: Pstmt ist = new estmt(SM,no_where,e,0);
1550: if (st_ilist == 0)
1551: st_ilist = ist;
1552: else
1553: itail->s_list = ist;
1554: itail = ist;
1555: }
1556: else {
1557: el = el ? new expr(G_CM,el,e) : e;
1558: }
1559: }
1560:
1561: if (i==0)
1562: v->size = count;
1563: else if (i==count)
1564: ;
1565: else if (i<count) {
1566: error("too manyIrs for%n (%d)",n, count);
1567: return 0;
1568: }
1569: else {
1570: // error('d',"too fewIrs for%n (%d)",n, count);
1571: if (cl->has_ictor())
1572: error('s',"too fewIrs for%n",n);
1573: else error( "too fewIrs for%n (C %srequires a defaultK)", n, cl->string );
1574: return 0;
1575: }
1576: return el;
1577: }
1578:
1579: int need_sti(Pexpr e, Ptable tbl, bit accept_name)
1580: /*
1581: check if non-static variables or operations are used
1582: INCOMPLETE
1583: */
1584: {
1585: if (e == 0) return 0;
1586: // error('d',"need_sti: %d - %d %k %t",tbl?1:0,accept_name,e->base,e->tp);
1587:
1588: switch (e->base) {
1589: case QUEST:
1590: if (need_sti(e->cond,tbl,0) && tbl==0) return 1;
1591: case PLUS:
1592: case MINUS:
1593: case MUL:
1594: case DIV:
1595: case MOD:
1596: case ER:
1597: case OR:
1598: case ANDAND:
1599: case OROR:
1600: case LS:
1601: case RS:
1602: case EQ:
1603: case NE:
1604: case LT:
1605: case LE:
1606: case GT:
1607: case GE:
1608: case INCR:
1609: case DECR:
1610: case ASSIGN:
1611: if (need_sti(e->e1,tbl,accept_name) && tbl==0) return 1;
1612: // no break;
1613:
1614: case UMINUS:
1615: case UPLUS:
1616: case NOT:
1617: case COMPL:
1618: if (need_sti(e->e2,tbl,accept_name) && tbl==0) return 1;
1619: // no break
1620:
1621: case SIZEOF:
1622: default:
1623:
1624: return 0;
1625:
1626: case CAST:
1627:
1628: return need_sti(e->e1,tbl,accept_name);
1629:
1630: case ADDROF:
1631: {
1632: int i = need_sti(e->e2,tbl,1);
1633: return i;
1634: }
1635:
1636: case NAME:
1637: if (accept_name && Pname(e)->n_stclass==STATIC) return 0;
1638:
1639: // if ((Pname(e)->n_stclass==AUTO || Pname(e)->n_stclass==REGISTER)
1640: // && strncmp(Pname(e)->string,"__Q",3) != 0 ) {
1641: // error("localN%n inIr for static",e);
1642: // return 0;
1643: // }
1644:
1645: if (e->tp->tconst()) {
1646: if (vec_const || fct_const) return 0;
1647: Neval = 0;
1648: e->eval();
1649: if (Neval == 0) return 0;
1650: }
1651: return 1;
1652:
1653: case DEREF:
1654: case REF:
1655: case DOT:
1656: if (accept_name||(e->tp && e->tp->base==VEC)) {
1657: int x1 = need_sti(e->e1,tbl,e->base == DOT);
1658: int x2 = need_sti(e->e2,tbl,0);
1659: return x1 || x2;
1660: }
1661: // no break
1662:
1663: case ELIST:
1664: // case ILIST:
1665: case G_CM:
1666: case CM:
1667: if (e->base==CM) {
1668: if (need_sti(e->e1,tbl,0) || need_sti(e->e2,tbl,0))
1669: return 1;
1670: else
1671: return 0;
1672: }
1673: case CALL:
1674: case G_CALL:
1675: case NEW:
1676: case GNEW:
1677: case 0: // hack for `new type (expr)'
1678: if (tbl) {
1679: need_sti(e->e1,tbl,accept_name);
1680: need_sti(e->e2,tbl,accept_name);
1681: if ( e->tp && e->tp->base == VEC &&
1682: e->base == NEW || e->base == GNEW )
1683: // preserve ICON,STRING,CCON,FCON
1684: need_sti(Pvec(e->tp)->dim,tbl);
1685: }
1686: else if (e->base == 0)
1687: return 0;
1688: // no break
1689: case ICALL:
1690: return 1;
1691: case ICON:
1692: case STRING:
1693: case CCON:
1694: case FCON:
1695: //error('d',"save %k tbl %d",e->base,tbl);
1696: if (tbl) {
1697: char* p = new char[strlen(e->string)+1];
1698: strcpy(p,e->string);
1699: e->string = p;
1700: }
1701: return 0;
1702: }
1703: }
1704:
1705: static void check_def_name( Pname nn, int scope )
1706: {
1707: // error('d', "check_def_name: nn: %n n_sto: %k scope: %k", nn,nn->n_sto,scope );
1708: if ( def_name==0 && pdef_name==0 && friend_in_class == 0 &&
1709: scope == EXTERN && nn->n_scope != STATIC &&
1710: nn->n_oper != NEW && nn->n_oper != DELETE ) {
1711: Pfct f = Pfct(nn->tp);
1712: if (f->body &&
1713: f->f_inline == 0 &&
1714: f->f_imeasure == 0) {
1715: // error('d', "check_def_name: do it: %n", nn );
1716: pdef_name = def_name = nn;
1717: ptbl_init(0);
1718: def_name = 0;
1719: }
1720: }
1721: }
1722:
1723: int stat_init = 0; // in an expression initializing a local static
1724: Pname name::dcl(Ptable tbl, TOK scope)
1725: /*
1726: enter a copy of this name into symbol table "tbl";
1727: - create local symbol tables as needed
1728:
1729: "scope" gives the scope in which the declaration was found
1730: - EXTERN, FCT, ARG, PUBLIC, or 0
1731: Compare "scope" with the specified storage class "n_sto"
1732: - AUTO, STATIC, REGISTER, EXTERN, OVERLOAD, FRIEND, or 0
1733:
1734: After name::dcl()
1735: n_stclass == 0 class or enum member
1736: REGISTER auto variables declared register
1737: AUTO auto variables not registers
1738: STATIC statically allocated object
1739: n_scope == 0 private class member
1740: PUBLIC public class member
1741: EXTERN name valid in this and other files
1742: STATIC name valid for this file only
1743: FCT name local to a function
1744: ARG name of a function argument
1745: ARGT name of a type defined in an
1746: argument list
1747: ARGS temporary class object with dtor in
1748: initialization of a local static
1749:
1750:
1751: typecheck function bodies;
1752: typecheck initializers;
1753:
1754: note that functions (error recovery) and classes (legal) nest
1755:
1756: The return value is used to chain symbol table entries, but cannot
1757: be used for printout because it denotes the sum of all type information
1758: for the name
1759:
1760: names of typenames are marked with n_oper==TNAME
1761:
1762: WARNING: The handling of scope and storage class is cursed!
1763: */
1764: {
1765: Pname nn;
1766: Ptype nnt = 0;
1767: Pname odcl = Cdcl;
1768: int sti_vb = 0; // set if initialize with virtual base class
1769:
1770: // if (this == 0) error('i',"0->N::dcl()");
1771: // if (tbl == 0) error('i',"%n->N::dcl(tbl=0,%k)",this,scope);
1772: // if (tbl->base != TABLE) error('i',"%n->N::dcl(tbl=%d,%k)",this,tbl->base,scope);
1773: // if (tp == 0) error('i',"N::dcl(%n,%k)T missing",this,scope);
1774:
1775: Cdcl = this;
1776: Ptype tx = tp;
1777:
1778: DB( if(Ddebug>=1) error('d',"dcl %n %t",this,tx); );
1779: // error('d',"dcl %n %t cc->cot: %d",this,tx,cc?cc->cot:0);
1780: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp;
1781:
1782: switch (base) {
1783: case TNAME:
1784: nn = tbl->look(string,0);
1785: tp->dcl(tbl);
1786: if (nn && nn->lex_level == lex_level) {
1787: //error('d', "dcl: cot: %s ccl: %s", cc->cot?cc->cot->string:"notset", ccl?ccl->string:"notset");
1788:
1789: if ( tp->check(nn->tp,0) )
1790: error("%n declared as %t and %t",nn,nn->tp,tp);
1791: else if ( nn->base == NAME && cc->cot == 0 &&
1792: (tp->base != COBJ || tp->base != EOBJ))
1793: error("%n declared as identifier and typedef", nn );
1794: Cdcl = odcl;
1795: return 0;
1796:
1797: }
1798: PERM(tp);
1799: nn = new name(string);
1800: nn->base = TNAME;
1801: nn->tp = tp;
1802: Pname tn = tbl->insert(nn,0);
1803: if (n_key == NESTED) {
1804: tn->n_key = NESTED;
1805: tn->tpdef = tpdef;
1806: }
1807: delete nn;
1808: Cdcl = odcl;
1809: return this;
1810:
1811: case NAME:
1812: switch (n_oper) {
1813: case COMPL:
1814: if (tp->base != FCT) {
1815: error("~%s notF",string);
1816: n_oper = 0;
1817: }
1818: break;
1819: case TNAME:
1820: if (tp->base != FCT) n_oper = 0;
1821: break;
1822: }
1823: break;
1824: default:
1825: error('i',"NX in N::dcl()");
1826: }
1827:
1828: if (n_qualifier) {
1829: // c::f()
1830: // class function,
1831: // friend declaration, or
1832: // static member initializer
1833: Pname cn = n_qualifier;
1834:
1835: switch (cn->base) {
1836: case TNAME:
1837: break;
1838: case NAME:
1839: cn = gtbl->look(cn->string,0);
1840: if (cn && cn->base==TNAME) break;
1841: default:
1842: error("badQr%n for%n",n_qualifier,this);
1843: Cdcl = odcl;
1844: return 0;
1845: }
1846:
1847: while (cn->tp->base == TYPE) cn->tp = Pbase(cn->tp)->b_name->tp;
1848: // error('d',"actualQr%n %t",cn,cn->tp);
1849: if (cn->tp->base != COBJ) {
1850: error(&where,"Qr%nnot aCN",n_qualifier);
1851: Cdcl = odcl;
1852: return 0;
1853: }
1854:
1855: cn = Pbase(cn->tp)->b_name;
1856: if (n_oper) check_oper(cn);
1857:
1858: Pclass cl = Pclass(cn->tp);
1859: if (cl == cc->cot) {
1860: n_qualifier = 0;
1861: goto xdr;
1862: }
1863: else if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
1864: error("C%nU",cn);
1865: Cdcl = odcl;
1866: return 0;
1867: }
1868: else if (cl->c_body==1) //III
1869: cl->dcl_print(0);
1870:
1871: Ptable etbl = cl->memtbl;
1872: Pname x = etbl->look(string,0);
1873: if (x==0 || x->n_table!=etbl) {
1874: error("%n is not aM of%n",this,cn);
1875: Cdcl = odcl;
1876: return 0;
1877: }
1878:
1879: if (tp->base == FCT) { //III
1880: // if (friend_in_class==0 && Pfct(tp)->body==0) { // c::f(); needed for friend
1881: if (friend_in_class==0
1882: && n_sto!=FRIEND
1883: && Pfct(tp)->body==0) { // c::f(); needed for friend
1884: error("QdN%n inFD",x);
1885: Cdcl = odcl;
1886: return 0;
1887: }
1888:
1889: if (Pfct(tp)->body==0) {
1890: Pfct(tp)->memof = cl;
1891: int xx;
1892: if (x->tp->base==OVERLOAD)
1893: xx = Pgen(x->tp)->find(Pfct(tp),0)==0;
1894: else
1895: xx = x->tp->check(tp,0);
1896:
1897: if (xx) {
1898: error("%n is not aM of%n",this,cn);
1899: Cdcl = odcl;
1900: return 0;
1901: }
1902: }
1903: }
1904: else {
1905: if (x->n_stclass != STATIC) { // e.g. int c::i = 7
1906: error("D of non staticCM %n",this);
1907: Cdcl = odcl;
1908: return 0;
1909: }
1910: if (n_sto) error("staticCM declared%k",n_sto);
1911: tbl = etbl;
1912: }
1913: }
1914: xdr:
1915: if (n_oper
1916: && tp->base!=FCT
1917: && n_sto!=OVERLOAD) error("operator%k not aF",n_oper);
1918:
1919:
1920: /* if a storage class was specified
1921: check that it is legal in the scope
1922: else
1923: provide default storage class
1924: some details must be left until the type of the object is known
1925: */
1926:
1927: n_stclass = n_sto;
1928: n_scope = scope; /* default scope & storage class */
1929:
1930: switch (n_sto) {
1931: default:
1932: error('i',"unX %k",n_sto);
1933: case FRIEND:
1934: {
1935: Pclass cl = cc->cot;
1936:
1937: switch (scope) {
1938: case 0:
1939: case PUBLIC:
1940: break;
1941: default:
1942: error("friend%n not inCD(%k)",this,scope);
1943: base = 0;
1944: Cdcl = odcl;
1945: return 0;
1946: }
1947:
1948: switch (n_oper) {
1949: case 0:
1950: case NEW:
1951: case DELETE:
1952: case CTOR:
1953: case DTOR:
1954: case TYPE:
1955: n_sto = 0;
1956: break;
1957: default:
1958: n_sto = OVERLOAD;
1959: }
1960:
1961: switch (tx->base) {
1962: case COBJ:
1963: nn = Pbase(tx)->b_name;
1964: break;
1965: case CLASS:
1966: nn = this;
1967: break;
1968: case FCT:
1969: cc->stack();
1970: cc->not = 0;
1971: cc->tot = 0;
1972: cc->cot = 0;
1973: friend_in_class++;
1974: // n_sto = EXTERN;
1975: n_sto = 0;
1976: nn = dcl(gtbl,EXTERN);
1977: if (nn == 0) {
1978: Cdcl = odcl;
1979: return 0;
1980: }
1981: friend_in_class--;
1982: cc->unstack();
1983: if (nn->tp->base == OVERLOAD) nn = Pgen(nn->tp)->find(Pfct(tx),1);
1984: break;
1985: default:
1986: error("badT%tof friend%n",tp,this);
1987: Cdcl = odcl;
1988: return 0;
1989: }
1990: PERM(nn);
1991: cl->friend_list = new name_list(nn,cl->friend_list);
1992: Cdcl = odcl;
1993: return nn;
1994: }
1995: case OVERLOAD:
1996: if (strict_opt||warning_opt)
1997: error(strict_opt?0:'w',"`overload' used (anachronism)");
1998: n_sto = 0;
1999: // ignore overload!
2000: switch (tp->base) {
2001: case FCT:
2002: break;
2003: default:
2004: base = 0;
2005: Cdcl = odcl;
2006: return this;
2007: }
2008: break;
2009: case REGISTER:
2010: if (tp->base == FCT) {
2011: error('w',"%n: register (ignored)",this);
2012: goto ddd;
2013: }
2014: case AUTO:
2015: switch (scope) {
2016: case 0:
2017: case PUBLIC:
2018: case EXTERN:
2019: error("%k not inF",n_sto);
2020: goto ddd;
2021: }
2022: if (n_sto==AUTO) n_sto = 0; // always redundant
2023: break;
2024: case EXTERN:
2025: switch (scope) {
2026: case ARG:
2027: //error("externA");
2028: goto ddd;
2029: case 0:
2030: case PUBLIC:
2031: /* extern is provided as a default for functions without body */
2032: if (tp->base != FCT) error("externM%n",this);
2033: goto ddd;
2034: case FCT:
2035: {
2036: Pname nn = gtbl->look( string, 0 );
2037: tp->dcl(tbl);
2038: if ( nn && tp->base != FCT &&
2039: tp->check(nn->tp,0))
2040: {
2041: error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp);
2042: Cdcl = odcl;
2043: return 0;
2044: }
2045: }
2046: }
2047: n_stclass = STATIC;
2048: n_scope = EXTERN; /* avoid FCT scoped externs to allow better checking */
2049: break;
2050: case STATIC:
2051: switch (scope) {
2052: case ARG:
2053: //error("static used forA%n",this);
2054: goto ddd;
2055: case 0:
2056: case PUBLIC:
2057: n_stclass = STATIC;
2058: n_scope = scope;
2059: break;
2060: default:
2061: n_scope = STATIC;
2062: }
2063: break;
2064: case 0:
2065: ddd:
2066: switch (scope) { /* default storage classes */
2067: case EXTERN:
2068: n_scope = EXTERN;
2069: n_stclass = STATIC;
2070: break;
2071: case FCT:
2072: if (tp->base == FCT) {
2073: n_stclass = STATIC;
2074: n_scope = EXTERN;
2075: }
2076: else
2077: n_stclass = AUTO;
2078: break;
2079: case ARG:
2080: n_stclass = AUTO;
2081: break;
2082: case 0:
2083: case PUBLIC:
2084: n_stclass = 0;
2085: break;
2086: }
2087: }
2088:
2089:
2090: /*
2091: now insert the name into the appropriate symbol table,
2092: and compare types with previous declarations of that name
2093:
2094: do type dependent adjustments of the scope
2095: */
2096: //error('d',"sw %d",tx->base);
2097: static int warn_ldouble=0;
2098:
2099: switch (tx->base) {
2100: case ASM:
2101: { Pbase b = Pbase(tp);
2102: Pname n = tbl->insert(this,0);
2103: n->assign();
2104: n->use();
2105: char* s = (char*) b->b_name; // save asm string. Shoddy
2106: int ll = strlen(s);
2107: char* s2 = new char[ll+1];
2108: strcpy(s2,s);
2109: b->b_name = Pname(s2);
2110: Cdcl = odcl;
2111: return this;
2112: }
2113:
2114: case CLASS:
2115: tp = tx;
2116: nn = dclass(this,tbl);
2117: Cdcl = odcl;
2118: return nn;
2119:
2120: case ENUM:
2121: tp = tx;
2122: nn = denum(this,tbl);
2123: Cdcl = odcl;
2124: return nn;
2125:
2126: case FCT:
2127: tp = tx;
2128: nn = dofct(tbl,scope);
2129: if (nn == 0) {
2130: Cdcl = odcl;
2131: return 0;
2132: }
2133:
2134: // error('d', "%s n_oper: %k, scope: %k", string, n_oper, scope );
2135: if (pdef_name == 0) check_def_name(nn, scope);
2136: break;
2137:
2138: case FIELD:
2139: switch (n_stclass) {
2140: case 0:
2141: case PUBLIC:
2142: break;
2143: default:
2144: error("%k field",n_stclass);
2145: n_stclass = 0;
2146: }
2147:
2148: if (cc->not==0 || cc->cot->csu==UNION || cc->cot->csu==ANON) {
2149: error(cc->not?"field in union":"field not inC");
2150: PERM(tp);
2151: Cdcl = odcl;
2152: return this;
2153: }
2154:
2155: if (string) {
2156: nn = tbl->insert(this,0);
2157: n_table = nn->n_table;
2158: if (Nold) error("twoDs of field%n",this);
2159: }
2160:
2161: tp->dcl(tbl);
2162: field_align();
2163: break;
2164:
2165: case COBJ:
2166: { Pclass cl = Pclass(Pbase(tx)->b_name->tp);
2167: //error('d',&where,"dcl %n; tx->base == cobj",this);
2168: if (cl->lex_level > lex_level)
2169: error("C%t is not visible in this scope",cl);
2170:
2171: if (cl->csu == ANON) { // export member names to enclosing scope
2172: if (tbl==gtbl && n_sto!=STATIC) error("extern anonymous union (declare as static)");
2173: char* p = cl->string;
2174: while (*p++ != 'C'); /* sneaky */
2175: int uindex = (int)str_to_long(p);
2176:
2177: // error('d', "%n->dcl() n_scope: %k n_protect: %k", this, n_scope, n_protect );
2178: // cannot cope with use counts for ANONs:
2179: Pbase(tp)->b_name->n_used = 1;
2180: Pbase(tp)->b_name->n_assigned_to = 1;
2181:
2182: Ptable mtbl = cl->memtbl;
2183: int i, err_msg = 0;
2184: for (Pname nn=mtbl->get_mem(i=1); nn; nn=mtbl->get_mem(++i)) {
2185: if (nn->tp->base == FCT) {
2186: error("FM%n for anonymous union",nn);
2187: break;
2188: }
2189: Ptable tb = nn->n_table;
2190: nn->n_table = 0;
2191: nn->n_scope = n_protect?n_protect:n_scope;
2192: Pname n = tbl->insert(nn,0);
2193: if (Nold) {
2194: error("twoDs of%n (one in anonymous union)",nn);
2195: break;
2196: }
2197:
2198: Pclass tc;
2199: if (tc = cl->in_class)
2200: --n->lex_level;
2201: if ( tc && tc->csu == ANON) {
2202: //error('d', "tc->csu anon %k %s", tc->csu, string );
2203: if ( n->n_anon ) {
2204: if ( !err_msg )
2205: error('s', "anonymous unions nested deeper than 2 levels" );
2206: err_msg = 1;
2207: }
2208: n->n_anon = string;
2209: }
2210:
2211: n->n_union = uindex;
2212: nn->n_table = tb;
2213: }
2214: }
2215: if (cl->c_abstract) error("D ofO of abstractC%t",cl);
2216: goto cde;
2217: }
2218:
2219: case VOID:
2220: if (n_scope != ARG) {
2221: error("badBT:%k%n",tx->base,this);
2222: Cdcl = odcl;
2223: return 0;
2224: }
2225: break;
2226:
2227: case LDOUBLE:
2228: if (warn_ldouble==0 && ansi_opt==0) {
2229: ++warn_ldouble;
2230: error('w',"long double supported under ``+a1'' option only, generating ``double%n''", this);
2231: }
2232: goto cde;
2233:
2234: case PTR:
2235: case VEC:
2236: case RPTR:
2237: tp->dcl(tbl);
2238:
2239: default:
2240: cde:
2241: //error('d',"cde: %n %t",this,tp);
2242: nn = tbl->insert(this,0);
2243: n_table = nn->n_table;
2244:
2245: if (Nold) {
2246:
2247: if ( nn->base == PUBLIC ) { // X::i
2248: error("twoDs ofCM%n", nn);
2249: Cdcl = odcl;
2250: return 0;
2251: }
2252:
2253: if (nn->tp->base == ANY) goto zzz;
2254:
2255: if (tp->check(nn->tp,0)) {
2256: error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp);
2257: Cdcl = odcl;
2258: return 0;
2259: }
2260: //error('d',"%n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope);
2261: if (n_sto && n_sto!=nn->n_scope) {
2262: if (n_sto==EXTERN && nn->n_scope==STATIC) {
2263: error('w',"%n declared extern after being declared static",this);
2264: goto ext_fudge;
2265: }
2266: else
2267: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:(scope==FCT?AUTO:EXTERN));
2268: }
2269: else if (nn->n_scope==STATIC && n_scope==EXTERN) {
2270: error('w',"static%n followed by definition",this);
2271: ext_fudge:
2272: if (n_initializer) {
2273: // error('d',"static%n redefined (WIr)",this);
2274: n_initializer = 0;
2275: }
2276: n_sto = EXTERN;
2277: }
2278: else if (nn->n_sto==STATIC && n_sto==STATIC )
2279: error("static%n declared twice",this);
2280: else {
2281: if (n_sto==0
2282: && nn->n_sto==EXTERN
2283: && n_initializer
2284: && tp->tconst())
2285: n_sto = EXTERN;
2286: n_scope = nn->n_scope;
2287:
2288: switch (scope) {
2289: case FCT:
2290: if (n_sto != EXTERN) {
2291: error("twoDs of%n",this);
2292: Cdcl = odcl;
2293: return 0;
2294: }
2295: break;
2296: case ARG:
2297: error("twoAs%n",this);
2298: Cdcl = odcl;
2299: return 0;
2300: case 0:
2301: case PUBLIC:
2302: error("twoDs ofM%n",this);
2303: Cdcl = odcl;
2304: return 0;
2305: case EXTERN:
2306: if (n_sto==0) {
2307: switch(nn->n_sto) {
2308: case 0:
2309: error("two definitions of%n",this);
2310: Cdcl = odcl;
2311: return 0;
2312: case EXTERN:
2313: if(nn->n_initializer) {
2314: error("two definitions of%n",this);
2315: Cdcl = odcl;
2316: }
2317: else
2318: nn->n_sto=0;
2319: break;
2320: }
2321: }
2322: else if(n_sto==EXTERN && n_initializer) {
2323: switch(nn->n_sto) {
2324: case 0:
2325: error("two definitions of%n",this);
2326: Cdcl = odcl;
2327: return 0;
2328: case EXTERN:
2329: nn->n_sto=0;
2330: break;
2331: }
2332: }
2333: break;
2334: }
2335: }
2336: n_scope = nn->n_scope;
2337: /* n_val */
2338: if (n_initializer) {
2339: if (nn->n_initializer || nn->n_val) error("twoIrs for%n",this);
2340: nn->n_initializer = n_initializer;
2341: }
2342: if (tp->base == VEC) {
2343: // handle: extern v[]; v[200];
2344: // and extern u[10]; u[11];
2345:
2346: Ptype ntp = nn->tp;
2347: while (ntp->base == TYPE) ntp = Pbase(ntp)->b_name->tp;
2348: if (Pvec(ntp)->dim == 0) Pvec(ntp)->dim = Pvec(tp)->dim;
2349: if (Pvec(ntp)->size) {
2350: if (Pvec(tp)->size
2351: && Pvec(ntp)->size!=Pvec(tp)->size)
2352: error("bad array size for%n: %d %dX",this,Pvec(tp)->size,Pvec(ntp)->size);
2353: }
2354: else
2355: Pvec(ntp)->size = Pvec(tp)->size;
2356: }
2357: }
2358: else {
2359: //error('d',"%n %t scope %d sto %k",this,tp,scope,n_sto);
2360: if (scope!=ARG
2361: && n_sto!=EXTERN
2362: && (!((scope==0 || scope==PUBLIC) && n_sto==STATIC)) // static member
2363: && n_initializer==0
2364: && tp->base==VEC
2365: && Pvec(tp)->size==0)
2366: error(&where,"dimension missing for array%n",this);
2367:
2368: if (scope==EXTERN
2369: && n_sto==0
2370: && tp->tconst()
2371: && vec_const==0
2372: && fct_const==0)
2373: nn->n_sto = n_sto = STATIC;
2374: }
2375:
2376: zzz:
2377: if (base != TNAME) {
2378: Ptype t = nn->tp;
2379:
2380: if (t->base == TYPE) {
2381: Ptype tt = Pbase(t)->b_name->tp;
2382: if (tt->base == FCT) nn->tp = t = tt;
2383: }
2384:
2385: switch (t->base) {
2386: case FCT:
2387: case OVERLOAD:
2388: break;
2389: default:
2390: fake_sizeof = 1;
2391: switch (nn->n_stclass) {
2392: default:
2393: if (nn->n_scope != ARG) {
2394: int x = t->align();
2395: int y = t->tsizeof();
2396:
2397: if (max_align < x) max_align = x;
2398:
2399: while (0 < bit_offset) {
2400: byte_offset++;
2401: bit_offset -= BI_IN_BYTE;
2402: }
2403: bit_offset = 0;
2404:
2405: if (byte_offset && 1<x) byte_offset = ((byte_offset-1)/x)*x+x;
2406: nn->n_offset = byte_offset;
2407: byte_offset += y;
2408: }
2409: break;
2410: case STATIC:
2411: if (n_sto != EXTERN
2412: && nn->n_scope
2413: && nn->n_scope!=PUBLIC)
2414: t->tsizeof(); // check that size is known
2415: }
2416: fake_sizeof = 0;
2417: }
2418: }
2419:
2420: { Ptype t = nn->tp;
2421: int const_old = const_save;
2422: bit vec_seen = 0;
2423: Pexpr init = n_initializer;
2424:
2425: lll:
2426: // error('d',"lll %n %t init %d %k",this,t,init,init?init->base:0);
2427: switch (t->base) {
2428: case COBJ:
2429: { Pname cn = Pbase(t)->b_name;
2430: Pclass cl = (Pclass)cn->tp;
2431: Pname ctor = cl->has_ctor();
2432: Pname dtor = cl->has_dtor();
2433: int stct = 0;
2434: //error('d',"obj %n; class '%s'; ctor '%s'; dtor '%s'",nn,cn->string,ctor?ctor->string:"???",dtor?dtor->string:"???");
2435: if (dtor) {
2436: Pstmt dls;
2437:
2438: // if dtor is not public check scope of class object
2439:
2440: //error('d',"dcl %n has dtor",nn);
2441: if (dtor->n_scope != PUBLIC) {
2442: //error('d',"dcl %n->n_scope: %d fct %n",nn,nn->n_scope,cc->nof);
2443: switch (nn->n_scope) {
2444: case ARG:
2445: case 0:
2446: case PUBLIC:
2447: break;
2448: default:
2449: check_visibility( dtor, 0, cl, tbl, cc->nof );
2450: }
2451: // if (nn->n_scope == FCT)
2452: // check_visibility( dtor, 0, cl, tbl, cc->nof );
2453: // else if ( nn->n_sto != EXTERN )
2454: // error("%k%n cannot access%n: %sM",nn->n_scope,nn,dtor,dtor->n_protect?"protected":"private");
2455: }
2456:
2457: switch ( nn->n_scope ) {
2458: case 0:
2459: case PUBLIC:
2460: if (n_stclass==STATIC) { //III
2461: Pclass cl = Pclass(nn->n_table->t_name->tp);
2462: if (cl->defined&DEFINED) goto dtdt;
2463: }
2464: break;
2465: case EXTERN:
2466: if (n_sto==EXTERN) break;
2467:
2468: case STATIC:
2469: { Pexpr c;
2470: dtdt:
2471: // local static class objects have destructors set up in simpl2.c
2472: // special case: temporary class object generated in init expression
2473: if (stat_init && scope == ARGS ) {
2474: nn->n_scope = ARGS;
2475: goto ggg;
2476: }
2477:
2478: if ( nn->lex_level
2479: && nn->n_sto == STATIC ) {
2480: if (ctor==0)
2481: error('s',"local static%n has%n but noK(add%n::%n())", nn, dtor, cn, cn );
2482: goto static_init;
2483: }
2484:
2485: Ptable otbl = tbl;
2486: // to collect temporaries generated
2487: // in static destructors where we
2488: // can find them again (in std_tbl)
2489: if (std_tbl == 0) std_tbl = new table(8,gtbl,0);
2490: tbl = std_tbl;
2491: if (vec_seen) {
2492: c = cdvec(vec_del_fct,nn,cl,dtor,0,zero);
2493: } else { // nn->cl::~cl(0);
2494: c = call_dtor(nn,dtor,0,DOT,one);
2495: }
2496: c->tp = any_type; // avoid another check
2497: dls = new estmt(SM,nn->where,c,0);
2498:
2499: // destructors for statics are executed in reverse order
2500: if (st_dlist) dls->s_list = st_dlist;
2501: st_dlist = dls;
2502: tbl = otbl;
2503: } // case STATIC
2504: } // switch nn->n_scope
2505: } // if dtor
2506:
2507: // local static class objects must defer setting up static dtor
2508: static_init:
2509: if (ctor) {
2510: // error('d',"ctor %n scope %k",ctor,nn->n_scope);
2511: Pexpr oo = nn;
2512: for (int vi=vec_seen; vi; vi--) oo = oo->contents();
2513: int sti = 0;
2514: switch (nn->n_scope) {
2515: case EXTERN:
2516: if (init==0 && n_sto==EXTERN) goto ggg;
2517: case STATIC:
2518: if (tbl == gtbl)
2519: sti = 1;
2520: else
2521: stct = 1;
2522: default:
2523: if (vec_seen && init) {
2524: if (1<vec_seen) {
2525: /* ?????
2526: if (init->base != ILIST)
2527: error("badIr forO ofC %t withK%n",cl,this);
2528: else
2529: */
2530: error('s',"Ir for multi-dimensional array%n ofOsofC %t withK",this,cl);
2531: }
2532: else {
2533: if (sti) {
2534: if (sti_tbl==0) sti_tbl = new table(8,gtbl,0);
2535: const_save = 1;
2536: (void) co_array_init(nn,sti_tbl);
2537: const_save = 0;
2538: n_initializer = init = 0;
2539: }
2540: else {
2541: n_initializer = init = co_array_init(nn,tbl);
2542: if (stct)
2543: nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 );
2544: }
2545: }
2546: goto ggg;
2547: }
2548: break;
2549: case PUBLIC:
2550: case 0:
2551: if (n_stclass==STATIC) { //III
2552: Pclass cl = Pclass(nn->n_table->t_name->tp);
2553: if (cl->defined&DEFINED) {
2554: sti = 1;
2555: break;
2556: }
2557: }
2558: {
2559: Pname c;
2560: if (vec_seen) {
2561: c = cl->has_ictor();
2562: if (c == 0)
2563: error("array ofC%n that does not have aK taking noAs",cn);
2564: else if (Pfct(c->tp)->nargs)
2565: error("defaultAs forK for array ofC%n",cn);
2566: }
2567: }
2568: // no break
2569: case ARG:
2570: goto ggg;
2571: }
2572:
2573: const_save = 1;
2574: nn->assign();
2575: Ptable otbl = tbl;
2576: if (sti) { // to collect temporaries generated
2577: // in static initializers where we
2578: // can find them again (in sti_tbl)
2579: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
2580: tbl = sti_tbl;
2581: if (n_sto == EXTERN) nn->n_sto = n_sto = 0;
2582: }
2583:
2584: if (init) {
2585: // error('d',"init %k",init->base);
2586: if (init->base==VALUE) {
2587: switch (init->tp2->base) {
2588: case CLASS:
2589: // error('d',"class %t %t",Pclass(init->tp2),cl);
2590: if (Pclass(init->tp2)!=cl) goto inin;
2591: break;
2592: default:
2593: Pname n2 = init->tp2->is_cl_obj();
2594: // error('d',"default %t %t",n2->tp,cl);
2595: if (n2==0 || Pclass(n2->tp)!=cl) goto inin;
2596: }
2597:
2598: Pexpr ee = init->e1;
2599: // error('d',"init->e1 %k",ee->base);
2600: if (ee && vec_seen==0)
2601: switch (ee->base) {
2602: case CALL: // T a = f();
2603: init = ee;
2604: goto inin;
2605: case ELIST: // T a(f());
2606: if (ee->e1->base==CALL
2607: && ee->e2 == 0) {
2608: init = ee->e1;
2609: goto inin;
2610: }
2611: } // end switch
2612:
2613: init->e2 = oo;
2614: init = init->typ(tbl);
2615:
2616: if (init->base == G_CM) // beware of type conversion operators
2617: switch (init->tp2->base) {
2618: case CLASS:
2619: if (Pclass(init->tp2)!=cl) goto inin;
2620: break;
2621: default:
2622: Pname n2 = init->tp2->is_cl_obj();
2623: if (n2==0 || Pclass(n2->tp)!=cl) goto inin;
2624: }
2625: }
2626: else {
2627: inin:
2628: // error('d',"inin %k",init->base);
2629: init = init->typ(tbl);
2630: //error('d', "inin: init->typ: %d %k n->tp %t init->tp %t",init->base,init->base,nn->tp,init->tp);
2631: if (init->base==G_CM
2632: && nn->tp->check(init->tp,0)==0)
2633: (void) replace_temp(init,nn->address());
2634: else
2635: init = class_init(nn,nn->tp,init,tbl);
2636: }
2637: }
2638: else if (vec_seen == 0) {
2639: //error('d',"make value");
2640: init = new texpr(VALUE,cl,0);
2641: init->e2 = oo;
2642: init = init->typ(tbl);
2643: }
2644:
2645: Pname c;
2646: if (vec_seen) {
2647: c = cl->has_ictor();
2648: if (c == 0)
2649: error("array ofC%n that does not have aK taking noAs",cn);
2650: else if (Pfct(c->tp)->nargs)
2651: error("defaultAs forK for array ofC%n",cn);
2652: }
2653:
2654: // error( 'd', "stct: %d init: %d", stct, init );
2655: if (stct) {
2656: if (tbl!=gtbl && nn->n_sto==EXTERN) {
2657: error(&where,"Id local extern%n",this);
2658: init = 0;
2659: }
2660: else if (init)
2661: init->base = STAT_INIT;
2662: else {
2663: if (tp->base == VEC && Pvec(tp)->size ) {
2664: Pexpr ilist = 0;
2665: for (int i=Pvec(tp)->size; i>0; i--) {
2666: Pexpr e = new texpr(VALUE,cl,0);
2667: ilist = new expr(ELIST, e, ilist);
2668: }
2669: nn->n_initializer=new expr(ILIST,ilist,0);
2670: init = co_array_init(nn,tbl);
2671: nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 );
2672: }
2673: else
2674: error('s',"local staticC%n (%t)",this, tp);
2675: }
2676: }
2677:
2678: // error('d', "%n->sti: %d vec_seen: %d n_stclass: %k", this, sti, vec_seen, n_stclass );
2679: if (sti) {
2680: if (vec_seen) { // _vec_new(vec,noe,sz,ctor);
2681: // error('d', "%n->dcl: n_stclass: %k ", this, n_stclass );
2682: if ( n_stclass == STATIC && n_initializer ) {
2683: const_save = 1;
2684: (void) co_array_init(nn,sti_tbl);
2685: const_save = 0;
2686: n_initializer = init = 0;
2687: goto ggg;
2688: }
2689:
2690: init = cdvec(vec_new_fct,nn,cl,c,-1,0);
2691: init->tp = any_type;
2692: }
2693: else {
2694: switch (init->base) {
2695: case DEREF: // *constructor?
2696: if (init->e1->base == G_CALL) {
2697: Pname fn = init->e1->fct_name;
2698: if (fn==0 || fn->n_oper!=CTOR) goto as;
2699: init = init->e1;
2700: break;
2701: }
2702: goto as;
2703: case G_CM:
2704: init = init->e1;
2705: // suppress further type checking
2706: if (init->tp == 0) init->tp= any_type;
2707: break;
2708: case ASSIGN:
2709: if (init->e1 == nn) break; // simple assignment
2710: as:
2711: default:
2712: init = new expr(ASSIGN,nn,init);
2713: }
2714: }
2715: Pstmt ist = new estmt(SM,nn->where,init,0);
2716: // constructors for statics are executed in order
2717: if (st_ilist == 0)
2718: st_ilist = ist;
2719: else
2720: itail->s_list = ist;
2721: itail = ist;
2722: init = 0; // suppress further processing
2723: } // if (sti)
2724: nn->n_initializer = n_initializer = init;
2725: const_save = const_old;
2726: tbl = otbl;
2727: }
2728: else if (init == 0) // no initializer
2729: goto str;
2730: else if (cl->is_simple()
2731: // && cl->csu!=UNION // accept ANSIism
2732: && cl->csu!=ANON
2733: ) { // struct
2734: init = init->typ(tbl);
2735: if (nn->tp->check(init->tp,0)==0
2736: && init->base==G_CM)
2737: (void) replace_temp(init,nn->address());
2738: else {
2739: if (ansi_opt==0
2740: && init->base==ILIST
2741: && cl->csu==UNION)
2742: error('s',"initialization of union withIL");
2743: goto str;
2744: }
2745: }
2746: else if (init->base == ILIST) { // class or union
2747: error("cannotI%nWIrL",nn);
2748: }
2749: else { // bitwise copy ok?
2750: // possible to get here?
2751: init = init->typ(tbl);
2752: //error('d',"init22 %t %t",nn->tp,init->tp);
2753: if (nn->tp->check(init->tp,0)==0) {
2754: if (init->base==G_CM)
2755: (void) replace_temp(init,nn->address());
2756: else
2757: goto str;
2758: }
2759: goto str;
2760: // else
2761: // error("cannotI%n:%k %s has noK",nn,cl->csu,cl->string);
2762: }
2763: break;
2764: }
2765: case VEC:
2766: t = Pvec(t)->typ;
2767: vec_seen++;
2768: goto lll;
2769: case TYPE:
2770: if (init==0 && Pbase(t)->b_const) {
2771: switch (n_scope) {
2772: case ARG:
2773: break;
2774: case 0:
2775: case PUBLIC:
2776: if ( cc->cot ) break;
2777: default: {
2778: Pname n = t->is_cl_obj();
2779: Pclass cl;
2780: if ( n ) cl = Pclass( n->tp );
2781:
2782: if (n_sto!=EXTERN &&
2783: (n==0 || (cl->has_ctor()==0 && is_empty(cl,1)==0)))
2784: error("uninitialized const%n",this);
2785: }
2786: }
2787: }
2788: t = Pbase(t)->b_name->tp;
2789: goto lll;
2790: case RPTR:
2791: if (init) {
2792: if (nn->n_scope == ARG) break;
2793: if (Pptr(nn->tp)->memof) error("R toCM%n ofT%t illegal",nn,nn->tp);
2794: ref_initializer++;
2795: init = init->typ(tbl);
2796: ref_initializer--;
2797: Nvirt = 0; // set within ref_init() call
2798: const_ptr = Pbase(Pptr(t)->typ)->tconst();
2799:
2800: if (n_sto==STATIC
2801: && init->lval(0)==0
2802: && fct_const==0)
2803: error("Ir for staticR%n not an lvalue",this);
2804: else
2805: nn->n_initializer = n_initializer = init = ref_init(Pptr(t),init,tbl);
2806:
2807: const_ptr = 0;
2808: if (Nvirt == VIRTUAL) sti_vb = 1;
2809: nn->assign();
2810:
2811: if (init->base==ILIST && init->e2==0) {
2812: new_list(init);
2813: list_check(nn,nn->tp,0,tbl);
2814: if (next_elem()) error(&where,"IrL too long");
2815: }
2816:
2817: }
2818: else {
2819: switch (nn->n_scope) {
2820: default:
2821: if (n_sto == EXTERN) break;
2822: error("uninitializedR%n",this);
2823: case ARG:
2824: break;
2825: case PUBLIC:
2826: case 0:
2827: //III if (n_sto == STATIC) error("a staticM%n cannot be aR",this);
2828: // error('d', "%n->dcl cot: %s", this, cc->cot?cc->cot->string:"notset");
2829: if ( cc->cot == 0 )
2830: error("uninitializedR%n",this);
2831: break;
2832: }
2833: }
2834: goto stgg;
2835: default:
2836: str:
2837: // error('d',"str %n %t %k %t",this,tp,init?init->base:0,init?init->tp:0);
2838: if (init == 0) {
2839: switch (n_scope) {
2840: case ARG:
2841: break;
2842: case 0:
2843: case PUBLIC:
2844: if ( cc->cot ) break;
2845: default:
2846: if (n_sto!=EXTERN && t->tconst()) error("uninitialized const%n",this);
2847: }
2848:
2849: break;
2850: }
2851:
2852: const_save = const_save
2853: || n_scope==ARG
2854: || (t->tconst() && vec_const==0);
2855:
2856: if ( tp->base == PTR ) {
2857: if ( cc && cc->nof
2858: && Pfct(cc->nof->tp)->f_const )
2859: cm_const_save = Pbase(Pptr(tp)->typ)->b_const;
2860: const_ptr = Pbase(Pptr(tp)->typ)->b_const;
2861: }
2862:
2863: if (n_sto==STATIC) stat_init++;
2864: nn->n_initializer = n_initializer = init = init->typ(tbl);
2865: if (n_sto==STATIC) stat_init--;
2866:
2867: cm_const_save = 0;
2868: const_ptr = 0;
2869:
2870: if (const_save) PERM(init);
2871: nn->assign();
2872: const_save = const_old;
2873: //error('d',"init2 %k %t",init->base,init->tp);
2874: switch (init->base) {
2875: case ILIST:
2876: if (init->e2) goto dfdf;//break; // pointer to member
2877: new_list(init);
2878: list_check(nn,nn->tp,0,tbl);
2879: if (next_elem()) error(&where,"IrL too long");
2880: break;
2881: case STRING:
2882: { Ptype v = nn->tp;
2883: while (v->base == TYPE) v = Pbase(v)->b_name->tp;
2884: if (v->base==VEC) {
2885: Ptype vv = Pvec(v)->typ;
2886: while(vv->base==TYPE) vv = Pbase(vv)->b_name->tp;
2887: if(vv->base==CHAR) {
2888: int sz = Pvec(v)->size;
2889: int isz = Pvec(init->tp)->size;
2890: if (sz == 0)
2891: Pvec(v)->size = isz;
2892: else if (sz < isz)
2893: error(&where,"Ir too long (%d characters) for%n[%d]",isz,nn,sz);
2894: break;
2895: }
2896: }
2897: // no break
2898: }
2899: default:
2900: dfdf:
2901: { Ptype nt = nn->tp;
2902: int ntc = Pbase(nt)->b_const;
2903:
2904: if (vec_seen) {
2905: error("badIr for array%n",nn);
2906: break;
2907: }
2908: tlx:
2909: switch (nt->base) {
2910: case TYPE:
2911: nt = Pbase(nt)->b_name->tp;
2912: ntc |= Pbase(nt)->b_const;
2913: goto tlx;
2914: case INT:
2915: case CHAR:
2916: case SHORT:
2917: case EOBJ:
2918: // if (init->base==ICON && init->tp==long_type)
2919: // error('w',"longIr constant for%k%n",nn->tp->base,nn);
2920: { Ptype t = init->tp;
2921: csi:
2922: switch (t->base) {
2923: case TYPE:
2924: t = Pbase(t)->b_name->tp; goto csi;
2925: case LONG:
2926: case FLOAT:
2927: case DOUBLE:
2928: case LDOUBLE:
2929: error('w',"%tIdW %t",nt,init->tp);
2930: }
2931: }
2932: // no break
2933: case LONG:
2934: if (Pbase(nt)->b_unsigned
2935: && init->base==UMINUS
2936: && init->e2->base==ICON)
2937: error('w',"negativeIr for unsigned%n",nn);
2938: if (ntc && scope!=ARG) {
2939: long i;
2940: Neval = 0;
2941: i = init->eval();
2942: if (Neval == 0) {
2943: DEL(init);
2944: nn->n_evaluated = n_evaluated = 1;
2945: nn->n_val = n_val = i;
2946: DEL(init);
2947: nn->n_initializer = n_initializer = 0;
2948: }
2949: }
2950: break;
2951: case PTR:
2952: Nvirt = 0;
2953: nn->n_initializer = n_initializer = init = ptr_init(Pptr(nt),init,tbl);
2954: //display_expr(init,string);
2955: if (Nvirt == VIRTUAL) sti_vb = 1;
2956: if (Pchecked) goto stgg;
2957: }
2958:
2959: { Pexpr x = try_to_coerce(nt,init,"initializer",tbl);
2960: if (x) {
2961: nn->n_initializer = n_initializer = init = x;
2962: goto stgg;
2963: }
2964: }
2965: //error('d',"check %t %t %k",nt,init->tp,init->base);
2966: // if (nt->check(init->tp,ASSIGN)) {
2967: Pname c1 = nt->is_cl_obj();
2968: Pname c2 = init->tp->is_cl_obj();
2969: if (c1
2970: && c2
2971: && Pclass(c2->tp)->has_base(Pclass(c1->tp))) {
2972: init = new texpr(CAST,new ptr(PTR,nt),init->address());
2973: init = init->typ(tbl);
2974: nn->n_initializer = n_initializer = init = init->contents();
2975: goto stgg;
2976: }
2977:
2978: if (nt->check(init->tp,ASSIGN)) {
2979: error("badIrT%t for%n (%tX)",init->tp,this,nn->tp);
2980: break;
2981: }
2982: }
2983:
2984: stgg:
2985: // error('d',"stgg %n init %k %t Nvirt: %k",this,init?init->base:0,init?init->tp:0, Nvirt);
2986: if (init && n_stclass==STATIC && (sti_vb || need_sti(init))) {
2987: /* check if non-static variables are used */
2988: int local = (0<lex_level);
2989: // error('d',"init %n %t local %d",nn,init->tp,local);
2990: if (local==0) need_sti(init,tbl); // save consts
2991:
2992: Pptr r = nn->tp->is_ref(); //III
2993:
2994: if (r) init = init->address();
2995: init = new expr(ASSIGN,nn,init);
2996: // error('d',"init r %t: nn %n %t init %t",r,nn,nn->tp,init->tp);
2997: if (r)
2998: init->tp = nn->tp;
2999: else if (nn->tp!=init->tp) { // static member refs
3000: TOK t = nn->tp->set_const(0); //JJJ
3001: init = init->typ(tbl);
3002: nn->tp->set_const(t); //JJJ
3003: }
3004:
3005: if (local) {
3006: if (init->base != ASSIGN) error('s',"Ir for local static too complicated");
3007: if (nn->n_sto == EXTERN) {
3008: error(&where,"Id local extern%n",this);
3009: init = 0;
3010: }
3011: else init->base = STAT_INIT;
3012: nn->n_initializer = n_initializer = init;
3013:
3014: }
3015: else {
3016: Pstmt ist = new estmt(SM,nn->where,init,0);
3017: // constructors for statics are executed in order
3018:
3019: if (st_ilist == 0)
3020: st_ilist = ist;
3021: else
3022: itail->s_list = ist;
3023: itail = ist;
3024: nn->n_initializer = n_initializer = init = 0; // suppress further processing
3025: nn->n_val = n_val = 1;
3026: }
3027: }
3028:
3029:
3030: } /* switch */
3031: } /* block */
3032: } /* default */
3033:
3034: } /* switch */
3035: ggg:
3036: //error('d',"ggg");
3037: PERM(nn);
3038: switch (n_scope) {
3039: case FCT:
3040: nn->n_initializer = n_initializer;
3041: break;
3042: default:
3043: { Ptype t = nn->tp;
3044: px:
3045: PERM(t);
3046: switch (t->base) {
3047: case PTR:
3048: case RPTR:
3049: case VEC: t = Pptr(t)->typ; goto px;
3050: case TYPE: t = Pbase(t)->b_name->tp; goto px;
3051: case FCT: t = Pfct(t)->returns; goto px; /* args? */
3052: }
3053: }
3054: }
3055:
3056: Cdcl = odcl;
3057: return nn;
3058: }
3059: 0707071010112043671004440001630000160000010172100466055375400000700000067044dcl2.c /*ident "@(#)ctrans:src/dcl2.c 1.2" */
3060: /**************************************************************************
3061:
3062: C++ source for cfront, the C++ compiler front-end
3063: written in the computer science research center of Bell Labs
3064:
3065: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
3066: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
3067:
3068: dcl2.c:
3069:
3070: *************************************************************************/
3071:
3072: #include "cfront.h"
3073: #include "size.h"
3074:
3075: Pname conv_dominates(Pname on1, Pname on2)
3076: /*
3077: compare for duplicates and dominance:
3078:
3079: on1 and on2 are two conversion operator functions
3080: return the the one that dominates the other (according to the
3081: class hierarchy) otherwise 0 (0 thus indicats ambiguous conversion)
3082: */
3083: {
3084: Ptype r1 = on1->tp->base==FCT ? Pfct(on1->tp)->returns
3085: : Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns;
3086: Ptype r2 = on2->tp->base==FCT ? Pfct(on2->tp)->returns
3087: : Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns;
3088: //error('d',"conv_dominates(%n,%n)",on1,on2);
3089: if (r1==r2 || r1->check(r2,0)==0) return on1;
3090: Pptr p1 = r1->is_ptr_or_ref();
3091: Pptr p2 = r2->is_ptr_or_ref();
3092: if (p1 && p2) {
3093: Pname cn1 = p1->typ->is_cl_obj();
3094: Pname cn2 = p2->typ->is_cl_obj();
3095: if (cn1 && cn2) {
3096: // is_cl_obj() returns b_name
3097: // Pclass c1 = Pclass(Pbase(cn1->tp)->b_name->tp);
3098: // Pclass c2 = Pclass(Pbase(cn2->tp)->b_name->tp);
3099: Pclass c1 = Pclass(cn1->tp);
3100: Pclass c2 = Pclass(cn2->tp);
3101: if (c1 && c2) {
3102: //if (c1==c2 || c1->has_base(c2))
3103: if (c1->has_base(c2))
3104: return on1;
3105: else if (c2->has_base(c1))
3106: return on2;
3107: }
3108: }
3109: }
3110: return 0;
3111: }
3112:
3113:
3114: Pstmt curr_loop;
3115: Pstmt curr_switch;
3116: Pblock curr_block;
3117:
3118: void stmt::reached()
3119: {
3120: register Pstmt ss = s_list;
3121:
3122: if (ss == 0) return;
3123:
3124: switch (ss->base) {
3125: case LABEL:
3126: case CASE:
3127: case DEFAULT:
3128: break;
3129: default:
3130: error('w',&ss->where,"S after%k not reached",base);
3131: for (; ss; ss=ss->s_list) { // delete unreacheable code
3132: switch (ss->base) {
3133: case LABEL:
3134: case CASE:
3135: case DEFAULT: // reachable
3136: s_list = ss;
3137: return;
3138: case DCL: // the dcl may be used later
3139: // keep to avoid cascading errors
3140: case IF:
3141: case DO:
3142: case WHILE:
3143: case SWITCH:
3144: case FOR:
3145: case BLOCK: // may hide a label
3146: s_list = ss;
3147: return;
3148: }
3149: }
3150: s_list = 0;
3151: }
3152: }
3153:
3154: Pexpr check_cond(Pexpr e, TOK b, Ptable tbl)
3155: {
3156: //error('d',"check_cond(%k %k) tbl %d",e->base,b,tbl);
3157: Pname cn;
3158: if (e == dummy) error("empty condition for %k",b);
3159:
3160: int const_obj = 0;
3161: const_obj = e->tp->tconst();
3162: Pexpr ee = e;
3163: while (ee && (ee->base==DOT || ee->base==REF)) {
3164: Pexpr m = ee->mem;
3165: if ( ee->base==REF && m->tp && m->tp->is_ptr())
3166: break;
3167: ee = ee->e1;
3168: }
3169: if (ee) {
3170: Ptype ttt = ee->tp;
3171: switch (e->base) {
3172: case REF:
3173: Pptr p = ttt?ttt->is_ptr():0;
3174: if (p && p->typ->tconst())
3175: const_obj = 1;
3176: break;
3177: case DOT:
3178: if (ttt && ttt->tconst())
3179: const_obj = 1;
3180: }
3181: }
3182:
3183: if (cn = e->tp->is_cl_obj()) {
3184: Pclass cl = Pclass(cn->tp);
3185: int i = 0;
3186: Pname found = 0;
3187: for (Pname on = cl->conv; on; on=on->n_list) {
3188: Pfct f = on->tp->base == FCT ? Pfct(on->tp)
3189: : Pfct(Pgen(on->tp)->fct_list->f->tp);
3190: Ptype t = f->returns;
3191: xx:
3192: switch (t->base) {
3193: case TYPE:
3194: t = Pbase(t)->b_name->tp;
3195: goto xx;
3196: case FLOAT:
3197: case DOUBLE:
3198: case LDOUBLE:
3199: case PTR:
3200: if (b == DEREF) break;
3201: case CHAR:
3202: case SHORT:
3203: case INT:
3204: case LONG:
3205: case EOBJ:
3206: // if (found==0 || found->tp->check(on->tp,0)) {
3207: //error('d',"found %n on %n",found,on);
3208: { Pname xx = found;
3209: if (found == 0) {
3210: i = 1;
3211: found = on;
3212: }
3213: else if ((found = really_dominate(found,on,const_obj)) == 0) {
3214: i = 2;
3215: found = on;
3216: error("two conversions for%nO in%kE: %n and %n",cn,b,xx,on);
3217: return e;
3218: }
3219: }
3220: }
3221: }
3222: //error('d',"i %d",i);
3223: switch (i) {
3224: case 0:
3225: error("%nO in%kE",cn,b);
3226: return e;
3227: /*
3228: case 1:
3229: { Pname xx = new name(found->string);
3230: Pref r = new ref(DOT,e,xx);
3231: Pexpr rr = r->typ(tbl);
3232: Pexpr c = new expr(G_CALL,rr,0);
3233:
3234: if (e->lval(0)) {
3235: // Pref r = new ref(DOT,e,found);
3236: // r->tp = found->tp;
3237: // Pexpr c = new expr(G_CALL,r,0);
3238: // c->fct_name = found;
3239: return c->typ(tbl);
3240: }
3241: else { // (temp=init,temp.coerce())
3242: Pname tmp = make_tmp('U',e->tp,tbl);
3243: Pexpr ass = init_tmp(tmp,e,tbl);
3244: // Pref r = new ref(DOT,tmp,found);
3245: // Pexpr rr = r->typ(tbl);
3246: // Pexpr c = new expr(G_CALL,rr,0);
3247: // c->fct_name = found;
3248: ass = new expr(CM,ass,c);
3249: return ass->typ(tbl);
3250: }
3251: }
3252: */
3253: case 1:
3254: { Pname xx = new name(found->string);
3255: Pexpr c;
3256:
3257: if (e->lval(0)) {
3258: Pref r = new ref(DOT,e,xx);
3259: Pexpr rr = r->typ(tbl);
3260: c = new expr(G_CALL,rr,0);
3261: }
3262: else { // (temp=init,temp.coerce())
3263: Pname tmp = make_tmp('U',e->tp,tbl);
3264: Pexpr ass = init_tmp(tmp,e,tbl);
3265: Pref r = new ref(DOT,tmp,xx);
3266: Pexpr rr = r->typ(tbl);
3267: c = new expr(G_CALL,rr,0);
3268: c = new expr(CM,ass,c);
3269: }
3270: return c->typ(tbl);
3271: }
3272: // default:
3273: // error("%d possible conversions for%nO in%kE",i,cn,b);
3274: // return e;
3275: }
3276:
3277: }
3278: if (e->tp->memptr()) {
3279: e = new mdot("i",e);
3280: e->i1 = 9;
3281: e = new expr(NE,e,zero);
3282: }
3283: else if (e->tp->num_ptr(b) == FCT)
3284: error("%k(F)",b);
3285: return e;
3286: }
3287:
3288: void stmt::dcl()
3289: /*
3290: typecheck statement "this" in scope "curr_block->tbl"
3291: */
3292: {
3293: Pstmt ss;
3294: Pname n;
3295: Pname nn;
3296: Pstmt ostmt = Cstmt;
3297: DB( if(Ddebug>=1) error('d',&where,"'%k'->stmt::dcl()",base); );
3298: for (ss=this; ss; ss=ss->s_list) {
3299: Pstmt old_loop, old_switch;
3300: Cstmt = ss;
3301: enum_promote = 0;
3302: Ptable tbl = curr_block->memtbl;
3303: //error('d',"stmt::dcl %k",ss->base);
3304: switch (ss->base) {
3305: case BREAK:
3306: inline_restr |= 16;
3307: if (curr_loop==0 && curr_switch==0)
3308: error("break not in loop or switch");
3309: ss->reached();
3310: break;
3311:
3312: case CONTINUE:
3313: inline_restr |= 32;
3314: if (curr_loop == 0) error("continue not in loop");
3315: ss->reached();
3316: break;
3317:
3318: case DEFAULT:
3319: if (curr_switch == 0) {
3320: error("default not in switch");
3321: break;
3322: }
3323: if (curr_switch->has_default) error("two defaults in switch");
3324: curr_switch->has_default = ss;
3325: ss->s->s_list = ss->s_list;
3326: ss->s_list = 0;
3327: ss->s->dcl();
3328: break;
3329:
3330: case SM:
3331: { if (ss->e ==0) break;
3332: TOK b = ss->e->base;
3333: switch (b) {
3334: case DUMMY:
3335: ss->e = 0;
3336: break;
3337: // check for unused results
3338: // don't check operators that are likely
3339: // to be overloaded to represent "actions":
3340: // ! ~ < <= > >= << >>
3341: case EQ:
3342: case NE:
3343: case PLUS:
3344: case MINUS:
3345: case REF:
3346: case DOT:
3347: case MUL:
3348: case DIV:
3349: case ADDROF:
3350: case AND:
3351: case OR:
3352: case ER:
3353: case DEREF:
3354: case ANDAND:
3355: case OROR:
3356: case NAME:
3357: case VALUE:
3358: if (ss->e->tp) break; // avoid looking at generated code
3359: ss->e = ss->e->typ(tbl);
3360: if (ss->e->base == CALL) break;
3361: if (ss->e->tp->base != VOID) {
3362: if ( ss->e->base == DEREF )
3363: error('w',"result of %sE not used",ss->e->e2?"[]":"*");
3364: else
3365: error('w',"result of%kE not used",b);
3366: if (ss->e->not_simple()==0) ss->e = dummy;
3367: }
3368: break;
3369: default:
3370: ss->e = ss->e->typ(tbl);
3371: }
3372: break;
3373: }
3374: case RETURN:
3375: { Pname fn = cc->nof;
3376: Pfct f = Pfct(fn->tp);
3377: Ptype rt = f->returns;
3378: Pexpr v = ss->e;
3379: //error('d',"rt %t",rt);
3380: while (rt->base == TYPE) rt = Pbase(rt)->b_name->tp;
3381: if (v != dummy) {
3382: if (rt->base == RPTR || rt->base == PTR) {
3383: const_ptr = Pbase(Pptr(rt)->typ)->tconst();
3384: }
3385: if (rt->base == RPTR) {
3386: ref_initializer++;
3387: v = v->typ(tbl);
3388: ref_initializer--;
3389: } else
3390: v = v->typ(tbl);
3391: const_ptr = 0;
3392:
3393: if (fn->n_oper==CTOR
3394: || fn->n_oper==DTOR
3395: || (rt->base==VOID && v->tp!=void_type)) {
3396: error("unexpected return value");
3397: // refuse to return the value:
3398: ss->e = dummy;
3399: }
3400: else {
3401: switch (rt->base) {
3402: // case TYPE: laready done above
3403: case RPTR:
3404: switch (v->base) {
3405: case NAME:
3406: if (Pname(v)->n_scope==FCT
3407: || Pname(v)->n_scope==ARG)
3408: error('w',"R to localV returned");
3409: break;
3410: case ICON:
3411: case CCON:
3412: case FCON:
3413: case STRING:
3414: if (Pptr(rt)->typ->tconst()==0)
3415: error('w',"R to literal returned");
3416: }
3417: v = ref_init(Pptr(rt),v,tbl);
3418: if (v->base==G_CM
3419: && v->e2->base==G_ADDROF
3420: && v->e2->e2->base==NAME)
3421: error('w',"R to temporary returned (return value is not lvalue or of wrongT)");
3422: case ANY:
3423: break;
3424: case COBJ:
3425: if (v->base == DEREF) {
3426: Pexpr v1 = v->e1;
3427: if (v1->base==CAST) {
3428: Pexpr v2 = v1->e1;
3429: if (v2->base == G_CM) { // *(T)(e1,e2) => (e1,*(T)e2)
3430: Pexpr v3 = v2->e2;
3431: v2->e2 = v;
3432: v2->tp = v->tp;
3433: v = v2;
3434: v1->e1 = v3;
3435: }
3436: }
3437: }
3438: if (f->f_result) {
3439: if (v->base==G_CM && rt->check(v->tp,0/*ASSIGN*/)==0)
3440: v = replace_temp(v,f->f_result);
3441: else {
3442: v = class_init(f->f_result->contents(),rt,v,tbl);
3443: Pname rcn = rt->is_cl_obj();
3444: if (Pclass(rcn->tp)->has_itor()==0) {
3445: // can happen for virtuals and for user defined conversions
3446: v->tp = rt;
3447: v = new expr(ASSIGN,f->f_result->contents(),v);
3448: v->tp = rt;
3449: }
3450: }
3451: }
3452: else
3453: v = class_init(0,rt,v,tbl);
3454: break;
3455: case PTR:
3456: { Pexpr x = v;
3457: v = ptr_init(Pptr(rt),v,tbl);
3458: if (v->base == ADDROF
3459: && v->e2->base == NAME
3460: && Pname(v->e2)->n_stclass == AUTO)
3461: error('w',"P to local variable%n returned",Pname(v->e2));
3462: // if (v==x ||v->e2==x) goto def;
3463: if (Pchecked == 0) goto def;
3464: goto ret_save;
3465: // break;
3466: }
3467: case INT:
3468: case CHAR:
3469: case LONG:
3470: case SHORT:
3471: if (Pbase(rt)->b_unsigned
3472: && v->base==UMINUS
3473: && v->e2->base==ICON)
3474: error('w',"negative returned fromF returning unsigned");
3475: default:
3476: def:
3477: {
3478: Pexpr x = try_to_coerce(rt,v,"return value",tbl);
3479: if (x)
3480: v = x;
3481: else if (rt->check(v->tp,ASSIGN))
3482: error("bad return valueT for%n:%t (%tX)",fn,v->tp,rt);
3483: }
3484:
3485: }
3486: ret_save:
3487: ss->ret_tp = rt;
3488: ss->e = v;
3489: }
3490: }
3491: else {
3492: if (rt->base != VOID) error("return valueX");
3493: }
3494: ss->reached();
3495: break;
3496: }
3497:
3498: case DO: // in DO the stmt is before the test
3499: inline_restr |= 8;
3500: old_loop = curr_loop;
3501: curr_loop = ss;
3502: { Pstmt st = ss->s;
3503: while(st && st->base == FOR) st = st->for_init;
3504: if (st && st->base == DCL)
3505: if (st==ss->s) error("D as onlyS in do-loop");
3506: }
3507: ss->s->dcl();
3508: ss->e = ss->e->typ(tbl);
3509: ss->e = check_cond(ss->e,DO,tbl);
3510: curr_loop = old_loop;
3511: break;
3512:
3513: case WHILE:
3514: inline_restr |= 8;
3515: old_loop = curr_loop;
3516: curr_loop = ss;
3517: ss->e = ss->e->typ(tbl);
3518: ss->e = check_cond(ss->e,WHILE,tbl);
3519: { Pstmt st = ss->s;
3520: while(st && st->base == FOR) st = st->for_init;
3521: if (st && st->base == DCL)
3522: if(st==ss->s) error("D as onlyS in while-loop");
3523: }
3524: ss->s->dcl();
3525: curr_loop = old_loop;
3526: break;
3527:
3528: case SWITCH:
3529: { int ne = 0;
3530: inline_restr |= 4;
3531: old_switch = curr_switch;
3532: curr_switch = ss;
3533: ss->e = ss->e->typ(tbl);
3534: ss->e = check_cond(ss->e,SWITCH,tbl);
3535: { Pstmt st = ss->s;
3536: while(st && st->base == FOR) st = st->for_init;
3537: if (st && st->base == DCL)
3538: if(st==ss->s) error("D as onlyS in switchS");
3539: }
3540: { Ptype tt = ss->e->tp;
3541: sii:
3542: switch (tt->base) {
3543: case TYPE:
3544: tt = Pbase(tt)->b_name->tp; goto sii;
3545: case EOBJ:
3546: ne = Penum(Pbase(tt)->b_name->tp)->no_of_enumerators;
3547: case ZTYPE:
3548: case ANY:
3549: case CHAR:
3550: case SHORT:
3551: case INT:
3552: case LONG:
3553: case FIELD:
3554: break;
3555: default:
3556: error("%t switchE",ss->e->tp);
3557: }
3558: }
3559: ss->s->dcl();
3560: if (ne) { /* see if the number of cases is "close to"
3561: but not equal to the number of enumerators
3562: */
3563: int i = 0;
3564: Pstmt cs;
3565: for (cs=ss->case_list; cs; cs=cs->case_list) i++;
3566: if (i && i!=ne) {
3567: if (ne < i) {
3568: ee: error('w',"switch (%t)W %d cases (%d enumerators)",ss->e->tp,i,ne);
3569: }
3570: else {
3571: switch (ne-i) {
3572: case 1: if (3<ne) goto ee;
3573: case 2: if (7<ne) goto ee;
3574: case 3: if (23<ne) goto ee;
3575: case 4: if (60<ne) goto ee;
3576: case 5: if (99<ne) goto ee;
3577: }
3578: }
3579: }
3580: }
3581: curr_switch = old_switch;
3582: break;
3583: }
3584: case CASE:
3585: if (curr_switch == 0) {
3586: error("case not in switch");
3587: break;
3588: }
3589: ss->e = ss->e->typ(tbl);
3590: ss->e->tp->num_ptr(CASE);
3591: { Ptype tt = ss->e->tp;
3592: iii:
3593: switch (tt->base) {
3594: case TYPE:
3595: tt = Pbase(tt)->b_name->tp; goto iii;
3596: case ZTYPE:
3597: case ANY:
3598: case CHAR:
3599: case SHORT:
3600: case INT:
3601: case LONG:
3602: case EOBJ:
3603: Neval = 0;
3604: long i = ss->e->eval();
3605: if (Neval == 0) {
3606: Pstmt cs;
3607: if (largest_int<i) error("long case value");
3608: for (cs=curr_switch->case_list; cs; cs=cs->case_list) {
3609: if (cs->case_value == i) error("case %d used twice in switch",i);
3610: }
3611: ss->case_value = int(i);
3612: ss->case_list = curr_switch->case_list;
3613: curr_switch->case_list = ss;
3614: }
3615: else
3616: error("bad case label: %s",Neval);
3617: break;
3618: default:
3619: error("%t caseE",ss->e->tp);
3620: }
3621: }
3622: // if (1) {
3623: // Neval = 0;
3624: // long i = ss->e->eval();
3625: // if (Neval == 0) {
3626: // Pstmt cs;
3627: // if (largest_int<i) error("long case value");
3628: // for (cs=curr_switch->case_list; cs; cs=cs->case_list) {
3629: // if (cs->case_value == i) error("case %d used twice in switch",i);
3630: // }
3631: // ss->case_value = int(i);
3632: // ss->case_list = curr_switch->case_list;
3633: // curr_switch->case_list = ss;
3634: // }
3635: // else
3636: // error("bad case label: %s",Neval);
3637: // }
3638: if (ss->s->s_list) error('i',"case%k",ss->s->s_list->base);
3639: ss->s->s_list = ss->s_list;
3640: ss->s_list = 0;
3641: ss->s->dcl();
3642: break;
3643:
3644: case GOTO:
3645: inline_restr |= 2;
3646: ss->reached();
3647: case LABEL:
3648: /* Insert label in function mem table;
3649: labels have function scope.
3650: */
3651: n = ss->d;
3652: nn = cc->ftbl->insert(n,LABEL);
3653:
3654: /* Set a ptr to the mem table corresponding to the scope
3655: in which the label actually occurred. This allows the
3656: processing of goto's in the presence of ctors and dtors
3657: */
3658: if (ss->base == LABEL) {
3659: nn->n_realscope = curr_block->memtbl;
3660: inline_restr |= 1;
3661: }
3662:
3663: if (Nold) {
3664: if (ss->base == LABEL) {
3665: if (nn->n_initializer) error("twoDs of label%n",n);
3666: nn->n_initializer = (Pexpr)1;
3667: }
3668: if (n != nn) ss->d = nn;
3669: }
3670: else {
3671: if (ss->base == LABEL) nn->n_initializer = (Pexpr)1;
3672: nn->where = ss->where;
3673: }
3674: if (ss->base == GOTO)
3675: nn->use();
3676: else {
3677: if (ss->s->s_list) error('i',"label%k",ss->s->s_list->base);
3678: ss->s->s_list = ss->s_list;
3679: ss->s_list = 0;
3680: nn->assign();
3681: }
3682: if (ss->s) ss->s->dcl();
3683: break;
3684:
3685: case IF:
3686: {
3687: Pexpr ee = ss->e->typ(tbl);
3688: if (ee->base == ASSIGN) {
3689: Neval = 0;
3690: (void)ee->e2->eval();
3691: if (Neval == 0)
3692: error('w',"constant assignment in condition");
3693: }
3694: ss->e = ee = check_cond(ee,IF,tbl);
3695:
3696: if (ss->s->base == DCL) error("D as onlyS after `if'");
3697:
3698: // pointer to member returns with a tp set to 0
3699: if ( ee->tp ) switch (ee->tp->base) {
3700: case INT:
3701: case EOBJ:
3702: case ZTYPE:
3703: { long i;
3704: Neval = 0;
3705: i = ee->eval();
3706:
3707: if (Neval == 0) {
3708: Pstmt sl = ss->s_list;
3709: if (i) {
3710: DEL(ss->else_stmt);
3711: ss->s->dcl();
3712: *ss = *ss->s;
3713: }
3714: else {
3715: DEL(ss->s);
3716: if (ss->else_stmt) {
3717: ss->else_stmt->dcl();
3718: *ss = *ss->else_stmt;
3719: }
3720: else {
3721: ss->base = SM;
3722: ss->e = dummy;
3723: ss->s = 0;
3724: }
3725: }
3726: ss->s_list = sl;
3727: continue;
3728: }
3729: }
3730: }
3731: ss->s->dcl();
3732: if (ss->else_stmt) {
3733: if (ss->else_stmt->base == DCL) error("D as onlyS after `else'");
3734: ss->else_stmt->dcl();
3735: }
3736: break;
3737: }
3738: case FOR:
3739: inline_restr |= 8;
3740: old_loop = curr_loop;
3741: curr_loop = ss;
3742: if (ss->for_init) {
3743: Pstmt fi = ss->for_init;
3744: switch (fi->base) {
3745: case SM:
3746: if (fi->e == dummy) {
3747: ss->for_init = 0;
3748: break;
3749: }
3750: fi->dcl();
3751: break;
3752: default:
3753: // for (stmt; e1; e2) stmt1 stmt2
3754: // => {stmt; for(; e1; e2) stmt1 stmt2}
3755: // if stmt != declaration
3756: // if stmt == declaration, temporarily
3757: // rewrite to avoid symbol table
3758: // problems in some contexts.
3759: // Then put decl back to avoid
3760: // extraneous {}.
3761: // Note: to maintain pointers, ss
3762: // must not change
3763: { Pstmt tmp = new stmt (SM,curloc,0);
3764: *tmp = *ss; // tmp = original for
3765: tmp->for_init = 0;
3766: fi->s_list = tmp;
3767: *ss = *fi;
3768: curr_loop = old_loop;
3769: ss->dcl();
3770: tmp = ss->s_list;
3771: if ( ss->base == DCL
3772: && tmp->base == FOR // sanity check
3773: && tmp->for_init == 0 // sanity check
3774: ) {
3775: // put DCL back in for init
3776: *fi = *ss;
3777: *ss = *tmp;
3778: ss->for_init = fi;
3779: fi->s_list = 0;
3780: } else {
3781: // non-decl stmt in for init
3782: // put stmts in block in case
3783: // they follow a condition...
3784: // allocate tmp to be sure
3785: // fields are initialized
3786: *fi = *ss;
3787: tmp = new block(ss->where,0,fi);
3788: tmp->own_tbl = 0;
3789: tmp->memtbl = curr_block->memtbl;
3790: tmp->permanent = ss->permanent;
3791: *ss = *tmp;
3792: tmp->permanent = 0; delete tmp;
3793: }
3794: // don't repeat stmt::dcl() for
3795: // remaining stmts
3796: goto done;
3797: }
3798: }
3799: }
3800: if (ss->e == dummy)
3801: ss->e = 0;
3802: else {
3803: ss->e = ss->e->typ(tbl);
3804: ss->e = check_cond(ss->e,FOR,tbl);
3805: }
3806: { Pstmt st = ss->s;
3807: while(st && st->base == FOR) st = st->for_init;
3808: if (st && st->base == DCL)
3809: if(st==ss->s) error("D as onlyS in for-loop");
3810: }
3811: ss->s->dcl();
3812: ss->e2 = (ss->e2 == dummy) ? 0 : ss->e2->typ(tbl);
3813: curr_loop = old_loop;
3814: break;
3815:
3816: case DCL: /* declaration after statement */
3817: {
3818: /* collect all the contiguous DCL nodes from the
3819: head of the s_list. find the next statement
3820: */
3821: int non_trivial = 0;
3822: int count = 0;
3823: Pname tail = ss->d;
3824: for (Pname nn=tail; nn; nn=nn->n_list) {
3825: // find tail;
3826: // detect non-trivial declarations
3827: count++;
3828:
3829: if (nn->n_list) tail = nn->n_list;
3830: Pname n = tbl->look(nn->string,0);
3831:
3832: if (n && n->n_table==tbl) non_trivial = 2;
3833: if (non_trivial == 2) continue;
3834: if ((nn->n_sto==STATIC && nn->tp->base!=FCT)
3835: || nn->tp->is_ref()
3836: || (nn->tp->tconst() && fct_const==0)) {
3837: non_trivial = 2;
3838: continue;
3839: }
3840:
3841: Pexpr in = nn->n_initializer;
3842: if (in)
3843: switch (in->base) {
3844: case ILIST:
3845: case STRING:
3846: non_trivial = 2;
3847: continue;
3848: }
3849: non_trivial = 1;
3850: Pname cln = nn->tp->is_cl_obj();
3851: if (cln == 0) cln = cl_obj_vec;
3852: if (cln == 0) continue;
3853: if (Pclass(cln->tp)->has_ctor()) {
3854: non_trivial = 2;
3855: continue;
3856: }
3857: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2;
3858: }
3859:
3860: while( ss->s_list && ss->s_list->base==DCL ) {
3861: Pstmt sx = ss->s_list;
3862: tail = tail->n_list = sx->d; // add to tail
3863: for (nn=sx->d; nn; nn=nn->n_list) {
3864: // find tail;
3865: // detect non-trivial declarations
3866: count++;
3867: if (nn->n_list) tail = nn->n_list;
3868: Pname n = tbl->look(nn->string,0);
3869: if (n && n->n_table==tbl) non_trivial = 2;
3870: if (non_trivial == 2) continue;
3871: if ((nn->n_sto==STATIC && nn->tp->base!=FCT)
3872: || nn->tp->is_ref()
3873: || (nn->tp->tconst() && fct_const==0)) {
3874: non_trivial = 2;
3875: continue;
3876: }
3877: Pexpr in = nn->n_initializer;
3878: if (in)
3879: switch (in->base) {
3880: case ILIST:
3881: case STRING:
3882: non_trivial = 2;
3883: continue;
3884: }
3885: non_trivial = 1;
3886: Pname cln = nn->tp->is_cl_obj();
3887: if (cln == 0) cln = cl_obj_vec;
3888: if (cln == 0) continue;
3889: if (Pclass(cln->tp)->has_ctor()) {
3890: non_trivial = 2;
3891: continue;
3892: }
3893: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2;
3894: }
3895: ss->s_list = sx->s_list;
3896: /* delete sx; */
3897: }
3898:
3899: Pstmt next_st = ss->s_list;
3900: //error('d',"dcl stmt : d %n non_trivial %d curr own_tbl %d inline_restr 0%o",ss->d,non_trivial,curr_block->own_tbl,inline_restr);
3901: if (non_trivial==2 // must
3902: || (non_trivial==1 // might
3903: && ( curr_block->own_tbl==0 // why not?
3904: || inline_restr&3 /* label seen */)
3905: )
3906: ) {
3907: if (curr_switch && non_trivial==2) {
3908: Pstmt cs = curr_switch->case_list;
3909: Pstmt ds = curr_switch->has_default;
3910: Pstmt bl;
3911: if (cs == 0)
3912: bl = ds;
3913: else if (ds == 0)
3914: bl = cs;
3915: else if (cs->where.line<ds->where.line)
3916: bl = ds;
3917: else
3918: bl = cs;
3919:
3920: if ((bl==0 || bl->s->base!=BLOCK) && curr_switch->s->memtbl==tbl)
3921: error('s',"non trivialD in switchS (try enclosing it in a block)");
3922: }
3923:
3924: /* Create a new block,
3925: put all the declarations at the head,
3926: and the remainder of the slist as the
3927: statement list of the block.
3928: */
3929: //ss->base = BLOCK; //DCL
3930:
3931: /* check that there are no redefinitions
3932: since the last "real" (user-written,
3933: non-generated) block
3934: */
3935: { Pname lastnn = 0;
3936: for( nn=ss->d; nn; nn=nn->n_list ) {
3937: Pname n;
3938: //n=curr_block->memtbl->look(nn->string,0);
3939: //error('d',"checking %n lex_level: %d n: %n n->lex_level: %d",nn,nn->lex_level,n,n?n->lex_level:0);
3940: //error('d'," own_tbl: %d curr_block: %d n->n_table: %d",curr_block->own_tbl,curr_block,n->n_table);
3941: //error('d'," real_block: %d n's real_block: %d",curr_block->memtbl->real_block,n->n_table->real_block);
3942: //if( curr_block->own_tbl
3943: if ( (n=curr_block->memtbl->look(nn->string,0))
3944: && n->n_table->real_block==curr_block->memtbl->real_block
3945: && n->tp->base!=FCT
3946: && n->tp->base!=OVERLOAD
3947: && nn->lex_level == n->lex_level ) {
3948: error("twoDs of%n",n);
3949: if (lastnn==0) ss->d=nn->n_list;
3950: else lastnn->n_list=nn->n_list;
3951: } else lastnn = nn;
3952: } // for nn
3953: }
3954:
3955: /* attach the remainder of the s_list
3956: as the statement part of the block.
3957: */
3958: ss->s = next_st;
3959: ss->s_list = 0;
3960:
3961: /* create the table in advance,
3962: in order to set the real_block
3963: ptr to that of the enclosing table
3964: */
3965: ss->memtbl = new table(count+4,tbl,0);
3966: ss->memtbl->real_block = curr_block->memtbl->real_block;
3967: Pblock(ss)->dcl(ss->memtbl);
3968: }
3969: else { /* to reduce the number of symbol tables,
3970: do not make a new block,
3971: instead insert names in enclosing block,
3972: and make the initializers into expression
3973: statements.
3974: */
3975: Pstmt sss = ss;
3976: { Pname lastnn = 0;
3977: for( nn=ss->d; nn; nn=nn->n_list ) {
3978: Pname n;
3979: //error('d',"nn %n",nn);
3980: //if( curr_block->own_tbl
3981: if ( (n=curr_block->memtbl->look(nn->string,0))
3982: && n->n_table->real_block==curr_block->memtbl->real_block
3983: && n->tp->base!=FCT && n->tp->base!=OVERLOAD
3984: && nn->lex_level == n->lex_level ) {
3985: error("twoDs of%n",n);
3986: n = 0;
3987: if (lastnn==0) ss->d=nn->n_list;
3988: else lastnn->n_list=nn->n_list;
3989: } else {
3990: n = nn->dcl(tbl,FCT);
3991: lastnn=nn;
3992: }
3993:
3994: if (n == 0) {
3995: if (ss) {
3996: ss->base = SM;
3997: ss->e = 0;
3998: }
3999: continue;
4000: }
4001: //error('d',"hoisted %n to outer blk",n);
4002:
4003: Pexpr in = n->n_initializer;
4004: n->n_initializer = 0;
4005:
4006: if (ss) {
4007: sss->base = SM;
4008: ss = 0;
4009: }
4010: else
4011: sss = sss->s_list = new estmt(SM,sss->where,0,0);
4012: if (in) {
4013: switch (in->base) {
4014: case G_CALL: /* constructor? */
4015: {
4016: Pname fn = in->fct_name;
4017: if (fn && fn->n_oper==CTOR) break;
4018: }
4019: default:
4020: in = new expr(ASSIGN,n,in);
4021: in->tp = n->tp;
4022: }
4023: // sss->e = in->typ(tbl);
4024: sss->e = in;
4025: }
4026: else
4027: sss->e = dummy;
4028: } // for nn
4029: }
4030:
4031: ss = sss;
4032: ss->s_list = next_st;
4033: }
4034: break;
4035: }
4036:
4037: case BLOCK:
4038: Pblock(ss)->dcl(tbl);
4039: break;
4040:
4041: case ASM:
4042: /* save string */
4043: {
4044: char* s = (char*)ss->e;
4045: int ll = strlen(s);
4046: char* s2 = new char[ll+1];
4047: strcpy(s2,s);
4048: ss->e = Pexpr(s2);
4049: break;
4050: }
4051: default:
4052: error('i',"badS(%p %d)",ss,ss->base);
4053: }
4054: }
4055: done:
4056: Cstmt = ostmt;
4057: }
4058:
4059: void block::dcl(Ptable tbl)
4060: /*
4061: Note: for a block without declarations memtbl denotes the table
4062: for the enclosing scope.
4063: A function body has its memtbl created by fct::dcl().
4064: */
4065: {
4066: int bit_old = bit_offset;
4067: int byte_old = byte_offset;
4068: int max_old = max_align;
4069: Pblock block_old = curr_block;
4070:
4071: if (base != BLOCK && base != DCL) error('i',"block::dcl(%d)",base);
4072:
4073: curr_block = this;
4074: //error('d',"%d->block::dcl(%d) base %k",this,tbl,base);
4075: //error('d'," memtbl %d own_tbl %d d %n s %k",memtbl,own_tbl,d,s?s->base:0);
4076: if (d) {
4077: own_tbl = 1;
4078: base = BLOCK;
4079: if (memtbl == 0) {
4080: int nmem = d->no_of_names()+4;
4081: memtbl = new table(nmem,tbl,0);
4082: memtbl->real_block = this;
4083: /* this is a "real" block from the
4084: source text, and not one created by DCL's
4085: inside a block. */
4086: }
4087: else
4088: if (memtbl != tbl) error('i',"block::dcl(?)");
4089:
4090: Pname nx;
4091: for (Pname n=d; n; n=nx) {
4092: nx = n->n_list;
4093: n->dcl(memtbl,FCT);
4094: switch (n->tp->base) {
4095: case CLASS:
4096: case ANON:
4097: case ENUM:
4098: break;
4099: default:
4100: delete n;
4101: }
4102: }
4103: }
4104: else if ( base == BLOCK ) {
4105: own_tbl = 1;
4106: if (memtbl == 0) {
4107: int nmem = 4;
4108: memtbl = new table(nmem,tbl,0);
4109: memtbl->real_block = this;
4110: /* this is a "real" block from the
4111: source text, and not one created by DCL's
4112: inside a block. */
4113: } else
4114: if (memtbl != tbl) error('i',"block::dcl(?)");
4115: } else {
4116: base = BLOCK;
4117: memtbl = tbl;
4118: }
4119:
4120: Pname odcl = Cdcl;
4121: if (s) s->dcl();
4122: if (own_tbl) {
4123: Pname m;
4124: int i;
4125: for (m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i)) {
4126: Ptype t = m->tp;
4127:
4128: if (in_class_dcl) m->lex_level -= 1;
4129:
4130: if (t == 0) {
4131: if (m->n_assigned_to == 0)
4132: error("label %sU",m->string);
4133: if (m->n_used == 0)
4134: error('w',"label %s not used", m->string);
4135: continue;
4136: }
4137: ll:
4138: switch (t->base) {
4139: case TYPE: t = Pbase(t)->b_name->tp; goto ll;
4140: case CLASS:
4141: case ANON:
4142: case ENUM:
4143: case FCT:
4144: //case VEC:
4145: continue;
4146: }
4147:
4148: if (m->n_addr_taken == 0) {
4149: if (m->n_used) {
4150: if (m->n_assigned_to) {
4151: }
4152: else if ( t->base != VEC ) {
4153: switch (m->n_scope) {
4154: case FCT:
4155: Cdcl = m;
4156: if (m->string[0] != '_' && m->string[1] != '_' )
4157: error('w',&m->where,"%n used but not set",m);
4158: }
4159: }
4160: }
4161: else {
4162: if (m->n_assigned_to) {
4163: }
4164: else if (m->string[0]!='_' || m->string[1]!='_') {
4165: switch (m->n_scope) {
4166: case ARG:
4167: case FCT:
4168: Cdcl = m;
4169: error('w',&m->where,"%n not used",m);
4170: }
4171: }
4172: }
4173: }
4174: }
4175: }
4176: Cdcl = odcl;
4177:
4178: d = 0;
4179:
4180: if (bit_offset) byte_offset += SZ_WORD;
4181: bit_offset = bit_old;
4182: byte_offset = byte_old;
4183: curr_block = block_old;
4184: }
4185:
4186: void name::field_align()
4187: /*
4188: adjust alignment
4189: */
4190: {
4191: Pbase fld = (Pbase)tp;
4192: int nbits = fld->b_bits;
4193:
4194: int a = (F_SENSITIVE) ? fld->b_fieldtype->align() : SZ_WORD;
4195: if (max_align < a) max_align = a;
4196:
4197: if (nbits == 0) { // force word alignment
4198: int b;
4199: if (bit_offset)
4200: nbits = BI_IN_WORD - bit_offset;
4201: else if (b = byte_offset%SZ_WORD)
4202: nbits = b * BI_IN_BYTE;
4203: // else
4204: // nbits = BI_IN_WORD;
4205: if (max_align < SZ_WORD) max_align = SZ_WORD;
4206: }
4207: else if (bit_offset == 0) { // take care of part of word
4208: int b = byte_offset%SZ_WORD;
4209: if (b) {
4210: byte_offset -= b;
4211: bit_offset = b*BI_IN_BYTE;
4212: }
4213: }
4214: //error('d',"byteoff %d bitoff %d bits %d",byte_offset,bit_offset,nbits);
4215: int x = (bit_offset += nbits);
4216: if (BI_IN_WORD < x) {
4217: fld->b_offset = 0;
4218: byte_offset += SZ_WORD;
4219: bit_offset = nbits;
4220: }
4221: else {
4222: fld->b_offset = bit_offset;
4223: if (BI_IN_WORD == x) {
4224: bit_offset = 0;
4225: byte_offset += SZ_WORD;
4226: }
4227: else
4228: bit_offset = x;
4229: }
4230: n_offset = byte_offset;
4231: }
4232: 0707071010112043701004440001630000160000010172500466055376100000700000171674dcl3.c /*ident "@(#)ctrans:src/dcl3.c 1.7" */
4233: /**************************************************************************
4234:
4235: C++ source for cfront, the C++ compiler front-end
4236: written in the computer science research center of Bell Labs
4237:
4238: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
4239: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
4240:
4241: dcl3.c:
4242: Routines used by ::dcl fucntions: fct::dcl() etc.
4243:
4244: *****************************************************************************/
4245:
4246: #include "cfront.h"
4247: #include "size.h"
4248: #include "template.h"
4249:
4250: static void vbase_pointers(Pname fn, Pclass cl)
4251: /*
4252: insert argument for virtual base pointers (if any)
4253: after f_this and before f_argtype
4254: */
4255: {
4256: //error('d',"vbase_pointers(%n,%t) %d %k",fn,cl,fn->tp,fn->n_oper);
4257: Pfct f = Pfct(fn->tp);
4258: if (fn->n_oper == CTOR) {
4259: Pname d = 0;
4260: for (Pbcl b = cl->baselist; b; b=b->next) {
4261: if (b->base != VIRTUAL) continue;
4262: Pname a = new name(b->bclass->string);
4263: a->tp = b->bclass->this_type;
4264: a->n_list = d;
4265: a->n_table = f->body ? f->body->memtbl : 0;
4266: a->where = fn->where;
4267: d = a;
4268: }
4269:
4270: if (d) {
4271: for (Pname dd =d;;) {
4272: if (d->n_list == 0) {
4273: d->n_list = f->f_args->n_list;
4274: break;
4275: }
4276: d = d->n_list;
4277: }
4278: f->f_args->n_list = dd;
4279: }
4280: }
4281: if (fn->n_oper == DTOR) { // add __free argument
4282: //error('d',"add __free to %n",fn);
4283: Pname fa = new name;
4284: fa->tp = int_type;
4285: fa->n_scope = ARG;
4286: fa->where = fn->where;
4287:
4288: Pname a = f->f_args;
4289: if (a == 0)
4290: f->f_args = fa;
4291: else {
4292: for(;;a = a->n_list) {
4293: // error('d',"a %d %t",a,a->tp);
4294: if (a->n_list == 0) {
4295: a->n_list = fa;
4296: break;
4297: }
4298: }
4299: }
4300: }
4301: }
4302:
4303: void make_res(Pfct f)
4304: /*
4305: returns X where X(X&) has been declared
4306: add "_result" argument of type X*
4307: */
4308: {
4309: Pname cl = f->returns->is_cl_obj();
4310: if (cl==0 || Pclass(cl->tp)->has_itor()==0) return;
4311:
4312: Pname rv = new name("_result");
4313: rv->tp = f->returns->addrof();
4314: rv->n_scope = FCT; // not a ``real'' argument
4315: rv->n_used = 1;
4316: rv->n_list = f->argtype;
4317: if (f->f_this)
4318: f->f_this->n_list = rv;
4319: else
4320: f->f_args = rv;
4321: f->f_result = rv;
4322: f->s_returns = void_type;
4323: }
4324:
4325: void name::check_oper(Pname cn)
4326: /*
4327: check declarations of operators, ctors, dtors
4328: */
4329: {
4330: // error('d', "%n->check_oper( %n ): n_oper: %k", this, cn, n_oper );
4331: switch (n_oper) {
4332: case CALL:
4333: case DEREF:
4334: case REF:
4335: if (cn == 0) error("operator%s must be aM",keys[n_oper]);
4336: break;
4337: case ASPLUS:
4338: case ASMINUS:
4339: case ASMUL:
4340: case ASDIV:
4341: case ASMOD:
4342: case ASAND:
4343: case ASOR:
4344: case ASER:
4345: case ASLS:
4346: case ASRS:
4347: if ( warning_opt ) {
4348: if ( cn == 0 || Pfct(tp)->f_static )
4349: error('w', "operator%s should be a non-staticMF",keys[n_oper]);
4350: }
4351: break;
4352: case ASSIGN:
4353: if (cn == 0)
4354: error(strict_opt?0:'w',"non-member operator%k() (anachronism)",n_oper);
4355: break;
4356: case NOT: /* unary operators only */
4357: case COMPL:
4358: // case INCR:
4359: // case DECR:
4360: Pfct f = Pfct(tp);
4361: if (cn && f->argtype)
4362: error("%n::%n takes noA",cn, this);
4363: else if (f->nargs == 2)
4364: error("%n takes 1A only",this);
4365: break;
4366: case INCR:
4367: case DECR:
4368: // check for postscript instance
4369: f = Pfct(tp);
4370: if (cn) { // member
4371: if ( f->argtype && f->nargs == 1 ) {
4372: Pname n = f->argtype;
4373: if ( n->tp->base != INT )
4374: error("%n must takeA ofT int, not %t",this,n->tp);
4375: }
4376: }
4377: else
4378: if (f->nargs == 2) { // non-member
4379: Pname n = f->argtype->n_list;
4380: if ( n->tp->base != INT )
4381: error("%n must takeA ofT int, not %t",this,n->tp);
4382: }
4383: break;
4384:
4385: case 0:
4386: case TNAME: /* may be a constructor */
4387: if (cn && ((strcmp(cn->string,string)==0) ||
4388: ((Pclass(cn->tp)->class_base ==
4389: instantiated_template_class) &&
4390: (strcmp(string,
4391: Ptclass(cn->tp)->unparametrized_tname()->string) == 0))))
4392: {
4393: if (tp->base == FCT) {
4394: Pfct f = Pfct(tp);
4395: if (f->returns!=defa_type)
4396: error("%s::%s()W returnT",string,string);
4397: f->returns = void_type;
4398: string = "__ct";
4399: n_oper = CTOR;
4400: }
4401: else
4402: error('s',"struct%nM%n",cn,cn);
4403: }
4404: else
4405: n_oper = 0;
4406: break;
4407: case DTOR: /* must be a destructor */
4408: //error('d',"dtor %s",string);
4409: if (cn == 0) {
4410: n_oper = 0;
4411: error("destructor ~%s() not inC",string);
4412: }
4413: else
4414: if ((strcmp(cn->string,string) == 0) ||
4415: ((Pclass(cn->tp)->class_base ==
4416: instantiated_template_class) &&
4417: (strcmp(string,
4418: Ptclass(cn->tp)->unparametrized_tname()->string)==0)))
4419: {
4420: dto:
4421: Pfct f = (Pfct)tp;
4422: string = "__dt";
4423: if (tp->base != FCT) {
4424: error("%s::~%s notF",cn->string,cn->string);
4425: tp = new fct(void_type,0,1);
4426: }
4427: else if (f->returns!=defa_type/* && f->returns!=void_type*/) {
4428: if ( f->returns != void_type ||
4429: f->body != 0 || friend_in_class == 0 )
4430: error("%s::~%s()W returnT",cn->string,cn->string);
4431: }
4432:
4433: if (f->argtype) {
4434: error("%s::~%s()WAs",cn->string,cn->string);
4435: f->nargs = 0;
4436: f->nargs_known = 1;
4437: f->argtype = 0;
4438: }
4439: f->returns = void_type;
4440: }
4441: else {
4442: if (strcmp(string,"__dt") == 0) goto dto;
4443: error("~%s in %s",string,cn->string);
4444: n_oper = 0;
4445: }
4446: break;
4447: case TYPE:
4448: // cond stores the type of the operator function
4449: // error('d',"type %t",cond);
4450: if (cn == 0) {
4451: // error("operator%t() not aM",Ptype(n_initializer));
4452: error("operator%t() not aM",Ptype(cond));
4453: n_oper = 0;
4454: // n_initializer = 0;
4455: cond = 0;
4456: }
4457: else {
4458: Pfct f = Pfct(tp);
4459: // n_initializer = 0;
4460: Ptype tx = Ptype(cond);
4461: cond = 0;
4462: if (f->base != FCT) error("badT for%n::operator%t()",cn,tx);
4463: if (f->returns != defa_type) {
4464: // if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx);
4465: error("resultT for%n::operator%t()",cn,tx);
4466: DEL(f->returns);
4467: }
4468: if (f->argtype) {
4469: error("%n::operator%t()WAs",cn,tx);
4470: f->argtype = 0;
4471: }
4472: f->returns = tx;
4473: Pname nx = tx->is_cl_obj();
4474: if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx);
4475: char buf[1024];
4476: char* bb = tx->signature(buf);
4477: int l2 = bb-buf;
4478: if (1023<l2) error('i',"N::check_oper():N buffer overflow");
4479: char* p = new char[l2+5];
4480: p[0] = '_';
4481: p[1] = '_';
4482: p[2] = 'o';
4483: p[3] = 'p';
4484: strcpy(p+4,buf);
4485: string = p;
4486: }
4487: break;
4488: }
4489: }
4490:
4491: Pexpr vbase_args(Pfct a, Pname bn)
4492: /*
4493: constructor a calls the constructor bn for a base class
4494: generate argument list needed for virtual base arguments
4495: */
4496: {
4497: Pfct b = Pfct(bn->tp);
4498: //error('d',"vbase_args%n: %t %k",bn,b,b->base);
4499: Pexpr args = 0;
4500: Pexpr tail = 0;
4501: if (b->base == OVERLOAD) b = Pfct(Pgen(b)->fct_list->f->tp); // doesn't matter which
4502: for (Pname d = b->f_args->n_list; d!=b->argtype; d=d->n_list) {
4503: for (Pname dd = a->f_args->n_list; dd; dd=dd->n_list)
4504: // using strcmp is a trick
4505: if (strcmp(dd->string,d->string)==0) break;
4506:
4507: Pexpr aa = new expr(ELIST,dd,0);
4508: if (args == 0)
4509: args = aa;
4510: else
4511: tail->e2 = aa;
4512: tail = aa;
4513: }
4514: return args;
4515: }
4516:
4517: void fct::init_bases(Pclass cl, Pexpr)
4518: /*
4519: in "cl"'s constructor "this" generate code to initialize base classes
4520: and members using the initializers "f->f_init"
4521:
4522: this->f_init == list of names of classes to be initialized
4523: COLON(b) => base class b
4524: => constructor call in f_init->n_initializer
4525: COLON() => unnamed base class
4526: => constructor call in f_init->n_initializer
4527: NAME(m) => member m
4528: => constructor call in m->n_initializer
4529: */
4530: {
4531: Ptable ftbl = body->memtbl;
4532: DB( if(Ddebug>=1) error('d',"init_bases %t init %d",cl,f_init); );
4533:
4534: // explicit initializers
4535: if ( cl && cl->csu == UNION && f_init && f_init->n_list )
4536: error(&f_init->where,"multipleIrs in unionK %s:: %s",cl->string,cl->string);
4537: for (Pname nx, nn=f_init; nn; delete nn,(nn=nx) ) {
4538: Pexpr i = nn->n_initializer;
4539: nn->n_initializer = 0;
4540: nx = nn->n_list;
4541:
4542: // error('d',"init_base %s %d",nn->string,i);
4543: if (nn->string) {
4544: // lookup in case type name hides a "real" member
4545: { Pname mmm = cl->memtbl->look(nn->string,0);
4546: if ( mmm ) nn->base = mmm->base;
4547: }
4548: if (nn->base == TNAME) { // base class
4549: char *bn;
4550: while ( nn->tp && nn->tp->base == TYPE )
4551: nn->tp = Pbase(nn->tp)->b_name->tp;
4552: if ( nn->tp && nn->tp->base == COBJ )
4553: bn = Pbase(nn->tp)->b_name->string;
4554: else
4555: bn = nn->string;
4556: for (Pbcl l = cl->baselist; l; l=l->next) {
4557: Pclass bcl = l->bclass;
4558: if ((strcmp(bcl->string,bn) == 0) ||
4559: ((bcl->class_base ==
4560: instantiated_template_class) &&
4561: ((strcmp(nn->string,
4562: Ptclass(bcl)->unparametrized_tname()->string)) == 0)))
4563: {
4564:
4565: // l->init is zeroed out in ctor_simpl
4566: // if error_count, simpl() not invoked
4567: if (l->init && error_count == 0)
4568: error("twoIrs for%t",bcl);
4569: else
4570: l->init = base_init(bcl,i,ftbl,l->obj_offset);
4571: goto con;
4572: }
4573: }
4574: error(&nn->where,"unexpectedAL: noBC%n",nn);
4575: con:
4576: continue;
4577: }
4578: else { // member initializer
4579: Pname m = cl->memtbl->look(nn->string,0);
4580: if (m && m->n_table==cl->memtbl)
4581: m->n_initializer = mem_init(m,i,ftbl);
4582: else
4583: error(&nn->where,"%n not inC %s",nn,cl->string);
4584: }
4585: }
4586: else { // unnamed base class
4587: Pbcl l = cl->baselist;
4588: if (l == 0) {
4589: error("unexpectedAL: noBC called");
4590: continue;
4591: }
4592:
4593: if (l->next) {
4594: bit cnt = 0, rvb = 0; // remote virtual base classes
4595: for (Pbcl ll = l; ll; ll = ll->next, ++cnt )
4596: if (ll->base==VIRTUAL && ll->promoted) ++rvb;
4597: if ( rvb )
4598: error("unnamedBCIr: %dBCes(%d non-explicit virtualBC%s)",cnt,rvb,rvb==1?"":"es");
4599: else error("unnamedBCIr: %dBCes",cnt);
4600: continue;
4601: }
4602:
4603: if (l->init)
4604: error("twoIrs for%t",l->bclass);
4605: else {
4606: error(strict_opt?0:'w',&nn->where,"N ofBC%t missing from BCIr (anachronism)",l->bclass);
4607: l->init = base_init(l->bclass,i,ftbl,l->obj_offset);
4608: }
4609: }
4610: } // for
4611:
4612: for (Pbcl l = cl->baselist; l; l=l->next) {
4613: // default initialization of base classes
4614: Pname ctor;
4615: Pclass bcl = l->bclass;
4616: if (l->init==0 && (ctor=bcl->has_ctor()))
4617: l->init = base_init(bcl,0,ftbl,l->obj_offset);
4618: }
4619: }
4620:
4621: int inline_restr; /* report use of constructs that the inline expanded
4622: cannot handle here */
4623:
4624: void fct::dcl(Pname n)
4625: {
4626: int nmem = TBLSIZE;
4627: Pname a;
4628: Pname ll;
4629: Ptable ftbl;
4630:
4631: Pptr cct = 0;
4632: int const_old = const_save;
4633:
4634: int bit_old = bit_offset;
4635: int byte_old = byte_offset;
4636: int max_old = max_align;
4637:
4638: if (base != FCT) error('i',"F::dcl(%d)",base);
4639: if (body == 0) error('i',"F::dcl(body=%d)",body);
4640: if (n==0 || n->base!=NAME) error('i',"F::dcl(N=%d %d)",n,(n)?n->base:0);
4641: DB( if(Ddebug>=1) error('d',"fct::dcl(%n) %k %d %t",n,n->n_scope,body->own_tbl,this); );
4642: if (body->own_tbl) return; // done already
4643:
4644: // if (f_inline==0 ) n->n_dcl_printed = 1; // beware of recursive calls, no decl needed
4645: // if (f_inline && debug_opt) n->n_dcl_printed = 2;
4646: if (body->memtbl == 0) body->memtbl = new table(nmem+3,gtbl,0);
4647: body->own_tbl = 1;
4648: ftbl = body->memtbl;
4649: ftbl->real_block = body;
4650:
4651: max_align = 0;//AL_FRAME;
4652: bit_offset = 0;
4653:
4654: cc->stack();
4655: cc->nof = n;
4656: cc->ftbl = ftbl;
4657:
4658: switch (n->n_scope) {
4659: case 0:
4660: case PUBLIC:
4661: { cc->not = n->n_table->t_name;
4662: cc->cot = Pclass(cc->not->tp);
4663: cc->tot = cc->cot->this_type;
4664: // if (f_this==0 || cc->tot==0) error('i',"F::dcl(%n): f_this=%d cc->tot=%d",n,f_this,cc->tot);
4665: if (f_this) f_this->n_table = ftbl; // fake for inline printout
4666: cc->c_this = f_this;
4667:
4668:
4669: Pclass cl = Pclass(cc->not->tp);
4670:
4671: if (cl->c_body!=3
4672: || n->n_initializer
4673: || n->n_sto==STATIC
4674: || f_inline
4675: || f_imeasure
4676: || f_virtual==0)
4677: ;
4678: else { // could be the function where we need to
4679: // output the vtbl
4680: int i;
4681: for (Pname nn=cl->memtbl->get_mem(i=1); nn; nn=cl->memtbl->get_mem(++i) ) {
4682: Ptype t = nn->tp;
4683: if (t)
4684: switch (t->base) {
4685: case FCT:
4686: if (nn == n) goto prnt;
4687: if (nn->n_initializer
4688: || nn->n_sto==STATIC
4689: || Pfct(nn->tp)->f_inline
4690: || Pfct(nn->tp)->f_imeasure
4691: || Pfct(nn->tp)->f_virtual==0) break;
4692: goto zaq;
4693:
4694: case OVERLOAD:
4695: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
4696: Pname nn = gl->f;
4697: if (nn == n) goto prnt;
4698: if (nn->n_initializer
4699: || nn->n_sto==STATIC
4700: || Pfct(nn->tp)->f_inline
4701: || Pfct(nn->tp)->f_imeasure
4702: || Pfct(nn->tp)->f_virtual==0) continue;
4703: goto zaq;
4704: }
4705: }
4706: }
4707: }
4708: goto zaq;
4709: prnt:
4710: cl->print_all_vtbls(cl);
4711: goto zaq;
4712: }
4713: }
4714: }
4715: zaq:
4716: // protect against: class x; x f(); class x { x(x&); ....
4717: if (f_result == 0) make_res(this);
4718: if (f_result) f_result->n_table = ftbl; // fake for inline printout
4719:
4720: returns->tsizeof(); // make sure size is known
4721:
4722: Pname ax;
4723: for (a=argtype, ll=0; a; a=ax) {
4724: ax = a->n_list;
4725: Pname nn = a->dcl(ftbl,ARG);
4726: Pname cn = nn->tp->is_cl_obj();
4727: if (cn == 0) cn = cl_obj_vec;
4728: if (cn) (void)cn->tp->tsizeof(); // make sure it is printed
4729: nn->n_assigned_to = nn->n_used = nn->n_addr_taken = 0;
4730: nn->n_list = 0;
4731:
4732: switch (nn->tp->base) {
4733: case CLASS:
4734: case ENUM: /* unlink types declared in arg list */
4735: nn->dcl_print(0);
4736: break;
4737: default:
4738: if (ll)
4739: ll->n_list = nn;
4740: else
4741: f_args = argtype = nn;
4742: ll = nn;
4743: }
4744: delete a;
4745: }
4746:
4747: if (f_result) { // link in f_result
4748: f_args = f_result;
4749: f_result->n_list = argtype;
4750: }
4751:
4752: if (f_this) { // link in f_this
4753: f_args = f_this;
4754: f_this->n_list = f_result ? f_result : argtype;
4755: }
4756:
4757: if (n->n_oper==CTOR || n->n_oper==DTOR) vbase_pointers(n,cc->cot);
4758:
4759: if (n->n_oper == CTOR) {
4760: const_save = 1;
4761: init_bases(cc->cot,f_init);
4762: }
4763: else if (f_init)
4764: error(0,"unexpectedAL: not aK");
4765:
4766: PERM(returns);
4767: const_save = f_inline&&debug_opt==0;
4768: inline_restr = 0;
4769: body->dcl(ftbl);
4770:
4771: defined |= DEFINED;
4772: if (f_inline && inline_restr && returns->base!=VOID) {
4773: f_inline = 0;
4774: char* s = (inline_restr & 32) ? "continue"
4775: : (inline_restr & 16) ? "break"
4776: : (inline_restr & 8) ? "loop"
4777: : (inline_restr & 4) ? "switch"
4778: : (inline_restr & 2) ? "goto"
4779: : (inline_restr & 1) ? "label"
4780: : "" ;
4781: if (warning_opt) {
4782: error('w', "\"inline\" ignored, %n contains %s",n,s);
4783: error('w', "out-of-line copy of %n created",n);
4784: }
4785: // if (cc->cot)
4786: n->simpl(); //BS6
4787: n->dcl_print(0);
4788: }
4789: const_save = const_old;
4790:
4791: if (f_inline && debug_opt==0) isf_list = new name_list(n,isf_list);
4792:
4793: bit_offset = bit_old;
4794: byte_offset = byte_old;
4795: max_align = max_old;
4796: cc->unstack();
4797:
4798: //error('d',"fct-> returns %t",returns);
4799: }
4800:
4801: Pexpr fct::base_init(Pclass bcl, Pexpr i, Ptable ftbl, int offset)
4802: /*
4803: have base class bcl and expr list i
4804: return "( *(base*)this ) . ctor( i )"
4805: ctor call generated in expr.typ()
4806: */
4807: {
4808: Ptype ty = bcl->this_type;
4809: Pexpr th = rptr(ty,f_this,offset); // base*
4810: Pname ctor = bcl->has_ctor();
4811:
4812: //error('d',"fct::B_init(C %t, i %d, %d) ctor %n",bcl,i,i?i->tp:0,ctor);
4813:
4814: Pexpr ii = (i && i->base==ELIST)?i->e1:i;
4815:
4816: if (ii
4817: && ii->base==DEREF
4818: && ii->e1->base==CAST
4819: && th->base==CAST) th->i2 = ii->e1->i2;
4820:
4821: if (ctor == 0) {
4822: if (i && i->base!=ELIST) i = new expr(ELIST,i,0);
4823:
4824: Pexpr v = new texpr(VALUE,bcl,i); // ?.base(i)
4825: v->e2 = new expr(DEREF,th,0); // (*(base*)this).base(i)
4826: v = v->typ(ftbl); // *base(&*(base*)this,i)
4827: //error('d',"v %k",v->base);
4828: switch (v->base) {
4829: case DEREF:
4830: return v->e1; // base(&*(base*)this,i)
4831: case ASSIGN: // degenerate base(base&): *(base*)this=i
4832: th = new texpr(CAST,ty,f_this);
4833: v = new expr(CM,v,th); // (*(base*)this=i,(base*)this);
4834: return v->typ(ftbl);
4835: default:
4836: return 0;
4837: }
4838: }
4839:
4840:
4841: Pname icn;
4842: if (i) {
4843: ii = ii->typ(ftbl);
4844: if (bcl->has_itor()==0
4845: && (icn=ii->tp->is_cl_obj())
4846: && (Pclass(icn->tp)==bcl || Pclass(icn->tp)->has_base(bcl))) {
4847: // degenerate base(base&): *(base*)this=i
4848: // memberwise copy
4849: //error('d',"copy %t",ty);
4850: // th = new cast(ty,f_this);
4851: // th = th->contents();
4852: th = new texpr(CAST,ty,f_this);
4853: th = th->contents();
4854: th = th->typ(ftbl);
4855: if (Pclass(icn->tp)!=bcl) { // cast needed
4856: Pptr r = new ptr(RPTR,Pptr(ty)->typ);
4857: ii = new texpr(CAST,r,ii);
4858: ii = ii->typ(ftbl);
4859: }
4860: ii = new expr(ASSIGN,th,ii);
4861: ii->tp = th->tp;
4862: // simulate `return this':
4863: // *(base*)this=i,(base*)this
4864: ii = new expr(CM,ii,new cast(ty,f_this));
4865: ii->tp = th->tp;
4866: return ii;
4867: // return ii->typ(ftbl); // don't find cl::operator=()
4868: }
4869: if (i->base == ELIST) i->e1 = ii;
4870: }
4871: //Pexpr x = call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
4872: //error('d',"call %n %t -> %d %k",ctor,ctor->tp,x,x->base);
4873: // return x;
4874: return call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
4875: }
4876:
4877:
4878: Pexpr fct::mem_init(Pname mn, Pexpr i, Ptable ftbl)
4879: /*
4880: return "member_ctor( m, i )"
4881: */
4882: {
4883: // a new entry for B::B_pub, in general, has no tp and no
4884: // real info: all the tp-> only work on our systems because
4885: // 0 pointer dereference isn't system memory. it core dumps
4886: // in set_const since no test is made on this == 0.
4887: //error('d',"mem_init %n",mn);
4888:
4889: // if (mn->n_stclass == STATIC) error('s',"MIr for static%n",mn);
4890: switch (mn->n_stclass) {
4891: case STATIC:
4892: error("MIr for static%n",mn);
4893: break;
4894: case ENUM:
4895: error("MIr for enumeration constant%n", mn);
4896: break;
4897: }
4898:
4899: Pname member = (mn->base==PUBLIC && mn->n_qualifier) ? mn->n_qualifier : mn;
4900:
4901: if (i) i = i->typ(ftbl);
4902: Pname cn = member->tp->is_cl_obj(); // first find the class name
4903:
4904: // if (member->n_stclass == STATIC) error('s',"MIr for static%n",member);
4905: // if (i) i = i->typ(ftbl);
4906: // Pname cn = member->tp->is_cl_obj(); // first find the class name
4907: Pref tn = new ref(REF,f_this,member);
4908: tn->tp = member->tp;
4909: //error('d',"MI for %n %t = %t",member,member->tp,i?i->tp:0);
4910: //error('d',"fthis %d %t member %n tp %t",f_this,f_this->tp,member,tn->tp);
4911: if (cn) {
4912: Pclass mcl = Pclass(cn->tp); // then find the classdef
4913: Pname ctor = mcl->has_ctor();
4914: Pname icn;
4915:
4916: if (i
4917: && mcl->has_itor()==0
4918: && (icn=i->tp->is_cl_obj())
4919: && Pclass(icn->tp)==mcl) { // bitwise copy
4920: Pexpr init = new expr(ASSIGN,tn,i);
4921: init->tp = tn->tp;
4922: // return init->typ(ftbl); // don't look for mcl.operator=()
4923: member->assign();
4924: return init;
4925: }
4926:
4927: if (ctor) return call_ctor(ftbl,tn,ctor,i,DOT);
4928:
4929: error("Ir forM%nW noK",member);
4930: return 0;
4931: }
4932:
4933: if (cl_obj_vec) {
4934: if (i && i->base == ELIST)
4935: error("illegalIrL for %t%nWinM initializationL",mn->tp,mn);
4936: else error('s',"Ir forCM %t%nWK",mn->tp,mn);
4937: return 0;
4938: }
4939:
4940: if (i && i->base == ELIST) {
4941: if (i->e2) error("Ir for%n not a simpleE",member);
4942: i = i->e1;
4943: }
4944:
4945: if (member->tp->is_ref() && (i == 0)) {
4946: error("empty Ir for reference %n", member);
4947: return 0 ;
4948: }
4949:
4950: // error( 'd', "fct_mem_init: %n %k", member, member->tp->base );
4951: switch (member->tp->base) {
4952: // case RPTR:
4953: // if ( i == 0 ) {
4954: // error( "empty Ir for reference %n", member );
4955: // return 0;
4956: // }
4957: // break;
4958: case VEC:
4959: case FCT:
4960: case OVERLOAD:
4961: error("Ir for%n ofT %t",member,member->tp);
4962: return 0;
4963: }
4964:
4965: //error('d',"tp %t",member->tp);
4966: if (member->tp->tconst()) {
4967: int save_ignore_const = ignore_const;
4968: ignore_const = 1;
4969: i = new expr(ASSIGN,tn,i);
4970: i = i->typ(ftbl);
4971: ignore_const = save_ignore_const;
4972: return i;
4973: }
4974:
4975: Pptr pt;
4976: if (pt = member->tp->is_ref()) {
4977: switch (pt->typ->base) {
4978: case FCT:
4979: case OVERLOAD:
4980: i = ptr_init(pt,i,ftbl);
4981: break;
4982: default:
4983: i = ref_init(pt,i,ftbl);
4984: }
4985: i = new expr(ASSIGN,tn,i);
4986: i->tp = tn->tp;
4987: member->assign(); // cannot call typ: would cause dereference
4988: return i;
4989: }
4990:
4991: i = new expr(ASSIGN,tn,i);
4992: return i->typ(ftbl); // typ performs the type check on the assignment
4993: }
4994:
4995: Pexpr replace_temp(Pexpr e, Pexpr n)
4996: /*
4997: e is on the form
4998: f(&temp,arg) , temp
4999: or
5000: &temp->ctor(arg) , temp
5001: or
5002: x->f(&temp,arg) , temp
5003: change it to
5004: f(n,arg)
5005: or
5006: n->ctor(arg)
5007: */
5008: {
5009: Pexpr c = e->e1; // f(&temp,arg) or &temp->ctor(args)
5010: Pexpr ff = c->e1;
5011: Pexpr a = c->e2; // maybe ELIST(&temp,arg)
5012: Pexpr tmp = e->e2;
5013:
5014: //error('d',"suppress(%d %k) %n",tmp->base,tmp->base,tmp->base==NAME?tmp:0);
5015: if (tmp->base==DEREF) tmp = tmp->e1;
5016: if (tmp->base==CAST) tmp = tmp->e1;
5017: if (tmp->base==ADDROF || tmp->base==G_ADDROF) tmp = tmp->e2;
5018: if (tmp->base != NAME) return e; //error('i',"replace %k",tmp->base);
5019: tmp->tp = any_type; // temporary not used: suppress it
5020:
5021: //error('d',"replace_temp(%k %k) c %k ff %k",e->base,n->base,c->base,ff->base);
5022: switch (ff->base) {
5023: case REF:
5024: if (ff->e1->base==G_ADDROF && ff->e1->e2==tmp)
5025: a = ff; // &tmp -> f()
5026: break;
5027: case DOT:
5028: if (ff->e1->base==NAME && ff->e1==tmp) {
5029: a = ff; // tmp . f()
5030: a->base = REF;
5031: }
5032: break;
5033: }
5034: a->e1 = n;
5035: return c;
5036: }
5037:
5038: Pname classdef::has_ictor()
5039: /*
5040: does this class have a constructor taking no arguments?
5041: */
5042: {
5043: Pname c = has_ctor();
5044: if (c == 0) return 0;
5045:
5046: Pfct f = Pfct(c->tp);
5047:
5048: switch (f->base) {
5049: default:
5050: error('i',"%s: badK (%k)",string,c->tp->base);
5051:
5052: case FCT:
5053: switch (f->nargs) {
5054: case 0: return c;
5055: default: if (f->argtype->n_initializer) return c;
5056: }
5057: return 0;
5058:
5059: case OVERLOAD:
5060: { for (Plist l=Pgen(f)->fct_list; l; l=l->l) {
5061: Pname n = l->f;
5062: f = (Pfct)n->tp;
5063: switch (f->nargs) {
5064: case 0: return n;
5065: default: if (f->argtype->n_initializer) return n;
5066: }
5067: }
5068: return 0;
5069: }
5070: }
5071: }
5072:
5073: int add_first; // fudge, use ctor arg instead
5074: Pname gen::add(Pname n)
5075: /*
5076: add "n" to the tail of "fct_list"
5077: (overloaded names are searched in declaration order)
5078:
5079: detect: multiple identical declarations
5080: declaration after use
5081: multiple definitions
5082: */
5083: {
5084: Pfct f = Pfct(n->tp);
5085: Pname nx;
5086: //error('d',"add(%n) %d",n,add_first);
5087: if (f->base != FCT) error("%n: overloaded nonF",n);
5088:
5089: if ( fct_list && (nx=find(f,1)) ) {
5090: //error('d',"found %n %t",nx,nx->tp);
5091: Linkage l1 = Pfct(nx->tp)->f_linkage;
5092: Linkage l2 = f->f_linkage;
5093: if ( l2 != linkage_default && l1 != l2 )
5094: error("inconsistent linkage specifications for%n",n);
5095: Nold = 1;
5096: }
5097: else {
5098: if (add_first==0 && f->f_signature==0) f->sign();
5099: //error('d',"signature: %d \"%s\" fct_list %d",f->f_signature,f->f_signature,fct_list);
5100: nx = new name;
5101: *nx = *n;
5102: // nx->n_tbl_list = Pname(n->string);
5103: nx->n_gen_fct_name = n->string;
5104: PERM(nx);
5105: Nold = 0;
5106: if (fct_list) {
5107: int clink = (f->f_linkage==linkage_C);
5108: Plist gl=fct_list;
5109: for(;;) {
5110: if (clink
5111: && Pfct(gl->f->tp)->f_linkage == linkage_C ) {
5112: error("two%ns with c linkage",n);
5113: if(f->f_signature==0) f->sign();
5114: }
5115: if (gl->l)
5116: gl = gl->l;
5117: else
5118: break;
5119: }
5120: gl->l = new name_list(nx,0);
5121: }
5122: else
5123: fct_list = new name_list(nx,0);
5124: nx->n_list = 0;
5125: }
5126: return nx;
5127: }
5128:
5129: void fct::sign()
5130: {
5131: switch ( f_linkage ) {
5132: case linkage_C:
5133: f_signature = "";
5134: return;
5135: case linkage_Cplusplus:
5136: case linkage_default:
5137: break;
5138: }
5139: char buf[1024];
5140: char* bb = signature(buf);
5141: int ll = bb-buf;
5142: if (1023 < ll) error('i',"gen::add():N buffer overflow");
5143: char* p = new char[ll+1];
5144: strcpy(p,buf);
5145: f_signature = p;
5146: //error('d',"fct::sign %s",p);
5147: }
5148:
5149: Pname gen::find(Pfct f, bit warn)
5150: {
5151: for (Plist gl=fct_list; gl; gl=gl->l) {
5152: Pname n = match(gl->f,f,warn);
5153: if (n) return n;
5154: }
5155: return 0;
5156: }
5157:
5158: Pname gen::match(Pname nx, Pfct f, bit warn)
5159: {
5160: Pfct fx = Pfct(nx->tp);
5161: Pname a, ax;
5162: int op = 0; // overloading problem: const, ref, vec/ptr, or basetype
5163: //error('d',"fx %d %d f %d %d",fx->nargs_known,fx->nargs,f->nargs_known,f->nargs);
5164:
5165: if (f->nargs_known != fx->nargs_known) return 0; // the bets are off
5166: // must rely on checks at
5167: // call points
5168: if (f->f_const != fx->f_const) return 0;
5169:
5170: if (fx->nargs != f->nargs
5171: && fx->nargs_known==1
5172: && f->nargs_known==1) return 0; // no warning for potential
5173: // problems due to default args
5174:
5175: for (ax=fx->argtype, a=f->argtype; a&&ax; ax=ax->n_list, a=a->n_list) {
5176: Ptype at = ax->tp;
5177: Ptype atp = a->tp;
5178: //error('d',"at %t atp %t",at,atp);
5179: if (at->check(atp,OVERLOAD) == 0) {
5180: //error('d',"at %t atp %t cp %d vrp %d",at,atp,const_problem,vrp_equiv);
5181: continue;
5182: }
5183: //error('d',"warn %d",warn);
5184: if (warn == 0) goto xx;
5185:
5186: /*
5187: warn against:
5188: overload f(X&), f(X); error
5189: overload f(int), f(const); error
5190: overload f(int*), f(int[10]); warn
5191: etc.
5192: */
5193:
5194: //error('d',"vrp_equiv %d const_problem %d",vrp_equiv,const_problem);
5195: if (const_problem) { // differ only in X vs const X
5196: if (at->is_ptr_or_ref()) return 0;
5197: op++;
5198: continue;
5199: }
5200:
5201: aaa:
5202: switch (atp->base) {
5203: case TYPE:
5204: atp = Pbase(atp)->b_name->tp;
5205: goto aaa;
5206: // case EOBJ:
5207: // atp = Penum(Pbase(atp)->b_name->tp)->e_type;
5208: // goto aaa;
5209: case RPTR: // differ only by X vs X& ?
5210: if (Pptr(atp)->typ->check(at,0)==0) {
5211: op++;
5212: continue;
5213: }
5214: }
5215:
5216: atl:
5217: switch (at->base) {
5218: case TYPE:
5219: at = Pbase(at)->b_name->tp;
5220: goto atl;
5221: // case EOBJ:
5222: // at = Penum(Pbase(at)->b_name->tp)->e_type;
5223: // goto atl;
5224: case RPTR: // differ only by X& vs X ?
5225: if (Pptr(at)->typ->check(atp,0)==0) {
5226: op++;
5227: continue;
5228: }
5229: break;
5230: // case CHAR: // differ only by int vs char ?
5231: // case SHORT:
5232: // case INT:
5233: // if (atp->base!=at->base && atp->base==EOBJ) {
5234: // op++;
5235: // continue;
5236: // }
5237: // break;
5238: }
5239: //error('d',"return 0");
5240: //goto xx;
5241: // some argument is really different
5242: // e.g. f(int), f(char*);
5243: return 0;
5244: }
5245:
5246: // arguments checked. Now look at leftover args, return type,etc.
5247:
5248: // if (warn && a && fx->nargs_known==ELLIPSIS) error('w',"... in%n'sAT hidesATs from the overloading mechanism",nx);
5249:
5250: if (a || ax) return 0;
5251:
5252: if (op == 0) {
5253: if (warn && fx->returns->check(f->returns,0))
5254: error("two different return valueTs for%n: %t and %t",nx,fx->returns,f->returns);
5255:
5256: return nx;
5257: }
5258: xx:
5259: if (warn && op)
5260: error("the overloading mechanism cannot tell a%t from a%t",fx,f);
5261:
5262: return 0;
5263: }
5264:
5265: int name::no_of_names()
5266: {
5267: register int i = 0;
5268: register Pname n;
5269: for (n=this; n; n=n->n_list) i++;
5270: return i;
5271: }
5272:
5273: static Pexpr lvec[20], *lll, *curr_e;
5274: static Pexpr last_il = 0;
5275: static Pexpr list_back = 0;
5276: static Pexpr last_el = 0, *last_lll;
5277:
5278: void new_list(Pexpr lx)
5279: {
5280: if (lx->base != ILIST) error('i',"IrLX");
5281:
5282: lll = last_lll = lvec;
5283: lll++;
5284: *lll = last_el = lx->e1;
5285: }
5286:
5287: Pexpr next_elem()
5288: {
5289: Pexpr e;
5290: Pexpr lx;
5291:
5292: if (lll == lvec) return 0;
5293:
5294: lx = *lll;
5295:
5296: if (list_back) {
5297: e = list_back;
5298: list_back = 0;
5299: return e;
5300: }
5301:
5302: if (lx == 0) { /* end of list */
5303: lll--;
5304: return 0;
5305: }
5306:
5307: switch (lx->base) {
5308: case ELIST:
5309: e = lx->e1;
5310: curr_e = &lx->e1;
5311: last_el = lx;
5312: last_lll = lll;
5313: *lll = lx->e2;
5314: switch (e->base) {
5315: case ILIST:
5316: lll++;
5317: *lll = e->e1;
5318: last_il = e;
5319: return Pexpr(1); // start of new ILIST
5320: case ELIST:
5321: error("nestedEL");
5322: return 0;
5323: default:
5324: {
5325: if (need_sti(e)) error('s',"generalIr inIrL");
5326: return e;
5327: }
5328: }
5329: case IVAL:
5330: case ZERO:
5331: lll--;
5332: return 0;
5333: default:
5334: error('i',"IrL %k",lx->base);
5335: }
5336: }
5337:
5338: static Pexpr insert_init(Pexpr newval) {
5339: // splice an initializer in front of the next element in the
5340: // initializer list. Provides initializers for unnamed bitfields.
5341: Pexpr t = new expr(ELIST,last_el->e1,last_el->e2);
5342:
5343: last_el->e1=newval;
5344: last_el->e2=t;
5345: lll = last_lll;
5346: *lll = last_el;
5347: return next_elem();
5348: }
5349:
5350: void skip_ilist()
5351: // skip ilist use to represent pointer to member function literal
5352: {
5353: Pexpr e = next_elem();
5354: e = next_elem();
5355: }
5356:
5357: void list_check(Pname nn, Ptype t, Pexpr il, Ptable tbl)
5358: /*
5359: see if the list "lll" can be assigned to something of type "t"
5360: "nn" is the name of the variable for which the assignment is taking place.
5361: "il" is the last list element returned by next_elem()
5362: */
5363: {
5364: Pexpr e;
5365: bit lst = 0;
5366: int i;
5367: Pclass cl;
5368: int tdef = 0;
5369:
5370: //error('d',"list_check%n: %t (%d)",nn,t,il);
5371: if (il == Pexpr(1)) {
5372: lst = 1;
5373: e = il;
5374: }
5375: else if (il)
5376: list_back = il;
5377:
5378: zzz:
5379: switch (t->base) {
5380: case TYPE:
5381: t = Pbase(t)->b_name->tp;
5382: tdef = 1;
5383:
5384: // did it used to be a VEC before arg_fudge was applied?
5385: if (t->base==PTR && Pvec(t)->size)
5386: t->base=VEC;
5387: goto zzz;
5388:
5389: case VEC:
5390: { Pvec v = Pvec(t);
5391: Ptype vt = v->typ;
5392:
5393: if (v->size) { /* get at most v->size initializers */
5394: if (v->typ->base == CHAR) {
5395: e = next_elem();
5396: if (e->base == STRING) { // v[size] = "..."
5397: int isz = Pvec(e->tp)->size;
5398: if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size);
5399: break;
5400: }
5401: else
5402: list_back = e;
5403: }
5404: for (i=0; i<v->size; i++) { // check next list element type
5405: Pfct MP = 0;
5406: ee:
5407: e = next_elem();
5408: if (e == 0) goto xsw; // too few initializers are ok
5409: vtz:
5410: //error('d',"vtz: %d",vt->base);
5411: switch (vt->base) {
5412: case TYPE:
5413: vt = Pbase(vt)->b_name->tp;
5414: goto vtz;
5415: case VEC:
5416: case COBJ:
5417: list_check(nn,vt,e);
5418: break;
5419: case PTR:
5420: if ((MP = vt->memptr()) &&
5421: e==Pexpr(1)) {
5422: if (vt->check(last_il->tp,ASSIGN))
5423: error("badIrT for%n:%t (%tX)",v,last_il->tp,vt);
5424: skip_ilist();
5425: break;
5426: }
5427: if (MP && e && e->base==ZERO) {
5428: *curr_e = new expr(ELIST,zero,zero);
5429: *curr_e = new expr(ILIST,*curr_e,zero);
5430: (*curr_e)->tp = zero_type;
5431: break;
5432: }
5433: if (MP && e && e->tp->base==OVERLOAD) {
5434: Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl);
5435: if(op) {
5436: *curr_e = op;
5437: break;
5438: }
5439: }
5440: // no break
5441: default:
5442: {
5443: if (e == (Pexpr)1) {
5444: error("unexpectedIrL");
5445: goto ee;
5446: }
5447:
5448: if (vt->check(e->tp,ASSIGN))
5449: error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
5450:
5451: Pptr p;
5452: if (vt->check(e->tp,0)
5453: && (p=vt->is_ptr())
5454: && Ptype(p)!=zero_type
5455: && p->typ!=char_type) {
5456: Pexpr te = e;
5457: Ptype t = p->typ;
5458: while ( t->base == TYPE ) t = Pbase(t)->b_name->tp;
5459: if ( t->base == COBJ )
5460: te = ptr_init( p, e, tbl );
5461: if ( te == e )
5462: *curr_e = new cast(vt,e);
5463: else *curr_e = te;
5464: }
5465: }
5466: }
5467: }
5468: if ( lst && (e=next_elem()) ) error("end ofIrLX after array");
5469: xsw:;
5470: }
5471: else { /* determine v->size */
5472: i = 0;
5473: (void) v->typ->tsizeof();
5474: xx:
5475: while ( e=next_elem() ) { // get another initializer
5476: Pfct MP = 0;
5477: i++;
5478: vtzz:
5479: //error('d',"vtzz");
5480: switch (vt->base) {
5481: case TYPE:
5482: vt = Pbase(vt)->b_name->tp;
5483: goto vtzz;
5484: case VEC:
5485: case COBJ:
5486: list_check(nn,vt,e);
5487: break;
5488: case PTR:
5489: if((MP = vt->memptr()) &&
5490: e==Pexpr(1)) {
5491: if (vt->check(last_il->tp,ASSIGN))
5492: error("badIrT for%n:%t (%tX)",v,last_il->tp,vt);
5493: skip_ilist();
5494: break;
5495: }
5496: if (MP && e && e->base==ZERO) {
5497: *curr_e = new expr(ELIST,zero,zero);
5498: *curr_e = new expr(ILIST,*curr_e,zero);
5499: (*curr_e)->tp = zero_type;
5500: break;
5501: }
5502: if (MP && e && e->tp->base==OVERLOAD) {
5503: Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl);
5504: if(op) {
5505: *curr_e = op;
5506: break;
5507: }
5508: }
5509: // no break
5510: default:
5511: { if (e == Pexpr(1)) {
5512: error("unexpectedIrL");
5513: goto xx;
5514: }
5515:
5516: if (vt->check(e->tp,ASSIGN))
5517: error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
5518:
5519: Pptr p;
5520: if (vt->check(e->tp,0)
5521: && (p=vt->is_ptr())
5522: && Ptype(p)!=zero_type
5523: && p->typ!=char_type) {
5524: Pexpr te = e;
5525: Ptype t = p->typ;
5526: while ( t->base == TYPE ) t = Pbase(t)->b_name->tp;
5527: if ( t->base == COBJ )
5528: te = ptr_init( p, e, tbl );
5529: if ( te == e )
5530: *curr_e = new cast(vt,e);
5531: else *curr_e = te;
5532: }
5533: }
5534: }
5535: }
5536: if (tdef==0) v->size = i;
5537: }
5538: break;
5539: }
5540:
5541: case CLASS:
5542: cl = Pclass(t);
5543: goto ccc;
5544:
5545: case COBJ: /* initialize members */
5546: cl = Pclass(Pbase(t)->b_name->tp);
5547: ccc:
5548: if (cl->defined == 0) {
5549: lll = lvec; // we are lost: ignore rest of list
5550: return;
5551: }
5552:
5553: if (cl->c_body == 1) cl->dcl_print(0);
5554:
5555: { Ptable tbl = cl->memtbl;
5556: Pname m;
5557:
5558: if (cl->baselist) {
5559: if (cl->baselist->next) error("IrL forO ofC with multipleBCs");
5560: list_check(nn,cl->baselist->bclass,0);
5561: }
5562:
5563: for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) {
5564: Ptype mt = m->tp;
5565: Pfct MP = 0;
5566: switch (mt->base) {
5567: case FCT:
5568: case OVERLOAD:
5569: case CLASS:
5570: case ENUM:
5571: continue;
5572: }
5573: if (m->n_stclass == STATIC ||
5574: m->n_stclass == ENUM ) continue;
5575: /* check assignment to next member */
5576: dd:
5577: while (mt->base == TYPE)
5578: mt = Pbase(mt)->b_name->tp;
5579:
5580: if ((MP = mt->memptr()) &&
5581: e==Pexpr(1) &&
5582: last_il->tp->base == PTR) {
5583: if(i==1) lst=0;
5584: }
5585: else e = next_elem();
5586:
5587: if (e == 0) return; //break;
5588:
5589: if(
5590: mt->base == FIELD
5591: &&
5592: m->string[0]=='_'
5593: &&
5594: m->string[1]=='_'
5595: &&
5596: m->string[2]=='F' // unnamed bitfield
5597: ) {
5598: e = insert_init(zero);
5599: }
5600:
5601: //error('d',"mtz%n: %d",m,mt->base);
5602: switch (mt->base) {
5603: case CLASS:
5604: case ENUM:
5605: break;
5606: case VEC:
5607: case COBJ:
5608: list_check(nn,m->tp,e);
5609: break;
5610: case PTR:
5611: if (MP && e==Pexpr(1)) {
5612: if (mt->check(last_il->tp,ASSIGN))
5613: error("badIrT for%n:%t (%tX)",m,last_il->tp,mt);
5614: skip_ilist();
5615: break;
5616: }
5617: if (MP && e && e->base==ZERO) {
5618: *curr_e = new expr(ELIST,zero,zero);
5619: *curr_e = new expr(ILIST,*curr_e,zero);
5620: (*curr_e)->tp = zero_type;
5621: break;
5622: }
5623: if (MP && e && e->tp->base==OVERLOAD) {
5624: Pexpr op = ptof(Pfct(Pptr(mt)->typ),e,tbl);
5625: if(op) {
5626: *curr_e = op;
5627: break;
5628: }
5629: }
5630: // no break
5631: default:
5632: { if (e == Pexpr(1)) {
5633: error("unexpectedIrL");
5634: goto dd;
5635: }
5636:
5637: if (mt->check(e->tp,ASSIGN))
5638: error("badIrT for%n:%t (%tX)",m,e->tp,m->tp);
5639:
5640: if(MP && e && e->base==CAST)
5641: *curr_e = e->e1;
5642:
5643: Pptr p;
5644: if (mt->check(e->tp,0)
5645: && (p=mt->is_ptr())
5646: && Ptype(p)!=zero_type
5647: && p->typ!=char_type)
5648: *curr_e = new cast(mt,e);
5649: }
5650: }
5651: }
5652: if (lst && (e=next_elem()) ) error("end ofIrLX afterCO");
5653: break;
5654: }
5655: default:
5656: e = next_elem();
5657:
5658: if (e == 0) {
5659: error("noIr forO");
5660: break;
5661: }
5662:
5663: if (e == Pexpr(1)) {
5664: error("unexpectedIrL");
5665: break;
5666: }
5667: //error('d',"t %t e->tp %t",t,e->tp);
5668: if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t);
5669: Pptr p;
5670: if (t->check(e->tp,0)
5671: && (p=t->is_ptr())
5672: && Ptype(p)!=zero_type
5673: && p->typ!=char_type)
5674: *curr_e = new cast(t,e);
5675: if (lst && (e=next_elem()) ) error("end ofIrLX afterO");
5676: break;
5677: }
5678: }
5679:
5680: int
5681: is_anon(char* string) {
5682: // error('d',"is_anon: %s", string );
5683: if ( string == 0 )
5684: return 0;
5685:
5686: if ( string[0]=='_' && string[1]=='_' &&
5687: (string[2]=='C' || string[2]=='E'))
5688: return 1;
5689: return 0;
5690: }
5691:
5692: Pname dclass(Pname n, Ptable tbl)
5693: {
5694: Pclass cl;
5695: Pbase bt;
5696: Pname bn;
5697: Pname ntbl = tbl->t_name;
5698: Ptype ntp = 0;
5699: TOK tscope;
5700:
5701: Pname nx = ktbl->look(n->string,0); // TNAME
5702: if (ntbl && ntbl->tp) ntp = ntbl->tp;
5703:
5704: tscope = ntp&&ntp->base==CLASS?NESTED:(n->lex_level?LOCAL:HIDDEN);
5705:
5706: DB( if(Ddebug>=1) error( 'd', &n->where, "dclass n %n %d nx %d", n,n->lex_level, nx); );
5707: // error( 'd', &n->where, "dclass n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name);
5708: if (nx == 0 || n->lex_level ||
5709: ntp && is_anon(n->string) == 0 && ntp->base == CLASS
5710: && (ktbl->look(n->string,tscope)))
5711: {
5712: if ( nx && ntp && ntp->base == CLASS ) {
5713: bt = (Pbase)nx->tp;
5714: bn = bt->b_name;
5715: cl = bn ? (Pclass)bn->tp : 0;
5716: if (cl && cl->lcl &&
5717: strcmp(cl->lcl,"FUDGE007")==0)
5718: goto bbb;
5719: else { bt=0; bn=0; cl=0; }
5720: }
5721:
5722: int tn = 0;
5723: for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list)
5724: {
5725: if (nx->n_key != tscope) continue;
5726: if (tscope==LOCAL &&
5727: nx->lex_level != n->lex_level ) continue;
5728:
5729: if (nx->tp->base != COBJ) {
5730: tn = 1;
5731: continue;
5732: }
5733:
5734: bt = (Pbase)nx->tp;
5735: bn = bt->b_name;
5736: cl = (Pclass)bn->tp;
5737:
5738: if (cl == 0) continue;
5739:
5740: // is this class nested within class table?
5741: if (tscope==NESTED &&
5742: strcmp(ntbl->string,cl->in_class->string))
5743: continue;
5744: else
5745: if ( tscope==LOCAL &&
5746: (cl->lcl==0 || strcmp(cl->lcl,Pclass(n->tp)->lcl)))
5747: continue;
5748:
5749: goto bbb;
5750: }
5751:
5752: if (tn)
5753: error("%n redefined using Tdef",n);
5754: else
5755: error('i',"%n is not aCN",n);
5756: }
5757: else {
5758: bt = Pbase(nx->tp); // COBJ
5759: if ( bt->base != COBJ ) {
5760: error("%n redefined using typedef",n);
5761: Pname tn = ktbl->look(n->string,HIDDEN);
5762: if ( tn->tp->base == COBJ )
5763: bt = Pbase(tn->tp);
5764: else error('i',"%n is not a CN", n );
5765: }
5766: bn = bt->b_name;
5767: }
5768: bbb:
5769: bn->where = nx->where;
5770: Pname bnn = tbl->insert(bn,CLASS); // copy for member lookup
5771: cl = Pclass(bn->tp);
5772:
5773: if (cl->class_base == template_class)
5774: error("C%n defined previously asYC", bn);
5775:
5776: if (cl->defined&(DEFINED|SIMPLIFIED))
5777: error("C%n defined twice",n);
5778: else {
5779: if (bn->n_scope == ARG) bn->n_scope = ARGT;
5780: cl->dcl(bn,tbl);
5781: }
5782: n->tp = cl;
5783: return bnn;
5784: }
5785:
5786: Pname denum(Pname n, Ptable tbl)
5787: {
5788: Penum en;
5789: Pbase bt;
5790: Pname bn;
5791: Pname ntbl = tbl->t_name;
5792: Ptype ntp = 0;
5793: TOK tscope;
5794:
5795: Pname nx = ktbl->look(n->string,0); // TNAME
5796: if (ntbl && ntbl->tp) ntp = ntbl->tp;
5797:
5798: // note: ***** add for local enumeration declaration
5799: // error( 'd', &n->where, "denum n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name);
5800: if (nx == 0 || /* n->lex_level ||*/
5801: ntp && is_anon(n->string)==0 && ntp->base == CLASS )
5802: {
5803: int tn = 0;
5804: tscope = ntp&&ntp->base==CLASS?NESTED:(/*n->lex_level?LOCAL:*/HIDDEN);
5805: for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list)
5806: {
5807: if (nx->n_key != tscope) continue;
5808: // if (tscope==LOCAL &&
5809: // nx->lex_level != n->lex_level ) continue;
5810:
5811: bt = (Pbase)nx->tp;
5812: bn = bt->b_name;
5813: en = (Penum)bn->tp;
5814:
5815: // is this class nested within class table?
5816: if (tscope==NESTED && en->in_class &&
5817: strcmp(ntbl->string,en->in_class->string))
5818: continue;
5819: }
5820: }
5821: else {
5822: bt = (Pbase)nx->tp;
5823: bn = bt->b_name;
5824: en = (Penum)bn->tp;
5825: }
5826:
5827: Pname bnn = tbl->insert(bn,CLASS);
5828: if (en->defined&(DEFINED|SIMPLIFIED))
5829: error("enum%n defined twice",n);
5830: else {
5831: if (bn->n_scope == ARG) bn->n_scope = ARGT;
5832: en->dcl(bn,tbl);
5833: }
5834: n->tp = en;
5835: return bnn;
5836: }
5837:
5838: static int
5839: is_probably_temp( char *str )
5840: {
5841: // error( 'd', "is_probably_temp( %s )", str );
5842:
5843: if ( str[0] != '_' || str[1] != '_' )
5844: return 0;
5845:
5846: switch (str[2]) {
5847: default:
5848: return 0;
5849: case 'A': case 'C': case 'D': case 'E': case 'F':
5850: case 'I': case 'K': case 'L': case 'M': case 'N':
5851: case 'Q': case 'R': case 'S': case 'T': case 'U':
5852: case 'V': case 'W': case 'X':
5853: return 1;
5854: }
5855:
5856: }
5857:
5858: static void
5859: check_for_local( Pexpr ee )
5860: {
5861: static Pname n[2] = {0,0}; // try not to flag multiple errors
5862: static index = 0;
5863:
5864: if ( ee==0 ) return;
5865:
5866: // error('d', "check_for_local( %k ) e1: %d e2: %d", ee->base, ee->e1, ee->e2);
5867:
5868: switch ( ee->base ) {
5869: case NAME:
5870: {
5871: Pname nn = Pname(ee);
5872: if ((nn->n_scope==FCT || nn->n_scope==ARG)
5873: && is_probably_temp(nn->string) == 0
5874: && n[0]!=nn && n[1]!=nn)
5875: {
5876: error("local%n used as defaultA", nn );
5877: n[index] = nn;
5878: index = index==0?1:0;
5879: }
5880: // no break;
5881: }
5882: case TNAME: case STRING: case IVAL:
5883: case ICON: case CCON: case FCON:
5884: case ZERO: case DUMMY: case SIZEOF:
5885: return;
5886: case QUEST:
5887: check_for_local( ee->cond );
5888: break;
5889: case MDOT:
5890: check_for_local( ee->mem );
5891: return;
5892: }
5893:
5894: check_for_local( ee->e1 );
5895: check_for_local( ee->e2 );
5896: }
5897:
5898: void dargs(Pname, Pfct f, Ptable tbl)
5899: {
5900: int argnamesize = 0; // if +a1, make sure arg names can be printed
5901: int oo = const_save;
5902: const_save = 1;
5903: if ( ansi_opt ) {
5904: Pname th = f->f_this;
5905: if ( th && th->string ) argnamesize += strlen(th->string) + 1;
5906: th = f->f_result;
5907: if ( th && th->string ) argnamesize += strlen(th->string) + 1;
5908: }
5909:
5910: for (Pname a=f->argtype; a; a=a->n_list) {
5911: Pexpr init;
5912:
5913: if (a->tp == 0) {
5914: error( "A has noT" );
5915: a->tp = any_type;
5916: continue;
5917: }
5918: if (ansi_opt && a->string) argnamesize += strlen(a->string) + 1;
5919:
5920: Pname cln = a->tp->is_cl_obj();
5921: //error('d',"dargs %t",a->tp);
5922: if (cln && Pclass(cln->tp)->has_itor()) // mark X(X&) arguments
5923: a->n_xref = 1;
5924: else {
5925: Ptype t = a->tp;
5926: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
5927: if (t->base == FCT) a->tp = new ptr(PTR,a->tp);
5928: }
5929:
5930: // if (init = a->n_initializer) { // default argument
5931: if ( a->n_key != NESTED &&
5932: (init = a->n_initializer)) { // default argument
5933: Pptr pt;
5934: if (init == dummy) {
5935: error("emptyIr");
5936: a->n_initializer = 0;
5937: continue;
5938: }
5939: if (cln) {
5940: if (init->base==VALUE) {
5941: switch (init->tp2->base) {
5942: case CLASS:
5943: if (Pclass(init->tp2)!=Pclass(cln->tp)) goto inin2;
5944: break;
5945: default:
5946: Pname n2 = init->tp2->is_cl_obj();
5947: if (n2==0 || Pclass(n2->tp)!=Pclass(cln->tp)) goto inin2;
5948: }
5949:
5950: a->n_initializer = init = 0;
5951: error('s',"K as defaultA");
5952: }
5953: else {
5954: inin2:
5955: if (init->base == ILIST) error("list as AIr");
5956: Pexpr i = init->typ(tbl);
5957: init = class_init(a,a->tp,i,tbl);
5958: if (i!=init && init->base==DEREF) {
5959: error('s',"K needed forAIr");
5960: init = 0;
5961: }
5962: else {
5963: dosimpl(init,cc->nof);
5964: // init->simpl();
5965: init->permanent = 2;
5966: }
5967: a->n_initializer = init;
5968: }
5969: }
5970: else if (pt = a->tp->is_ref()) {
5971: ref_initializer++;
5972: init = init->typ(tbl);
5973: ref_initializer--;
5974: int tcount = stcount;
5975: init = ref_init(pt,init,tbl);
5976: if (tcount != stcount) {
5977: error('s',"needs temporaryV to evaluateAIr");
5978: init = 0;
5979: }
5980: else {
5981: dosimpl(init,cc->nof);
5982: // init->simpl();
5983: init->permanent = 2;
5984: }
5985: a->n_initializer = init;
5986: }
5987: else {
5988: Pptr p = a->tp->is_ptr();
5989: init = init->typ(tbl);
5990: if (p) init = ptr_init(p,init,tbl);
5991:
5992: if (a->tp->check(init->tp,ARG)) {
5993: int i = can_coerce(a->tp,init->tp);
5994:
5995: switch (i) {
5996: case 1:
5997: if (Ncoerce) {
5998: Pname cn = init->tp->is_cl_obj();
5999: Pname xx = new name(Ncoerce->string);
6000: Pref r = new ref(DOT,init,xx);
6001: init = new expr(G_CALL,r,0);
6002: init = init->typ(tbl);
6003: }
6004: break;
6005: default:
6006: error("%d possible conversions for defaultA",i);
6007: case 0:
6008: error("badIrT%t forA%n (%tX)",init->tp,a,a->tp);
6009: DEL(init);
6010: a->n_initializer = init = 0;
6011: }
6012: }
6013:
6014: if (init) {
6015: dosimpl(init,cc->nof);
6016: // init->simpl();
6017: init->permanent = 2;
6018: a->n_initializer = init;
6019: Neval = 0;
6020: long i = init->eval();
6021: if (Neval == 0) {
6022: a->n_evaluated = 1;
6023: a->n_val = i;
6024: }
6025: }
6026: }
6027: if ( a->n_initializer )
6028: check_for_local(a->n_initializer);
6029: }
6030: }
6031: if ( ansi_opt && argnamesize ) {
6032: char* ps = new char[ argnamesize ];
6033: Pname a = f->f_this;
6034: if ( a && a->string ) {
6035: int i = strlen(a->string) + 1;
6036: if ( (argnamesize -= i) < 0 ) goto bad;
6037: strcpy(ps,a->string);
6038: a->string = ps;
6039: ps += i;
6040: }
6041: a = f->f_result;
6042: if ( a && a->string ) {
6043: int i = strlen(a->string) + 1;
6044: if ( (argnamesize -= i) < 0 ) goto bad;
6045: strcpy(ps,a->string);
6046: a->string = ps;
6047: ps += i;
6048: }
6049: for ( a = f->argtype; a; a = a->n_list ) {
6050: if ( a->string == 0 ) continue;
6051: int i = strlen(a->string) + 1;
6052: if ( (argnamesize -= i) < 0 ) goto bad;
6053: strcpy(ps,a->string);
6054: a->string = ps;
6055: ps += i;
6056: }
6057: if ( argnamesize ) bad:error('i',"bad argN size for%t",f);
6058: }
6059: const_save = oo;
6060: }
6061:
6062: void merge_init(Pname nn, Pfct f, Pfct nf)
6063: {
6064: // Pname a1 = f->f_args; if (a1==0) a1 = f->argtype;
6065: // Pname a2 = nf->f_args;//nf->argtype;
6066: Pname a1 = f->argtype;
6067: Pname a2 = nf->argtype;
6068:
6069: for (; a1; a1=a1->n_list, a2=a2->n_list) {
6070: int i1 = a1->n_initializer || a1->n_evaluated;
6071: int i2 = a2->n_initializer || a2->n_evaluated;
6072:
6073: if (i1 && i2) error(&a1->where,"twoIrs for%nA%n",nn,a1);
6074:
6075: if (i1) {
6076: a2->n_initializer = a1->n_initializer;
6077: a2->n_evaluated = a1->n_evaluated;
6078: a2->n_val = a1->n_val;
6079: }
6080: if (i2) {
6081: a1->n_initializer = a2->n_initializer;
6082: a1->n_evaluated = a2->n_evaluated;
6083: a1->n_val = a2->n_val;
6084: }
6085:
6086: }
6087: }
6088:
6089: Pexpr try_to_coerce(Ptype rt, Pexpr e, char* s, Ptable tbl)
6090: /*
6091: ``e'' is of class ``cn'' coerce it to type ``rt''
6092: */
6093: {
6094: int i;
6095: Pname cn;
6096: //error('d',"try_to_coerce(%t, %t, %s, %d)",rt,e->tp,s,tbl);
6097:
6098: if ((cn=e->tp->is_cl_obj()) && (i=can_coerce(rt,e->tp)) && Ncoerce) {
6099: if (1 < i) error("%d possible conversions for %s",i,s);
6100: //error('d',"coerce %n",Ncoerce);
6101: Pclass cl = Pclass(cn->tp);
6102: // Pref r = new ref(DOT,e,Ncoerce);
6103: // Pexpr rr = r->typ(tbl);
6104: // Pexpr c = new expr(G_CALL,rr,0);
6105: // c->fct_name = Ncoerce;
6106: Pname xx = new name(Ncoerce->string);
6107: Pref r = new ref(DOT,e,xx);
6108: Pexpr c = new expr(G_CALL,r,0);
6109: // return c->typ(tbl);
6110: c = c->typ(tbl);
6111: //error('d',"coerce -> %k %t",c->base,c->tp);
6112: return c;
6113: }
6114: //error('d',"coerce ->0");
6115: return 0;
6116: }
6117:
6118: int in_class_dcl;
6119:
6120: Pname name::dofct(Ptable tbl, TOK scope)
6121: {
6122: Pfct f = Pfct(tp);
6123: Pname class_name;
6124: Ptable etbl;
6125: in_class_dcl = cc->not!=0;
6126: int just_made = 0;
6127: // int fvirt = 0; //BSopt
6128: DB( if(Ddebug>=1) error('d',"dofct %n %d %t %s",this,tp,tp,tbl==gtbl?"global":""); );
6129: // error( 'd', "%n->dofct(): n_initializer: %d f->f_virtual: %d", this, n_initializer, f->f_virtual);
6130:
6131: if (f->f_inline) n_sto = STATIC;
6132:
6133: if (n_stclass)
6134: switch (n_stclass) {
6135: case EXTERN:
6136: case STATIC:
6137: case OVERLOAD:
6138: break;
6139: default:
6140: error("%n declared%k",this,n_stclass);
6141: n_stclass = EXTERN;
6142: }
6143:
6144: tp->dcl(tbl); // must be done before the type check
6145:
6146: if (n_qualifier) { // qualified name: c::f() checked above
6147: class_name = Pbase(n_qualifier->tp)->b_name;
6148: etbl = Pclass(class_name->tp)->memtbl;
6149:
6150: if (f->f_virtual) {
6151: error("virtual specifier illegal outsideCD(%n::%s())",class_name,this->string);
6152: f->f_virtual = 0;
6153: }
6154:
6155:
6156: if (n_sto
6157: && n_sto!=FRIEND // friend X::f();
6158: && f->f_inline==0) { // inline causes n_sto==STATIC
6159: error("%k specified for QdN%n",n_sto,this);
6160: n_sto = 0;
6161: }
6162: }
6163: else {
6164: class_name = cc->not;
6165:
6166: // beware of local function declarations in member functions
6167: if (class_name && tbl!=cc->cot->memtbl) {
6168: class_name = 0;
6169: in_class_dcl = 0;
6170: }
6171:
6172: if (f->f_static && f->f_virtual) {
6173: error("virtual staticM");
6174: f->f_virtual = 0;
6175: }
6176:
6177: if (n_oper) check_oper(class_name);
6178: etbl = tbl;
6179: }
6180:
6181: // Pfct(tp)->memof = class_name ? Pclass(class_name->tp) : 0;
6182:
6183: if (class_name) {
6184: Pclass cl;
6185: f->memof = cl = Pclass(class_name->tp);
6186: if (f->f_virtual==0 && find_virtual(f->memof,this))
6187: f->f_virtual = VTOK;
6188: //error('d',"class_name: %s fct: %s virtual: %d", class_name->string, string, f->f_virtual );
6189:
6190: if (f->f_static && f->f_virtual) {
6191: error("virtual staticM");
6192: f->f_virtual = 0;
6193: }
6194:
6195: if ( cl->csu == UNION && f->f_virtual ) // don't worry about ANON
6196: error( "%n: cannot declare a virtualFWin union", this );
6197: }
6198:
6199: if(f->f_const && f->memof==0) {
6200: error("onlyMFs can be constant");
6201: }
6202:
6203: if (etbl==0 || etbl->base!=TABLE) error('i',"N::dcl: etbl=%d",etbl);
6204:
6205: switch (n_oper) {
6206: case CTOR:
6207: if (f->f_virtual) {
6208: error("virtualK");
6209: f->f_virtual = 0;
6210: }
6211:
6212: // case DTOR:
6213: // f->f_const = 1;
6214: break;
6215:
6216: case REF:
6217: if (f->argtype)
6218: error("%n takes no argument",this);
6219: else if (f->returns->is_ptr() == 0) {
6220: Pname cn = f->returns->is_cl_obj();
6221: if (cn==0 && f->returns->base==RPTR) cn = Pptr(f->returns)->typ->is_cl_obj();
6222: if (cn==0 || Pclass(cn->tp)->has_oper(REF)==0) {
6223: if ( cn && class_name && // B B::operator->();
6224: strcmp(cn->string, class_name->string)==0 )
6225: error("%s::%n cannot return aR orCO ofC%n",cn->string,this,cn);
6226: else error("%n must return aP toCO, aR toCO, or aCO",this);
6227: tp = any_type; // suppress further checking
6228: }
6229: }
6230: break;
6231:
6232: case NEW: // void* operator new(long)
6233: if (f->f_virtual)
6234: error("virtual%n (operator new() is static)",this);
6235: if (class_name) f->f_static = 1; // if member: static by default
6236: if (f->nargs_known != 1)
6237: error("ATs must be fully specified for%n",this);
6238: else if (f->nargs<1)
6239: error("%n requires a firstA ofT size_t",this);
6240: else if (f->argtype->tp->check(size_t_type,0)) {
6241: if (strict_opt==0
6242: && ( f->argtype->tp->check(long_type,0)==0 ||
6243: f->argtype->tp->check(ulong_type,0)==0)) {
6244: error('w',"%n firstA should be size_t (anachronism)",this);
6245: f->argtype->tp = size_t_type;
6246: if (f->f_signature) f->sign();
6247: }
6248: else
6249: error("%n requires a firstA ofT size_t",this);
6250: }
6251: else {
6252: Ptype t = f->s_returns ? f->s_returns : f->returns;
6253: if (t->check(Pvoid_type,0)) error("bad returnT for %n",this);
6254: }
6255: break;
6256:
6257: case DELETE: // void operator delete(void*) or
6258: // void operator delete(void*, long)
6259: if (f->f_virtual)
6260: error("virtual%n (operator delete() is static)",this);
6261: if (class_name) f->f_static = 1; // if member: static by default
6262: if (f->nargs_known != 1)
6263: error("ATs must be fully specified for%n",this);
6264: else {
6265: Ptype t = f->s_returns ? f->s_returns : f->returns;
6266: if (t->base != VOID)
6267: error("bad returnT for %n", this);
6268: else {
6269: switch (f->nargs) {
6270: default:
6271: error("%n takes 1 or 2As",this);
6272: break;
6273: case 1:
6274: case 2:
6275: { Pname a = f->argtype;
6276: if (a->tp->check(Pvoid_type,0))
6277: error("%n's 1stA must be a void*",this);
6278: else if (a = a->n_list) {
6279: if (class_name == 0)
6280: error("%n takes only oneA",this);
6281: else if (a->tp->check(size_t_type,0)) {
6282: if (strict_opt==0
6283: && a->tp->check(long_type,0)==0) {
6284: error('w',"%n's 2ndA should be a size_t (anachronism)",this);
6285: a->tp = size_t_type;
6286: if (f->f_signature) f->sign();
6287: }
6288: else
6289: error("%n's 2ndA must be a size_t",this);
6290: }
6291: }
6292: }
6293: }
6294: }
6295: }
6296: break;
6297:
6298: case ASSIGN:
6299: if (class_name && f->nargs==1) {
6300: Ptype t = f->argtype->tp;
6301: Pname an = t->is_cl_obj(); // X::operator=(X) ?
6302: if (an==0 && (t=t->is_ref())) { // X::operator=(X&) ?
6303: t = Pptr(t)->typ;
6304: rx1:
6305: switch (t->base) {
6306: case TYPE: t = Pbase(t)->b_name->tp; goto rx1;
6307: case COBJ: an = Pbase(t)->b_name;
6308: }
6309: }
6310: if (an && an==class_name) Pclass(an->tp)->c_xref |= C_ASS;
6311: }
6312: else if (f->nargs == 2) {
6313: Ptype t = f->argtype->tp;
6314: Pname an1;
6315: if (t=t->is_ref()) { // operator=(X&,?) ?
6316: t = Pptr(t)->typ;
6317: rx2:
6318: switch (t->base) {
6319: case TYPE: t = Pbase(t)->b_name->tp; goto rx2;
6320: case COBJ: an1 = Pbase(t)->b_name;
6321: }
6322: }
6323: t = f->argtype->n_list->tp;
6324: Pname an2 = t->is_cl_obj(); // operator=(X&,X) ?
6325: if (an2==0 && (t=t->is_ref())) { // operator=(X&,X&) ?
6326: t = Pptr(t)->typ;
6327: rx3:
6328: switch (t->base) {
6329: case TYPE: t = Pbase(t)->b_name->tp; goto rx3;
6330: case COBJ: an2 = Pbase(t)->b_name;
6331: }
6332: }
6333: if (an1 && an1==an2) Pclass(an1->tp)->c_xref |= C_ASS;
6334: }
6335: }
6336:
6337: switch (scope) {
6338: case FCT:
6339: case ARG:
6340: if (n_sto == STATIC) error("D of staticF in aF");
6341: else { // detect local re-definition
6342: Pname nx = gtbl->look(string,0);
6343: if (nx) {
6344: switch (nx->tp->base) {
6345: case FCT:
6346: if (tp->check(nx->tp,0))
6347: error('w',"%n has been locally re-declared as%t",this,tp);
6348: else {
6349: if(Pfct(nx->tp)->f_signature==0)
6350: Pfct(nx->tp)->sign();
6351: if (Pfct(tp)->f_signature == 0)
6352: Pfct(tp)->sign();
6353: if ( strcmp(Pfct(nx->tp)->f_signature,Pfct(tp)->f_signature))
6354: error('w',"%n of type %t has been locally re-declared with different linkage",this,tp);
6355: }
6356: break;
6357: case OVERLOAD:
6358: { Pname ny = Pgen(nx->tp)->find(f,0);
6359: if (ny == 0)
6360: error('w',"overloadedF%n has been locally declared as%t",this,tp);
6361: else {
6362: if(Pfct(ny->tp)->f_signature==0)
6363: Pfct(ny->tp)->sign();
6364: if (Pfct(tp)->f_signature == 0)
6365: Pfct(tp)->sign();
6366: if (strcmp(Pfct(ny->tp)->f_signature,Pfct(tp)->f_signature))
6367: error('w',"overloadedF%n of type %t has been locally re-declared with different linkage",this,tp);
6368: }
6369: }
6370: break;
6371: } // switch nx->base
6372: } // if nx
6373: } // else
6374: } // switch scope
6375:
6376: Pname nn = etbl->insert(this,0);
6377: if ( f->body ) nn->where = where;
6378: nn->assign();
6379: n_table = etbl;
6380: //error('d',"%n->dofct(): n_initializer:%d f->f_virtual:%d",this,n_initializer,f->f_virtual);
6381: if (n_initializer) {
6382: if (f->f_virtual == 0) error("Ir for non-virtualF%n",this);
6383: if (n_initializer != zero) error("virtualFIr must be 0");
6384: }
6385:
6386: if (Nold) {
6387: Pfct nf = Pfct(nn->tp);
6388: // error('d',"old %n: %t and %t",nn,nf,tp);
6389: int flag = 0;
6390: Pname af=0,anf=0;
6391: if (nf->base==ANY || f->base==ANY)
6392: ; // wild card -- do nothing
6393: else
6394: if (nf->base == OVERLOAD) {
6395: string = nn->string;
6396: nn = Pgen(nf)->add(this);
6397:
6398: if (Nold == 0) {
6399: if (f->body && n_qualifier) {
6400: error("badAL for%n",this);
6401: return 0;
6402: }
6403: goto thth;
6404: }
6405: // else {
6406: // if (f->body==0 && friend_in_class==0) error('w',"%n redeclared",nn);
6407: // }
6408: nf = Pfct(nn->tp);
6409: if (f->body && nf->body) {
6410: // Preserve the original definition
6411: // in the case of a PT class; i.e,
6412: // the one supplied by the user
6413: if (!(class_name &&
6414: (Pclass(class_name->tp)->class_base ==
6415: instantiated_template_class) &&
6416: nn->n_redefined))
6417: {
6418: error("two definitions of%n",nn);
6419: f->body = 0;
6420: }
6421: return 0;
6422: }
6423: if (f->body) goto bdbd;
6424: goto stst;
6425: }
6426: else if (nf->base != FCT) {
6427: error("%n declared both as%t and asF",this,nf);
6428: f->body = 0;
6429: }
6430: else {
6431: // error('d',"%t->check(%t) -> %d %d",nf,f,nf->check(f,OVERLOAD));
6432: if (nf->check(f,OVERLOAD) || const_problem) {
6433: if (f->body && n_qualifier) {
6434: error("%nT mismatch: %t and %t",nn,nf,f);
6435: return 0;
6436: }
6437: Pgen g = new gen;
6438: add_first = 1;
6439: Pname n1 = g->add(nn);
6440: add_first = 0;
6441: string = nn->string;
6442: Pname n2 = g->add(this);
6443: nn->tp = g;
6444: nn = n2;
6445: goto thth;
6446: }
6447:
6448: af = f->argtype;
6449: anf = nf->argtype;
6450: for (; af && anf; af=af->n_list,anf=anf->n_list) {
6451: Ptype at = af->tp;
6452: Ptype atp = anf->tp;
6453: if(!exact1(af,atp)) break;
6454: if(at->base!=PTR ||
6455: Pptr(at)->rdo == Pptr(atp)->rdo) continue;
6456: int k = Pptr(at)->typ->tconst();
6457: int l = Pptr(atp)->typ->tconst();
6458: if(k==l) flag=1;
6459: }
6460: if ( flag && !af && !anf) {
6461: error("the overloading mechanism cannot tell a%t from a%t",nf,f);
6462: }
6463:
6464: if (in_class_dcl) {
6465: // error("twoDs of%n",this);
6466: // f->body = 0;
6467: // return 0;
6468: }
6469: else if (nf->f_static && f->f_inline==0 && n_sto==STATIC) {
6470: //error('d',"MF%n declared static outsideF",this);
6471: n_sto = 0;
6472: }
6473: else if (n_sto && n_sto!=nn->n_scope) {
6474: if (n_sto==EXTERN && nn->n_scope==STATIC)
6475: error('w',"%n declared extern after being declared static",this);
6476: else if (nf->f_inline==0 && f->f_inline==0) {
6477: if (nn->tp==new_fct->tp || nn->tp==del_fct->tp)
6478: nn->n_sto = n_sto;
6479: else
6480: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:EXTERN);
6481: }
6482: }
6483:
6484: //error('d',"fct %n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope);
6485: //error('d',"link %d lcount %d sig %s",linkage,lcount,nf->f_signature);
6486:
6487: {
6488: Linkage l1 = nf->f_linkage;
6489: Linkage l2 = f->f_linkage;
6490: if ( l2!=linkage_default && l1!=l2)
6491: error("inconsistent linkage specifications for%n",this);
6492: }
6493: if (nf->body && f->body) {
6494: // Preserve the original definition
6495: // in the case of a PT class; i.e,
6496: // the one supplied by the user
6497: if (!(class_name &&
6498: (Pclass(class_name->tp)->class_base ==
6499: instantiated_template_class) &&
6500: nn->n_redefined))
6501: {
6502: error("two definitions of%n",this);
6503: f->body = 0;
6504: }
6505: return 0;
6506: }
6507:
6508: if (f->body) goto bdbd;
6509:
6510: goto stst;
6511:
6512: bdbd:
6513: // error('d',"nn %n init: %d f_virt: %d f->body: %d", nn,nn->n_initializer,nf->f_virtual,f->body);
6514: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
6515: f->f_virtual = nf->f_virtual;
6516: f->f_this = nf->f_this;
6517: f->f_result = nf->f_result;
6518: f->s_returns = nf->s_returns;
6519: f->f_args = nf->f_args;
6520: // f->argtype = nf->argtype;
6521: f->f_signature = nf->f_signature;
6522: f->f_const = nf->f_const;
6523: f->f_static = nf->f_static;
6524: nn->tp = f;
6525: if (f->f_inline) {
6526: if (nf->f_inline==0) {
6527: if (nn->n_used && nn->n_sto!=STATIC)
6528: error("%n declared with external linkage and called before defined as inline",nn);
6529: // else if (nf->memof)
6530: // error('w',"%n declared as non-inline but defined as inline",nn);
6531: else if (nn->n_used) {
6532: nn->take_addr(); // force printout
6533: if (warning_opt) error('w',"%n called before defined as inline",nn);
6534: }
6535: }
6536: nf->f_inline = 1;
6537: nn->n_sto = STATIC;
6538: }
6539: else if (nf->f_inline) {
6540: // error('w',"%n defined as inline but not declared as inline",this);
6541: f->f_inline = 1;
6542: }
6543: goto stst2;
6544:
6545: stst:
6546: //error('d',"stst");
6547: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
6548: f->f_args = nf->f_args;
6549: // f->argtype = nf->argtype;
6550: stst2:
6551: //error('d',"stst2 %n printed %d",nn,nn->n_dcl_printed);
6552: if (f->f_inline) n_sto = STATIC;
6553:
6554: /* superceded above (line 1978 and following)
6555: if (n_sto
6556: && nn->n_scope!=n_sto
6557: && friend_in_class==0
6558: && f->f_inline==0){ // allow re-def to "static"
6559: if (n_sto == STATIC)
6560: nn->n_sto = STATIC;
6561: else {
6562: error("%n both%k and%k",this,n_sto,nn->n_scope);
6563: }
6564: }
6565: */
6566:
6567: //// addition for 2.1
6568:
6569: if(n_sto == STATIC && nn->n_sto == EXTERN &&
6570: (!strcmp(string,"__nw") || !strcmp(string,"__dl")))
6571: nn->n_sto = STATIC;
6572:
6573: //// end of addition
6574:
6575: n_scope = nn->n_scope; // first specifier wins
6576: n_sto = nn->n_sto;
6577: }
6578: }
6579: else { // new function: make f_this for member functions
6580: thth:
6581: just_made = 1;
6582: if (f->f_inline)
6583: nn->n_sto = STATIC;
6584: else if (class_name==0 && n_sto==0 && f->body==0)
6585: nn->n_sto = EXTERN;
6586: //error('d',"thth %n %t static %d sto %k",nn,f,f->f_static,nn->n_sto);
6587: if (f->f_static)
6588: switch (n_oper) { // what about + ??
6589: case CTOR:
6590: case DTOR:
6591: case TYPE:
6592: case CALL:
6593: case DEREF:
6594: case REF:
6595: case ASSIGN:
6596: error("%n cannot be a staticMF",nn);
6597: f->f_static = 0;
6598: }
6599:
6600: if (class_name
6601: && f->f_static==0 // no ``this'' in static members
6602: && n_oper!=NEW // X::operator new() static by default
6603: && n_oper!=DELETE // X::operator delete() static by default
6604: && etbl!=gtbl) { // beware of implicit declaration
6605: Pname cn = nn->n_table->t_name;
6606: Pname tt = new name("this");
6607: tt->n_scope = ARG;
6608: tt->where = no_where;
6609: // tt->n_sto = ARG;
6610: tt->tp = Pclass(class_name->tp)->this_type;
6611: PERM(tt);
6612: Pfct(nn->tp)->f_this = f->f_this = Pfct(nn->tp)->f_args = f->f_args = tt;
6613: tt->n_list = f->argtype;
6614: //error('d',"nn %n tp %t const %d",nn,nn->tp,f->f_const);
6615: if (f->f_const /*&& n_oper!=CTOR && n_oper!=DTOR*/) {
6616: Pbase x = Pbase(Pptr(tt->tp)->typ);
6617: Pbase y = new basetype(COBJ,0);
6618: *y = *x;
6619: y->b_const = 1;
6620: tt->tp = new ptr(PTR,y);
6621: Pptr(tt->tp)->rdo = 1;
6622: PERM(tt->tp);
6623: }
6624: }
6625: else {
6626: Pfct(nn->tp)->f_args = f->f_args = f->f_result?f->f_result:f->argtype;
6627: Pfct(nn->tp)->f_signature = f->f_signature;
6628: Pfct(nn->tp)->f_const = f->f_const;
6629: Pfct(nn->tp)->f_static = f->f_static;
6630: }
6631:
6632: // if C++ linkage encode type in function name
6633: if (Pfct(nn->tp)->f_signature==0) Pfct(nn->tp)->sign();
6634:
6635: if (f->f_result == 0) {
6636: //error('d',"re1 %n %t %d",this,f,f);
6637: make_res(f);
6638: }
6639: else if (f->f_this)
6640: f->f_this->n_list = f->f_result;
6641:
6642: if (nn->n_oper==CTOR || nn->n_oper==DTOR) vbase_pointers(nn,Pclass(class_name->tp));
6643:
6644: if (f->f_virtual) {
6645: switch (nn->n_scope) {
6646: default:
6647: error("nonC virtual%n",this);
6648: break;
6649: case 0:
6650: case PUBLIC:
6651: // if (fvirt) //BSopt
6652: cc->cot->virt_count = 1;
6653: Pfct(nn->tp)->f_virtual = f->f_virtual;
6654: break;
6655: }
6656: }
6657: }
6658:
6659: /* an operator must take at least one class object or
6660: reference to class object argument
6661: */
6662:
6663: if (just_made)
6664: switch (n_oper) {
6665: case CTOR:
6666: switch (f->nargs) { // check for X(X) and X(X&)
6667: case 0:
6668: break;
6669: default: // handle X(X&, int i = 0)
6670: { Pname n2 = f->argtype->n_list;
6671: if (n2->n_initializer==0 && n2->n_evaluated==0) break;
6672: }
6673: case 1:
6674: {
6675: Ptype t = f->argtype->tp;
6676: clll:
6677: switch (t->base) {
6678: case TYPE:
6679: t = Pbase(t)->b_name->tp;
6680: goto clll;
6681: case RPTR: /* X(X&) ? */
6682: t = Pptr(t)->typ;
6683: cxll:
6684: switch (t->base) {
6685: case TYPE:
6686: t = Pbase(t)->b_name->tp;
6687: goto cxll;
6688: case COBJ:
6689: if (class_name == Pbase(t)->b_name)
6690: Pclass(class_name->tp)->c_itor = nn;
6691: }
6692: break;
6693: case COBJ: /* X(X) ? */
6694: if (class_name == Pbase(t)->b_name) {
6695: error("badK %s(%s) use %s(%s&)",class_name->string,class_name->string,class_name->string,class_name->string);
6696: f->argtype->tp = any_type;
6697: }
6698: }
6699: }
6700: }
6701: if (Pclass(class_name->tp)->c_ctor == 0) Pclass(class_name->tp)->c_ctor = nn;
6702: break;
6703:
6704: case TYPE:
6705: // somewhat simple minded solution to the inheritance of
6706: // conversion operator problem
6707: nn->n_list = Pclass(class_name->tp)->conv;
6708: Pclass(class_name->tp)->conv = nn;
6709: break;
6710:
6711: case DTOR:
6712: Pclass(class_name->tp)->c_dtor = nn;
6713: break;
6714:
6715: case NEW:
6716: case DELETE:
6717: case CALL:
6718: case 0:
6719: break;
6720:
6721: default:
6722: for (Pname a=f->argtype; a; a=a->n_list) {
6723: if ( a->n_initializer )
6724: error( "%n: operatorFs cannot take defaultA", this );
6725: }
6726:
6727: if (f->nargs_known != 1) {
6728: error("ATs must be fully specified for%n",nn);
6729: }
6730: // this doesn't catch unary operator off by one errors
6731: // for simplicity, placed that check in check_oper(), above
6732: else if (class_name == 0) {
6733: switch (f->nargs) {
6734: case 1:
6735: case 2:
6736: for (a=f->argtype; a; a=a->n_list) {
6737: Ptype tx = a->tp;
6738: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp;
6739: if (tx->is_ref()) tx = Pptr(tx)->typ;
6740: if (tx->is_cl_obj()) goto cok;
6741: }
6742: error("%n must take at least oneCTA",nn);
6743: break;
6744: default:
6745: error("%n must take 1 or 2As",nn);
6746: }
6747: }
6748: else {
6749: switch (f->nargs) {
6750: case 0:
6751: case 1:
6752: break;
6753: default:
6754: error("%n must take 0 or 1As",nn);
6755: }
6756: }
6757: cok:;
6758: }
6759:
6760: int i = 0; // check that every argument after an argument with
6761: // initializer have an initializer
6762: for (Pname a = f->f_args/*f->argtype*/; a; a=a->n_list) {
6763: if (a->n_initializer)
6764: i = 1;
6765: else if (i)
6766: error("trailingA%n withoutIr",a);
6767: }
6768:
6769: /*
6770: the body cannot be checked until the name
6771: has been checked and entered into its table
6772: */
6773: if (f->body) f->dcl(nn);
6774: return nn;
6775: }
6776:
6777: 0707071010112043711004440001630000160000010174600466055376600000700000154273dcl4.c /*ident "@(#)ctrans:src/dcl4.c 1.4" */
6778: /**************************************************************************
6779:
6780: C++ source for cfront, the C++ compiler front-end
6781: written in the computer science research center of Bell Labs
6782:
6783: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
6784: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
6785:
6786: dcl4.c:
6787: Declaration of class and enum
6788:
6789: *************************************************************************/
6790:
6791: #include "cfront.h"
6792: #include "size.h"
6793: #include "template.h"
6794:
6795: Pname find_vptr(Pclass);
6796: void fix_args(Pfct f, Pclass cl)
6797: /*
6798: This function is used to cope with the case where cl::cl(cl&) is
6799: declared AFTER f has been declared
6800: set n_xref bit for f
6801: */
6802: {
6803: for (Pname a = f->argtype; a; a = a->n_list) {
6804: Pname n = a->tp->is_cl_obj();
6805: if (n && Pclass(n->tp)==cl) a->n_xref = 1;
6806: }
6807: }
6808:
6809: Pname merge_conv(Pname c1, Pname c2)
6810: {
6811: if (c1 == 0) return c2;
6812: if (c2 == 0) return c1;
6813: if (c1 == c2) return c1;
6814: error('s',"cannot merge lists of conversion functions");
6815: return c1;
6816: }
6817:
6818: static Eppp;
6819:
6820: char* get_classname(char* s)
6821: /*
6822: retrieve the outermost class name in a vtable name
6823: */
6824: {
6825: //error('d',"get_classname(%s)",s);
6826: char* s1 = 0;
6827:
6828: while (*s) {
6829: s1 = s;
6830: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++);
6831: if (*s) s += 2; // bypass "__"
6832: }
6833:
6834: return s1;
6835: }
6836:
6837: char* drop_classname(char* s)
6838: /*
6839: retrieve all but the outermost class name in a vtable name
6840: */
6841: {
6842: //error('d',"drop_classname(%s)",s);
6843: char* r = new char[strlen(s)+1];
6844: sprintf(r,s);
6845: s = r;
6846:
6847: char* s1 = s;
6848: while (*s) {
6849: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++);
6850: if (*s) {
6851: s1 = s;
6852: s += 2; // bypass "__"
6853: }
6854: }
6855:
6856: *s1 = '\0';
6857:
6858: return (*r) ? r : 0;
6859: }
6860:
6861: Pbcl classdef::get_base( char *s )
6862: /*
6863: Find the base class whose name matches the argument
6864: */
6865: {
6866: //error('d',"%t::get_base(%s)",this,s);
6867: for (Pbcl b = baselist; b; b = b->next) {
6868: for ( char *s1 = s, *s2 = b->bclass->string;
6869: *s1 && *s2 && *s1 == *s2;
6870: s1++, s2++);
6871:
6872: if (!(*s1 || *s2))
6873: break;
6874: }
6875:
6876: return b;
6877: }
6878:
6879: int classdef::get_offset(char* s)
6880: /*
6881: Get offset represented by string as viewed from "this"
6882: */
6883: {
6884: //error('d',"%t::get_offset(%s)",this,s);
6885: if (!s) return 0;
6886:
6887: Pbcl b = get_base(get_classname(s));
6888:
6889: return b->obj_offset + b->bclass->get_offset(drop_classname(s));
6890: }
6891:
6892: char* vtbl_str(char* s1, char* s2)
6893: /*
6894: combine two pieces of a vtbl name
6895: */
6896: {
6897: //error('d',"vtbl_str(%s,%s)",s1,s2);
6898: char* s3;
6899: if (s1)
6900: if (s2) {
6901: s3 = new char[strlen(s1)+strlen(s2)+3];
6902: sprintf(s3,"%s__%s",s1,s2);
6903: return s3;
6904: }
6905: else
6906: return s1;
6907: else
6908: return s2;
6909: }
6910:
6911: void classdef::add_vtbl(velem* v, char* s, bit virt_flag, int n_init)
6912: /*
6913: add vtbl to virt_list
6914: */
6915: {
6916: // error('d',"%t->add_vtbl(%d,%s)",this,v,s);
6917: Pvirt vtab = new virt(this, v, s, virt_flag, n_init);
6918:
6919: if (virt_flag) has_vvtab = 1;
6920:
6921: if (!virt_list) {
6922: virt_list = vtab;
6923: return;
6924: }
6925:
6926: // If conficting vtable entries are made because of
6927: // a virtual base class, must be considered an error.
6928: for (Pvirt vt = virt_list; vt; vt = vt->next )
6929: // if (strcmp(vt->string,s)==0) {
6930: if (vt->string && strcmp(vt->string,s)==0) {
6931: velem* ivec = vt->virt_init;
6932: Pname on = ivec[0].n;
6933: Pname nn = v[0].n;
6934: Pclass ocl,ncl;
6935: for (int i=0; on && nn; i++,on=ivec[i].n,nn=v[i].n) {
6936: ocl = Pfct(on->tp)->memof;
6937: ncl = Pfct(nn->tp)->memof;
6938: if (on != nn)
6939: if (!ocl->has_base(ncl))
6940: if (!ncl->has_base(ocl))
6941: break;
6942: else {
6943: ivec[i].n = nn;
6944: ivec[i].offset = v[i].offset;
6945: }
6946: }
6947: if (on || nn)
6948: error("virtualB: ambiguous%n and%n", on, nn);
6949: return;
6950: }
6951:
6952: vtab->next = virt_list->next;
6953: virt_list->next = vtab;
6954: }
6955:
6956: static int Voffset; // cope with offsets of virtuals in deep nests
6957: int vcounter;
6958: static vmax;
6959: const vpChunk = 32;
6960:
6961: int classdef::do_virtuals(Pvirt vtab, char* str, int leftmost, bit virt_flag)
6962: /*
6963: make vtbl for b in "this"
6964: match up virtuals and assign virtual indices for the base or delegate "bcl"
6965: first base class shares ``this'' and vtbl with this class
6966: */
6967: {
6968: if (vmax<vcounter) vmax = vcounter;
6969: int vpsz = (vmax+vcounter)/vpChunk+1; // fragmentation prevention
6970: vpsz *= vpChunk;
6971: Pname* vp = new Pname[vpsz];
6972: velem* ivec = vtab ? vtab->virt_init : 0;
6973: int vo = Voffset;
6974: int vc = 0;
6975: int changed = 0;
6976:
6977: // error('d',"%t->do_virtuals(%d,%s) voffset %d",this,vtab,str,Voffset);
6978: // error('d',"virt_count %d vpsz %d vcounter %d",virt_count,vpsz,vcounter);
6979:
6980: if (ivec) { // vtbl replacement for ivec
6981:
6982: if (vtab->is_vbase) {
6983: str = 0;
6984: Voffset = get_offset(vtab->string);
6985: }
6986: else
6987: Voffset = Voffset + vtab->vclass->get_offset(vtab->string);
6988: Pname vn;
6989: for (int i=0; vn=ivec[i].n; i++) {
6990:
6991: /* go through virtual table's list of virtuals:
6992: first see if the function is simply inherited
6993: if not, check for a match
6994: if not, then add as new
6995: */
6996: // Pname vn = ivec[i];
6997: if ( i >= vpsz ) { // resize vp vector
6998: int tvpsz = vpsz + vpChunk;
6999: Pname *tvp = new Pname[ tvpsz ];
7000: for ( int j = 0; j < i; ++j )
7001: tvp[ j ] = vp[ j ];
7002: delete [vpsz] vp;
7003: vp = tvp;
7004: //error( 'd',"resizing: i: %d vpsz: %d tvpsz: %d", i, vpsz, tvpsz );
7005: vpsz = tvpsz;
7006: }
7007:
7008: // char* s = Pchar(vn->n_tbl_list);
7009: char* s = vn->n_gen_fct_name;
7010: Pname n = memtbl->look(s?s:vn->string, 0);
7011:
7012: // error('d',"vn %n %s n %n %d",vn,s,n,Voffset);
7013: // error('d',"n %n %k", n, n?n->base:0 );
7014: if (n == 0 || // FCT + FCT
7015: n->base == PUBLIC ) { // base::FCT
7016: inher: // inherit
7017: // if (vn->n_initializer) error("cannot inherit pure virtualF%n",vn);
7018: if (vn->n_initializer) c_abstract = 1;
7019: vp[i] = vn;
7020: if ( ivec[i].offset && vtab->is_vbase )
7021: vp[i]->n_offset = Voffset - vo;
7022: else
7023: vp[i]->n_offset = ivec[i].offset;
7024: continue;
7025: }
7026:
7027: Pfct f = Pfct(n->tp);
7028: // error ('d', "f %d", f );
7029: if (f == 0 ) continue;
7030: // error('d',"f %t %d",f,f->f_virtual);
7031:
7032: if (s && f->base==OVERLOAD) { // OVERLOAD + OVERLOAD
7033: // vn is overloaded and s is its name
7034: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l)
7035: if (gl->f == vn) goto inher;
7036: }
7037:
7038: Pfct vnf = Pfct(vn->tp);
7039: // re-define?
7040: switch (f->base) {
7041: default:
7042: error('w',&n->where,"%n hides virtual%n",n,vn);
7043: vp[i] = vn; // not a new overloaded: inherit
7044: if ( ivec[i].offset && vtab->is_vbase )
7045: vp[i]->n_offset = Voffset - vo;
7046: else
7047: vp[i]->n_offset = ivec[i].offset;
7048: break;
7049: case FCT: // derived::FCT
7050: {
7051: if (vnf->check(f,VIRTUAL) == 0) { // derived::FCT match base::FCT
7052: // error('d',"vnf1 %t f %t vcheck %d",vnf,f,Vcheckerror);
7053: // VTOK: virtual, but no index assigned
7054: // you can only inherit an index from your first base
7055: if (Vcheckerror) error("bad virtualT match for %n",vn);
7056: if (f->f_virtual==VTOK) f->f_virtual = i+1;
7057: vp[i] = n;
7058: vp[i]->n_offset = Voffset;
7059: changed = 1;
7060: }
7061: else {
7062: // error('d',"vnf2 %t f %t vcheck %d",vnf,f,Vcheckerror);
7063: if (Vcheckerror)
7064: error("bad virtualT match for %n",vn);
7065: else
7066: switch (f->f_virtual) {
7067: case 0:
7068: case VTOK:
7069: error('w',&n->where,"%n hides virtual%n",n,vn);
7070: }
7071: vp[i] = vn; // not a new overloaded: inherit
7072: if ( ivec[i].offset && vtab->is_vbase )
7073: vp[i]->n_offset = Voffset - vo;
7074: else
7075: vp[i]->n_offset = ivec[i].offset;
7076: }
7077: break;
7078: }
7079: case OVERLOAD: // derived::OVERLOAD
7080: {
7081: int hit = 0;
7082: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
7083: // try each fct from derived class
7084: Pname fn = gl->f;
7085: Pfct f = Pfct(fn->tp);
7086:
7087: if (f->check(vnf,VIRTUAL) == 0) { // derived::FCT
7088: if (Vcheckerror) error("bad virtualT match for %n",vn);
7089: if (f->f_virtual==VTOK) f->f_virtual = i+1;
7090: vp[i] = fn;
7091: vp[i]->n_offset = Voffset;
7092: changed = 1;
7093: goto found;
7094: }
7095: else {
7096: if (Vcheckerror) error("bad virtualT match for %n",vn);
7097: }
7098: if (Vcheckerror == 0)
7099: switch (f->f_virtual) {
7100: case 0:
7101: case VTOK:
7102: hit = 1;
7103: }
7104:
7105: }
7106:
7107: if (hit)
7108: error('w',&n->where,"%n hides virtual%n ofT %t",n,vn,vn->tp);
7109:
7110: vp[i] = vn; // not a new overloaded: inherit
7111: if ( ivec[i].offset && vtab->is_vbase )
7112: vp[i]->n_offset = Voffset - vo;
7113: else
7114: vp[i]->n_offset = ivec[i].offset;
7115: found:
7116: break;
7117: }
7118: }
7119: }
7120:
7121: Voffset = vo;
7122: vc = i;
7123: }
7124:
7125: // error( 'd', "do_virtuals: out of loop: vc: %d vpsz: %d changed: %d", vc, vpsz,changed );
7126:
7127: if (leftmost) {
7128: /*
7129: add new virtuals:
7130: `VTOK' marks ``new virtual, no index assigned''.
7131: You can only be new once (no base or first base).
7132: */
7133: int i;
7134: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
7135: Pfct f = Pfct(nn->tp);
7136:
7137: if ( vc >= vpsz ) { // resize vp vector
7138: int tvpsz = vpsz + vpChunk;
7139: Pname *tvp = new Pname[ tvpsz ];
7140: for ( int j = 0; j < vc; ++j )
7141: tvp[ j ] = vp[ j ];
7142: delete [vpsz] vp;
7143: vp = tvp;
7144: vpsz = tvpsz;
7145: }
7146:
7147: // error('d',"f %n %t",nn,f);
7148: if (f)
7149: switch (f->base) {
7150: case FCT:
7151: //error('d',"fv %d",f->f_virtual);
7152: if (f->f_virtual == VTOK) {
7153: // declared virtual, or
7154: // virtual in some base
7155: f->f_virtual = ++vc;
7156: vp[f->f_virtual-1] = nn;
7157: vp[f->f_virtual-1]->n_offset = 0;
7158: f->f_vdef = 1;
7159: changed = 2;
7160: }
7161: break;
7162: case OVERLOAD:
7163: { for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
7164: Pname fn = gl->f;
7165: Pfct f = Pfct(fn->tp);
7166:
7167:
7168: if ( vc >= vpsz ) { // resize vp vector
7169: int tvpsz = vpsz + vpChunk;
7170: Pname *tvp = new Pname[ tvpsz ];
7171: for ( int j = 0; j < vc; ++j ) {
7172: tvp[ j ] = vp[ j ];
7173: }
7174: delete [vpsz] vp;
7175: vp = tvp;
7176: vpsz = tvpsz;
7177: }
7178:
7179:
7180: if (f->f_virtual == VTOK) {
7181: f->f_virtual = ++vc;
7182: vp[f->f_virtual-1] = fn;
7183: vp[f->f_virtual-1]->n_offset = 0;
7184: f->f_vdef = 1;
7185: changed = 2;
7186: }
7187: }
7188: break;
7189: }
7190: }
7191: }
7192: // error('d',"%s changed %d has_vvtab %d",string,changed,has_vvtab);
7193: // error('d',"vc %d vpsz %d",vc,vpsz);
7194: virt_count = 0;
7195: if (changed)
7196: virt_count = vc;
7197: else if (has_vvtab) {
7198: virt_merge = 1;
7199: if (vc && vtab->is_vbase)
7200: leftmost = 0;
7201: }
7202: }
7203:
7204: // error('d',"vc %d ch %d vp[%d] virt_count %d",vc,changed,vpsz,virt_count);
7205: if (changed || !leftmost) {
7206: // vc==0 if all explicit virtuals in fact were declared in base
7207: velem* v = new velem[vc+1];
7208:
7209: for (int i=0; i<vc; i++) {
7210: v[i].n = vp[i];
7211: v[i].offset = vp[i]->n_offset;
7212: }
7213: v[vc].n = 0;
7214:
7215: if (leftmost)
7216: add_vtbl(v,0,0,0);
7217: else
7218: add_vtbl(v,vtbl_str(vtab->string,str),virt_flag||vtab->is_vbase,vc+1);
7219: delete vp;
7220: vcounter = 0;
7221: return 1;
7222: }
7223:
7224: delete vp;
7225: vcounter = 0;
7226: return 0;
7227: }
7228:
7229: int classdef::all_virt(Pclass bcl, char* s, int leftmost, bit virt_flag)
7230: {
7231: int i = 0;
7232: if (bcl->virt_count) {
7233: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
7234: // if (has_base(blist->vclass))
7235: // if (blist->vclass==bcl
7236: // // bcl is virtual in both
7237: // || ((Nvirt=0,blist->vclass->has_base(bcl)) && Nvirt==VIRTUAL
7238: // && (Nvirt=0,has_base(bcl)) && Nvirt==VIRTUAL
7239: // )
7240: // )
7241: if (virt_merge && !(virt_flag || blist->is_vbase))
7242: continue;
7243:
7244: i += do_virtuals(blist, s, leftmost, virt_flag);
7245: if (!i && leftmost && !virt_merge)
7246: return 0;
7247:
7248: leftmost = 0;
7249: }
7250: }
7251:
7252: // finding virt_list stops recursive step
7253: // if vtables found and updated, return number
7254: if (i) return i;
7255:
7256: for (Pbcl b = bcl->baselist; b; b = b->next) {
7257: // if (b->base==PTR) continue;
7258: if (b->promoted) continue;
7259: // error('d',"b %t vl %d bl %d",b->bclass,b->bclass->virt_list,b->bclass->baselist);
7260: if (leftmost && b->base == VIRTUAL) {
7261: i += do_virtuals(0, 0, 1, 0);
7262: if (!i && !virt_merge)
7263: return 0;
7264: leftmost = 0;
7265: }
7266: int vo = Voffset;
7267: Voffset += b->obj_offset;
7268: // error('d',"offset %t %d",b->bclass,Voffset);
7269:
7270: if (b->base==VIRTUAL)
7271: i += all_virt(b->bclass, b->bclass->string, leftmost, 1);
7272: else
7273: i += all_virt(b->bclass, vtbl_str(b->bclass->string,s), leftmost, virt_flag);
7274: if (!i && leftmost && !virt_merge)
7275: return 0;
7276:
7277: Voffset = vo;
7278: leftmost = 0;
7279: }
7280:
7281: // if recursion updated vtables, return number
7282: if (i) return i;
7283:
7284: // no vtables updated in recursion
7285: // look for new virtuals
7286: if (leftmost)
7287: return do_virtuals(0, 0, 1, 0);
7288: else
7289: return 0;
7290: }
7291:
7292: Pexpr copy_obj(Pexpr l, Pexpr r, int sz)
7293: /*
7294: generate:
7295: struct _s { char[sz]; };
7296: *(struct _s*)this->m = *(struct _s*)arg.mem;
7297: */
7298: {
7299: if ( !sz ) sz = 1;
7300: //error('d',"copy(%d)",sz);
7301: char* s = make_name('S');
7302: fprintf(out_file,"struct %s { char v[%d]; };\n",s,sz);
7303: Pname n = new name(s);
7304: Ptype t = new basetype(COBJ,n);
7305: t = new ptr(PTR,t);
7306:
7307: l = new texpr(CAST,t,l);//new cast(t,l);
7308: l = l->contents();
7309:
7310: r = new texpr(CAST,t,r);//new cast(t,r);
7311: r = r->contents();
7312:
7313: return new expr(ASSIGN,l,r);
7314: }
7315:
7316: /*
7317: Pname make_default_ctor(Pclass cl)
7318: {
7319: //error('d',"make_ctor %t",cl);
7320: Pname cn = ktbl->look(cl->string,0);
7321: if (cn) cn = Pbase(cn->tp)->b_name;
7322: cc->stack();
7323: cc->not = cn;
7324: cc->cot = cl;
7325: Pname fn = new name(cl->string);
7326: Pfct f = new fct(defa_type,0,1);
7327: fn->tp = f;
7328: fn->n_oper = TNAME;
7329: // fn->n_sto = STATIC;
7330:
7331: Pfct(f)->f_inline = 1;
7332: f->body = new block(curloc,0,0);
7333:
7334: Pname nn = fn->dcl(cl->memtbl,PUBLIC);
7335: delete fn;
7336:
7337: cc->unstack();
7338: nn->simpl();
7339: if (debug_opt) nn->dcl_print(0);
7340: //error('d',"make_ctor->");
7341: return nn;
7342: }
7343:
7344: Pname make_default_dtor(Pclass cl)
7345: {
7346: //error('d',"make_dtor %t",cl);
7347: Pname cn = ktbl->look(cl->string,0);
7348: if (cn) cn = Pbase(cn->tp)->b_name;
7349: cc->stack();
7350: cc->not = cn;
7351: cc->cot = cl;
7352: Pname fn = new name(cl->string);
7353: Pfct f = new fct(defa_type,0,1);
7354: fn->tp = f;
7355: fn->n_oper = DTOR;
7356: // fn->n_sto = STATIC;
7357:
7358: Pfct(f)->f_inline = 1;
7359: f->body = new block(curloc,0,0);
7360:
7361: Pname nn = fn->dcl(cl->memtbl,PUBLIC);
7362: delete fn;
7363:
7364: cc->unstack();
7365: nn->simpl();
7366: if (debug_opt) nn->dcl_print(0);
7367: //error('d',"make_dtor->");
7368: return nn;
7369: }
7370: */
7371:
7372: Ptype find_arg_type(Pclass cl)
7373: // first determine argument type
7374: {
7375: int i;
7376: int mod = 0;
7377: for (Pbcl b = cl->baselist; b; b = b->next) {
7378: Pclass bcl = b->bclass;
7379: switch (b->base) {
7380: case VIRTUAL:
7381: case NAME: // generate :b(*(b*)&arg)
7382: {
7383: Pname itor = bcl->has_itor();
7384: if (itor && itor->tp->base==FCT) {
7385: Pname a = Pfct(itor->tp)->argtype;
7386: Pptr p = a->tp->is_ref();
7387: if (p && p->typ->tconst()==0) {
7388: mod = 1;
7389: goto ll1;
7390: }
7391: }
7392: }
7393: }
7394: }
7395: ll1:
7396: if (mod == 0) {
7397: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) {
7398: Pname cln;
7399: // ignore static members
7400: if (m->n_evaluated || m->n_stclass==STATIC) continue;
7401:
7402: if (cln = m->tp->is_cl_obj()) {
7403: Pname itor = Pclass(cln->tp)->has_itor();
7404: if (itor && itor->tp->base==FCT) {
7405: Pname a = Pfct(itor->tp)->argtype;
7406: Pptr p = a->tp->is_ref();
7407: if (p && p->typ->tconst()==0) {
7408: mod = 1;
7409: goto ll2;
7410: }
7411: }
7412: }
7413: }
7414: }
7415: ll2:
7416: //error('d',"mod %d",mod);
7417: Pbase bp = new basetype(INT,0);
7418: *bp = *Pbase(Pptr(cl->this_type)->typ);
7419: if (mod == 0) bp->b_const = 1;
7420: return new ptr(RPTR,bp);
7421: }
7422:
7423: Pname classdef::make_itor(int def)
7424: /*
7425: make cn::cn(const cn&) :bases_and_members_of_cn {}
7426: */
7427: {
7428: //error('d',"%t->make_itor(%d) %d",this,def,obj_size);
7429: Pstmt s;
7430: Pname e;
7431: int i;
7432: Pname arg = new name(make_name('A'));
7433: arg->tp = find_arg_type(this);
7434:
7435: // c_xref = 2; // now it has X(X&)
7436: c_xref |= C_XREF; // now it has X(X&)
7437:
7438: if (def) {
7439: // define itor
7440: int slow = 0; // slow==0 => copy using vector copy
7441: int first = 1;
7442: Pexpr es = 0;
7443: s = new estmt(SM,no_where,0,0);
7444: e = 0;
7445:
7446:
7447: if (warning_opt && 128<obj_size)
7448: error('w',"copying a %d byte object (ofC %s)",obj_size,string);
7449:
7450: if (baselist) slow = 1;
7451:
7452: //for (Pbcl v = baselist; v; v = v->next)
7453: // if (v->base == VIRTUAL) {
7454: // slow = 1;
7455: // break;
7456: // }
7457:
7458: // initialize bases:
7459: if (slow) {
7460: for (Pbcl b = baselist; b; b = b->next) {
7461: Pclass bcl = b->bclass;
7462: Ptype pt = bcl->this_type;
7463: //error('d',"base %t %k offset %d ptroffset %d",bcl,b->base,b->obj_offset,b->ptr_offset);
7464: switch (b->base) {
7465: case VIRTUAL:
7466: case NAME: // generate :b(*(b*)&arg)
7467: {
7468: Pexpr b2 = new name(arg->string);
7469: b2 = b2->address();
7470: b2 = new texpr(CAST,pt,b2);//new cast(pt,b2);
7471: b2->i2 = 1;
7472: b2 = b2->contents();
7473:
7474: Pname ee = new name(bcl->string);
7475: ee->base = TNAME;
7476: ee->n_initializer = b2;
7477: if (e) ee->n_list = e;
7478: e = ee;
7479: break;
7480: }
7481: }
7482: }
7483: }
7484:
7485: // initialize members
7486: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
7487: // ignore static members
7488: if (m->n_evaluated || m->n_stclass==STATIC) continue;
7489:
7490: if (strcmp(m->string,"__vptr")==0) {
7491: // error('d',"%t vptr: %d",this,first);
7492: if (first==0 && m->n_offset) {
7493: Pexpr th = new expr(THIS,0,0);
7494: Pexpr a = new name(arg->string);
7495: a = a->address();
7496: Pexpr ee = copy_obj(th,a,m->n_offset);
7497: es = es ? new expr(CM,es,ee) : ee;
7498: }
7499: slow = 1;
7500: first = 0;
7501: continue;
7502: }
7503: Ptype mt = m->tp;
7504: tx:
7505: switch (mt->base) {
7506: case TYPE:
7507: mt = Pbase(mt)->b_name->tp;
7508: goto tx;
7509: case VEC:
7510: { Pname cn = Pvec(mt)->typ->is_cl_obj();
7511: //error('d',"vec %n %t xref %d",m,mt,cn?Pclass(cn->tp)->c_xref:0);
7512: if (cn && Pclass(cn->tp)->c_xref&(C_XREF|C_VBASE)) {
7513: error('s',"copy of %n[], no memberwise copy for%n",cn,cn);
7514: slow = 1; // make sure an assignment operator
7515: // is generated so that there will
7516: // be no more error messages
7517: }
7518:
7519: if (slow && mt->tsizeof()) {
7520: /*
7521: generate:
7522: struct _s { char[sizeof(m)]; };
7523: *(struct _s*)this->m = *(struct _s*)arg.mem;
7524: */
7525: Pexpr l = new name(m->string);
7526: Pexpr r = new name(m->string);
7527: r = new ref(DOT,new name(arg->string),r);
7528: Pexpr ee = copy_obj(l,r,mt->tsizeof());
7529: es = es ? new expr(CM,es,ee) : ee;
7530: break;
7531: }
7532: }
7533: case FCT:
7534: case OVERLOAD:
7535: case CLASS:
7536: case ENUM:
7537: break;
7538: case COBJ:
7539: { Pclass mcl = Pclass(Pbase(mt)->b_name->tp);
7540: if (slow==0 // if slow, previous members have
7541: // already been copied
7542: && mcl->c_xref&(C_VBASE|C_XREF)) {
7543: slow = 1;
7544: if (first==0 && m->n_offset) {
7545: //AAA copy up to here
7546: Pexpr th = new expr(THIS,0,0);
7547: Pexpr a = new name(arg->string);
7548: a = a->address();
7549: Pexpr ee = copy_obj(th,a,m->n_offset);
7550: es = es ? new expr(CM,es,ee) : ee;
7551: }
7552: }
7553: // no break
7554: }
7555:
7556: default:
7557: if (slow) {
7558: //error('d',"slow %s %s",m->string,arg->string);
7559: Pname ee = new name(m->string);
7560: ee->n_initializer = new ref(DOT,new name(arg->string),new name(m->string));
7561: if (e) ee->n_list = e;
7562: e = ee;
7563: }
7564: }
7565: first = 0;
7566: }
7567:
7568: if (slow == 0) {
7569: /* really simple just copy:
7570: the only problem was a vptr which can be
7571: ignored since X(X&) is going to reset it anyway
7572: don't use assignment of this struct to avoid operator=
7573: */
7574: Pexpr th = new expr(THIS,0,0);
7575: Pexpr a = new name(arg->string);
7576: a = a->address();
7577: Pexpr ee = copy_obj(th,a,obj_size);
7578: es = es ? new expr(CM,es,ee) : ee;
7579: }
7580:
7581: s->e = es;
7582: Pname cn = ktbl->look(string,0);
7583: if (cn) cn = Pbase(cn->tp)->b_name;
7584: cc->stack();
7585: cc->not = cn;
7586: cc->cot = this;
7587: }
7588: Pname fn = new name(string);
7589: Pfct f = new fct(defa_type,arg,1);
7590: fn->tp = f;
7591: fn->n_oper = TNAME;
7592: // fn->n_sto = STATIC;
7593:
7594: Pfct(f)->f_inline = def?1:ITOR; // ITOR means ``define itor() if used''
7595: if (def) {
7596: f->body = new block(curloc,0,s);
7597: f->f_init = e;
7598: }
7599:
7600: Pname nn = fn->dcl(memtbl,PUBLIC);
7601: delete fn;
7602:
7603: if (def) {
7604: cc->unstack();
7605: nn->simpl();
7606: if (debug_opt) nn->dcl_print(0);
7607: }
7608: //error('d',"make_itor->");
7609: return nn;
7610: }
7611:
7612: int make_assignment(Pname cn)
7613: /*
7614: write the function:
7615:
7616: X& X::operator=(const X&) { assign all bases and members }
7617:
7618: return 1 is a function is really synthesized
7619: */
7620: {
7621: Pclass cl = Pclass(cn->tp);
7622: Pstmt s = new estmt(SM,no_where,0,0);
7623: Pexpr e = 0;
7624: Pname arg = new name(make_name('A'));
7625: basetype* bp = new basetype(INT,0);
7626: *bp = *Pbase(Pptr(cl->this_type)->typ);
7627: bp->b_const = 1;
7628: // arg->tp = new ptr(RPTR,bp);
7629: arg->tp = find_arg_type(cl);
7630: //error('d',"make_assignment %t %d",cl,cl->obj_size);
7631: // cl->c_xref |= 4; // now it has X::operator=(const X&)
7632:
7633: if (warning_opt && 128<cl->obj_size)
7634: error('w',"copying a %d byte object (ofC %s)",
7635: cl->obj_size,cl->string);
7636: {
7637: int slow = 0; // slow==0 => copy using vector copy
7638: int first = 1; // first==1 => first member of (derived) class
7639:
7640: if (cl->baselist) slow = 1; // be dumb and safe
7641: // for (Pbcl v = cl->baselist; v; v = v->next)
7642: // if (v->base==VIRTUAL || v->c_xref&(C_VBASE|C_ASS)) {
7643: // slow = 1;
7644: // break;
7645: // }
7646:
7647: if (slow) {
7648: for (Pbcl b = cl->baselist; b; b = b->next) {
7649: Pclass bcl = b->bclass;
7650: Ptype pt = bcl->this_type;
7651: switch (b->base) {
7652: case NAME:
7653: { // generate: *(bcl*)this = *(bcl*)&arg;
7654: //error('d',"base %t",bcl);
7655: Pexpr b1 = new expr(THIS,0,0);
7656: b1 = new texpr(CAST,pt,b1);
7657: b1 = b1->contents();
7658:
7659: Pexpr b2 = new name(arg->string);
7660: b2 = b2->address();
7661: b2 = new texpr(CAST,pt,b2);
7662: b2->i2 = 1;
7663: b2 = b2->contents();
7664:
7665: Pexpr ee = new expr(ASSIGN,b1,b2);
7666: e = e ? new expr(CM,e,ee) : ee;
7667: break;
7668: }
7669: case VIRTUAL:
7670: if (warning_opt)
7671: error('w',"copying an object ofC%n with a virtualBC",cn);
7672: if (b->ptr_offset) {
7673: // copy object, but not pointer
7674: // generate: *(bcl*)this->Pw = *(bcl*)arg->Pw;
7675:
7676: // I don't know how to avoid copying the object
7677: // once for each pointer
7678:
7679: Pexpr b1 = new expr(THIS,0,0);
7680: b1 = new mdot(bcl->string,b1);
7681: b1->i1 = 3;
7682: b1->tp = pt;
7683: b1 = new expr(DEREF,b1,0);//b1->contents();
7684:
7685: Pexpr b2 = new name(arg->string);
7686: b2 = b2->address();
7687: b2 = new mdot(bcl->string,b2);
7688: b2->i1 = 3;
7689: b2->tp = pt;
7690: b2 = new expr(DEREF,b2,0);//b2->contents();
7691:
7692: Pexpr ee = new expr(ASSIGN,b1,b2);
7693: e = e ? new expr(CM,e,ee) : ee;
7694: }
7695: break;
7696: }
7697: }
7698: }
7699:
7700: int i;
7701: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) {
7702: // ignore static members
7703: if (m->n_evaluated || m->n_stclass==STATIC) continue;
7704:
7705: if (strcmp(m->string,"__vptr")==0) { // don't copy vptrs
7706: // we may be copying
7707: // into a base class object
7708: if (first==0 && m->n_offset) {
7709: // copy up to (but not including) vptr
7710: // don't copy if first member
7711: Pexpr th = new expr(THIS,0,0);
7712: Pexpr a = new name(arg->string);
7713: a = a->address();
7714: Pexpr ee = copy_obj(th,a,m->n_offset);
7715: e = e ? new expr(CM,e,ee) : ee;
7716: }
7717: slow = 1;
7718: first = 0;
7719: continue;
7720: }
7721: Ptype mt = m->tp;
7722: tx:
7723: switch (mt->base) {
7724: case TYPE:
7725: mt = Pbase(mt)->b_name->tp;
7726: goto tx;
7727: case VEC:
7728: { Pname cn = Pvec(mt)->typ->is_cl_obj();
7729: if (cn && Pclass(cn->tp)->c_xref&(C_ASS|C_VBASE)) {
7730: error('s',"copy of %n[], no memberwise copy for%n",cn,cn);
7731: slow = 1; // make sure an assignment operator
7732: // is generated so that there will
7733: // be no more error messages
7734: }
7735:
7736: if (slow && mt->tsizeof()) {
7737: // protect against sizeof(mt)==0: char[]
7738: /*
7739: generate:
7740: struct _s { char[sizeof(m)]; };
7741: *(struct _s*)this->m = *(struct _s*)arg.mem;
7742: */
7743: Pexpr l = new name(m->string);
7744: Pexpr r = new name(m->string);
7745: r = new ref(DOT,new name(arg->string),r);
7746: Pexpr ee = copy_obj(l,r,mt->tsizeof());
7747: e = e ? new expr(CM,e,ee) : ee;
7748: break;
7749: }
7750: }
7751: case FCT:
7752: case OVERLOAD:
7753: case CLASS:
7754: case ENUM:
7755: break;
7756: case RPTR:
7757: error("cannot assignC%t:RM%n",cl,m);
7758: break;
7759: case COBJ:
7760: //error('d',"cobj %n %d %d",m,slow,Pclass(Pbase(mt)->b_name->tp)->c_xref);
7761: if (slow==0
7762: && Pclass(Pbase(mt)->b_name->tp)->c_xref&(C_VBASE|C_ASS)) {
7763: // must use its assignment operation
7764: if (first==0 && m->n_offset) {
7765: // copy up to this member
7766: Pexpr th = new expr(THIS,0,0);
7767: Pexpr a = new name(arg->string);
7768: a = a->address();
7769: e = copy_obj(th,a,m->n_offset);
7770: }
7771: slow = 1;
7772: }
7773: // no break: copy cobj itself
7774: default:
7775: //error('d',"defa %n %d",m,slow);
7776: if (slow) {
7777: if (m->tp->tconst()) error("cannot assignC%t: const M%n",cl,m);
7778: Pname ms = new name(m->string);
7779: Pname as = new name(arg->string);
7780: Pexpr ee = new ref(DOT,as,new name(m->string));
7781: ee = new expr(ASSIGN,ms,ee);
7782: e = e ? new expr(CM,e,ee) : ee;
7783: }
7784: }
7785: first = 0;
7786: }
7787:
7788: if (slow == 0) {
7789: /* really simple just copy:
7790: */
7791: //error('d',"slow");
7792: /*
7793: Pexpr th = new expr(THIS,0,0);
7794: Pexpr a = new name(arg->string);
7795: a = a->address();
7796: Pexpr ee = copy_obj(th,a,cl->tsize());
7797: e = e ? new expr(CM,e,ee) : e;
7798: */
7799: //error('d',"%n simple assignment",cn);
7800: // cl->c_xref ^= C_ASS; // Didn't mean it: No X::operator=(X&)
7801: return 0;
7802: }
7803:
7804: }
7805:
7806: Pexpr rv = new expr(THIS,0,0);
7807: rv = new expr(DEREF,rv,0);//b1->contents();
7808:
7809: s->e = e ? new expr(CM,e,rv) : e;
7810: s->s_list = new estmt(RETURN,no_where,rv,0);
7811:
7812: cc->stack();
7813: cc->not = cn;
7814: cc->cot = cl;
7815:
7816: cl->c_xref |= C_ASS; // now it has X::operator=(const X&)
7817:
7818: Pname fn = new name(oper_name(ASSIGN));
7819: Pfct f = new fct(new ptr(RPTR,Pptr(cl->this_type)->typ),arg,1);
7820: f->f_inline = 1;
7821: fn->tp = f;
7822: fn->n_oper = ASSIGN;
7823: fn->n_sto = STATIC;
7824: Pname nn = fn->dcl(cl->memtbl,PUBLIC);
7825: delete fn;
7826: Pfct(nn->tp)->body = new block(curloc,0,s);
7827: Pfct(nn->tp)->dcl(nn);
7828:
7829: cc->unstack();
7830: nn->simpl();
7831: //error('d',"make_assign->");
7832: return 1;
7833: }
7834:
7835: void classdef::dcl(Pname cname, Ptable tbl)
7836: {
7837: int bvirt = 0;
7838: int dvirt = 0;
7839: int scope = PUBLIC;
7840: int protect = 0;
7841: int st = 1; // nothing private or protected seen: a struct
7842: // int nstd = (in_class && nested_sig)?2:(in_class?1:0); // nested class
7843:
7844: int byte_old = byte_offset;
7845: int bit_old = bit_offset;
7846: int max_old = max_align;
7847: int boff = 0;
7848:
7849: int in_union = 0;
7850: int usz;
7851: int make_ctor = 0;
7852: int make_dtor = 0;
7853:
7854: /* this is the place for paranoia */
7855: if (this == 0) error('i',"0->Cdef::dcl(%p)",tbl);
7856: if (base != CLASS) error('i',"Cdef::dcl(%d)",base);
7857: if (cname == 0) error('i',"unNdC");
7858: if (cname->tp != this) error('i',"badCdef");
7859: if (tbl == 0) error('i',"Cdef::dcl(%n,0)",cname);
7860: if (tbl->base != TABLE) error('i',"Cdef::dcl(%n,tbl=%d)",cname,tbl->base);
7861: DB( if(Ddebug>=1) error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl); );
7862: // error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl);
7863:
7864: switch (csu) {
7865: case UNION:
7866: in_union = UNION;
7867: break;
7868: case ANON:
7869: in_union = ANON;
7870: break;
7871: case CLASS:
7872: scope = 0;
7873: }
7874:
7875: max_align = AL_STRUCT;
7876:
7877: if (lex_level) {
7878: // error('d',&cname->where,"%t::dcl in_class: %t lex_level %d ",this,in_class, lex_level);
7879: if ( in_class )
7880: lex_level = 0;
7881: else {
7882: in_fct = cc->nof;
7883: if ( lcl == 0 ) lcl = make_name( 'L' );
7884: }
7885: }
7886:
7887: if (strlen == 0) strlen = ::strlen(string);
7888: if (baselist) {
7889: /*
7890: check base classes.
7891: duplicates were removed in start_cl() in norm.c.
7892: remove bad classes.
7893: add virtual bases from bases to the list.
7894:
7895: check against
7896: class b : a {}
7897: class c : a, b {} // first a inaccessible
7898: */
7899:
7900: Pbcl ll = 0;
7901: Pbcl lll = 0;
7902: Pbcl vlist = 0;
7903: for (Pbcl lx, l=baselist; l; l=lx) { // remove bad bases
7904: Pclass cl = l->bclass;
7905: /* restriction lifted: nested and local classes
7906: int b_nstd = (cl->in_class && cl->nested_sig)
7907: ?2:(cl->in_class?1:0);
7908:
7909: if (b_nstd)
7910: error((b_nstd==2)?0:'w',"%s derived from nestedC %s", string, cl->string);
7911: if (cl->lex_level)
7912: error('w',"%s derived from localC %s", string, cl->string);
7913: */
7914:
7915: lx = l->next;
7916:
7917: //error('d',"base1 %t %k init %d",cl,l->ppp,l->init);
7918: // ``class'' => private base ``struct'' => public base
7919: if (l->ppp == 0) {
7920: l->ppp = csu==CLASS ? PRIVATE : PUBLIC;
7921: #ifndef OLD
7922: if (l->ppp == PRIVATE) error('w',"B%t private by default: please be explicit ``: private%t",cl,cl);
7923: #endif
7924: }
7925: // if you have a ``class'' as base you cannot remain a
7926: // ``mere struct''
7927: if (cl && cl->csu == CLASS) st = 0;
7928:
7929: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
7930: error("BC %sU",cl->string);
7931: continue;
7932: }
7933: else
7934: (void)cl->tsizeof(); // ensure printout
7935:
7936: if (cl->csu==UNION || cl->csu==ANON) {
7937: error("C derived from union");
7938: continue;
7939: }
7940:
7941: if (in_union) {
7942: error("derived union");
7943: continue;
7944: }
7945:
7946: if (l->base==VIRTUAL) {
7947: // constraint removed ...
7948: // if (cl->has_ictor()==0 && cl->has_ctor()) {
7949: // error("virtualB%t has no defaultIr",cl);
7950: // continue;
7951: // }
7952: // order of virtual classes doesn't matter
7953: l->next = vlist;
7954: vlist = l;
7955: }
7956: else { // keep ordinary base classes in order
7957: if (ll == 0) {
7958: lll = l;
7959: l->next = 0;
7960: }
7961: else
7962: ll->next = l;
7963: ll = l;
7964: }
7965: }
7966: if (ll) {
7967: ll->next = vlist; // put virtual bases at end
7968: baselist = lll;
7969: }
7970: else
7971: baselist = vlist;
7972:
7973: lll = 0;
7974: for (l=baselist; l; l=l->next) { // detect unmanageable duplicates
7975: Pclass b = l->bclass;
7976: for (ll=baselist; ll; ll=ll->next)
7977: if (b!=ll->bclass && ll->bclass->check_dup(b,l->base)) {
7978: if (lll)
7979: lll->next = l->next;
7980: else
7981: baselist = l->next;
7982: goto mmm;
7983: }
7984:
7985: lll = l;
7986: mmm:;
7987: }
7988:
7989: for (l=baselist; l; l=l->next) { // promote virtual bases
7990: Pclass b = l->bclass;
7991: for (ll=b->baselist; ll; ll=ll->next) {
7992: if (ll->base == VIRTUAL) {
7993: Pclass v = ll->bclass;
7994: for (Pbcl lll=baselist; lll; lll=lll->next)
7995: if (lll->bclass == v) goto nnn;
7996: // error('w',"%t is virtualB of%t",v,this);
7997: baselist = new basecl(v,baselist);
7998: baselist->base = VIRTUAL;
7999: baselist->promoted = 1;
8000: // needs a more complete check of visibility rules
8001: //error('d',"promote %t %k",v,ll->ppp);
8002: baselist->ppp = ll->ppp;
8003: }
8004: nnn:;
8005: }
8006: }
8007:
8008: ll = 0;
8009: lll = 0;
8010: l=baselist;
8011: baselist = 0;
8012: vlist = 0;
8013: for (; l; l=lx) {
8014: // sort virtual bases so that no virtual base
8015: // is ahead of its own virtual base
8016: lx = l->next;
8017: if (l->base == VIRTUAL) { // add to sorted vlist
8018: // each class before its bases
8019: if (vlist == 0) {
8020: vlist = l;
8021: l->next = 0;
8022: }
8023: else {
8024: Pclass lb = l->bclass;
8025: Pbcl v_prev = 0;
8026: for (Pbcl vx, v = vlist; v; v=vx) {
8027: Pclass vb = v->bclass;
8028: vx = v->next;
8029:
8030: if (lb->has_base(vb)) {
8031: // put l ahead of v
8032: l->next = v;
8033: if (v_prev)
8034: v_prev->next = l;
8035: else
8036: vlist = l;
8037: break;
8038: }
8039: if (vx == 0) {
8040: // stick l at end
8041: v->next = l;
8042: l->next = 0;
8043: break;
8044: }
8045: v_prev = v;
8046: }
8047: }
8048: }
8049: else { // keep in order
8050: if (ll == 0) {
8051: lll = l;
8052: l->next = 0;
8053: }
8054: else
8055: ll->next = l;
8056: ll = l;
8057: }
8058: }
8059:
8060: if (ll) {
8061: ll->next = vlist; // put virtual bases at end
8062: baselist = lll;
8063: }
8064: else
8065: baselist = vlist;
8066:
8067: for (l=baselist; l; l=l->next) { // allocate base class objects
8068: Pclass cl = l->bclass;
8069: //error('d',"base %t %k init %d",cl,l->ppp,l->init);
8070: if (l->base == VIRTUAL) { // : virtual bclass
8071: // pointer and object for virtual base MAY
8072: // be allocated at the end - but not here
8073: c_xref |= C_VBASE;
8074: dvirt += cl->virt_count;
8075: }
8076: else { // : bclass =>allocate
8077: int ba = cl->align();
8078: if (max_align<ba) max_align = ba;
8079:
8080: if (cl == baselist->bclass) {
8081: // pad to ensure alignment:
8082: boff = cl->real_size;
8083: // not obj_size-real_size, we can
8084: // optimize vbase object away
8085: int xtra = boff%ba;
8086: // align
8087: if (xtra) boff += ba-xtra;
8088: }
8089: else { // let C handle the padding:
8090: int xtra = boff%ba;
8091: if (xtra) boff += ba-xtra; // align
8092: l->obj_offset = boff;
8093: // don't use waste
8094: boff += cl->obj_size;
8095: }
8096: bvirt += cl->virt_count;
8097: }
8098:
8099: if (cl->has_vvtab) has_vvtab = 1;
8100: c_xref |= cl->c_xref;
8101:
8102: //error('d',"%t: base %t conv %d base conv %d",this,cl,conv,cl->conv);
8103: conv = merge_conv(conv,cl->conv);
8104: }
8105: }
8106:
8107: memtbl->set_name(cname);
8108:
8109: // int nmem = mem_list->no_of_names();
8110: int nmem = 0;
8111: int fct_mem = 0;
8112: { for (Pname m = mem_list; m; m=m->n_list) {
8113: nmem++;
8114: if (m->tp && m->tp->base==FCT) fct_mem++;
8115: }
8116: }
8117: if (nmem) memtbl->grow((nmem<=2)?3:nmem);
8118:
8119: cc->stack();
8120: cc->not = cname;
8121: cc->cot = this;
8122:
8123: byte_offset = usz = boff;
8124: bit_offset = 0;
8125:
8126: int real_virts = 0;
8127: Pbase bt = new basetype(COBJ,cname);
8128: bt->b_table = memtbl;
8129: Ptype cct = bt->addrof();
8130: // for strict opt type of `this': X *const
8131: // '2' distinguishes this case from a real constant object
8132: if (strict_opt) Pptr(cct)->rdo = 2;
8133: this_type = cc->tot = cct;
8134: PERM(cct);
8135: PERM(bt);
8136:
8137: for (Pname px, p=mem_list; p; p=px) {
8138: /*
8139: look at each member;
8140: declare it and determine its visibility
8141: calculate offsets and sizes
8142: */
8143: px = p->n_list;
8144: // error( 'd', "p: %n %k n_scope: %d", p, p->base, p->n_scope );
8145:
8146: switch (p->base) {
8147: case PUBLIC:
8148: scope = PUBLIC;
8149: protect = 0;
8150: goto prpr;
8151:
8152: case PRIVATE:
8153: scope = 0;
8154: protect = 0;
8155: goto prpr;
8156:
8157: case PROTECTED:
8158: scope = 0;
8159: protect = PROTECTED;
8160: prpr:
8161: if (in_union == ANON) error(&p->where,"%k in anonymous unionD",p->base);
8162: continue;
8163:
8164: case PR: // visibility control: C::M
8165: {
8166: char* qs = p->n_qualifier->string;
8167: char* ms = p->string;
8168: TOK ppp = scope?PUBLIC:(protect?PROTECTED:PRIVATE);
8169:
8170: p->base = NAME;
8171: p->n_scope = scope;
8172: p->n_protect = protect;
8173:
8174: if (strcmp(ms,qs) == 0) ms = "__ct";
8175:
8176: ppbase = PUBLIC;
8177:
8178: if (is_base(qs) == 0) {
8179: error("%kQr %s not aBC of %s",ppp,qs,string);
8180: continue;
8181: }
8182:
8183: mex = 1;
8184: tcl = mec = this;
8185: c_body = 0; // this search must not be interpreted as a use
8186: Pname os = Cdcl;
8187: Cdcl = p;
8188: Pexpr ee = find_name(ms,0,1);
8189: Cdcl = os;
8190: c_body = 1;
8191:
8192: // error('d', "ee: %k ", ee->base );
8193:
8194: // while (ee->base == MDOT || ee->base == REF)
8195: while (ee && (ee->base == MDOT || ee->base == REF))
8196: ee = ee->mem;
8197: Pname mx = Pname(ee);
8198:
8199: // error('d', "ee: %k mx: %n", ee->base, mx );
8200:
8201: if (mx == 0) {
8202: error("C %s does not have aM %s",qs,ms);
8203: continue;
8204: }
8205:
8206: if (mx->tp->base == OVERLOAD) {
8207: error('s',"%k specification of overloaded%n",ppp,mx);
8208: continue;
8209: }
8210:
8211: TOK pp = mx->n_scope?PUBLIC:mx->n_protect?PROTECTED:PRIVATE;
8212:
8213: // error('d',"mx %n pp %k ppp %k",mx,pp,ppp);
8214: if (ppp != pp) {
8215: error(&p->where,"%kM%n specified%k",pp,mx,ppp);
8216: continue;
8217: }
8218:
8219:
8220: p->n_qualifier = mx;
8221: Pname m = memtbl->insert(p,0);
8222: m->base = PUBLIC;
8223: if (Nold) error("twoDs ofCM%n",p);
8224: continue;
8225: }
8226: }
8227:
8228: // error('d',"mem%n tp %d %k scope %d",p,p->tp->base,p->tp->base,scope);
8229:
8230: if (scope==0) {
8231: if (p->n_sto != STATIC) st = 0;
8232: }
8233: else
8234: if ( p->tp->base == TYPE ) {
8235: Pname nn = p->tp->is_cl_obj();
8236: if (nn) {
8237: // error( 'd', "nn: %n %k tp %t %k", nn, nn->base, nn->tp, nn->tp->base );
8238: if ((Pclass(nn->tp)->csu == CLASS) && (strcmp(this->string,nn->string))) st = 0;
8239: }
8240: }
8241:
8242: if (p->tp->base == FCT) {
8243: int ff = 0;
8244: Pfct f = Pfct(p->tp);
8245: Pblock b = f->body;
8246: f->body = 0;
8247: if (b)
8248: f->f_inline = 1;
8249: /* restriction lifted: nested classes
8250: else
8251: if (nstd)
8252: error((nstd==2)?0:'w',&p->where,"non-inlineMF%n in nestedC %s",p,string);
8253: */
8254: else
8255: if (lex_level)
8256: error('w',&p->where,"non-inlineMF%n in localC %s",p,string);
8257:
8258: switch (p->n_sto) {
8259: case FRIEND:
8260: ff = 1;
8261: break;
8262: case STATIC: // accept static member functions
8263: //error('d',"inline %d",f->f_inline);
8264: // if (f->f_inline==0)
8265: /* restriction lifted: nested classes
8266: if (nstd)
8267: error((nstd==2)?0:'w',"staticMF%n in nestedC %s",p,string);
8268: else
8269: */
8270: if (lex_level)
8271: error('w',"staticMF%n in localC %s",p,string);
8272: f->f_static = 1;
8273: p->n_sto = 0;
8274: break;
8275: case AUTO:
8276: // case STATIC:
8277: case REGISTER:
8278: case EXTERN:
8279: error(&p->where,"M%n cannot be%k",p,p->n_sto);
8280: p->n_sto = 0;
8281: }
8282:
8283: if (f->f_virtual) real_virts++;
8284:
8285: Pname m = p->dcl(memtbl,scope);
8286: if (m == 0 || m->tp->base != FCT) continue;
8287: if (m->n_initializer) {
8288: c_abstract = 1;
8289: if (m->n_oper == DTOR)
8290: error('w',"please provide an out-of-line definition: %n {}; which is needed by derived classes",m);
8291: }
8292: if (ff == 0) m->n_protect = protect;
8293: if (b) {
8294: if (m->tp->defined&DEFINED || Pfct(m->tp)->body )
8295: error(&p->where,"two definitions of%n",m);
8296: else
8297: Pfct(m->tp)->body = b;
8298: // Pfct(m->tp)->f_inline = 1;
8299: }
8300: if (ff==0 && p->where.line!=m->where.line)
8301: error(&p->where,"%n cannot be redeclared inCD",p);
8302: }
8303: else {
8304: Eppp = scope?scope:protect?protect:0;
8305:
8306: if (p->base == TNAME) {
8307: // typedef names are exported to
8308: // surrounding non-class scope
8309: // NOTE: name should actually be declared in
8310: // the innermost block of the current
8311: // function, but this info isn't available
8312: if ( cc->nof ) {
8313: if (p->tp &&
8314: Pbase(p->tp)->base != COBJ &&
8315: Pbase(p->tp)->base != EOBJ) {
8316: Pname n = cc->ftbl->look(p->string,0);
8317: if (n && n->base != TNAME &&
8318: n->lex_level &&
8319: n->tp != p->tp ) {
8320: error('s',"transitional model of nestedTs within%n (%s asTdef and%t)",cc->nof,p->string,n->tp);
8321: error('i', "cannot recover from previous errors" );
8322: }
8323: }
8324: else p->dcl(cc->ftbl,scope);
8325: }
8326: else
8327: p->dcl(gtbl,scope);
8328:
8329: // typedefs need to be generated outside class
8330: if ( p->tp && Pbase(p->tp)->base != COBJ ) {
8331: Pname n = gtbl->look(p->string,0);
8332: if ( n && lex_level == 0 && n->base != TNAME )
8333: error(&p->where,"%nredefined: identifier and typedef",p);
8334: p->dcl_print(0);
8335: }
8336: continue;
8337: };
8338:
8339: if (p->n_initializer) {
8340: error(&p->where,"Ir forM%n",p);
8341: p->n_initializer = 0;
8342: }
8343:
8344: if (p->tp->base==OVERLOAD) {
8345: for (Plist gl=Pgen(p->tp)->fct_list; gl; gl=gl->l) {
8346: Pname nn = gl->f;
8347: Pfct ff = Pfct(nn->tp);
8348: if ( ff->f_virtual ) real_virts++;
8349: }
8350: }
8351:
8352: // error('d',"lex_level %d p %n lex %d nested_scope: %k",lex_level,p,p->lex_level, nested_scope);
8353:
8354: TOK is_friend = p->n_sto;
8355: if ( lex_level && p->tp->base == VEC ) lcl_tbl = tbl;
8356: if ( protect && p->tp->base == COBJ &&
8357: Pclass(Pbase(p->tp)->b_name->tp)->csu == ANON )
8358: p->n_protect = protect;
8359: Pname m = p->dcl(memtbl,scope);
8360: lcl_tbl = 0;
8361: Eppp = 0;
8362: if (m == 0) continue;
8363:
8364: m->n_protect = protect;
8365:
8366: if (m->n_stclass==STATIC) {
8367: if (in_union) error("staticM%n in union",m);
8368: if ( is_friend != FRIEND ) {
8369: /* restriction lifted: nested classes
8370: if (nstd)
8371: error((nstd==2)?0:'w',"staticM%n in nestedC %s",m,string);
8372: else
8373: */
8374: if (lex_level)
8375: error(strict_opt?0:'w',"staticM%n in localC %s (anachronism)",m,string);
8376: }
8377: // Ptype t = m->tp;
8378: // Pname cn = t->is_cl_obj();
8379: // if ((cn && Pclass(cn->tp)->has_ctor())
8380: // || t->is_ref()
8381: // || (t->tconst() && vec_const == 0))
8382: m->n_sto = EXTERN;
8383: if (tbl == gtbl) stat_mem_list = new name_list(m,stat_mem_list);
8384: if (m->n_initializer) error('s',"staticM%nWIr",m);
8385: }
8386:
8387: if (in_union) {
8388: if (usz < byte_offset) usz = byte_offset;
8389: byte_offset = 0;
8390: if(in_union==ANON) m->n_offset+=byte_old;
8391: }
8392: }
8393: }
8394:
8395: /* restriction lifted: nested and local classes
8396: if (real_virts) {
8397: if (nstd)
8398: error((nstd==2)?0:'w',"nestedC%s contains%d virtualF",string,real_virts);
8399: else
8400: if (lex_level)
8401: error('w',"localC%s contains%d virtualF",string,real_virts);
8402: }
8403: */
8404:
8405: if (st && csu==CLASS) csu = STRUCT; // nothing private => STRUCT
8406: if (st==0 && csu==STRUCT) csu = CLASS; // all is not public => CLASS
8407:
8408: if (in_union) byte_offset = usz;
8409:
8410: // now look look at the members
8411:
8412: Pname ct = has_ctor();
8413: Pname dt = has_dtor();
8414:
8415: int i;
8416:
8417: int omex = mex; mex = 0;
8418: Pname on = has_oper(NEW);
8419: Pname od = has_oper(DELETE);
8420: mex = omex;
8421:
8422: if (dt && ct==0 && Pfct(dt->tp)->f_virtual == 0 ) error('w',"%s has%n but noK",string,dt);
8423: if (on && od==0) error('w',"%s has%n but no operator delete()",string,on);
8424: if (od && on==0) error('w',"%s has%n but no operator new()",string,od);
8425:
8426: if (dt==0 && od && od && od->n_table==memtbl) make_dtor = 1;
8427:
8428: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
8429: /*
8430: The members have been declared.
8431: now look at each to see if it needs defining
8432: */
8433: Ptype t = m->tp;
8434:
8435: if (t == 0) continue; // public declarations
8436: // error('d', "m %n %d", m, m->n_scope );
8437:
8438: switch (t->base) {
8439: default:
8440: if (ct==0
8441: && m->n_stclass!=ENUM
8442: && m->n_stclass!=STATIC) {
8443: if (t->is_ref()) error("R%n inC %sWoutK",m,string);
8444: if (t->tconst()
8445: && vec_const==0
8446: && m->n_evaluated==0)
8447: error("const%n inC %sWoutK",m,string);
8448: }
8449: case VEC:
8450: break;
8451: case FCT:
8452: case OVERLOAD:
8453: case CLASS:
8454: case ENUM:
8455: continue;
8456: }
8457:
8458: Pname cn = t->is_cl_obj();
8459: if (cn == 0) cn = cl_obj_vec;
8460: if (cn == 0) continue;
8461:
8462: Pclass cl = Pclass(cn->tp);
8463: c_xref |= cl->c_xref;
8464: //error('d',"m %n %t %d",m,cl,cl->c_xref);
8465: if (cl->has_ctor()) {
8466: if (m->n_stclass == STATIC)
8467: ; // error('s',"staticM%n ofC%nWK",m,cn);
8468: else if (in_union) {
8469: if (strncmp("__C",string,3) == 0)
8470: error("M %s ofC%nWK in union",m->string,cn); // tagless union
8471: else error("M%n ofC%nWK in union",m,cn);
8472: }
8473: else if (ct == 0) {
8474: // does mctor have a default constructor?
8475: if (make_ctor==0 && cl->has_ictor()==0)
8476: error("%t needs aK; it has aMWK requiringAs",this);
8477: make_ctor = 1;
8478: }
8479: }
8480:
8481: if (cl->has_dtor()) {
8482: if (m->n_stclass==STATIC)
8483: ; // error('s',"staticM%n ofC%nW destructor",m,cn);
8484: else if (in_union) {
8485: if (strncmp("__C",string,3) == 0) // tagless union
8486: error("M %s ofC%nW destructor in union",m->string,cn);
8487: else error("M%n ofC%nW destructor in union",m,cn);
8488: }
8489: else if (dt==0)
8490: make_dtor = 1;
8491: }
8492: }
8493:
8494: if (has_dtor()==0 && make_dtor==0) {
8495: // can dtor be inherited (from single base class)?
8496: Pclass bcl = 0;
8497: for (Pbcl b = baselist; b; b = b->next) {
8498: switch (b->base) {
8499: case NAME:
8500: if (bcl == 0) {
8501: Pname d = b->bclass->has_dtor();
8502: if (d==0) break;
8503: if (strict_opt == 0) {
8504: if (d->n_scope==PUBLIC
8505: && Pfct(d->tp)->f_virtual==0) {
8506: bcl = b->bclass;
8507: break;
8508: }
8509: }
8510: }
8511: // two dtors or non-public dtors force creation
8512: make_dtor = 1;
8513: goto zbzb;
8514: case VIRTUAL:
8515: if (b->bclass->has_dtor()) make_dtor = 1;
8516: goto zbzb;
8517: }
8518: }
8519: if (bcl) c_dtor = bcl->has_dtor();
8520: zbzb:;
8521: }
8522:
8523: if (make_dtor && dt==0) { // make x::~x() {}
8524:
8525: // must be done before vtbls are made in case dtor is virtual
8526: //error('d',"%t: make_dtor",this);
8527: Pname n = new name(string);
8528: Pfct f = new fct(defa_type,0,1);
8529: f->f_inline = /*IDTOR; */ 1;
8530: n->tp = f;
8531: n->n_oper = DTOR;
8532: dt = n->dcl(memtbl,PUBLIC);
8533: delete n;
8534: Pfct(dt->tp)->body = /*0; */ new block(curloc,0,0);
8535: dt = has_dtor();
8536: }
8537:
8538: if (virt_count && find_vptr(this)==0) {
8539: // we only need a vptr if this class has virtual
8540: // functions and none of its first bases have vptrs
8541: //error('d',"%s virt_count %d",string,virt_count);
8542: Pname vp = new name("__vptr");
8543: vp->tp = Pvptr_type;
8544: (void) vp->dcl(memtbl,0);
8545: delete vp;
8546: c_xref |= C_VPTR;
8547: }
8548: else {
8549: //error("byte_offset %d bit_offset %d bitsinbyte %d",byte_offset,bit_offset,BI_IN_BYTE);
8550: //error(" div %d mod %d",bit_offset/BI_IN_BYTE,bit_offset%BI_IN_BYTE);
8551: // no more bit fields. absorb bit_offset
8552: if (bit_offset) {
8553: byte_offset += (bit_offset/BI_IN_BYTE + (bit_offset%BI_IN_BYTE?1:0));
8554: bit_offset = 0;
8555: }
8556: }
8557: //error("byte_offset %d bit_offset %d",byte_offset,bit_offset);
8558:
8559: for (Pbcl b = baselist; b; b = b->next) { // allocate virtual base pointers
8560: if (b->base != VIRTUAL) continue;
8561: Pclass bcl = b->bclass;
8562:
8563: // search non-virtual bases for this virtual base
8564: for (Pbcl bb = baselist; bb; bb = bb->next)
8565: if (bb->base == NAME) {
8566: for (Pbcl l = bb->bclass->baselist; l; l=l->next)
8567: if (l->base==VIRTUAL && l->bclass==bcl) goto eee;
8568: }
8569: {
8570: if (obj_align<AL_WPTR) obj_align = AL_WPTR;
8571: if (max_align<AL_WPTR) max_align = AL_WPTR;
8572: int waste = byte_offset%AL_WPTR;
8573: if (waste) byte_offset += AL_WPTR-waste; // align
8574: b->ptr_offset = byte_offset+1; // ensure != 0
8575: byte_offset += sizeof(int*);
8576: }
8577: eee:;
8578: }
8579:
8580: real_size = byte_offset; // the rest may be optimized away
8581:
8582: for (b = baselist; b; b = b->next) { // allocate virtual class objects
8583: if (b->base != VIRTUAL) continue;
8584: Pclass bcl = b->bclass;
8585:
8586: // if necessary
8587: if (b->obj_offset = has_allocated_base(bcl)) continue;
8588:
8589: int ba = bcl->align();
8590: if (obj_align<ba) obj_align = ba;
8591: if (max_align<ba) max_align = ba;
8592: int waste = byte_offset%ba;
8593: if (waste) byte_offset += ba-waste; // align
8594: b->obj_offset = byte_offset; // offset in this
8595: b->allocated = 1;
8596: //error('d',"virtual %t in %t at %d",bcl,this,b->obj_offset);
8597: byte_offset += bcl->tsizeof();
8598: }
8599:
8600: // no more data members.
8601: // pad object (so that copying into a base object
8602: // doesn't destroy derevid class members):
8603: if (byte_offset==0) { // empty struct: waste a member
8604: Pname c = new name (make_name('W'));
8605: c->tp = char_type;
8606: (void) c->dcl(memtbl,0);
8607: real_size = byte_offset = 1;
8608: }
8609: if (byte_offset < SZ_STRUCT) byte_offset = SZ_STRUCT;
8610: int waste = byte_offset%max_align;
8611: //error('d',"max_align %d waste %d byte_offset %d",max_align,waste,byte_offset);
8612: if (waste) byte_offset += max_align-waste;
8613: obj_size = byte_offset;
8614: obj_align = max_align;
8615:
8616: // make vtbls
8617: // this cannot be done until the bases
8618: // have been allocated in this class
8619: // so that the offsets (deltas) are known
8620: if (all_virt(this,0,1,0)) {
8621: if (has_ctor()==0) make_ctor = 1;
8622: }
8623: else if (has_vvtab)
8624: error("virtualB: conflicting vtable initialization");
8625:
8626: // error('d',"%t->classdef: virt_count: %d virt_merge: %d",this,virt_count,virt_merge);
8627:
8628: Pname hito = has_itor();
8629:
8630: if (hito) c_xref |= C_XREF; // has user defined X(X&)
8631: //error('d',"%t hito %d ctor %d",this,hito,make_ctor);
8632: if (hito==0 && c_xref&(C_VPTR|C_VBASE|C_XREF)) {
8633: // X(X&) needed if bitwise copy is illegal
8634: // or if any constructor is defined
8635:
8636: hito = make_itor(0);
8637: // if the base has B::B(void)
8638: // the derived should have D::D(void)
8639: if (baselist) {
8640: int mc = 1; // can make and ictor
8641: for (Pbcl b = baselist; b; b = b->next) {
8642: if (b->bclass->has_ctor()
8643: && b->bclass->has_ictor()==0)
8644: mc = 0;
8645: }
8646: make_ctor = mc;
8647: /*
8648: int mc = 1; // can make an ictor
8649: for (Pbcl b = baselist; b; b = b->next) {
8650: if (b->bclass->has_ctor()) {
8651: Pname c = b->bclass->has_ictor();
8652: // no copy constructor?
8653: // non-public copy constructor?
8654: if (c==0 || c->n_scope==0) mc = 0;
8655: }
8656: }
8657: make_ctor = mc;
8658: */
8659: }
8660: else
8661: make_ctor = 1;
8662: }
8663:
8664: if (c_ctor==0 && make_ctor==0) { // can ctor be inherited (from single base class)?
8665: /*
8666: int bb = 0;
8667: for (Pbcl b = baselist; b; b = b->next) {
8668: switch (b->base) {
8669: case NAME:
8670: { Pname c = b->bclass->has_ctor();
8671: // if (b->bclass->has_ctor() == 0) break;
8672: if (c == 0) break;
8673: if (c->n_scope==PUBLIC && bb++==0) break;
8674: }
8675: // no break: two bases: needs ctor
8676: case VIRTUAL:
8677: make_ctor = 1; // virtual base: need ctor
8678: goto zaza;
8679: }
8680: }
8681: */
8682: Pname btor = 0;
8683: Pclass bc = 0;
8684: for (Pbcl b = baselist; b; b = b->next) {
8685: switch (b->base) {
8686: case NAME:
8687: { Pname c = b->bclass->has_ctor();
8688: if (c == 0) break;
8689: if (c->n_scope==PUBLIC && b==baselist) {
8690: bc = b->bclass;
8691: btor = bc->has_ictor();
8692: break;
8693: }
8694: }
8695: // no break: two bases: needs ctor
8696: case VIRTUAL:
8697: make_ctor = 1; // virtual base: need ctor
8698: goto zaza;
8699: }
8700: }
8701: // c_ctor = btor;
8702: //error('d',"btor %n",btor);
8703: if (bc) {
8704: if (btor)
8705: make_ctor = 1;
8706: else
8707: error("K needed for %s, BC%t hasK",string,bc);
8708: }
8709: zaza:;
8710: }
8711:
8712: if (make_ctor && ct==0) { // make x::x() {}
8713: //error('d',"%t: make_ctor",this);
8714: Pname n = new name(string);
8715: Pfct f = new fct(defa_type,0,1);
8716: f->f_inline = 1; // ICTOR; // ICTOR means ``define ctor() if used''
8717: n->tp = f;
8718: n->n_oper = TNAME;
8719: ct = n->dcl(memtbl,PUBLIC);
8720: delete n;
8721: Pfct(ct->tp)->body = /* 0; */ new block(curloc,0,0);
8722: }
8723:
8724: defined |= DEFINED;
8725:
8726: if (ansi_opt) {
8727: char* s = csu==UNION || csu==ANON ? "union" : "struct";
8728: fprintf(out_file,"%s %s;",s,string);
8729: }
8730: //error('d',"defined %s",string);
8731:
8732: // fix argument lists for inlines
8733: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
8734: Pfct f = Pfct(p->tp);
8735: if (f==0) continue; // public declarations
8736:
8737: switch (f->base) {
8738: case FCT:
8739: /* prohibit something like the following:
8740: typedef int t1;
8741: class x {
8742: typedef int t1;
8743: t1 foo();
8744: };
8745: */
8746: if (f->returns->base == TYPE) {
8747: Pname nn = Pbase(f->returns)->b_name;
8748: while ( nn->tp->base == TYPE )
8749: nn = Pbase(nn->tp)->b_name;
8750: if (nn->n_key == NESTED) {
8751: Ptype tt;
8752: if ( nn->tp->base != EOBJ &&
8753: nn->tp->base != COBJ )
8754: tt = nn->tpdef;
8755: else tt = Pbase(nn->tp)->b_name->tp;
8756: if ( tt && tt->nested_sig )
8757: error('w',"nested %s as returnT for non-inlineMF, use %t::%s %n{} in definition (anachronism)",nn->string,tt->in_class,nn->string,p);
8758: }
8759: }
8760:
8761: if (hito && f->argtype) fix_args(f,this);
8762: if (p->n_oper == CTOR) f->s_returns = this_type;
8763: if (f->body) p->n_sto = STATIC;
8764: break;
8765: case OVERLOAD:
8766: { Pgen g = Pgen(f);
8767: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8768: Pname n = gl->f;
8769: Pfct f = Pfct(n->tp);
8770:
8771: if (hito && f->argtype) fix_args(f,this);
8772: if (n->n_oper == CTOR) f->s_returns = this_type;
8773: if (f->body) n->n_sto = STATIC;
8774: }
8775: }
8776: }
8777: }
8778:
8779: // define members defined inline
8780: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
8781: Pfct f = Pfct(p->tp);
8782: if (f==0) continue; // public declarations
8783:
8784: switch (f->base) {
8785: case FCT:
8786: if (f->body) {
8787: f->dcl(p);
8788: p->simpl();
8789: }
8790: break;
8791: case OVERLOAD:
8792: { Pgen g = Pgen(f);
8793: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8794: Pname n = gl->f;
8795: Pfct f = Pfct(n->tp);
8796:
8797: if (f->body) {
8798: f->dcl(n);
8799: n->simpl();
8800: }
8801: }
8802: }
8803: }
8804: }
8805:
8806: byte_offset = byte_old;
8807: bit_offset = bit_old;
8808: max_align = max_old;
8809:
8810: cc->unstack(); // friends are not in class scope
8811:
8812: // fix arguments lists for friends defined inline
8813: for (Plist fl=friend_list; fl; fl=fl->l) {
8814: Pname p = fl->f;
8815: Pfct f = Pfct(p->tp);
8816:
8817: switch (f->base) {
8818: case FCT:
8819: if (hito && f->argtype) fix_args(f,this);
8820: if (f->body &&
8821: (f->defined&(DEFINED|SIMPLIFIED)) == 0)
8822: p->n_sto = STATIC;
8823: else
8824: if (p->n_scope == STATIC)
8825: error(strict_opt?0:'w',"static%n declared friend toC%t",p,this);
8826: break;
8827: case OVERLOAD:
8828: { Pgen g = Pgen(f);
8829: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8830: Pname n = gl->f;
8831: Pfct f = Pfct(n->tp);
8832:
8833: if (hito && f->argtype) fix_args(f,this);
8834: if (f->body &&
8835: (f->defined&(DEFINED|SIMPLIFIED)) == 0)
8836: n->n_sto = STATIC;
8837: else
8838: if (p->n_scope == STATIC)
8839: error(strict_opt?0:'w',"static%n declared friend toC%t",p,this);
8840: }
8841: }
8842: }
8843: }
8844:
8845: // define friends defined inline and modify return types if necessary
8846: for (fl=friend_list; fl; fl=fl->l) {
8847: Pname p = fl->f;
8848: Pfct f = Pfct(p->tp);
8849:
8850: switch (f->base) {
8851: case FCT:
8852: if (f->body &&
8853: (f->defined&(DEFINED|SIMPLIFIED)) == 0) {
8854: f->dcl(p);
8855: p->simpl();
8856: }
8857: break;
8858: case OVERLOAD:
8859: { Pgen g = Pgen(f);
8860: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8861: Pname n = gl->f;
8862: Pfct f = Pfct(n->tp);
8863:
8864: if (f->body &&
8865: (f->defined&(DEFINED|SIMPLIFIED)) == 0) {
8866: f->dcl(n);
8867: n->simpl();
8868: }
8869: }
8870: }
8871: }
8872: }
8873:
8874: if (tbl != gtbl) this->simpl();
8875:
8876: if ( statStat && strcmp(statStat->string,string)==0) {
8877: //error('d', "classdef::dcl: statstat: %n this %s", statStat, string);
8878: statStat->hide();
8879: statStat = 0;
8880: }
8881: // error('d',"classdef::dcl defined: %d",defined);
8882: // catch refs to this class in body of nested class function
8883: // (i.e., ref to member of this class...)
8884: if ( (defined&REF_SEEN) != 0 ) dcl_print(0);
8885:
8886: if ( debug_opt ) {
8887: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
8888: Pfct f = Pfct(p->tp);
8889: if (f==0) continue; // public declarations
8890:
8891: switch (f->base) {
8892: case FCT:
8893: if (f->body) {
8894: if ( c_body == 1 ) dcl_print(0);
8895: p->dcl_print(0);
8896: }
8897: break;
8898: case OVERLOAD:
8899: {
8900: Pgen g = Pgen(f);
8901: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8902: Pname n = gl->f;
8903: Pfct f = Pfct(n->tp);
8904: if (f->body) {
8905: if ( c_body == 1 ) dcl_print(0);
8906: p->dcl_print(0);
8907: }
8908: }
8909: }
8910: }
8911: }
8912:
8913: for (fl=friend_list; fl; fl=fl->l) {
8914: Pname p = fl->f;
8915: Pfct f = Pfct(p->tp);
8916:
8917: switch (f->base) {
8918: case FCT:
8919: if (f->body &&
8920: (f->defined&(DEFINED|SIMPLIFIED)) == 0)
8921: p->dcl_print(0);
8922: break;
8923: case OVERLOAD:
8924: {
8925: Pgen g = Pgen(f);
8926: for (Plist gl=g->fct_list; gl; gl=gl->l) {
8927: Pname n = gl->f;
8928: Pfct f = Pfct(n->tp);
8929:
8930: if (f->body &&
8931: (f->defined&(DEFINED|SIMPLIFIED)) == 0)
8932: p->dcl_print(0);
8933: }
8934: }
8935: }
8936: }
8937: } // end, if (debug_opt)
8938: }
8939:
8940: void enumdef::dcl(Pname n, Ptable tbl)
8941: {
8942: // if (this == 0) error('i',"0->enumdef::dcl(%p)",tbl);
8943: Pname px;
8944: Pname p = mem;
8945: DB( if(Ddebug>=1) error('d',&n->where,"enumdef(%n,%d)",n,tbl); );
8946: Pbase b = new basetype(EOBJ,n);
8947: b->b_const = 1;
8948:
8949: #define FIRST_ENUM 0
8950: int enum_count = FIRST_ENUM;
8951: no_of_enumerators = mem->no_of_names();
8952: int largest = 0;
8953:
8954: if (p == 0) mem = new name(make_name('e'));
8955:
8956: for (; p; p=px) {
8957: px = p->n_list;
8958: // error( 'd', "p %n", p );
8959: if (p->n_initializer) {
8960: Pexpr i = p->n_initializer->typ(tbl);
8961: Neval = 0;
8962: long ii = i->eval();
8963: if (largest_int<ii) error("long enumerator");
8964: enum_count = int(ii);
8965: if (Neval) error("%s",Neval);
8966: DEL(i);
8967: p->n_initializer = 0;
8968: }
8969: p->n_evaluated = 1;
8970: largest |= enum_count;
8971: p->n_val = enum_count++;
8972: p->tp = b;
8973:
8974: Pname nn = tbl->insert(p,0);
8975: if (Nold) {
8976: if (nn->n_stclass == ENUM) {
8977: // error( (p->n_val!=nn->n_val)?0:'w',"enumerator%n declared twice",nn);
8978: // if (p->n_val!=nn->n_val)
8979: error("enumerator%n declared twice",nn);
8980:
8981: }
8982: else
8983: error("incompatibleDs of%n",nn);
8984: }
8985: else {
8986: nn->n_stclass = ENUM; // no store will be allocated
8987: if (Eppp == PROTECTED)
8988: nn->n_protect = PROTECTED;
8989: else if (Eppp == PUBLIC)
8990: nn->n_scope = PUBLIC;
8991: }
8992: p->string = nn->string;
8993: // delete p;
8994: }
8995:
8996: // mem = 0;
8997:
8998: // chose a shorter representation for the enum?
8999: // if (largest&0133 == largest)
9000: // e_type = char_type;
9001: // else if largest&077777 == largest)
9002: // e_type = short_type;
9003: // else
9004: e_type = int_type;
9005:
9006: defined |= DEFINED;
9007: }
9008:
9009:
9010: 0707071010112044131004440001630000160000010175600466055377200000600000013077del.c /*ident "@(#)ctrans:src/del.c 1.3" */
9011: /************************************************************
9012:
9013: C++ source for cfront, the C++ compiler front-end
9014: written in the computer science research center of Bell Labs
9015:
9016: Copyright (c) 1984 AT&T, Inc. All rights Reserved
9017: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9018:
9019: del.c:
9020:
9021: walk the trees to reclaim storage
9022:
9023: **************************************************************/
9024:
9025: #include "cfront.h"
9026:
9027: void name::del()
9028: {
9029: DB( if(Adebug>=1) {
9030: fprintf(stderr,"\n*** '%s'->del()",string?string:"???");
9031: display_type(tp); putc(' ',stderr);
9032: where.put(stderr); putc('\n',stderr);
9033: }
9034: if ( base!=NAME && base!=TNAME ) error('i',"name::del() of%k -- id==%ld",base,node::id);
9035: );
9036: Pexpr i = n_initializer;
9037:
9038: // error('d', "\nname::del: %d %s", this, string?string:"no name" );
9039: // NFn++;
9040: DEL(tp);
9041: if(i && i!=(Pexpr)1) DEL(i);
9042: delete this;
9043: }
9044:
9045: void type::del()
9046: {
9047: DB( if(Adebug>=1) {
9048: fprintf(stderr,"\n*** '");
9049: display_type(this);
9050: fprintf(stderr," '->del()\n");
9051: }
9052: );
9053: //fprintf(stderr,"DEL(type=%d %d)\n",this,base);
9054: permanent = 3; /* do not delete twice */
9055: switch (base) {
9056: case TNAME:
9057: case NAME:
9058: error('i',"%d->T::del():N %s %d",this,Pname(this)->string,base);
9059: case FCT:
9060: { Pfct f = (Pfct) this;
9061: DEL(f->returns);
9062: delete f;
9063: break;
9064: }
9065: case VEC:
9066: { Pvec v = (Pvec) this;
9067: DEL(v->dim);
9068: DEL(v->typ);
9069: delete v;
9070: break;
9071: }
9072: case PTR:
9073: case RPTR:
9074: { Pptr p = (Pptr) this;
9075: DEL(p->typ);
9076: delete p;
9077: break;
9078: }
9079: }
9080: }
9081:
9082: void expr::del()
9083: {
9084: DB( if(Adebug>=1) {
9085: fprintf(stderr,"\n*** expr::del(): ");
9086: display_expr(this,0,1);
9087: if(Adebug>=2) display_expr(this);
9088: });
9089: //fprintf(stderr,"DEL(expr=%d: %d %d %d)\n",this,base,e1,e2); fflush(stderr);
9090: permanent = 3;
9091: switch (base) {
9092: case IVAL:
9093: if (this == one) return;
9094: //case FVAL:
9095: case THIS:
9096: case ICON:
9097: case FCON:
9098: case CCON:
9099: case STRING:
9100: case TEXT:
9101: goto dd;
9102: case DUMMY:
9103: case ZERO:
9104: case NAME:
9105: return;
9106: case CAST:
9107: case SIZEOF:
9108: case NEW:
9109: case GNEW:
9110: case VALUE:
9111: DEL(tp2);
9112: break;
9113: case REF:
9114: case DOT:
9115: DEL(e1);
9116: if (e2) DEL(e2);
9117: case MDOT:
9118: if (mem && mem->base!=NAME) DEL(mem);
9119: if ( i1 == 5 ) delete string4;
9120: goto dd;
9121: case QUEST:
9122: DEL(cond);
9123: break;
9124: case ICALL:
9125: delete il->i_args;
9126: delete il;
9127: goto dd;
9128: case ELIST: { // limit recursion
9129: Pexpr tp = e2;
9130: while ( tp && tp->e2 && tp->e2->base == ELIST ) {
9131: Pexpr x = tp;
9132: if ( x->permanent ) break;
9133: x->permanent = 3;
9134: tp = tp->e2;
9135: if ( x->e1 ) DEL(x->e1);
9136: delete x;
9137: }
9138: e2 = tp;
9139: break;
9140: }
9141: }
9142:
9143: DEL(e1);
9144: DEL(e2);
9145: dd:
9146: delete this;
9147: }
9148:
9149: void stmt::del()
9150: {
9151: DB( if(Adebug>=1) {
9152: fprintf(stderr,"\n*** stmt::del(): ");
9153: display_stmt(this,0,1);
9154: if(Adebug>=2) display_stmt(this);
9155: });
9156: //fprintf(stderr,"DEL(stmt %d %s)\n",this,keys[base]); fflush(stderr);
9157: permanent = 3;
9158: switch (base) {
9159: case SM:
9160: case WHILE:
9161: case DO:
9162: case RETURN:
9163: case CASE:
9164: case SWITCH:
9165: DEL(e);
9166: break;
9167: case PAIR:
9168: DEL(s2);
9169: break;
9170: case BLOCK:
9171: DEL(d);
9172: DEL(s);
9173: if (own_tbl) DEL(memtbl);
9174: DEL(s_list);
9175: goto dd;
9176: case FOR:
9177: DEL(e);
9178: DEL(e2);
9179: DEL(for_init);
9180: break;
9181: case IF:
9182: DEL(e);
9183: DEL(else_stmt);
9184: break;
9185: }
9186:
9187: DEL(s);
9188: DEL(s_list);
9189: dd:
9190: delete this;
9191: }
9192:
9193: void table::del()
9194: {
9195: // error('d',"\n*** %d::del() -- '%s'\n",this, t_name?t_name->string:"???");
9196:
9197: for (register i=1; i<free_slot; i++) {
9198: Pname n = entries[i];
9199: if (n==0) error('i',"table.del(0)");
9200: DB( if(Adebug>=2) { fprintf(stderr," name: '%s'",n->string);
9201: display_type(n->tp); putc('\n',stderr);
9202: });
9203:
9204: // error( 'd',"\ntable::del: %s n_scope: %d, n_stclass: %d", n->string, n->n_scope, n->n_stclass );
9205:
9206: if (n->n_stclass == STATIC) continue;
9207: switch (n->n_scope) {
9208: case ARG:
9209: case ARGT:
9210: break;
9211: default:
9212: { char* s = n->string;
9213: if (s && (s[0]!='_' || s[1]!='_' || s[2]!='X')) delete s;
9214: /* delete n; */
9215: n->del();
9216: }
9217: }
9218: }
9219: //delete entries;
9220: //delete hashtbl;
9221: delete this;
9222: }
9223:
9224: // local class
9225: void delete_local()
9226: {
9227: DB( if(Adebug>=1) {
9228: fprintf( stderr, "delete_local: vlist: %d", vlist );
9229: });
9230: // error( 'd', "delete_local: vlist: %d", vlist );
9231: do {
9232: for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt);
9233: vlist = 0;
9234:
9235: for (Plist l=isf_list; l; l=l->l) {
9236: Pname n = l->f;
9237: Pfct f = Pfct(n->tp);
9238: // error('d',"isf %n f %d",n,f);
9239: if ( f == 0 ) { error('d', "delete_local: f == 0" );break;}
9240: if (f->base == OVERLOAD) {
9241: n = Pgen(f)->fct_list->f; // first fct
9242: f = Pfct(n->tp);
9243: }
9244:
9245: if (debug_opt==0 && n->n_addr_taken) {
9246: f->f_inline = 0;
9247: if (n->n_dcl_printed<2) {
9248: if (warning_opt)
9249: error('w',"out-of-line copy of %n created",n);
9250: n->dcl_print(0);
9251: }
9252: }
9253: }
9254: //isf_list = 0;
9255: } while (vlist);
9256:
9257: for ( Plist l = local_class; l; l = l->l )
9258: {
9259: Pname n = l->f;
9260: // error( 'd' , "delete_local() %d %n %t", n, n, n->tp );
9261: Pname nn = Pbase(n->tp)->b_name;
9262: Pclass cl = Pclass(nn->tp);
9263: for (Pname px, p=cl->mem_list; p; p=px) {
9264: px = p->n_list;
9265: if (p->tp)
9266: switch (p->tp->base) {
9267: case FCT:
9268: { Pfct f = (Pfct)p->tp;
9269: if (f->body) {
9270: if (f->f_inline==0
9271: && f->f_imeasure==0) {
9272:
9273: if (ansi_opt && f->f_this) {
9274: f->f_this->n_table = 0;
9275: for (Pname n=f->f_this->n_list; n; n=n->n_list)
9276: n->n_table = 0;
9277: }
9278:
9279: DEL(f->body);
9280: f->body = 0;
9281: }
9282: }
9283: }
9284: case COBJ:
9285: case EOBJ:
9286: DEL(p);
9287: break;
9288: case CLASS:
9289: case ENUM:
9290: break;
9291: default:
9292: delete p;
9293: } // end switch
9294: else delete p;
9295: } // end for mem
9296: DEL(cl->memtbl);
9297: cl->mem_list = 0;
9298: cl->permanent = 3;
9299: nn->permanent = 0;
9300: DEL(nn);
9301: n->permanent = 0;
9302: extern void table_delete( char*, TOK, int );
9303: table_delete( n->string, LOCAL, n->lex_level );
9304: DEL(n);
9305: }
9306: }
9307: 0707071010112045761004440001630000160000010210600466055414200001200000013534discrim.c /* ident "@(#)ctrans:src/discrim.c 1.2" */
9308: /************ add copyright **********************
9309: * union discriminator functions for nodes in cfront.
9310: * all return 0 for none,
9311: * -1 for bad union index, -2 for inconsistent
9312: * or otherwise messed up nodes
9313: */
9314: #include "cfront.h"
9315: #define DEFINE_TOKEN_CLASS_TABLE
9316: #include "node_classes.h"
9317:
9318: int basetype::discriminator(int which_union)
9319: {
9320: switch(which_union)
9321: {
9322: case 0:
9323: switch(base) {
9324: case FIELD: return 1;
9325: case FCT: return 2;
9326: default: return discrim_none_valid;
9327: }
9328: default:
9329: return discrim_bad_index;
9330: }
9331: }
9332:
9333: int fct::discriminator(int)
9334: {
9335: return discrim_bad_index;
9336: }
9337:
9338: int expr::discriminator(int which_union)
9339: {
9340: switch(which_union) {
9341: case 0:
9342: return 1; /* tp, never syn_class */
9343: case 1: /* e1, i1, string */
9344: switch(base) {
9345: case DEREF:
9346: case ICALL:
9347: case REF:
9348: case DOT:
9349: case VALUE:
9350: case SIZEOF:
9351: case NEW:
9352: case GNEW:
9353: case DELETE:
9354: case CAST:
9355: case CALL:
9356: case G_CALL:
9357: case ASSIGN:
9358: case EQ:
9359: case NE:
9360: case GT:
9361: case GE:
9362: case LE:
9363: case LT:
9364: case ELIST:
9365: case ILIST:
9366: case QUEST:
9367: case CM:
9368: case G_CM:
9369: case PLUS:
9370: case MINUS:
9371: case MUL:
9372: case DIV:
9373: case MOD:
9374: case LS:
9375: case RS:
9376: case AND:
9377: case OR:
9378: case ER:
9379: case ANDAND:
9380: case OROR:
9381: case ASOR:
9382: case ASER:
9383: case ASAND:
9384: case ASPLUS:
9385: case ASMINUS:
9386: case ASMUL:
9387: case ASMOD:
9388: case ASDIV:
9389: case ASLS:
9390: case ASRS:
9391: case DECR:
9392: case INCR:
9393: return 1;
9394: case MDOT:
9395: case IVAL:
9396: return 2;
9397: case TNAME:
9398: case NAME:
9399: case ICON:
9400: case FCON:
9401: case CCON:
9402: case ID:
9403: case STRING:
9404: case TEXT:
9405: return 3;
9406: default: return discrim_none_valid;
9407: }
9408: case 2: /* e2, i2, string2, n_initializer */
9409: /* i2 is a complete mystery. It is set to 1,
9410: and never referenced. But I'm not sure that
9411: someone somewhere doesn't test one of the other
9412: union elements for equal to 1, so therefore this test. */
9413: if(i2 == 1)return 2;
9414: switch(base) {
9415: case DELETE:
9416: case VALUE:
9417: case ICALL:
9418: case CALL:
9419: case G_CALL:
9420: case ASSIGN:
9421: case EQ:
9422: case NE:
9423: case GT:
9424: case GE:
9425: case LE:
9426: case LT:
9427: case DEREF:
9428: case ELIST:
9429: case QUEST:
9430: case CM:
9431: case G_CM:
9432: case UMINUS:
9433: case NOT:
9434: case COMPL:
9435: case ADDROF:
9436: case G_ADDROF:
9437: case PLUS:
9438: case MINUS:
9439: case MUL:
9440: case DIV:
9441: case MOD:
9442: case LS:
9443: case RS:
9444: case AND:
9445: case OR:
9446: case ER:
9447: case ANDAND:
9448: case OROR:
9449: case ASOR:
9450: case ASER:
9451: case ASAND:
9452: case ASPLUS:
9453: case ASMINUS:
9454: case ASMUL:
9455: case ASMOD:
9456: case ASDIV:
9457: case ASLS:
9458: case ASRS:
9459: case DECR:
9460: case INCR:
9461: case NEW: /*- the placement expression list hangs off e2 -*/
9462: return 1;
9463: case TEXT:
9464: return 3;
9465: case NAME:
9466: case TNAME:
9467: /* The n_initializer field is used for TNAMEs when describing base */
9468: /* class initializations. The TNAME refers to the base class, and */
9469: /* the actuals arguments are hung off the n_initializer list */
9470: return 4;
9471: default: return discrim_none_valid;
9472: }
9473: case 3: /* tp2, fct_name, cond, mem, as_type, n_table, il, query_this */
9474: switch(base) {
9475: case VALUE:
9476: case SIZEOF:
9477: case NEW:
9478: case GNEW:
9479: case CAST:
9480: return 1;
9481: case CALL:
9482: case G_CALL:
9483: return 2;
9484: case QUEST:
9485: return 3;
9486: case REF:
9487: case DOT:
9488: case MDOT:
9489: return 4;
9490: case ASOR:
9491: case ASER:
9492: case ASAND:
9493: case ASPLUS:
9494: case ASMINUS:
9495: case ASMUL:
9496: case ASMOD:
9497: case ASDIV:
9498: case ASLS:
9499: case ASRS:
9500: case DECR:
9501: case INCR:
9502: case ASSIGN:
9503: return 5;
9504:
9505: case NAME:
9506: case TNAME:
9507: if (Pname(this)->n_oper==TYPE &&
9508: (strcmp(Pname(this)->string, "_type")==0)) {
9509: // error('d',"string %s n_oper: %k", string, Pname(this)->n_oper);
9510: return 3;
9511: }
9512: return 6;
9513:
9514: case ICALL:
9515: case ANAME:
9516: return 7;
9517:
9518: default: return discrim_none_valid;
9519: }
9520:
9521: default:
9522: return discrim_bad_index;
9523: }
9524: }
9525:
9526: int name::discriminator (int which_union)
9527: {
9528: switch(which_union) {
9529: case 0: /* n_qualifier, n_realscope */
9530: if(base == LABEL) return 2;
9531: else return 1;
9532: default:
9533: return discrim_bad_index;
9534: }
9535: }
9536:
9537: int stmt::discriminator (int which_union)
9538: {
9539: switch(which_union) {
9540: case 0: /* d, e2, has_default, case_value, ret_tp */
9541: switch(base) {
9542: case BLOCK:
9543: case GOTO:
9544: case LABEL:
9545: case DCL:
9546: return 1;
9547: case FOR:
9548: return 2;
9549: case SWITCH:
9550: return 3;
9551: case PAIR:
9552: case RETURN:
9553: return 4;
9554: default: return discrim_none_valid;
9555: }
9556: case 1: /* e, own_tbl, s2 */
9557: switch(base) {
9558: case FOR:
9559: case IF:
9560: case WHILE:
9561: case DO:
9562: case RETURN:
9563: case SWITCH:
9564: case SM:
9565: case SM_PARAM:
9566: case CASE:
9567: return 1;
9568: case BLOCK:
9569: return 2;
9570: case PAIR:
9571: return 3;
9572: default:
9573: return discrim_none_valid;
9574: }
9575: case 2: /* for_init, else_stmt, case_list */
9576: switch(base) {
9577: case FOR:
9578: return 1;
9579: case IF:
9580: return 2;
9581: case SWITCH:
9582: case CASE:
9583: return 3;
9584: default:
9585: return discrim_none_valid;
9586: }
9587: default:
9588: return discrim_bad_index;
9589: }
9590: }
9591:
9592: static node_class token_to_class_map[DUMMY_LAST_NODE];
9593: static char map_initialized;
9594:
9595: node_class classify_node (Pnode node, int& error)
9596: {
9597: int ncx;
9598: node_class nclass;
9599:
9600: error = 0;
9601:
9602: if (! map_initialized) {
9603: map_initialized = 1 ;
9604: for(ncx = 0; ncx < sizeof (token_classes) / sizeof (token_class);
9605: ncx ++)
9606: token_to_class_map[token_classes[ncx].token]
9607: = token_classes[ncx].nclass;
9608: }
9609:
9610: if (!((node->base > 0) && (node->base < DUMMY_LAST_NODE))) {
9611: error = 1;
9612: return nc_unused;
9613: }
9614:
9615: nclass = token_to_class_map[node->base];
9616:
9617: switch(nclass) {
9618: case nc_fct:
9619: case nc_name:
9620: if(node->baseclass) nclass = nc_baseclass;
9621: }
9622:
9623: return nclass;
9624: }
9625:
9626: node_class classify_node (Pnode node)
9627: {
9628: int err;
9629: node_class nclass = classify_node (node, err);
9630: if(err) error ('i', "failed to classify node.");
9631: return nclass;
9632: }
9633: 0707071010112045771004440001630000160000010210700466055414600001200000041601doprint.c /* ident "@(#)ctrans:src/doprint.c 1.2" */
9634: /*
9635: ************* obviously, have to do something here!!!
9636:
9637: * Copyright (c) 1988 Regents of the University of California.
9638: * All rights reserved.
9639: *
9640: * Redistribution and use in source and binary forms are permitted
9641: * provided that the above copyright notice and this paragraph are
9642: * duplicated in all such forms and that any documentation,
9643: * advertising materials, and other materials related to such
9644: * distribution and use acknowledge that the software was developed
9645: * by the University of California, Berkeley. The name of the
9646: * University may not be used to endorse or promote products derived
9647: * from this software without specific prior written permission.
9648: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9649: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
9650: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
9651: */
9652:
9653: /*
9654: $Header: /usr2/odi/lib.src/RCS/doprint.C,v 1.3 89/09/19 12:00:34 benson Exp $
9655:
9656: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
9657: All rights reserved.
9658:
9659: */
9660:
9661: #include <sys/types.h>
9662: #include <stdarg.h>
9663: #include <ctype.h>
9664: #include <iostream.h>
9665: #include <strstream.h>
9666: #include <memory.h>
9667: #include <math.h>
9668: #include <string.h>
9669: #include "print_self.h"
9670:
9671: /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
9672: #define MAXEXP 308
9673: /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
9674: #define MAXFRACT 39
9675:
9676: #define DEFPREC 6
9677:
9678: #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
9679:
9680: #define PUTC(ch) (void) fp.put(ch)
9681:
9682: #define ARG() \
9683: _ulong = flags&LONGINT ? va_arg(argp, long) : \
9684: flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int);
9685:
9686: #define todigit(c) ((c) - '0')
9687: #define tochar(n) ((n) + '0')
9688:
9689: #define LONGINT 0x01 /* long integer */
9690: #define LONGDBL 0x02 /* long double; unimplemented */
9691: #define SHORTINT 0x04 /* short integer */
9692: #define ALT 0x08 /* alternate form */
9693: #define LADJUST 0x10 /* left adjustment */
9694: #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
9695: #define HEXPREFIX 0x40 /* add 0x or 0X prefix */
9696:
9697:
9698: static char * exponent(char * p, int exp, u_char fmtch);
9699: static char * round(double fract,
9700: int * exp,
9701: char * start,
9702: char * end,
9703: char ch,
9704: char * signp);
9705:
9706:
9707:
9708: static
9709: cvt(double number,
9710: register int prec,
9711: int flags,
9712: char * signp,
9713: u_char fmtch,
9714: char * startp,
9715: char * endp)
9716: {
9717: register char *p, *t;
9718: register double fract;
9719: int dotrim, expcnt, gformat;
9720: double integer, tmp;
9721:
9722: dotrim = expcnt = gformat = 0;
9723: fract = modf(number, &integer);
9724:
9725: /* get an extra slot for rounding. */
9726: t = ++startp;
9727:
9728: /*
9729: * get integer portion of number; put into the end of the buffer; the
9730: * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
9731: */
9732: for (p = endp - 1; integer; ++expcnt) {
9733: tmp = modf(integer / 10, &integer);
9734: *p-- = tochar((int)((tmp + .01) * 10));
9735: }
9736: switch(fmtch) {
9737: case 'f':
9738: /* reverse integer into beginning of buffer */
9739: if (expcnt)
9740: for (; ++p < endp; *t++ = *p);
9741: else
9742: *t++ = '0';
9743: /*
9744: * if precision required or alternate flag set, add in a
9745: * decimal point.
9746: */
9747: if (prec || flags&ALT)
9748: *t++ = '.';
9749: /* if requires more precision and some fraction left */
9750: if (fract) {
9751: if (prec)
9752: do {
9753: fract = modf(fract * 10, &tmp);
9754: *t++ = tochar((int)tmp);
9755: } while (--prec && fract);
9756: if (fract)
9757: startp = round(fract, (int *)NULL, startp,
9758: t - 1, (char)0, signp);
9759: }
9760: for (; prec--; *t++ = '0');
9761: break;
9762: case 'e':
9763: case 'E':
9764: eformat: if (expcnt) {
9765: *t++ = *++p;
9766: if (prec || flags&ALT)
9767: *t++ = '.';
9768: /* if requires more precision and some integer left */
9769: for (; prec && ++p < endp; --prec)
9770: *t++ = *p;
9771: /*
9772: * if done precision and more of the integer component,
9773: * round using it; adjust fract so we don't re-round
9774: * later.
9775: */
9776: if (!prec && ++p < endp) {
9777: fract = 0;
9778: startp = round((double)0, &expcnt, startp,
9779: t - 1, *p, signp);
9780: }
9781: /* adjust expcnt for digit in front of decimal */
9782: --expcnt;
9783: }
9784: /* until first fractional digit, decrement exponent */
9785: else if (fract) {
9786: /* adjust expcnt for digit in front of decimal */
9787: for (expcnt = -1;; --expcnt) {
9788: fract = modf(fract * 10, &tmp);
9789: if (tmp)
9790: break;
9791: }
9792: *t++ = tochar((int)tmp);
9793: if (prec || flags&ALT)
9794: *t++ = '.';
9795: }
9796: else {
9797: *t++ = '0';
9798: if (prec || flags&ALT)
9799: *t++ = '.';
9800: }
9801: /* if requires more precision and some fraction left */
9802: if (fract) {
9803: if (prec)
9804: do {
9805: fract = modf(fract * 10, &tmp);
9806: *t++ = tochar((int)tmp);
9807: } while (--prec && fract);
9808: if (fract)
9809: startp = round(fract, &expcnt, startp,
9810: t - 1, (char)0, signp);
9811: }
9812: /* if requires more precision */
9813: for (; prec--; *t++ = '0');
9814:
9815: /* unless alternate flag, trim any g/G format trailing 0's */
9816: if (gformat && !(flags&ALT)) {
9817: while (t > startp && *--t == '0');
9818: if (*t == '.')
9819: --t;
9820: ++t;
9821: }
9822: t = exponent(t, expcnt, fmtch);
9823: break;
9824: case 'g':
9825: case 'G':
9826: /* a precision of 0 is treated as a precision of 1. */
9827: if (!prec)
9828: ++prec;
9829: /*
9830: * ``The style used depends on the value converted; style e
9831: * will be used only if the exponent resulting from the
9832: * conversion is less than -4 or greater than the precision.''
9833: * -- ANSI X3J11
9834: */
9835: if (expcnt > prec || !expcnt && fract && fract < .0001) {
9836: /*
9837: * g/G format counts "significant digits, not digits of
9838: * precision; for the e/E format, this just causes an
9839: * off-by-one problem, i.e. g/G considers the digit
9840: * before the decimal point significant and e/E doesn't
9841: * count it as precision."
9842: */
9843: --prec;
9844: fmtch -= 2; /* G->E, g->e */
9845: gformat = 1;
9846: goto eformat;
9847: }
9848: /*
9849: * reverse integer into beginning of buffer,
9850: * note, decrement precision
9851: */
9852: if (expcnt)
9853: for (; ++p < endp; *t++ = *p, --prec);
9854: else
9855: *t++ = '0';
9856: /*
9857: * if precision required or alternate flag set, add in a
9858: * decimal point. If no digits yet, add in leading 0.
9859: */
9860: if (prec || flags&ALT) {
9861: dotrim = 1;
9862: *t++ = '.';
9863: }
9864: else
9865: dotrim = 0;
9866: /* if requires more precision and some fraction left */
9867: if (fract) {
9868: if (prec) {
9869: do {
9870: fract = modf(fract * 10, &tmp);
9871: *t++ = tochar((int)tmp);
9872: } while(!tmp);
9873: while (--prec && fract) {
9874: fract = modf(fract * 10, &tmp);
9875: *t++ = tochar((int)tmp);
9876: }
9877: }
9878: if (fract)
9879: startp = round(fract, (int *)NULL, startp,
9880: t - 1, (char)0, signp);
9881: }
9882: /* alternate format, adds 0's for precision, else trim 0's */
9883: if (flags&ALT)
9884: for (; prec--; *t++ = '0');
9885: else if (dotrim) {
9886: while (t > startp && *--t == '0');
9887: if (*t != '.')
9888: ++t;
9889: }
9890: }
9891: return(t - startp);
9892: }
9893:
9894: static char * round(double fract,
9895: int * exp,
9896: char * start,
9897: char * end,
9898: char ch,
9899: char * signp)
9900: {
9901: double tmp;
9902:
9903: if (fract)
9904: (void)modf(fract * 10, &tmp);
9905: else
9906: tmp = todigit(ch);
9907: if (tmp > 4)
9908: for (;; --end) {
9909: if (*end == '.')
9910: --end;
9911: if (++*end <= '9')
9912: break;
9913: *end = '0';
9914: if (end == start) {
9915: if (exp) { /* e/E; increment exponent */
9916: *end = '1';
9917: ++*exp;
9918: }
9919: else { /* f; add extra digit */
9920: *--end = '1';
9921: --start;
9922: }
9923: break;
9924: }
9925: }
9926: /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
9927: else if (*signp == '-')
9928: for (;; --end) {
9929: if (*end == '.')
9930: --end;
9931: if (*end != '0')
9932: break;
9933: if (end == start)
9934: *signp = 0;
9935: }
9936: return(start);
9937: }
9938:
9939: static char * exponent(char * p, int exp, u_char fmtch)
9940: {
9941: register char *t;
9942: char expbuf[MAXEXP];
9943:
9944: *p++ = fmtch;
9945: if (exp < 0) {
9946: exp = -exp;
9947: *p++ = '-';
9948: }
9949: else
9950: *p++ = '+';
9951: t = expbuf + MAXEXP;
9952: if (exp > 9) {
9953: do {
9954: *--t = tochar(exp % 10);
9955: } while ((exp /= 10) > 9);
9956: *--t = tochar(exp);
9957: for (; t < expbuf + MAXEXP; *p++ = *t++);
9958: }
9959: else {
9960: *p++ = '0';
9961: *p++ = tochar(exp);
9962: }
9963: return(p);
9964: }
9965:
9966: int vostream_printf(const char *fmt0, va_list argp, ostream& fp)
9967: {
9968: register const u_char *fmt; /* format string */
9969: register int ch; /* character from fmt */
9970: register int cnt; /* return value accumulator */
9971: register int n; /* random handy integer */
9972: register char *t; /* buffer pointer */
9973: double _double; /* double precision arguments %[eEfgG] */
9974: u_long _ulong; /* integer arguments %[diouxX] */
9975: int base; /* base for [diouxX] conversion */
9976: int dprec; /* decimal precision in [diouxX] */
9977: int fieldsz; /* field size expanded by sign, etc */
9978: int flags; /* flags as above */
9979: int fpprec; /* `extra' floating precision in [eEfgG] */
9980: int prec; /* precision from format (%.3d), or -1 */
9981: int realsz; /* field size expanded by decimal precision */
9982: int size; /* size of converted field or string */
9983: int width; /* width from format (%8d), or 0 */
9984: char sign; /* sign prefix (' ', '+', '-', or \0) */
9985: char softsign; /* temporary negative sign for floats */
9986: char *digs; /* digits for [diouxX] conversion */
9987: char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
9988:
9989: fmt = (const u_char *)fmt0;
9990: digs = "0123456789abcdef";
9991: for (cnt = 0;; ++fmt) {
9992: for (;(ch = *fmt) && ch != '%'; ++cnt, ++fmt)
9993: PUTC(ch);
9994: if (!ch)return (cnt);
9995:
9996: flags = 0; dprec = 0; fpprec = 0; width = 0;
9997: prec = -1;
9998: sign = '\0';
9999:
10000: rflag: switch (*++fmt) {
10001: case ' ':
10002: /*
10003: * ``If the space and + flags both appear, the space
10004: * flag will be ignored.''
10005: * -- ANSI X3J11
10006: */
10007: if (!sign)
10008: sign = ' ';
10009: goto rflag;
10010: case '#':
10011: flags |= ALT;
10012: goto rflag;
10013: case '*':
10014: /*
10015: * ``A negative field width argument is taken as a
10016: * - flag followed by a positive field width.''
10017: * -- ANSI X3J11
10018: * They don't exclude field widths read from args.
10019: */
10020: if ((width = va_arg(argp, int)) >= 0)
10021: goto rflag;
10022: width = -width;
10023: /* FALLTHROUGH */
10024: case '-':
10025: flags |= LADJUST;
10026: goto rflag;
10027: case '+':
10028: sign = '+';
10029: goto rflag;
10030: case '.':
10031: if (*++fmt == '*')
10032: n = va_arg(argp, int);
10033: else {
10034: n = 0;
10035: while (isascii(*fmt) && isdigit(*fmt))
10036: n = 10 * n + todigit(*fmt++);
10037: --fmt;
10038: }
10039: prec = n < 0 ? -1 : n;
10040: goto rflag;
10041: case '0':
10042: /*
10043: * ``Note that 0 is taken as a flag, not as the
10044: * beginning of a field width.''
10045: * -- ANSI X3J11
10046: */
10047: flags |= ZEROPAD;
10048: goto rflag;
10049: case '1': case '2': case '3': case '4':
10050: case '5': case '6': case '7': case '8': case '9':
10051: n = 0;
10052: do {
10053: n = 10 * n + todigit(*fmt);
10054: } while (isascii(*++fmt) && isdigit(*fmt));
10055: width = n;
10056: --fmt;
10057: goto rflag;
10058: case 'L':
10059: flags |= LONGDBL;
10060: goto rflag;
10061: case 'h':
10062: flags |= SHORTINT;
10063: goto rflag;
10064: case 'l':
10065: flags |= LONGINT;
10066: goto rflag;
10067: case 'c':
10068: *(t = buf) = va_arg(argp, int);
10069: size = 1;
10070: sign = '\0';
10071: goto pforw;
10072: case 'D':
10073: flags |= LONGINT;
10074: /*FALLTHROUGH*/
10075: case 'd':
10076: case 'i':
10077: ARG();
10078: if ((long)_ulong < 0) {
10079: _ulong = -_ulong;
10080: sign = '-';
10081: }
10082: base = 10;
10083: goto number;
10084: case 'e':
10085: case 'E':
10086: case 'f':
10087: case 'g':
10088: case 'G':
10089: _double = va_arg(argp, double);
10090: /*
10091: * don't do unrealistic precision; just pad it with
10092: * zeroes later, so buffer size stays rational.
10093: */
10094: if (prec > MAXFRACT) {
10095: if (*fmt != 'g' && *fmt != 'G' || (flags&ALT))
10096: fpprec = prec - MAXFRACT;
10097: prec = MAXFRACT;
10098: }
10099: else if (prec == -1)
10100: prec = DEFPREC;
10101: /*
10102: * softsign avoids negative 0 if _double is < 0 and
10103: * no significant digits will be shown
10104: */
10105: if (_double < 0) {
10106: softsign = '-';
10107: _double = -_double;
10108: }
10109: else
10110: softsign = 0;
10111: /*
10112: * cvt may have to round up past the "start" of the
10113: * buffer, i.e. ``intf("%.2f", (double)9.999);'';
10114: * if the first char isn't NULL, it did.
10115: */
10116: *buf = NULL;
10117: size = cvt(_double, prec, flags, &softsign, *fmt, buf,
10118: buf + sizeof(buf));
10119: if (softsign)
10120: sign = '-';
10121: t = *buf ? buf : buf + 1;
10122: goto pforw;
10123: case 'n':
10124: if (flags & LONGINT)
10125: *va_arg(argp, long *) = cnt;
10126: else if (flags & SHORTINT)
10127: *va_arg(argp, short *) = cnt;
10128: else
10129: *va_arg(argp, int *) = cnt;
10130: break;
10131: case 'O':
10132: flags |= LONGINT;
10133: /*FALLTHROUGH*/
10134: case 'o':
10135: ARG();
10136: base = 8;
10137: goto nosign;
10138: case 'T': // Type
10139: {
10140: streampos cur_pos;
10141: streampos new_pos;
10142:
10143: cur_pos = fp.tellp();
10144:
10145: _Print_self * obj = va_arg (argp, _Print_self *);
10146: obj->print_self (fp);
10147:
10148: new_pos = fp.tellp();
10149:
10150: cnt += int (new_pos - cur_pos);
10151: }
10152: break;
10153:
10154: case 'p':
10155: /*
10156: * ``The argument shall be a pointer to void. The
10157: * value of the pointer is converted to a sequence
10158: * of printable characters, in an implementation-
10159: * defined manner.''
10160: * -- ANSI X3J11
10161: */
10162: /* NOSTRICT */
10163: _ulong = (u_long)va_arg(argp, void *);
10164: base = 16;
10165: goto nosign;
10166: case 's':
10167: if (!(t = va_arg(argp, char *)))
10168: t = "(null)";
10169: if (prec >= 0) {
10170: /*
10171: * can't use strlen; can only look for the
10172: * NUL in the first `prec' characters, and
10173: * strlen() will go further.
10174: */
10175: char *p;
10176:
10177: if (p = (char *) memchr(t, 0, prec)) {
10178: size = p - t;
10179: if (size > prec)
10180: size = prec;
10181: } else
10182: size = prec;
10183: } else
10184: size = strlen(t);
10185: sign = '\0';
10186: goto pforw;
10187: case 'U':
10188: flags |= LONGINT;
10189: /*FALLTHROUGH*/
10190: case 'u':
10191: ARG();
10192: base = 10;
10193: goto nosign;
10194: case 'X':
10195: digs = "0123456789ABCDEF";
10196: /* FALLTHROUGH */
10197: case 'x':
10198: ARG();
10199: base = 16;
10200: /* leading 0x/X only if non-zero */
10201: if (flags & ALT && _ulong != 0)
10202: flags |= HEXPREFIX;
10203:
10204: /* unsigned conversions */
10205: nosign: sign = '\0';
10206: /*
10207: * ``... diouXx conversions ... if a precision is
10208: * specified, the 0 flag will be ignored.''
10209: * -- ANSI X3J11
10210: */
10211: number: if ((dprec = prec) >= 0)
10212: flags &= ~ZEROPAD;
10213:
10214: /*
10215: * ``The result of converting a zero value with an
10216: * explicit precision of zero is no characters.''
10217: * -- ANSI X3J11
10218: */
10219: t = buf + BUF;
10220: if (_ulong != 0 || prec != 0) {
10221: do {
10222: *--t = digs[_ulong % base];
10223: _ulong /= base;
10224: } while (_ulong);
10225: digs = "0123456789abcdef";
10226: if (flags & ALT && base == 8 && *t != '0')
10227: *--t = '0'; /* octal leading 0 */
10228: }
10229: size = buf + BUF - t;
10230:
10231: pforw:
10232: /*
10233: * All reasonable formats wind up here. At this point,
10234: * `t' points to a string which (if not flags&LADJUST)
10235: * should be padded out to `width' places. If
10236: * flags&ZEROPAD, it should first be prefixed by any
10237: * sign or other prefix; otherwise, it should be blank
10238: * padded before the prefix is emitted. After any
10239: * left-hand padding and prefixing, emit zeroes
10240: * required by a decimal [diouxX] precision, then print
10241: * the string proper, then emit zeroes required by any
10242: * leftover floating precision; finally, if LADJUST,
10243: * pad with blanks.
10244: */
10245:
10246: /*
10247: * compute actual size, so we know how much to pad
10248: * fieldsz excludes decimal prec; realsz includes it
10249: */
10250: fieldsz = size + fpprec;
10251: if (sign)
10252: fieldsz++;
10253: if (flags & HEXPREFIX)
10254: fieldsz += 2;
10255: realsz = dprec > fieldsz ? dprec : fieldsz;
10256:
10257: /* right-adjusting blank padding */
10258: if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
10259: for (n = realsz; n < width; n++)
10260: PUTC(' ');
10261: /* prefix */
10262: if (sign)
10263: PUTC(sign);
10264: if (flags & HEXPREFIX) {
10265: PUTC('0');
10266: PUTC((char)*fmt);
10267: }
10268: /* right-adjusting zero padding */
10269: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
10270: for (n = realsz; n < width; n++)
10271: PUTC('0');
10272: /* leading zeroes from decimal precision */
10273: for (n = fieldsz; n < dprec; n++)
10274: PUTC('0');
10275:
10276: /* the string or number proper */
10277:
10278: fp.write(t, size);
10279:
10280: /* trailing f.p. zeroes */
10281: while (--fpprec >= 0)
10282: PUTC('0');
10283: /* left-adjusting padding (always blank) */
10284: if (flags & LADJUST)
10285: for (n = realsz; n < width; n++)
10286: PUTC(' ');
10287: /* finally, adjust cnt */
10288: cnt += width > realsz ? width : realsz;
10289: break;
10290: case '\0': /* "%?" prints ?, unless ? is NULL */
10291: return (cnt);
10292: default:
10293: PUTC(*fmt);
10294: cnt++;
10295: }
10296: }
10297: /* NOTREACHED */
10298: }
10299:
10300: int ostream_printf(ostream& stream, const char * format ...)
10301: {
10302: int ret;
10303:
10304: va_list args;
10305: va_start(args, format);
10306: ret = vostream_printf(format, args, stream);
10307: va_end(args);
10308: return ret;
10309: }
10310:
10311: // There are intended to be more convienient that stirring up
10312: // an strstream by hand.
10313:
10314: int printf_to_string (char * string, int length, const char * format ...)
10315: {
10316: ostrstream& stream = ostrstream (string, length, (ios::open_mode)ios::app);
10317:
10318: va_list args;
10319: va_start(args, format);
10320:
10321: vostream_printf (format, args, stream);
10322:
10323: va_end(args);
10324: stream.str();
10325: return stream.pcount();
10326: }
10327:
10328: // caller of this must free() the string that comes back.
10329:
10330: char * printf_to_alloc_string (const char * format ...)
10331: {
10332: ostrstream& stream = ostrstream ();
10333:
10334: va_list args;
10335: va_start(args, format);
10336:
10337: vostream_printf (format, args, stream);
10338:
10339: va_end(args);
10340: return stream.str();
10341: }
10342: 0707071010112044141004440001630000160000010176000466055377500001000000031505error.c /*ident "@(#)ctrans:src/error.c 1.4" */
10343: /**************************************************************************
10344:
10345: C++ source for cfront, the C++ compiler front-end
10346: written in the computer science research center of Bell Labs
10347:
10348: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
10349: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
10350:
10351: error.c :
10352:
10353: write error messages
10354:
10355: Until scan_started != 0 no context can be assumed
10356:
10357: ***************************************************************************/
10358:
10359: #ifdef __cplusplus
10360: #include <stdlib.h>
10361: #endif
10362:
10363: #include "cfront.h"
10364: #include "size.h"
10365: #include "template.h"
10366:
10367: int error_count;
10368: static int no_of_warnings;
10369: char scan_started;
10370:
10371: #define ERRTRACE 20
10372:
10373: static char* abbrev_tbl[] = {
10374: " argument",
10375: " base",
10376: " class",
10377: " declaration",
10378: " expression",
10379: " function",
10380: " global",
10381: "H",
10382: " initialize",
10383: "J",
10384: " constructor", // 'K' !
10385: " list",
10386: " member",
10387: " name",
10388: " object",
10389: " pointer",
10390: " qualifie",
10391: " reference",
10392: " statement",
10393: " type",
10394: " undefined",
10395: " variable",
10396: " with",
10397: " expected", // 'X'
10398: " template", // 'Y'???
10399: " parameter", // 'Z'???
10400: };
10401:
10402: ea* ea0;
10403:
10404: void error_init()
10405: {
10406: static char errbuf[BUFSIZ];
10407: setbuf(stderr,errbuf);
10408: ea0 = new ea;
10409: }
10410:
10411: #define INTERNAL 127
10412:
10413: void ext(int n)
10414: {
10415: int useit=n; // to avoid n not used warning during build
10416: // for testing only
10417: // if (n == INTERNAL)
10418: // abort();
10419: exit(error_count?error_count:1);
10420: }
10421:
10422: /* static */
10423: void print_loc()
10424: {
10425: loc* sl = (Cstmt) ? &Cstmt->where : 0;
10426: loc* dl = (Cdcl && (Cdcl->base==NAME || Cdcl->base==TNAME)) ? &Cdcl->where : 0;
10427: if (sl && dl && sl->file==dl->file) { // Cstmt and Cdcl in same file
10428: if (sl->line<=dl->line) {
10429: if (curloc.file==dl->file && curloc.line<dl->line)
10430: // hack to compensate for YACC's
10431: // bad manners in the use of line numbers
10432: sl->put(out_file);
10433: else
10434: dl->put(out_file);
10435: }
10436: else
10437: sl->put(out_file);
10438: }
10439: else if (sl && sl->file==curr_file) // Cstmt in current file
10440: sl->put(out_file);
10441: else if (dl && dl->file==curr_file) // Cdcl in current file
10442: dl->put(out_file);
10443: else
10444: curloc.put(out_file);
10445: }
10446:
10447: static void print_context()
10448: {
10449: putc('\n',out_file);
10450: }
10451:
10452: static char in_error = 0;
10453: static loc dummy_loc;
10454:
10455: void yyerror(char* s)
10456: {
10457: error(s);
10458: }
10459:
10460: int error(const char* s)
10461: {
10462: return error(0,s);
10463: }
10464:
10465: int error(int t, const char* s)
10466: {
10467: return error(t,&dummy_loc,s,*ea0,*ea0,*ea0,*ea0);
10468: }
10469:
10470: int error(const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
10471: {
10472: return error(0,&dummy_loc,s,a0,a1,a2,a3);
10473: }
10474:
10475: int error(loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
10476: {
10477: return error(0,lc,s,a0,a1,a2,a3);
10478: }
10479:
10480: int error(int t, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
10481: {
10482: return error(t,&dummy_loc,s,a0,a1,a2,a3);
10483: }
10484:
10485: int suppress_error;
10486:
10487: int error(int t, loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
10488: /*
10489: "int" not "void" because of "pch" in lex.c
10490:
10491: legal error types are:
10492: 'w' warning (not counted in error count)
10493: 'd' debug
10494: 'D' debug -- no prefix
10495: 's' "not implemented" message
10496: 'l' "compiler limit exceeded" message
10497: 0 error
10498: 'i' internal error (causes abort)
10499: 't' error while printing error message
10500: */
10501: {
10502: if (suppress_error) return 0;
10503:
10504: if (in_error++)
10505: if (t == 't')
10506: t = 'i';
10507: else if (4 < in_error) {
10508: fprintf(stderr,"\nOops!, error while handling error\n");
10509: ext(13);
10510: }
10511:
10512: FILE * of = out_file;
10513: out_file = stderr;
10514:
10515: if (!scan_started || t=='t')
10516: putch('\n');
10517: else if (lc != &dummy_loc) {
10518: if(t != 'D') lc->put(out_file);
10519: } else {
10520: if(t != 'D') print_loc();
10521: }
10522:
10523: switch (t) {
10524: case 0:
10525: putstring("error: ");
10526: break;
10527: case 'd':
10528: putstring("DEBUG: ");
10529: case 'D':
10530: break;
10531: case 'w':
10532: no_of_warnings++;
10533: putstring("warning: ");
10534: break;
10535: case 'l':
10536: putstring("compiler limit exceeded: ");
10537: break;
10538: case 's':
10539: putstring("sorry, not implemented: ");
10540: break;
10541: case 'i':
10542: if (error_count++) {
10543: fprintf(out_file,"sorry, %s cannot recover from earlier errors\n",prog_name);
10544: ext(INTERNAL);
10545: }
10546: else
10547: fprintf(out_file,"internal %s error: ",prog_name);
10548: }
10549:
10550: ea argv[4];
10551: ea* a = argv;
10552: argv[0] = a0;
10553: argv[1] = a1;
10554: argv[2] = a2;
10555: argv[3] = a3;
10556:
10557: int c;
10558:
10559: while (c = *s++) {
10560: if ('A'<=c && c<='Z')
10561: putstring(abbrev_tbl[c-'A']);
10562: else if (c == '%') {
10563: switch (c = *s++) {
10564: case 'k': // TOK assumed passed as an int
10565: { TOK x = TOK(a->i);
10566: if (0<x && x<=MAXTOK && keys[x])
10567: fprintf(out_file," %s",keys[x]);
10568: else
10569: fprintf(out_file," token(%d)",x);
10570: break;
10571: }
10572: case 't': // Ptype
10573: { Ptype tt = Ptype(a->p);
10574: if (tt == 0) break;
10575:
10576: putch(' ');
10577:
10578: int nt = ntok;
10579: emode = 1;
10580: tt->dcl_print(0);
10581: emode = 0;
10582: ntok = nt;
10583: break;
10584: }
10585: case 'n': // Pname
10586: { Pname nn = Pname(a->p);
10587: if (nn && nn->string) {
10588: // suppress generated class names:
10589: if (nn->string[0]=='_'
10590: && nn->string[1]=='_'
10591: && nn->string[2]=='C') break;
10592: emode = 1;
10593: putch(' ');
10594: nn->print();
10595: emode = 0;
10596: }
10597: else
10598: putstring(" ?");
10599: break;
10600: }
10601: case 'p': // pointer
10602: { char* f = sizeof(char*)==sizeof(int)?" %d":" %ld";
10603: fprintf(out_file,f,a->p);
10604: break;
10605: }
10606: case 'c': // char assumed passed as an int
10607: putch(a->i);
10608: break;
10609:
10610: case 'd': // int
10611: fprintf(out_file," %d",a->i);
10612: break;
10613:
10614: case 'o': // int
10615: fprintf(out_file," %o",a->i);
10616: break;
10617:
10618: case 's': // char*
10619: char *s = ((char *)a->p);
10620: if ( s ) putst((char*)a->p);
10621: break;
10622: }
10623: a++;
10624: }
10625: else
10626: putch(c);
10627: }
10628:
10629: /*
10630: switch (t) {
10631: case 'd':
10632: case 't':
10633: case 'w':
10634: putch('\n');
10635: break;
10636: default:
10637: */
10638: print_context();
10639: /*
10640: }
10641: */
10642:
10643: templ_inst::head->print_error_loc();
10644: fflush(stderr);
10645: if (!scan_started && t!='d' && t!='w') ext(4);
10646:
10647: // now we may want to carry on
10648: out_file = of;
10649: switch (t) {
10650: case 't':
10651: if (--in_error) return 0;
10652: case 'i':
10653: ext(INTERNAL);
10654: case 0:
10655: case 'l':
10656: case 's':
10657: if (MAXERR<++error_count) {
10658: fprintf(stderr,"Sorry, too many errors\n");
10659: ext(7);
10660: }
10661: }
10662:
10663: in_error = 0;
10664: return 0;
10665: }
10666:
10667:
10668:
10669: #ifdef DBG
10670: #define OPEREP(v) ((v)>MAXTOK || (v)<=0 ? 0 : keys[v])
10671: void
10672: display_type( Ptype t )
10673: {
10674: if ( t ) { putc(' ',stderr);
10675: FILE * of = out_file;
10676: out_file = stderr;
10677: extern int ntok; int nt = ntok;
10678: emode=1; (t)->dcl_print(0); emode=0;
10679: //fprintf(stderr," <node %d",t->node::id);
10680: if(!t->allocated)fprintf(stderr," UNALLOCATED!");
10681: //putc('>',stderr);
10682: ntok = nt;
10683: out_file = of;
10684: } else fprintf(stderr," <null type>");
10685: }
10686: #define INDENT(in) { for ( int i = in; i > 0; --i ) fprintf(stderr," "); }
10687: static indent = 0;
10688:
10689: void
10690: display_expr( Pexpr ptr, char* label, int oneline )
10691: {
10692: INDENT(indent);
10693: if ( label ) fprintf(stderr, "%s:", label);
10694: if ( ptr == 0 ) {
10695: fprintf(stderr, "NULL EXPR\n" );
10696: return;
10697: }
10698: fprintf(stderr,"%d",ptr->node::id);
10699: if(!ptr->allocated)fprintf(stderr," UNALLOCATED!");
10700: putc(':',stderr);
10701: char* s = OPEREP(ptr->base);
10702: if ( s == 0 )
10703: fprintf(stderr, "token(%d)", ptr->base );
10704: else
10705: fprintf(stderr,"%s",s);
10706: if ( ptr->displayed ) { // recursion!!!
10707: if ( ptr->base == NAME )
10708: fprintf(stderr," '%s'",Pname(ptr)->string);
10709: fprintf(stderr," RECURSION!!!\n");
10710: ptr->displayed = 0;
10711: return;
10712: }
10713: ptr->displayed = 1;
10714: switch ( ptr->base ) {
10715: case QUEST:
10716: display_type(ptr->tp);
10717: putc('\n',stderr);
10718: if ( !oneline ) {
10719: ++indent;
10720: display_expr( ptr->cond, "cond" );
10721: display_expr( ptr->e1, "e1" );
10722: display_expr( ptr->e2, "e2" );
10723: --indent;
10724: }
10725: break;
10726: case REF: case DOT:
10727: display_type(ptr->tp);
10728: putc('\n',stderr);
10729: if ( !oneline ) {
10730: ++indent;
10731: display_expr( ptr->e1, "e1" );
10732: display_expr( ptr->mem, "mem" );
10733: --indent;
10734: }
10735: break;
10736: case MDOT:
10737: display_type(ptr->tp);
10738: fprintf(stderr," string2:'%s'\n",ptr->string2?ptr->string2:"");
10739: if ( !oneline ) {
10740: ++indent;
10741: display_expr( ptr->mem, "mem" );
10742: --indent;
10743: }
10744: break;
10745: case ICALL:
10746: fprintf(stderr," fn=='%s'",ptr->il->fct_name->string);
10747: display_type(ptr->tp);
10748: putc('\n',stderr);
10749: if ( !oneline ) {
10750: ++indent;
10751: for ( int i = 0; i < ptr->il->i_slots; ++i ) {
10752: ia *aa = &ptr->il->i_args[i];
10753: INDENT(indent);
10754: fprintf(stderr,"arg:'%s'",aa->local&&aa->local->string?aa->local->string:"");
10755: display_type(aa->tp);
10756: putc('\n',stderr);
10757: ++indent;
10758: display_expr( aa->arg, "actual" );
10759: --indent;
10760: }
10761: display_expr( ptr->e1, "e1" );
10762: display_expr( ptr->e2, "e2" );
10763: --indent;
10764: }
10765: break;
10766: case SIZEOF:
10767: if ( ptr->tp2 ) {
10768: putc('(',stderr);
10769: display_type(ptr->tp2);
10770: putc(')',stderr);
10771: }
10772: display_type(ptr->tp);
10773: putc('\n',stderr);
10774: if ( !oneline ) {
10775: if ( ptr->e1 ) {
10776: ++indent;
10777: display_expr(ptr->e1,"e1");
10778: --indent;
10779: }
10780: if ( ptr->e2 ) {
10781: ++indent;
10782: display_expr(ptr->e2,"e2");
10783: --indent;
10784: }
10785: }
10786: break;
10787: case ZERO:
10788: display_type(ptr->tp);
10789: putc('\n',stderr);
10790: break;
10791: case NAME: case TNAME: case STRING:
10792: case ICON: case ID:
10793: case FCON: case CCON:
10794: case IVAL:
10795: fprintf(stderr," '%s'",(ptr->string)?ptr->string:"<0>");
10796: display_type(ptr->tp);
10797: if(ptr->string2)fprintf(stderr," string2=='%s'",ptr->string2);
10798: if ( ptr->permanent ) fprintf(stderr, " (permanent)");
10799: if ( ptr->base == IVAL ) fprintf(stderr, " i1==%d", ptr->i1);
10800: putc('\n',stderr);
10801: if ( !oneline && (ptr->base == NAME || ptr->base == TNAME) ) {
10802: Pname n = Pname(ptr);
10803: ++indent;
10804: INDENT(indent);
10805: fprintf(stderr, "n_sto==%d", n->n_sto );
10806: fprintf(stderr, " n_stclass==%d",n->n_stclass);
10807: fprintf(stderr, " n_scope==%d",n->n_scope);
10808: fprintf(stderr, " n_protected==%d\n", n->n_protect );
10809: INDENT(indent);
10810: fprintf(stderr, "n_oper=='%s'", (s=OPEREP(n->base))?s:"0");
10811: fprintf(stderr, " n_val==%d", n->n_val );
10812: fprintf(stderr, " n_xref==%d",n->n_xref);
10813: fprintf(stderr, " lex_level==%d\n", n->lex_level );
10814: INDENT(indent);
10815: fprintf(stderr, "n_used==%d",n->n_used);
10816: fprintf(stderr, " n_assigned_to==%d",n->n_assigned_to);
10817: fprintf(stderr, " n_addr_taken==%d\n",n->n_addr_taken );
10818: INDENT(indent);
10819: fprintf(stderr, "n_union==%d", n->n_union);
10820: fprintf(stderr, " n_list=='%s'", n->n_list?n->n_list->string:"<0>" );
10821: fprintf(stderr, " n_qualifier=='%s'", n->n_qualifier?n->n_qualifier->string:"<0>" );
10822: if ( n->n_initializer ) {
10823: fprintf(stderr, " n_initializer:\n" );
10824: ++indent;
10825: display_expr( n->n_initializer );
10826: --indent;
10827: } else fprintf(stderr, " n_initializer==<0>\n");
10828: --indent;
10829: }
10830: break;
10831: case BLOCK:
10832: ((Pstmt)ptr)->where.put(stderr); putc(' ',stderr);
10833: putc('\n',stderr);
10834: break;
10835: default:
10836: display_type(ptr->tp);
10837: putc('\n',stderr);
10838: if ( !oneline && ptr->base > 0
10839: && (ptr->base<165 || ptr->base==MEMPTR) ) {
10840: ++indent;
10841: display_expr( ptr->e1, "e1" );
10842: display_expr( ptr->e2, "e2" );
10843: --indent;
10844: }
10845: break;
10846: }
10847: ptr->displayed = 0;
10848: return;
10849: }
10850: void
10851: display_stmt( Pstmt ptr, char* label, int oneline )
10852: {
10853: INDENT(indent);
10854: if ( label ) fprintf(stderr, "%s:", label);
10855: if ( ptr == 0 ) {
10856: fprintf(stderr, "NULL STMT\n" );
10857: return;
10858: }
10859: fprintf(stderr,"%d",ptr->node::id);
10860: if(!ptr->allocated)fprintf(stderr," UNALLOCATED!");
10861: putc(':',stderr);
10862: char* s = OPEREP(ptr->base);
10863: if ( s == 0 )
10864: fprintf(stderr, "token(%d)", ptr->base );
10865: else
10866: fprintf(stderr,"%s",s);
10867: if ( ptr->displayed ) { // recursion!!!
10868: if ( ptr->base == NAME )
10869: fprintf(stderr," '%s'",Pname(ptr)->string);
10870: fprintf(stderr," RECURSION!!!\n");
10871: ptr->displayed = 0;
10872: return;
10873: }
10874: putc(' ',stderr);
10875: ptr->where.put(stderr);
10876: if ( oneline ) { putc('\n',stderr); return; }
10877: ptr->displayed = 1;
10878: switch ( ptr->base ) {
10879: case BLOCK:
10880: fprintf(stderr," .. ");
10881: ptr->where2.put(stderr);
10882: putc('\n',stderr);
10883: ++indent;
10884: { for( Pstmt st = ptr->s; st; st = st->s_list )
10885: display_stmt( ptr->s, "s" );
10886: }
10887: --indent;
10888: break;
10889: case IF:
10890: putc('\n',stderr);
10891: ++indent;
10892: display_expr(ptr->e,"cond");
10893: display_stmt(ptr->s,"if-clause");
10894: --indent;
10895: if ( ptr->else_stmt ) {
10896: INDENT(indent);
10897: fprintf(stderr,"else\n");
10898: ++indent;
10899: display_stmt(ptr->else_stmt,"else-clause");
10900: --indent;
10901: }
10902: break;
10903: case DO:
10904: putc('\n',stderr);
10905: ++indent;
10906: display_stmt(ptr->s,"do-stmt");
10907: display_expr(ptr->e,"cond");
10908: --indent;
10909: break;
10910: case WHILE:
10911: putc('\n',stderr);
10912: ++indent;
10913: display_expr(ptr->e,"cond");
10914: display_stmt(ptr->s,"while-stmt");
10915: --indent;
10916: break;
10917: case FOR:
10918: putc('\n',stderr);
10919: ++indent;
10920: display_stmt(ptr->for_init,"init");
10921: display_expr(ptr->e,"cond");
10922: display_expr(ptr->e2,"incr");
10923: display_stmt(ptr->s,"stmt");
10924: --indent;
10925: break;
10926: case RETURN:
10927: putc('\n',stderr);
10928: ++indent;
10929: display_expr(ptr->e,"e");
10930: --indent;
10931: break;
10932: case SM:
10933: putc('\n',stderr);
10934: ++indent;
10935: display_expr(ptr->e,"e");
10936: --indent;
10937: break;
10938: default:
10939: putc('\n',stderr);
10940: break;
10941: }
10942: ptr->displayed = 0;
10943: return;
10944: }
10945:
10946: void
10947: display_namelist( Plist nl, char* s, int verbose )
10948: {
10949: error('d',"namelist: %s",s?s:"");
10950: ++indent;
10951: for ( Plist l = nl; l; l = l->l ) {
10952: Pname n = l->f;
10953: INDENT(indent);
10954: fprintf(stderr," %d",n);
10955: error('D'," %n %k n_key %d",n,n?n->tp->base:0,n?n->n_key:0);
10956: if ( verbose ) {
10957: ++indent;
10958: display_expr(n);
10959: --indent;
10960: }
10961: }
10962: --indent;
10963: }
10964: #endif
10965: 0707071010112044151004440001630000160000010176300466055400100001100000053752expand.c /*ident "@(#)ctrans:src/expand.c 1.3" */
10966: /*****************************************************************
10967:
10968: C++ source for cfront, the C++ compiler front-end
10969: written in the computer science research center of Bell Labs
10970:
10971: Copyright (c) 1984 AT&T, Inc. All rights Reserved
10972: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
10973:
10974: expand.c:
10975:
10976: expand inline functions
10977:
10978: ******************************************************************/
10979:
10980: #include "cfront.h"
10981: static Ptable Scope;
10982: // extern void display_expr(Pexpr);
10983:
10984: static char* temp(char* vn, Pname fn)
10985: //
10986: // make the name of the temporary: __Xvn00xxxxxx
10987: // xxxxxx is a representation of fn's address -
10988: // anything unique will do. we use radix 32 here
10989: // add two bytes to make the name sensitive to the scope
10990: // to avoid re-using temps when an inline is expanded in
10991: // more than one other inline that is then called in the
10992: // same expression
10993: //
10994: {
10995: if (vn[0]!='_' || vn[1]!='_' || vn[2]!='X') {
10996: unsigned long a = (unsigned long) fn->tp;
10997:
10998: // al = the number of radix-32 chars in a
10999: unsigned long aa = a;
11000: int al = 0;
11001: while (aa) {
11002: al++;
11003: aa >>= 5;
11004: }
11005:
11006: // allocate memory for the result
11007: int ll = strlen(vn);
11008: char* s = new char[ll+al+8];
11009: register char* p = s;
11010:
11011: // append _ _ X vn
11012: *p++ = '_';
11013: *p++ = '_';
11014: *p++ = 'X';
11015: strcpy(p,vn);
11016: p += ll;
11017: *p++ = '0';
11018: *p++ = '0';
11019:
11020: // append representation of `a'
11021: while (a) {
11022: *p++ = "abcdefghijklmnopqrstuvwxyz012345"[a&037];
11023: a >>= 5;
11024: }
11025:
11026: // append scope representation and trailing null
11027: *p++ = 'a' + ((int(Scope)>>4)&15);
11028: *p++ = 'a' + ((int(Scope)>>8)&15);
11029: *p = '\0';
11030: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,s);
11031: return s;
11032: }
11033: else {
11034: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,vn);
11035: return vn;
11036: }
11037:
11038: }
11039:
11040: Pname dcl_local(Ptable scope, Pname an, Pname fn)
11041: {
11042: if (scope == 0 || scope->base == 0) {
11043: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
11044: scope = sti_tbl;
11045: // error('s',"cannot expand inlineF needing temporaryV in nonF context");
11046: // return an;
11047: }
11048:
11049: if (an->n_stclass == STATIC) {
11050: if (an->tp->base!=FCT) error('s',&fn->where,"cannot expand inlineF with static%n",an);
11051: return an;
11052: }
11053:
11054: Pname cn = fn->n_table->t_name;
11055: char* s = temp(an->string,fn);
11056: Pname nx = new name(s);
11057: Ptype atp = an->tp;
11058: //error('d',"dcl_local(%d,%n,%n) -> %s",scope,an,fn,s);
11059: while (atp->base == TYPE) atp = Pbase(atp)->b_name->tp;
11060: if (atp->base == VEC) {
11061: if (an->n_scope == ARG) {
11062: Pptr t = new ptr(PTR,Pvec(atp)->typ);
11063: nx->tp = t;
11064: }
11065: else {
11066: error('s',&fn->where,"cannot expand inlineF needing temporaryV of vectorT");
11067: return an;
11068: }
11069: }
11070: else
11071: nx->tp = atp;
11072: PERM(nx->tp);
11073:
11074: nx->n_used = an->n_used;
11075: nx->n_assigned_to = an->n_assigned_to;
11076: nx->n_addr_taken = an->n_addr_taken;
11077: nx->n_xref = an->n_xref;
11078: //error('d',"nx %n %t,",nx,nx->tp);
11079: Pname r = scope->look(nx->string,0);
11080: if (r) {
11081: //error('d',"ll %n %t",ll,ll->tp);
11082: if (r->tp->check(nx->tp,0))
11083: error('s',&fn->where,"cannot expand inlineF %n with two local variables with the sameN (%s)",fn,an->string);
11084: else
11085: r = 0;
11086: }
11087: if (r==0) {
11088: r = scope->insert(nx,0);
11089: //error('d',"%d %d %d %d",r->n_stclass,an->n_stclass,r->lex_level,an->lex_level);
11090: r->n_stclass = an->n_stclass;
11091: r->lex_level = an->lex_level;
11092: delete nx;
11093: r->where.line = 0;
11094: }
11095: return r;
11096: }
11097:
11098: int ck_cast(Ptype t1, Ptype t2)
11099: /*
11100: return a value of type t2 from a function returning a t1
11101: return 1 if cast is needed
11102: */
11103: {
11104: st:
11105: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
11106: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
11107:
11108: if (t1 == t2) return 0;
11109:
11110: if (t1->base != t2->base) return 1;
11111:
11112: switch (t1->base) {
11113: case RPTR:
11114: case PTR:
11115: { t1 = Pptr(t1)->typ;
11116: if (t1->base == VOID) return 1;
11117: t2 = Pptr(t2)->typ;
11118: goto st;
11119: }
11120: case CHAR:
11121: case SHORT:
11122: case INT:
11123: case LONG:
11124: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) return 1;
11125: break;
11126: case COBJ:
11127: {
11128: Pname nn = Pbase(t1)->b_name;
11129:
11130: if (Pclass(nn->tp)->csu==UNION ) return 0;
11131:
11132: if (t2->base==COBJ && nn->tp==Pbase(t2)->b_name->tp) return 0;
11133:
11134: return 1;
11135: }
11136: }
11137:
11138: return 0;
11139: }
11140:
11141: int makeCM( Ptype t )
11142: /* return 1 if the type is not a primitive type
11143: * this will cause the generation of (t,0)
11144: * note: ``t'' is guaranteed not to be 0
11145: */
11146: {
11147: while ( t->base == TYPE )
11148: t = Pbase(t)->b_name->tp;
11149:
11150: switch (t->base) {
11151: case FLOAT:
11152: case DOUBLE:
11153: case LDOUBLE:
11154: case CHAR:
11155: case SHORT:
11156: case INT:
11157: case LONG:
11158: case EOBJ:
11159: return 0;
11160: default:
11161: return 1;
11162: }
11163: }
11164:
11165: static ret_seen = 0;
11166:
11167: Pstmt stmt::expand()
11168: /*
11169: copy the statements with the formal arguments replaced by ANAMES
11170:
11171: called once only per inline function
11172: expand_tbl!=0 if the function should be transformed into an expression
11173: and expand_tbl is the table for local variables
11174: */
11175: {
11176: if (this == 0) error('i',"0->S::expand() for%n",expand_fn);
11177: Pstmt ostmt = Cstmt;
11178: if ( where.line ) Cstmt = this;
11179:
11180: if (memtbl) { /* check for static variables */
11181: register Ptable t = memtbl;
11182: register int i;
11183: for (register Pname n = t->get_mem(i=1); n; n=t->get_mem(++i)) {
11184: if (n->n_stclass == STATIC) {
11185: if (n->tp->base == FCT) continue;
11186: error('s',"cannot expand inlineF with static%n",n);
11187: n->n_stclass = AUTO;
11188: }
11189: n->where.line = 0;
11190: }
11191: }
11192:
11193: if (expand_tbl) { /* make expression */
11194: Pexpr ee;
11195:
11196: if (memtbl) { // temporaries
11197: int i;
11198: for (Pname n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
11199: //error('d',"block %n %k %d %d",n,base,memtbl->real_block == this,n->lex_level);
11200: if (n->base!=NAME || n->tp==any_type) continue;
11201:
11202: if (base==BLOCK
11203: && memtbl->real_block == this
11204: && n->lex_level < 2
11205: && (n->string[0]!='_' // promoted from called
11206: // inlines
11207: || n->string[1]!='_'
11208: || ( n->string[2]!='X'
11209: && n->string[2]!='K'))
11210: ) {
11211: //error('d',"not promoting%n",n);
11212: continue;
11213: }
11214:
11215: if (memtbl != scope)
11216: {
11217: Pname nn = dcl_local(scope,n,expand_fn);
11218: nn->base = NAME;
11219: n->string = nn->string;
11220: }
11221: else if (n->tp->base!=FCT && n->tp->base!=OVERLOAD){
11222: n->string = temp(n->string, expand_fn);
11223: n->where.line = 0;
11224: }
11225: }
11226: }
11227:
11228: switch (base) {
11229: default:
11230: error('s',"cannot expand inlineF%n with %kS in inline",expand_fn,base);
11231: Cstmt = ostmt;
11232: return Pstmt(dummy);
11233:
11234: case BLOCK:
11235: DB(if(Edebug>=2){error('d',"stmt::expand() -- block");display_stmt(this);});
11236: if (s_list) {
11237: ee = Pexpr(s_list->expand());
11238: if (s) {
11239: ee = new expr(CM, Pexpr(s->expand()), ee);
11240: ee->tp = ee->e2->tp;
11241: PERM(ee);
11242: }
11243: Cstmt = ostmt;
11244: return Pstmt(ee);
11245: }
11246:
11247: if (s) {
11248: Pstmt st = s->expand();
11249: Cstmt = ostmt;
11250: return st;
11251: }
11252:
11253: Cstmt = ostmt;
11254: return Pstmt(zero);
11255:
11256: case PAIR:
11257: ee = s2 ? Pexpr(s2->expand()) : 0;
11258: ee = new expr(CM, s?Pexpr(s->expand()):0, ee);
11259: ee->tp = ee->e2->tp;
11260: if (s_list) {
11261: ee = new expr(CM, ee, Pexpr(s_list->expand()));
11262: ee->tp = ee->e2->tp;
11263: }
11264: PERM(ee);
11265: Cstmt = ostmt;
11266: return Pstmt(ee);
11267:
11268: case RETURN:
11269: ret_seen = 1;
11270: s_list = 0;
11271:
11272: if (e == 0)
11273: ee = zero;
11274: else {
11275: ee = e->expand();
11276: Ptype tt = Pfct(expand_fn->tp)->returns;
11277: if (tt == 0) tt = Pfct(expand_fn->tp)->returns;
11278: //error('d',"return::expand() -- ee==%k tt==%t",ee?ee->base:0,tt);
11279: //display_expr(ee);
11280: if (tt!=ee->tp && ck_cast(tt,ee->tp)) ee = new cast(tt,ee);
11281: }
11282:
11283: Cstmt = ostmt;
11284: return Pstmt(ee);
11285:
11286: case SM:
11287: if (e== 0 || e==dummy)
11288: ee = zero;
11289: else {
11290: if (e->base == DEREF) e = e->e1;
11291: ee = e->expand();
11292: }
11293: // no break;
11294:
11295: case ASM:
11296: if (s_list) {
11297: ee = new expr(CM, ee, (Pexpr)s_list->expand());
11298: ee->tp = ee->e2->tp;
11299: PERM(ee);
11300: }
11301: Cstmt = ostmt;
11302: return (Pstmt)ee;
11303:
11304: case IF:
11305: {
11306: int ors = ret_seen;
11307: ret_seen = 0;
11308: ee = Pexpr(s->expand());
11309: if(ee->base==ASSIGN && ee->e1->tp &&
11310: ee->e1->tp->base != PTR)
11311: ee = new expr(G_CM,ee,zero);
11312: Pexpr qq = new expr(QUEST,ee,zero);
11313: int ret1 = ret_seen;
11314: ret_seen = 0;
11315:
11316: qq->cond = e->expand();
11317: qq->e2 = else_stmt ? Pexpr(else_stmt->expand()) : zero;
11318: int ret2 = ret_seen;
11319: if (ret1+ret2 && s_list) {
11320: error('s',"cannot expand inlineF%n with S after \"return\"",expand_fn);
11321: ret_seen = 0;
11322: }
11323: ret_seen += ret1;
11324: ret_seen += ret2;
11325: ret_seen += ors;
11326:
11327: // handle ``if (x) class_object_valued_expression;''
11328:
11329: Ptype t1 = qq->e1->tp;
11330: Ptype t2 = qq->e2->tp;
11331:
11332: if (t1 && t1->base==FCT)
11333: t1 = Pfct(t1)->s_returns ? Pfct(t1)->s_returns : Pfct(t1)->returns;
11334:
11335: if (t2 && t2->base==FCT)
11336: t2 = Pfct(t2)->s_returns ? Pfct(t2)->s_returns : Pfct(t2)->returns;
11337:
11338: Pname c1 = t1?t1->is_cl_obj():0;
11339: Pname c2 = t2?t2->is_cl_obj():0;
11340:
11341: int z1 = c1 && c1!=c2;
11342: int z2 = c2 && c1!=c2;
11343:
11344: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
11345: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
11346: //display_expr(qq);
11347: if (c1==0
11348: && c2==0
11349: && t1
11350: && t2
11351: && t2->check(t1,ASSIGN)
11352: && t1->check(t2,ASSIGN)) {
11353: z1 = makeCM( t1 );
11354: z2 = makeCM( t2 );
11355: if ((z1 && ret1) || (z2 && ret2))
11356: error('s',"cannot expand inlineF with return in ifS");
11357: }
11358:
11359: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
11360: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
11361: //display_expr(qq);
11362: if (t1 && z1==0) {
11363: // since zero is acceptable to all pointer types
11364: // we need only ``fix'' z1 and z2 will take care
11365: // of itself
11366: z1 = t1->is_ptr_or_ref()
11367: && t2
11368: && t2->is_ptr_or_ref()
11369: && t1->check(t2,0)
11370: && !const_problem;
11371: }
11372:
11373: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
11374: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
11375: //display_expr(qq);
11376: if (z1) {
11377: Pexpr v = (z2==0 && (t2->is_ptr_or_ref())) ? new cast(t2,zero) : zero;
11378: qq->e1 = new expr(CM,qq->e1,v);
11379: qq->e1->tp = qq->e1->e1->tp;
11380: }
11381:
11382: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
11383: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
11384: //display_expr(qq);
11385: if (z2) {
11386: Pexpr v = (z1==0 && (t1->is_ptr_or_ref())) ? new cast(t1,zero) : zero;
11387: qq->e2 = new expr(CM,qq->e2,v);
11388: qq->e2->tp = qq->e2->e1->tp;
11389: }
11390:
11391: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
11392: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
11393: //display_expr(qq);
11394: if (s_list) {
11395: qq = new expr(CM,qq,Pexpr(s_list->expand()));
11396: qq->tp = qq->e2->tp;
11397: }
11398: else
11399: qq->tp = qq->e1->tp;
11400: PERM(qq);
11401: Cstmt = ostmt;
11402: return Pstmt(qq);
11403: }
11404: }
11405: }
11406:
11407: where.line = 0;
11408:
11409: switch (base) {
11410: default:
11411: if (e) e = e->expand();
11412: break;
11413: case PAIR:
11414: if (s2) s2 = s2->expand();
11415: break;
11416: case BLOCK:
11417: break;
11418: case FOR:
11419: if (for_init) for_init = for_init->expand();
11420: if (e2) e2 = e2->expand();
11421: case ASM:
11422: break;
11423: // case LABEL:
11424: // case GOTO:
11425: case RETURN:
11426: // case BREAK:
11427: // case CONTINUE:
11428: error('s',"cannot expand inlineF%n with %kS",expand_fn,base);
11429: }
11430:
11431: if (s) s = s->expand();
11432: if (s_list) s_list = s_list->expand();
11433: PERM(this);
11434: Cstmt = ostmt;
11435: return this;
11436: }
11437:
11438: Pexpr expr::expand()
11439: {
11440: if (this == 0) error('i',"E::expand(0)");
11441:
11442: switch (base) {
11443: case NAME:
11444: if (expand_tbl && Pname(this)->n_scope==FCT) {
11445: Pname n = Pname(this);
11446: char* s = n->string;
11447: if (s[0]=='_' && s[1]=='_' && s[2]=='X') break;
11448: Pname cn = expand_fn->n_table->t_name;
11449: // n->string = temp(s,expand_fn->string,(cn)?cn->string:0);
11450: n->string = temp(s,expand_fn);
11451: }
11452: case DUMMY:
11453: case ICON:
11454: case FCON:
11455: case CCON:
11456: case IVAL:
11457: //case FVAL:
11458: //case LVAL:
11459: case STRING:
11460: case ZERO:
11461: case TEXT:
11462: case ANAME:
11463: case MDOT:
11464: break;
11465: case ICALL:
11466: if (expand_tbl && e1==0) {
11467: int ors = ret_seen;
11468: ret_seen = 0;
11469: Pname fn = il->fct_name;
11470: Pfct f = Pfct(fn->tp);
11471: if (f->f_expr==0
11472: // f->returns==void_type
11473: // && f->s_returns!=int_type
11474: // && fn->n_oper!=CTOR
11475: )
11476: error('s',&fn->where,"cannot expand value-returning inline%n with call of non-value-returning inline%n",expand_fn,fn);
11477: // else
11478: // error("inline%n called before defined",fn);
11479: ret_seen = ors;
11480: }
11481: break;
11482: case SIZEOF:
11483: case CAST:
11484: if (tp2) PERM(tp2);
11485: goto rrr;
11486: case QUEST:
11487: cond = cond->expand();
11488: default:
11489: if (e2) e2 = e2->expand();
11490: case REF:
11491: case DOT:
11492: rrr:
11493: if (e1) e1 = e1->expand();
11494: break;
11495: }
11496:
11497: switch (base) {
11498: case CM:
11499: case G_CM:
11500: if (tp==0) tp=e2->tp;
11501: }
11502:
11503: PERM(this);
11504: return this;
11505: }
11506:
11507: int nin;
11508:
11509: static int watch_out;
11510: bit expr::not_simple()
11511: /*
11512: is a temporary variable needed to hold the value of this expression
11513: as an argument for an inline expansion?
11514: return 1; if side effect
11515: return 2; if modifies expression
11516: */
11517: {
11518: int s;
11519: //error('d',"not_simple%k",base);
11520: switch (base) {
11521: default:
11522: return 2;
11523: case NAME:
11524: if (nin==0 && Pname(this)->n_table==gtbl) return 2; // unsafe: aliasing
11525: case ZERO:
11526: case IVAL:
11527: //case FVAL:
11528: case ICON:
11529: case CCON:
11530: case FCON:
11531: return 0;
11532: case STRING:
11533: ::watch_out = 1;
11534: return 0;
11535: case MDOT:
11536: return mem->not_simple();
11537: case SIZEOF:
11538: return (e1==0 || e1==dummy) ? 0 : e1->not_simple();
11539: case G_ADDROF:
11540: case ADDROF:
11541: return e2->not_simple();
11542: case CAST:
11543: return e1->not_simple();
11544: case DOT:
11545: ::watch_out = 1;
11546: return e1->not_simple();
11547: case REF:
11548: ::watch_out = 1;
11549: return e1->not_simple();
11550: case UMINUS:
11551: case NOT:
11552: case COMPL:
11553: return e2->not_simple();
11554: case DEREF:
11555: s = e1->not_simple();
11556: if (1<s) return 2;
11557: if (e2==0) return s;
11558: return s |= e2->not_simple();
11559: case MUL:
11560: case DIV:
11561: case MOD:
11562: case PLUS:
11563: case MINUS:
11564: case LS:
11565: case RS:
11566: case AND:
11567: case OR:
11568: case ER:
11569: case LT:
11570: case LE:
11571: case GT:
11572: case GE:
11573: case EQ:
11574: case NE:
11575: case ANDAND:
11576: case OROR:
11577: case CM:
11578: s = e1->not_simple();
11579: if (1<s) return 2;
11580: return s |= e2->not_simple();
11581: case QUEST:
11582: s = cond->not_simple();
11583: if (1<s) return 2;
11584: s |= e1->not_simple();
11585: if (1<s) return 2;
11586: return s |= e2->not_simple();
11587: case ANAME:
11588: if (curr_icall) {
11589: Pname n = (Pname)this;
11590: int argno = int(n->n_val);
11591: for (Pin il=curr_icall; il; il=il->i_next)
11592: if (n->n_table == il->i_table) goto aok;
11593: goto bok;
11594: aok:
11595: return (il->i_args[argno].local) ? 0 : il->i_args[argno].arg->not_simple();
11596: }
11597: bok: error('i',"expand aname%n",this);
11598: case G_CM:
11599: case VALUE:
11600: case NEW:
11601: case GNEW:
11602: case CALL:
11603: case G_CALL:
11604: case ICALL:
11605: case ASSIGN:
11606: case INCR:
11607: case DECR:
11608: case ASPLUS:
11609: case ASMINUS:
11610: case ASMUL:
11611: case ASDIV:
11612: case ASMOD:
11613: case ASAND:
11614: case ASOR:
11615: case ASER:
11616: case ASLS:
11617: case ASRS:
11618: return 2;
11619: }
11620: }
11621:
11622: extern void uninline(Pname fn);
11623: //extern Pname new_fct;
11624: //extern Pname del_fct;
11625: extern Pstmt del_list;
11626: extern Pstmt break_del_list;
11627: extern Pstmt continue_del_list;
11628: extern Pname curr_fct;
11629: extern Pexpr init_list;
11630:
11631: extern Pname make_default_ctor(Pclass cl);
11632: void expand_itor(Pclass cl)
11633: {
11634: //error('d',"expand_itor(%t)",cl);
11635: Pexpr s2 = curr_expr;
11636: Pstmt s5 = del_list;
11637: Pstmt s6 = break_del_list;
11638: Pstmt s7 = continue_del_list;
11639: Pname s8 = curr_fct;
11640: Pexpr s9 = init_list;
11641: (void) cl->make_itor(1);
11642: curr_expr = s2;
11643: del_list = s5;
11644: break_del_list = s6;
11645: continue_del_list = s7;
11646: curr_fct = s8;
11647: init_list = s9;
11648: }
11649: /*
11650: extern Pname make_default_dtor(Pclass cl);
11651: void expand_dtor(Pclass cl)
11652: {
11653: //error('d',"expand_itor(%t)",cl);
11654: Pexpr s2 = curr_expr;
11655: Pstmt s5 = del_list;
11656: Pstmt s6 = break_del_list;
11657: Pstmt s7 = continue_del_list;
11658: Pname s8 = curr_fct;
11659: Pexpr s9 = init_list;
11660: (void) make_default_dtor(cl);
11661: curr_expr = s2;
11662: del_list = s5;
11663: break_del_list = s6;
11664: continue_del_list = s7;
11665: curr_fct = s8;
11666: init_list = s9;
11667: }
11668:
11669:
11670: void expand_ictor(Pclass cl)
11671: {
11672: //error('d',"expand_itor(%t)",cl);
11673: Pexpr s2 = curr_expr;
11674: Pstmt s5 = del_list;
11675: Pstmt s6 = break_del_list;
11676: Pstmt s7 = continue_del_list;
11677: Pname s8 = curr_fct;
11678: Pexpr s9 = init_list;
11679: (void) make_default_ctor(cl);
11680: curr_expr = s2;
11681: del_list = s5;
11682: break_del_list = s6;
11683: continue_del_list = s7;
11684: curr_fct = s8;
11685: init_list = s9;
11686: }
11687: */
11688: Pexpr fct::expand(Pname fn, Ptable scope, Pexpr ll)
11689: /*
11690: expand call to (previously defined) inline function in "scope"
11691: with the argument list "ll"
11692: (1) declare variables in "scope"
11693: (2) initialize argument variables
11694: (3) link to body
11695: */
11696: {
11697: Scope = scope;
11698: //error('d',"expand%s() body %d f_expr %d inline %d",fn->string,body,f_expr,f_inline);
11699: if (f_inline == ITOR) {
11700: Pexpr s1 = last_expanded;
11701: expand_itor(memof);
11702: last_expanded = s1;
11703: last_stmt = stmtno;
11704: this = Pfct(fn->tp);
11705: if (f_inline==0 && f_imeasure) {
11706: uninline(fn);
11707: return 0;
11708: }
11709: }
11710:
11711: //error('d',"expand %n body %d f_expr %d defined %d",fn,body,f_expr,defined);
11712: //error('d',"inline %d memtbl %d scope %d",f_inline,Pfct(fn->tp)->body->memtbl,scope);
11713: //display_stmt(body);
11714: if ((body==0 && f_expr==0) // before defined
11715: || ((defined&SIMPLIFIED)==0) // before simplified
11716: || (Pfct(fn->tp)->body->memtbl==scope) // while defining
11717: || (f_inline>1) // recursive call
11718: ) { // so don't expand
11719: if (warning_opt) error('w',"cannot inline%n in thisE",fn);
11720: if (fn->n_addr_taken++==0) fn->dcl_print(0);
11721: return 0;
11722: }
11723:
11724: if (fn->n_oper==CTOR) {
11725: Pclass cl = Pclass(fn->n_table->t_name->tp);
11726: if (cl->c_body == 3) cl->print_all_vtbls(cl);
11727: }
11728:
11729: Pin il = new iline;
11730: Pexpr ic = new texpr(ICALL,0,0);
11731: int ns = 0;
11732: for (Pname an = f_args; an; an=an->n_list) ns++;
11733: il->fct_name = fn;
11734: il->i_args = new ia[il->i_slots = ns];
11735: ic->il = il;
11736: ic->tp = s_returns ? s_returns : returns;
11737: // Pname at = (f_this) ? f_this : (f_result) ? f_result : argtype;
11738: Pname at = f_args;
11739:
11740: f_inline++;
11741:
11742: if (at) il->i_table = at->n_table;
11743: int i = 0;
11744: int not_simple = 0; /* is a temporary argument needed? */
11745:
11746: for (Pname n=at; n; n=n->n_list, i++) {
11747: /* check formal/actual argument pairs
11748: and generate temporaries as necessary
11749: */
11750:
11751: if (ll == 0) error('i',"F::expand(%n):AX",fn);
11752: Pexpr ee;
11753:
11754: if (ll->base == ELIST) {
11755: ee = ll->e1;
11756: ll = ll->e2;
11757: }
11758: else {
11759: ee = ll;
11760: ll = 0;
11761: }
11762:
11763: /* could be avoided when expanding into a block */
11764: il->i_args[i].local = 0;
11765: int s ;
11766:
11767: // try to protect agains aliasing through pointers and references
11768: for (Pname m=at; m; m=m->n_list) {
11769: Pptr p;
11770: if (n!=m) {
11771: // if ((p=m->tp->is_ptr()) || (p=m->tp->is_ref()))
11772: if (p=m->tp->is_ptr_or_ref())
11773: if (p->check(n->tp,0)==0 || p->typ->check(n->tp,0)==0) goto zxc;
11774:
11775: }
11776: }
11777:
11778: ::watch_out = 0;
11779: int notsimple; notsimple = ee->not_simple();
11780: if ( notsimple==0 && ::watch_out && n->n_used > 1 ) goto zxc;
11781: if (n->n_assigned_to==FUDGE111
11782: && ee!=zero
11783: && notsimple==0) {
11784: if (ee && ee->e1 && (ee->e1->base == NAME) &&
11785: (! strcmp (ee->e1->string,"this"))) goto zxc;
11786: }
11787: else if (n->n_addr_taken || n->n_assigned_to)
11788: goto zxc;
11789: else if (s=notsimple) {
11790: if (/*n->n_used==0 // n_used not set for ``this''
11791: || */1<s
11792: || 1<n->n_used ) { // not safe
11793: zxc:
11794: if (last_expanded && last_expanded==curr_expr && last_stmt==stmtno) {
11795: if (warning_opt)
11796: error('w',"%n not inlined, called twice in an expression",fn);
11797: f_inline--;
11798: delete il->i_args;
11799: delete il;
11800: if (fn->n_addr_taken++==0) fn->dcl_print(0);
11801: return 0;
11802: }
11803: //error('d',"zxc %n %t ee %d %t",n,n->tp,ee->base,ee->tp);
11804: if (ee && ee->tp && (ee->tp->base==EOBJ) && ansi_opt)
11805: ; // do nothing
11806: else {
11807: Pname nn = dcl_local(scope,n,fn);
11808: nn->base = NAME;
11809: il->i_args[i].local = nn;
11810: ++not_simple;
11811: // if (nn->tp->is_ref()
11812: // && ee->tp
11813: // && ee->tp->is_ptr_or_ref()==0) ee = ee->address();
11814: }
11815: }
11816: }
11817:
11818: il->i_args[i].arg = ee;
11819: il->i_args[i].tp = n->tp;
11820: }
11821:
11822: Ptable tbl = body->memtbl;
11823: if (f_expr) { // generate comma expression
11824:
11825: char loc_var = 0;
11826:
11827: /* look for local variables needing declaration: */
11828: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
11829: //error('d',"n %n %d",n,n->base);
11830: //error('d',"loc %n %d %d %d",n,n->n_used,n->n_assigned_to,n->n_addr_taken);
11831: if (n->base==NAME // don't re-declare the args
11832: && (n->tp->base!=FCT && n->tp->base!=OVERLOAD)
11833: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
11834: if (last_expanded && last_expanded==curr_expr && last_stmt == stmtno) {
11835: if (warning_opt) error('w',"cannot inline%n in thisE",fn);
11836: f_inline--;
11837: delete il->i_args;
11838: delete il;
11839: if (fn->n_addr_taken++==0) fn->dcl_print(0);
11840: return 0;
11841: }
11842: Pname nn = dcl_local(scope,n,fn);
11843: nn->base = NAME;
11844: n->string = nn->string;
11845:
11846: loc_var++;
11847: }
11848: }
11849:
11850: if (i /*not_simple*/ || loc_var) {
11851: if(!curr_expr) curr_expr = dummy;
11852: last_expanded = curr_expr;
11853: last_stmt = stmtno;
11854: }
11855:
11856: Pexpr ex;
11857: if (not_simple) {
11858: Pexpr etail = ex = new expr(CM,0,0);
11859: for (i=0; i<il->i_slots; i++) {
11860: Pname n = il->i_args[i].local;
11861: if (n == 0) continue;
11862: Pexpr e = il->i_args[i].arg;
11863: // if used assign
11864: // otherwise (e.g. unused argument)
11865: // simply evaluate for sideeffects
11866: if (n->n_used
11867: || n->n_assigned_to
11868: || n->n_addr_taken) {
11869: Pexpr mptr_assign(Pexpr n, Pexpr in);
11870: Pptr p1 = n->tp->is_ptr();
11871: Pptr p2 = e->tp ? e->tp->is_ptr() : 0;
11872: if (p1 && p1->memof && p1!=p2) {
11873: switch (e->base) {
11874: case CM:
11875: case G_CM:
11876: e->e2 = mptr_assign(n,e->e2);
11877: break;
11878: case ICALL:
11879: break;
11880: default:
11881: e = mptr_assign(n,e);
11882: }
11883: etail->e1 = e;
11884: }
11885: else
11886: etail->e1 = new expr(ASSIGN,n,e);
11887: }
11888: else
11889: etail->e1 = e;
11890: if (--not_simple)
11891: etail = etail->e2 = new expr(CM,0,0);
11892: else
11893: break;
11894: }
11895: etail->e2 = f_expr;
11896: }
11897: else
11898: ex = f_expr;
11899: ic->e1 = ex;
11900: }
11901: else { // generate block:
11902: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
11903: // mangle local names
11904: if (n->base==NAME
11905: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
11906: // Pname cn = fn->n_table->t_name;
11907: // n->string = temp(n->string,fn->string,(cn)?cn->string:0);
11908: n->string = temp(n->string,fn);
11909: }
11910: }
11911: Pstmt ss;
11912: if (not_simple) {
11913: if(!curr_expr) curr_expr = dummy;
11914: last_expanded = curr_expr;
11915: last_stmt = stmtno;
11916: Pstmt st = new estmt(SM,curloc,0,0);
11917: st->where.line = 0;
11918: Pstmt stail = st;
11919: for (i=0; i<il->i_slots; i++) {
11920: Pname n = il->i_args[i].local;
11921: if (n == 0) continue;
11922: Pexpr e = il->i_args[i].arg;
11923: Pptr p1 = n->tp->is_ptr();
11924: Pptr p2 = e->tp->is_ptr();
11925: Pexpr mptr_assign(Pexpr n, Pexpr in);
11926: if (p1 && p1->memof && p1!=p2) {
11927: switch (e->base) {
11928: case CM:
11929: case G_CM:
11930: e->e2 = mptr_assign(n,e->e2);
11931: break;
11932: default:
11933: e = mptr_assign(n,e);
11934: }
11935: stail->e = e;
11936: }
11937: else
11938: stail->e = new expr(ASSIGN,n,e);
11939: if (--not_simple) {
11940: stail = stail->s_list = new estmt(SM,curloc,0,0);
11941: stail->where.line = 0;
11942: }
11943: else
11944: break;
11945: }
11946: stail->s_list = body;
11947: ss = new block(curloc,0,st);
11948: ss->where.line = 0;
11949: }
11950: else
11951: ss = body;
11952: ic->e2 = Pexpr(ss);
11953: }
11954:
11955: f_inline--;
11956: //error('d',"expand%n -- returning%k", fn, ic?ic->base:0);
11957: //display_expr(ic);
11958: return ic;
11959: }
11960: 0707071010112044261004440001630000160000010177000466055400600000700000116316expr.c /*ident "@(#)ctrans:src/expr.c 1.8" */
11961: /***************************************************************************
11962:
11963: C++ source for cfront, the C++ compiler front-end
11964: written in the computer science research center of Bell Labs
11965:
11966: Copyright (c) 1984 AT&T, Inc. All rights Reserved
11967: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
11968:
11969: expr.c:
11970:
11971: type check expressions
11972:
11973: ************************************************************************/
11974:
11975: #include "cfront.h"
11976: #include "size.h"
11977:
11978: int const_save;
11979: int const_ptr;
11980: extern Ptype Pfct_type;
11981:
11982: Pexpr expr::address()
11983: {
11984: // error('d',"address %k %d %s",base,base,base==NAME||base==ANAME?string:"?");
11985: // error('d',"address e1 %d %k e2 %d %k", e1, e1?e1->base:0, e2, e2?e2->base:0);
11986: switch (base) {
11987: case DEREF:
11988: if (e2 == 0) return e1; // &*e => e
11989: break;
11990: case QUEST: // &(a?b:c) => a?&b:&c
11991: e1 = e1->address();
11992: // no break;
11993: case G_CM:
11994: if ( e1 && e1->base == G_CALL &&
11995: e2 && e2->base == G_ADDROF)
11996: return this;
11997: case CM:
11998: e2 = e2->address(); // &(e1,e2) => (e1,&e2)
11999: tp = e2->tp; //LLL
12000: return this;
12001: case INCR:
12002: case DECR: // &(++a) => (++a,&a)
12003: if (e1) break;
12004: nin++;
12005: if (e2->not_simple()) error('s',"& of%k",base);
12006: nin--;
12007: e1 = new expr(base,0,e2);
12008: e2 = e2->address();
12009: base = G_CM;
12010: tp = e2->tp;
12011: return this;
12012: case ASSIGN: // &(a=b) => ((a=b),&a)
12013: case ASPLUS:
12014: case ASMINUS:
12015: case ASMUL:
12016: case ASDIV:
12017: case ASMOD:
12018: case ASAND:
12019: case ASOR:
12020: case ASER:
12021: case ASLS:
12022: case ASRS:
12023: nin++;
12024: if (e1->not_simple()) error('s',"& of%k",base);
12025: nin--;
12026: Pexpr a = new expr(base,e1,e2);
12027: a->tp = a->e1->tp;
12028: base = G_CM;
12029: e1 = a;
12030: e2 = a->e1->address();
12031: tp = e2->tp;
12032: return this;
12033:
12034: case NAME:
12035: if (Pname(this)->n_stclass == REGISTER) error("& register%n",Pname(this));
12036: Pname(this)->take_addr();
12037: break;
12038: case CALL:
12039: case CAST:
12040: case NEW:
12041: case GNEW:
12042: if (tp && tp->is_ptr_or_ref()) { // hack?
12043: return this;
12044: }
12045: break;
12046: }
12047:
12048: register Pexpr ee = new expr(G_ADDROF,0,this);
12049: if (tp) { // tp==0 ???
12050: ee->tp = tp->addrof();
12051:
12052: switch (tp->base) {
12053: case PTR:
12054: Pptr(ee->tp)->memof = Pptr(tp)->memof;
12055: break;
12056: case FCT:
12057: if (Pfct(tp)->f_static==0)
12058: Pptr(ee->tp)->memof = Pfct(tp)->memof;
12059: break;
12060: case OVERLOAD:
12061: if (Pfct(Pgen(tp)->fct_list->f->tp)->f_static==0)
12062: Pptr(ee->tp)->memof = Pfct(Pgen(tp)->fct_list->f->tp)->memof;
12063: }
12064: }
12065:
12066: return ee;
12067: }
12068:
12069: Pexpr expr::contents()
12070: {
12071: //error('d',"deref %k %d %t",base,base,tp);
12072: // if (base==ADDROF || base==G_ADDROF) return e2; // *&
12073: switch (base) {
12074: case ADDROF:
12075: case G_ADDROF:
12076: return e2; // *&
12077: case ELIST:
12078: //error('d',"contents of elist");
12079: e1 = e1->contents();
12080: tp = e1->tp;
12081: return this;
12082: };
12083:
12084: register Pexpr ee = new expr(DEREF,this,0);
12085: if (tp) { // tp==0 ???
12086: Ptype tt = tp;
12087: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
12088: ee->tp = Pptr(tt)->typ;
12089: Pname cn = ee->tp->is_cl_obj();
12090: if (cn) {
12091: Pclass cl = Pclass(cn->tp);
12092: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl
12093: }
12094: }
12095: return ee;
12096: }
12097:
12098: static Pexpr
12099: make_postfix( Pexpr op )
12100: { // apply the postfix form of increment/decrement operator
12101: Pexpr e = op->e1->base==NAME?op->e1:op->e1->mem;
12102: for (Plist fl=Pgen(e->tp)->fct_list;fl; fl=fl->l) {
12103: Pname n = fl->f;
12104: Pfct f = Pfct(n->tp);
12105: if ((f->nargs==1 && f->f_this) ||
12106: (f->nargs==2 && f->f_this==0)) {
12107:
12108: if (op->e1->base == NAME) {
12109: op->e1 = n;
12110: op->e2->e2 = new expr(ELIST,zero,0);
12111: } else {
12112: op->e1->mem = n;
12113: op->e2 = new expr(ELIST,zero,0);
12114: }
12115:
12116: op->fct_name = n;
12117: n->dcl_print(0);
12118: return op;
12119: }
12120: }
12121: error('w',"no postfix instance of%n, although overloaded",Pname(e));
12122: return op; // as it were
12123: }
12124:
12125: int bound;
12126: int chars_in_largest; // no of characters in largest int
12127: static Pclass mpglob;
12128:
12129: Pexpr expr::typ(Ptable tbl)
12130: /*
12131: find the type of "this" and place it in tp;
12132: return the typechecked version of the expression:
12133: "tbl" provides the scope for the names in "this"
12134: */
12135: {
12136: //if (this == 0) error('i',"0->expr::typ");
12137: Pname n;
12138: Ptype t = 0;
12139: Ptype t1, t2;
12140: TOK b = base;
12141: TOK r1, r2;
12142: #define nppromote(b) t=np_promote(b,r1,r2,t1,t2,1)
12143: #define npcheck(b) (void)np_promote(b,r1,r2,t1,t2,0)
12144: if (tbl->base != TABLE) error('i',"expr::typ(%d)",tbl->base);
12145:
12146: DB( if(Tdebug>=1) {
12147: error('d',"%d->expr::typ(%d) %k %t",this,tbl,b,tp);
12148: display_expr(this);
12149: });
12150: // error('d',"%k->typ %n tp: %t", b,b==NAME?this:0,tp);
12151: // error('d'," e1 %d %k e1 %d %k",e1,e1?e1->base:0,e2,e2?e2->base:0);
12152:
12153: if (tp) {
12154: switch (b) {
12155: case NAME:
12156: //?? Pname(this)->use();
12157: break;
12158: case MDOT:
12159: mem = mem->typ(tbl);
12160: } ;
12161: // if (b == NAME) Pname(this)->use();
12162: return this;
12163: }
12164:
12165: extern Pname Ntmp;
12166:
12167: switch (b) { // is it a basic type
12168: case MDOT:
12169: error('i',"mdot %s",string2);
12170: case DUMMY:
12171: error("emptyE");
12172: tp = any_type;
12173: return this;
12174:
12175: case ZERO:
12176: tp = zero_type;
12177: return this;
12178:
12179: case IVAL:
12180: tp = int_type;
12181: return this;
12182:
12183: //case FVAL:
12184: // tp = float_type;
12185: // return this;
12186:
12187: case ICON:
12188: /* is it long?
12189: explicit long?
12190: decimal larger than largest signed int
12191: octal or hexadecimal larger than largest unsigned int
12192: */
12193: { int ll = strlen(string);
12194: switch (string[ll-1]) {
12195: case 'l':
12196: case 'L':
12197: switch (string[ll-2]) {
12198: case 'u':
12199: case 'U':
12200: string[ll-2] = 0;
12201: tp = ulong_type;
12202: goto cast_n_save;
12203: }
12204: lng:
12205: tp = long_type;
12206: goto save;
12207: case 'u':
12208: case 'U': // 1u => unsigned(1)
12209: switch (string[ll-2]) {
12210: case 'l':
12211: case 'L':
12212: string[ll-2] = 0;
12213: ulng:
12214: tp = ulong_type;
12215: goto cast_n_save;
12216: default:
12217: string[ll-1] = 0;
12218: uint:
12219: tp = uint_type;
12220: goto cast_n_save;
12221: }
12222: }
12223:
12224: // no suffix - see if we can figure it out
12225: if (string[0] == '0') { // assume 8 bits in byte
12226: register index = 1;
12227: switch (string[1]) {
12228: case 'x':
12229: case 'X':
12230: while(string[++index]=='0') ;
12231: ll -= index;
12232: int HSZ = SZ_INT+SZ_INT;
12233: if(ll < HSZ) goto nrm;
12234: if(ll == HSZ)
12235: if(string[2]>='8') goto uint;
12236: else goto nrm;
12237: if(SZ_INT==SZ_LONG) break;
12238: HSZ = SZ_LONG+SZ_LONG;
12239: if(ll < HSZ) goto lng;
12240: if(ll == HSZ)
12241: if(string[2]>='8') goto ulng;
12242: else goto lng;
12243: break;
12244: default: // OCTAL
12245: register IBITS = BI_IN_BYTE*SZ_INT;
12246: while(string[index]=='0') index++;
12247: register char x = string[index];
12248: int lbt = x=='1' ? 1 :
12249: ( x=='2' || x=='3' ? 2 : 3 );
12250: int nbits = (ll-index-1)*3 + lbt;
12251: if(nbits < IBITS) goto nrm;
12252: if(nbits == IBITS) goto uint;
12253: if(nbits < BI_IN_BYTE*SZ_LONG) goto lng;
12254: }
12255: goto ulng;
12256: }
12257: else { // DECIMAL
12258: if (ll<chars_in_largest) {
12259: nrm:
12260: tp = int_type;
12261: goto save;
12262: }
12263: if (ll>chars_in_largest) {
12264: if(SZ_INT==SZ_LONG || ll>2*chars_in_largest)
12265: goto ulng;
12266: goto lng;
12267: }
12268: // ll == chars_in_largest
12269: char* p = string;
12270: char* q = LARGEST_INT;
12271: do if (*p>*q) {
12272: if(SZ_INT==SZ_LONG) goto ulng;
12273: goto lng;
12274: } while (*p++==*q++ && *p);
12275: }
12276:
12277: goto nrm;
12278: }
12279: case CCON:
12280: tp = c_strlen(string)<5 ? char_type : int_type; // stored as 'a'
12281: goto save;
12282:
12283: case FCON:
12284: { int ll = strlen(string);
12285: int last = string[ll-1];
12286: tp = double_type;
12287: if (last=='F' || last=='f') {
12288: tp = float_type;
12289: if (!ansi_opt) {
12290: string[ll-1] = 0;
12291: goto cast_n_save;
12292: }
12293: }
12294: else if (last=='L' || last=='l') {
12295: if (ansi_opt == 0) string[ll-1] = 0;
12296: tp = ldouble_type;
12297: }
12298: goto save;
12299: }
12300: case STRING: // type of "as\tdf" is char[6]
12301: // c_strlen counts the terminating '\0'
12302: { Pvec v = new vec(char_type,0);
12303: v->size = c_strlen(string);
12304: tp = v;
12305: }
12306: save:
12307: if (const_save) { // "as\tdf" needs 7 chars for storage
12308: char* p = new char[strlen(string)+1];
12309: strcpy(p,string);
12310: string = p;
12311: }
12312:
12313: return this;
12314:
12315: cast_n_save:
12316: if (const_save) { // "as\tdf" needs 7 chars for storage
12317: char* p = new char[strlen(string)+1];
12318: strcpy(p,string);
12319: string = p;
12320: }
12321:
12322: return new cast(tp,this);
12323:
12324: case THIS:
12325: delete this;
12326: if (cc->c_this) {
12327: cc->c_this->use();
12328: return cc->c_this;
12329: }
12330: error("``this'' used in nonC context");
12331: n = new name("this");
12332: n->tp = any_type;
12333: return tbl->insert(n,0);
12334:
12335: case NAME:
12336: {
12337: Pname q = Pname(this)->n_qualifier; // suppress virtual iff x::
12338: Pexpr ee = find_name(Pname(this),cc->cot,tbl,0,cc->nof);
12339: if (q && (ee->base==REF || ee->base==DOT))
12340: ee->n_initializer = Pexpr(q);
12341: //error('d',"ee %k %t %n",ee->base,ee->tp,ee->base==NAME?ee:ee->base==REF?ee->mem:0);
12342: // if (ee->tp->base == RPTR) return ee->contents();
12343: if (ee->tp->is_ref()) return ee->contents();
12344:
12345: if (ee->base==NAME && Pname(ee)->n_xref) {
12346: // fudge to handle X(X&) args
12347: ee = new expr(DEREF,ee,0);
12348: ee->tp = ee->e1->tp; // !!
12349: }
12350:
12351: return ee;
12352: }
12353:
12354: case ADDROF:
12355: case G_ADDROF: // handle lookup for &s::i
12356: mpglob = 0;
12357: if (e2->base == NAME) e2 = find_name(Pname(e2),cc->cot,tbl,ADDROF,cc->nof);
12358: if (e2->base==NAME && Pname(e2)->n_xref) {
12359: // fudge to handle X(X&) args
12360: e2 = new expr(DEREF,e2,0);
12361: e2->tp = e2->e1->tp; // !!
12362: }
12363: if (e2->base==DOT) { // &f().x = > &(tmp=f(),&tmp)->x
12364: switch (e2->e1->base) {
12365: case CALL:
12366: case G_CALL:
12367: case VALUE:
12368: error("& non-lvalue");
12369: }
12370: }
12371: break;
12372:
12373: case SIZEOF:
12374: if (tp2) {
12375: tp2->dcl(tbl);
12376: switch (tp2->base) {
12377: case VOID:
12378: error("sizeof(void)");
12379: break;
12380: case CLASS:
12381: {
12382: Pclass cl = Pclass(tp2);
12383: if (cl->c_body==1
12384: && (cl->defined&(DEFINED|SIMPLIFIED)) == 0)
12385: error('s',"class defined within sizeof");
12386: }
12387: }
12388:
12389: if (e1 && e1!=dummy) {
12390: e1 = e1->typ(tbl);
12391: DEL(e1);
12392: e1 = dummy;
12393: }
12394: Pptr r = tp2->is_ref();
12395: if (r) tp2 = r->typ; // sizeof(T&)==sizeof(T)
12396: }
12397: else if (e1 == dummy) {
12398: error("sizeof emptyE");
12399: tp = any_type;
12400: return this;
12401: }
12402: else {
12403: e1 = e1->typ(tbl);
12404: tp2 = e1->tp;
12405: if(tp2->base == VEC) tp2->permanent = 1;
12406: if (e1->base==ILIST) // PtoM
12407: e1 = dummy;
12408: else if (tp2 == char_type) // sizeof ('a')
12409: e1 = dummy;
12410: }
12411: (void) tp2->tsizeof();
12412: tp = size_t_type;
12413: return this;
12414:
12415: case CAST:
12416: // return docast(tbl);
12417:
12418: { Pexpr ee = docast(tbl);
12419: return ee->tp->is_ref() ? ee->contents() : ee;
12420: }
12421:
12422:
12423: case VALUE:
12424: if ( tp2->base == COBJ || tp2->base == EOBJ) {
12425: char *s = Pbase(tp2)->b_name->string;
12426: //Pname tn = gtbl->look( s, 0 );
12427: //??? non type name apparently takes precedence
12428: // Don't use global ftn if it hides local
12429: // class ctor. (Note: More info is needed
12430: // to detect all cases.)
12431: Pname tn = tbl->look( s, 0 );
12432: //error( 'd', "tn: %n %t lex_levels: %d %d", tn, tn?tn->tp:0, tn?tn->lex_level:0, Pbase(tp2)->b_name->lex_level );
12433: if ( tn && tn->n_qualifier == 0
12434: && tn->lex_level == Pbase(tp2)->b_name->lex_level
12435: && (tn->tp->base==FCT || tn->tp->base==OVERLOAD))
12436: {
12437: Pexpr et = new expr( CALL, tn, e1 );
12438: *this = *et;
12439: b = CALL;
12440: break;
12441: }
12442: }
12443: return dovalue(tbl);
12444:
12445: case NEW:
12446: case GNEW:
12447: return donew(tbl);
12448:
12449: case DELETE: // delete e1 OR delete[e2] e1
12450: case GDELETE:
12451: { int i;
12452: if (e1->base == ADDROF) error('w',"delete &E");
12453: e1 = e1->typ(tbl);
12454: i = e1->tp->num_ptr(DELETE);
12455: if (i != 'P') error("nonP deleted");
12456: if (e2) {
12457: e2 = e2->typ(tbl);
12458: e2->tp->integral(DELETE);
12459: }
12460: tp = void_type;
12461: return this;
12462: }
12463:
12464: case ILIST: /* an ILIST is pointer to an ELIST */
12465: e1 = e1->typ(tbl);
12466: tp = any_type;
12467: return this;
12468:
12469: case ELIST:
12470: { Pexpr e;
12471: Pexpr ex;
12472:
12473: if (e1 == dummy && e2==0) {
12474: error("emptyIrL");
12475: tp = any_type;
12476: return this;
12477: }
12478:
12479: for (e=this; e; e=ex) {
12480: Pexpr ee = e->e1;
12481: //error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0);
12482: if (e->base != ELIST) error('i',"elist%k",e->base);
12483: if (ex = e->e2) { /* look ahead for end of list */
12484: if (ee == dummy) error("EX in EL");
12485: if (ex->e1 == dummy && ex->e2 == 0) {
12486: /* { ... , } */
12487: DEL(ex);
12488: e->e2 = ex = 0;
12489: }
12490: }
12491: e->e1 = ee->typ(tbl);
12492: t = e->e1->tp;
12493: if (t->base == FCT) { // yuk!
12494: ee = new expr(G_ADDROF,0,e->e1);
12495: e->e1 = ee->typ(tbl);
12496: t = e->e1->tp;
12497: }
12498: }
12499: tp = t;
12500: return this;
12501: }
12502:
12503: case DOT:
12504: case REF:
12505: { if (e2) { // *. or ->*
12506: if (b == REF) b = base = REFMUL;
12507: break;
12508: }
12509:
12510: Pbase b;
12511:
12512: e1 = e1->typ(tbl);
12513: t = e1->tp;
12514:
12515: // check that . (->) is applied to class object (pointer)
12516: if (base == REF) {
12517: xxx:
12518: switch (t->base) {
12519: case TYPE:
12520: t = Pbase(t)->b_name->tp;
12521: goto xxx;
12522: case COBJ:
12523: { Pname n = Pclass(Pbase(t)->b_name->tp)->has_oper(REF);
12524: if (n) {
12525: n->n_used += 2;
12526: e1 = new call(new ref(DOT,e1,n),0);
12527: return typ(tbl);
12528: }
12529: // no break;
12530: }
12531: default:
12532: error("nonP ->%n",mem);
12533: t = any_type;
12534: // no break;
12535: case ANY:
12536: goto qqq;
12537: case PTR:
12538: case VEC:
12539: b = Pbase(Pptr(t)->typ);
12540: }
12541: }
12542: else { // base == DOT
12543: qqq:
12544: switch (t->base) {
12545: case TYPE: t = Pbase(t)->b_name->tp; goto qqq;
12546: default: error("nonO .%n",mem); t = any_type;
12547: case ANY:
12548: case COBJ: break;
12549: }
12550: //error('d',"dot %k",e1->base);
12551: switch (e1->base) {
12552: case QUEST:
12553: case ASSIGN:
12554: case INCR:
12555: case DECR:
12556: case ASPLUS:
12557: case ASMINUS:
12558: case ASMUL:
12559: case ASDIV:
12560: case ASMOD:
12561: case ASAND:
12562: case ASOR:
12563: case ASER:
12564: case ASLS:
12565: case ASRS:
12566: case CM:
12567: case G_CM:
12568: base = REF;
12569: e1 = e1->address();
12570: break;
12571: case CALL:
12572: case G_CALL:
12573: //error('d'," f(). %n mem->tp %t",e1->fct_name,mem->tp);
12574: #ifdef FDOTRIGHT
12575: // this rewrite is only necessary on machines with broken C compilers
12576: // there seems to be a lot of those
12577: // and for inlines (a,b).c
12578: if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline)
12579: #endif
12580: { // f(). => (tmp=f(),&tmp)->
12581: Pname tmp = make_tmp('Q',e1->tp,tbl);
12582: //error('d',"fdot2 %k",e1->base);
12583: e1 = init_tmp(tmp,e1,tbl);
12584: Pexpr aa = tmp->address();
12585: e1 = new expr(G_CM,e1,aa);
12586: e1->tp = aa->tp;
12587: base = REF;
12588: break;
12589: }
12590: }
12591: b = Pbase(t);
12592: }
12593:
12594: xxxx:
12595: switch (b->base) {
12596: case TYPE:
12597: b = Pbase(b->b_name->tp);
12598: goto xxxx;
12599: default:
12600: error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem);
12601: case ANY:
12602: tp = any_type;
12603: return this;
12604: case COBJ:
12605: { Pclass cl = Pclass(Pbase(b)->b_name->tp);
12606: if (cl->c_body == 1) cl->dcl_print(0);
12607: break;
12608: }
12609: }
12610:
12611: /*
12612: x.m is not a const even if x is a const object, this case is handled
12613: by lval() rejecting it
12614: */
12615:
12616: if (mem->tp) {
12617: tp = mem->tp;
12618: for (Pexpr ee = mem; ee->base==REF; ee = ee->e1) {
12619: if (ee->e1 == cc->c_this) { // this-> => p->
12620: ee->e1 = e1;
12621: ee->base = base;
12622: return mem->tp->is_ref() ? mem->contents() : mem;
12623: }
12624: }
12625:
12626: // return tp->base==RPTR ? contents() : this;
12627: return tp->is_ref() ? contents() : this;
12628: }
12629:
12630:
12631: Pname q = Pname(mem)->n_qualifier;
12632: Pexpr e = find_name(Pname(mem),Pclass(b->b_name->tp),0,base,cc->nof);
12633: if (q && (e->base==REF || e->base==DOT))
12634: Pname(e)->n_initializer = Pexpr(q);
12635: //error('d',"e %k %t %n",e->base,e->tp,e->base==NAME?e:e->base==REF?e->mem:0);
12636:
12637: for (Pexpr ee = e; ee->base==REF; ee = ee->e1) {
12638: if (ee->e1 == cc->c_this) { // this-> => p->
12639: ee->e1 = e1;
12640: ee->base = base;
12641: break;
12642: }
12643: }
12644:
12645: if (e->base == NAME) {
12646: switch (e->tp->base) {
12647: case FCT:
12648: case OVERLOAD:
12649: mem = e;
12650: tp = e->tp;
12651: e = this;
12652: }
12653: }
12654:
12655: // function or static member
12656: return e->tp->is_ref() ? e->contents() : e;
12657: }
12658:
12659: //?? case G_CALL:
12660: case CALL: /* handle undefined function names */
12661: //error('d',"call %k %t %k",e1->base,e1->tp,e2?e2->base:0);
12662: if (e1->base==NAME && e1->tp==0) {
12663: Pname q = Pname(e1)->n_qualifier;
12664: e1 = find_name(Pname(e1),cc->cot,tbl,CALL,cc->nof);
12665: //error('d',"e1 %k %t %n",e1->base,e1->tp,e1->base==NAME?e1:e1->base==REF?e1->mem:0);
12666: if (q && (e1->base==REF ||e1->base==DOT)) // suppress virtual call
12667: e1->n_initializer = Pexpr(q);
12668: }
12669:
12670: if (e1->base==NAME && Pname(e1)->n_xref) {
12671: // fudge to handle X(X&) args
12672: e1 = new expr(DEREF,e1,0);
12673: e1->tp = e1->e1->tp; // !!
12674: }
12675:
12676: switch (e1->base) {
12677: case DOT:
12678: /*
12679: #ifdef FDOTRIGHT
12680: {
12681: //error('d',"fdot1 %k",e1->e1->base);
12682: switch (e1->e1->base) {
12683: case CALL:
12684: case G_CALL: // f().g() => (tmp=f(),tmp.g())
12685: { Pexpr ee = e1->e1;
12686: Pexpr ex = ee->typ(tbl);
12687: Pname tmp = make_tmp('Q',ex->tp,tbl);
12688: ex = init_tmp(tmp,ex,tbl);
12689:
12690: Pexpr ee2 = new expr(base,e1,e2);
12691: e1->base = DOT;
12692: e1->e1 = tmp;
12693:
12694: base = G_CM;
12695: e1 = ex;
12696: e2 = ee2;
12697:
12698: return typ(tbl);
12699: }
12700: }
12701: break;
12702: }
12703: #endif
12704: */
12705: case REF: // becomes ob.x::~x(0) or
12706: if (e2==0 // becomes p->x::~x(0)
12707: && Pref(e1)->mem
12708: && Pref(e1)->mem->base==NAME
12709: && Pname(Pref(e1)->mem)->n_oper==DTOR) {
12710: e1 = e1->typ(tbl);
12711: Pexpr ee = call_dtor(e1->e1,Pref(e1)->mem,0,e1->base,one);
12712: ee->tp = void_type;
12713: return ee;
12714: }
12715: }
12716: break;
12717:
12718: case QUEST:
12719: cond = cond->typ(tbl);
12720: case ANDAND:
12721: case OROR:
12722: Ntmp = 0;
12723: }
12724:
12725: if (e1) {
12726: e1 = e1->typ(tbl);
12727: if (e1->tp->is_ref()) e1 = e1->contents();
12728: t1 = e1->tp;
12729: // if (t1->is_cl_obj()) t1->tsizeof();
12730: }
12731: else
12732: t1 = 0;
12733:
12734: if (e2) {
12735: e2 = e2->typ(tbl);
12736: if (e2->tp->is_ref()) e2 = e2->contents();
12737: t2 = e2->tp;
12738: // if (t2->is_cl_obj()) t2->tsizeof();
12739: }
12740: else
12741: t2 = 0;
12742:
12743: // error('d',"b %k t1 %t t2 %t",b,t1,t2);
12744: switch (b) { // filter out non-overloadable operators
12745: default:
12746: {
12747: Pexpr x = try_to_overload(tbl);
12748: if (x) {
12749: if (b==INCR || b==DECR) {
12750: Pexpr fe = x->e1->base==NAME?x->e1:x->e1->mem;
12751: // by default, prefix version of operator is chosen
12752: // t2 set ==> ++n, t1 set ==> n++
12753: if (fe->tp->base==OVERLOAD && t2==0 && t1)
12754: x=make_postfix(x);
12755: }
12756: return x;
12757: }
12758: // if (x) return x;
12759: // error('d',"e2: %t t2: %t", e2->tp, t2);
12760: if (t2 && t1==0 && t2!=e2->tp) t2 = e2->tp;
12761: }
12762: case DOT:
12763: case G_CM:
12764: case G_ADDROF:
12765: case G_CALL:
12766: case QUEST:
12767: break;
12768: }
12769:
12770: switch (b) {
12771: case QUEST:
12772: case ANDAND:
12773: case OROR:
12774: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,b);
12775: }
12776:
12777: t = (t1==0) ? t2 : (t2==0) ? t1 : 0;
12778: // error('d', "expr::typ t %t", t );
12779: // error('d',"b2 %d %k",b,b);
12780: switch (b) { /* are the operands of legal types */
12781: case REFMUL:
12782: base = REF;
12783: // no break;
12784: case DOT:
12785: { // a .* p => &a MEMPTR p => appropriate indirection
12786: // to be considered: what happens if a .* expression
12787: // is used except in a call/=?
12788: Pexpr a = e1->typ(tbl);
12789: Ptype at = a->tp;
12790: if (base == DOT) {
12791: a = a->address();
12792: at = at->addrof(); // beware of n_xref
12793: }
12794:
12795: while (at->base == TYPE) at = Pbase(at)->b_name->tp;
12796: Pname cn = Pptr(at)->typ->is_cl_obj();
12797: Pclass mm = cn ? Pclass(cn->tp) : 0;
12798:
12799: Pexpr p = e2->typ(tbl);
12800: Ptype pt = p->tp;
12801: Pname pcn = pt->is_cl_obj();
12802:
12803: //error('d',"mm %t pt %t",mm,pt);
12804: if (pcn) {
12805: Pclass cl = Pclass(pcn->tp);
12806: Pname found = 0;
12807: for (Pname on=cl->conv; on; on=on->n_list) {
12808: Pfct f = Pfct(on->tp);
12809: Pptr frt = Pptr(f->returns);
12810: while (frt->base == TYPE) frt = Pptr(Pbase(frt)->b_name->tp);
12811: if (frt->base!=PTR || Pptr(frt)->memof==0) break;
12812: if (Pptr(frt)->memof==mm || mm->has_base(Pptr(frt)->memof)) {
12813: if (found)
12814: error("two possible conversions forP toM: %n and %n",found,on);
12815: else
12816: found = on;
12817: }
12818: }
12819: //error('d',"found %n",found);
12820: if (found) {
12821: p = new ref(DOT,p,found);
12822: p = new call(p,0);
12823: p = p->typ(tbl);
12824: pt = p->tp;
12825: }
12826:
12827: }
12828: while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp;
12829: if (pt->base!=PTR || Pptr(pt)->memof==0) {
12830: error("P toMX in .*E: %t",pt);
12831: tp = any_type;
12832: base = DUMMY;
12833: return this;
12834: }
12835: Pclass pm = Pptr(pt)->memof;
12836:
12837: // while (at->base == TYPE) at = Pbase(at)->b_name->tp;
12838: // Pname cn = Pptr(at)->typ->is_cl_obj();
12839: // Pclass mm = cn ? Pclass(cn->tp) : 0;
12840: //error('d',"mm %t %t %d %d",mm,pm,pm->baseof(mm),mm->has_base(pm));
12841:
12842: // if (mm!=pm && pm->baseof(mm)==0 && mm->has_base(pm)==0) {
12843: if (mm != pm) {
12844: if (mm->has_base(pm) == 0) {
12845: error("badOT in .*E: %t (%s*X)",a->tp,pm->string);
12846: tp = any_type;
12847: //return this;
12848: }
12849: a = new texpr(CAST,pm->this_type,a);
12850: e1 = a = a->typ(tbl);
12851: }
12852:
12853: Ptype tpx = Pptr(pt)->typ;
12854: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
12855:
12856: if (tpx->base == FCT) { // a.*p => (&a MEMPTR p)
12857: base = MEMPTR;
12858: tp2 = mm; // keep the class for simpl.c
12859: e1 = a;
12860: e2 = p;
12861: }
12862: else { // a .* p => *(typeof(p))((char*)&a + (int)p-1)
12863: a = new cast(Pchar_type,a);
12864: p = new cast(int_type,p);
12865: p = new expr(MINUS,p,one);
12866: p->tp = int_type;
12867: Pexpr pl = new expr(PLUS,a,p);
12868: pl->tp = Pchar_type;
12869: base = DEREF;
12870: pt = new ptr(PTR,tpx); // need a T* not a T C::*
12871: Pptr(pt)->rdo = Pptr(tpx)->rdo;
12872: mpglob = pm;
12873: // PERM(pt);
12874: e1 = new cast(pt,pl);
12875: e2 = 0;
12876: }
12877: tp = tpx;
12878: return tp->is_ref() ? contents() : this;
12879: }
12880:
12881: case G_CALL:
12882: case CALL:
12883: tp = call_fct(tbl); /* two calls of use() for e1's names */
12884: if (tp->is_ref()) return contents();
12885: return this;
12886:
12887: case DEREF:
12888: if (e1 == dummy) error("O missing before []\n");
12889: if (e2 == dummy) error("subscriptE missing");
12890:
12891: if (t) { /* *t */
12892: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
12893: // t->vec_type();
12894: if (t->base==PTR && Pptr(t)->memof) error("P toM dereferenced");
12895: tp = t->deref();
12896: }
12897: else { // e1[e2] that is *(e1+e2)
12898: //error('d',"deref %t[%t]",t1,t2);
12899: if (t1->vec_type()) { // e1[e2]
12900: switch (t2->base) {
12901: case CHAR:
12902: case SHORT:
12903: case INT:
12904: case LONG:
12905: case EOBJ:
12906: break;
12907: default:
12908: { Pname cn = t2->is_cl_obj();
12909: if (cn) // conversion to integral?
12910: e2 = check_cond(e2,DEREF,tbl);
12911: else
12912: t2->integral(DEREF);
12913: }
12914: }
12915: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
12916: if (t1->base==PTR && Pptr(t1)->memof) error("P toM dereferenced");
12917: tp = t1->deref();
12918: (void) tp->tsizeof();
12919: }
12920: else if (t2->vec_type()) { // really e2[e1]
12921: t1->integral(DEREF);
12922: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
12923: if (t2->base==PTR && Pptr(t2)->memof) error("P toM dereferenced");
12924: tp = t2->deref();
12925: (void) tp->tsizeof();
12926: }
12927: else {
12928: error("[] applied to nonPT:%t[%t]",t1,t2);
12929: tp = any_type;
12930: }
12931: }
12932:
12933: if (tp->is_ref()) return contents();
12934:
12935: return this;
12936:
12937: case G_ADDROF:
12938: case ADDROF:
12939: //error('d',"addrof(%d) %k %d",base,e2->base,e2->base);
12940: switch (e2->base) { // potential lvalues
12941: case G_CM:
12942: if (base==ADDROF && e2->e2->base==NAME) {
12943: // check for cfront generated result variable
12944: char* s = e2->e2->string;
12945: if (s[0]=='_' && s[1] && s[1]=='_') {
12946: if (s[2] && (s[2]=='R' || s[2]=='V')) {
12947: error("address of non-lvalue");
12948: break;
12949: }
12950: }
12951: }
12952: case CM: // &(a,b) => (a,&b)
12953: {
12954: Pexpr ee = e2;
12955: ee->tp = 0;
12956: ee->e2 = new expr(base,0,ee->e2);
12957: delete this;
12958: return ee->typ(tbl);
12959: }
12960: case QUEST: // & (a?b:c) => (a?&b:&c)
12961: {
12962: Pexpr ee = e2;
12963: ee->tp = 0;
12964: ee->e1 = new expr(base,0,ee->e1);
12965: ee->e2 = new expr(base,0,ee->e2);
12966: delete this;
12967: return ee->typ(tbl);
12968: }
12969: case INCR:
12970: case DECR:
12971: if (e2->e1) break;
12972: case ASSIGN:
12973: case ASPLUS:
12974: case ASMINUS:
12975: case ASMUL:
12976: case ASDIV:
12977: case ASMOD:
12978: case ASAND:
12979: case ASOR:
12980: case ASER:
12981: case ASLS:
12982: case ASRS:
12983: return e2->address();
12984: }
12985:
12986: if (e2->lval(ADDROF) == 0) {
12987: if (error_count) { // error_count == 0 possible
12988: // in case of & const
12989: tp = any_type;
12990: return this;
12991: }
12992: }
12993:
12994: tp = t->addrof();
12995:
12996: if( base==ADDROF && mpglob)
12997: Pptr(tp)->memof = mpglob;
12998:
12999: if (e2->tp->base == VEC) {
13000: if(e2->base != NAME) {
13001: base = CAST;
13002: tp2 = tp;
13003: e1 = e2;
13004: e2 = 0;
13005: return this;
13006: }
13007: }
13008:
13009: // tp = t->addrof();
13010:
13011: if (t->base==FCT)
13012: Pptr(tp)->memof = Pfct(t)->memof;
13013:
13014: // if (t->tconst() && vec_const==0 && fct_const==0) Pptr(tp)->rdo = 1;
13015: // ??? & (const T) is NOT T*const but const T*
13016:
13017: switch (e2->base) {
13018: case NAME:
13019: mname: // check for &s::i
13020: { Pname n2 = Pname(e2);
13021: Pname cn = (n2->n_table && n2->n_table!=gtbl) ? n2->n_table->t_name : 0;
13022: // error('d',"n2 %k cn %n t %t",n2->base,cn,t);
13023: if (cn == 0) break;
13024: // Pptr(tp)->memof = Pclass(cn->tp);
13025:
13026: if (t->base==FCT && Pfct(t)->f_this==0) {
13027: Pptr(tp)->memof = 0;
13028: break;
13029: }
13030:
13031: switch (t->base) {
13032: case OVERLOAD:
13033: return e2;
13034: case FCT:
13035: // error('d', "cn->tp: %d, %k", cn->tp, cn->tp->base);
13036: Pptr(tp)->memof = Pclass(cn->tp); //SSS
13037:
13038: if (Pfct(t)->f_virtual) {
13039: // { 0,vtbl index,0 }
13040: e1 = new ival(Pfct(t)->f_virtual);
13041: e1 = new expr(ELIST,zero,e1);
13042: e2 = zero;
13043: base = ILIST;
13044: // tp = int_type;
13045: return this;
13046: } // use the pointer
13047:
13048: // { 0,-1,(int(*)())ptr }
13049: e1 = new ival(-1);
13050: e1 = new expr(ELIST,zero,e1);
13051: // e2 is the name
13052: e2 = new cast(Pfct_type,e2);
13053: base = ILIST;
13054: // tp = int_type;
13055: return this;
13056:
13057: // return e2;
13058:
13059: default:
13060: if (n2->n_stclass != STATIC) { // offset + 1
13061: //error('d',"n2 %n %d",n2,n2->n_offset);
13062: //error('d',"q %n cn %n",n2->n_qualifier,cn);
13063: e1 = new ival(n2->n_offset+1);
13064: Pptr(tp)->memof = Pclass(cn->tp);
13065: //error('d',"cl %d %s i %d",Pclass(cn->tp),Pclass(cn->tp)?Pclass(cn->tp)->string:"0",n2->n_offset);
13066: }
13067: else
13068: return this;
13069: }
13070: //error('d',"int_type");
13071: e1->tp = int_type;
13072: e2 = 0;
13073: tp2 = tp;
13074: base = CAST;
13075: return this;
13076: }
13077: case DOT:
13078: case REF:
13079: {
13080: Pname m = Pname(e2->mem);
13081: // error( 'd', "e2->mem->base: %k", e2->mem->base );
13082: // Pname m = (e2->mem->base == MDOT) ? Pname(e2->mem->mem) : Pname(e2->mem);
13083: while ( m->base == MDOT ) m = Pname(Pexpr(m)->mem);
13084:
13085: Pfct f = Pfct(m->tp);
13086:
13087: if (f->base == FCT || f->base == OVERLOAD) { // &p->f
13088: Pexpr q = Pname(e2)->n_initializer; // &p->x::f
13089:
13090: if (q && bound==0 && e2->e1==cc->c_this) {
13091: // FUDGE: &this->x::f => &x::f
13092: DEL(e2);
13093: e2 = m;
13094: goto mname;
13095: }
13096:
13097: bound = 1;
13098: if(!f->f_static) {
13099: error(strict_opt?0:'w',
13100: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
13101: m->n_table->t_name->string,
13102: m->n_table->t_name->string,
13103: m->string
13104: );
13105: }
13106:
13107: if (q || f->f_virtual==0) {
13108: // & x.f => & f
13109: DEL(e2);
13110: e2 = m;
13111: }
13112: }
13113: break;
13114:
13115: }
13116: case MEMPTR:
13117: // &(p->*q)
13118: error("& .* E");
13119: }
13120:
13121: return this;
13122:
13123: case UMINUS:
13124: t->numeric(UMINUS);
13125: tp = t;
13126: return this;
13127:
13128: case UPLUS:
13129: t->num_ptr(UPLUS);
13130: tp = t;
13131: if (ansi_opt==0) {
13132: base = PLUS;
13133: e1 = zero;
13134: }
13135: return this;
13136:
13137: case NOT:
13138: e2 = check_cond(e2,NOT,tbl);
13139: tp = int_type;
13140: return this;
13141:
13142: case COMPL:
13143: t->integral(COMPL);
13144: tp = t;
13145: return this;
13146:
13147: case INCR:
13148: case DECR:
13149: {
13150: // error('d',"incr-decr: e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0);
13151: Pexpr e = e1?e1:e2; // e1!=0 ==> e++ or e--
13152: // e1==0 ==> ++e or --e
13153:
13154: e->lval(b);
13155:
13156: switch(e->base) {
13157: case QUEST:
13158: e->tp=0;
13159: e->e1 = e1 ? new expr(base,e->e1,0) : new expr(base,0,e->e1);
13160: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
13161: delete this;
13162: return e->typ(tbl);
13163: case CM:
13164: case G_CM:
13165: e->tp=0;
13166: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
13167: delete this;
13168: return e->typ(tbl);
13169: case INCR:
13170: case DECR:
13171: if(e->e1)
13172: break;
13173: nin++;
13174: if(e->e2->not_simple())
13175: error('s',"overly complex %k of %k",b,e->base);
13176: nin--;
13177: e = new expr(G_CM,e,e->e2->typ(tbl));
13178: if (e1) e1=e; else e2=e;
13179: // e1?e1:e2 = e;
13180: return typ(tbl);
13181: case ASSIGN:
13182: case ASPLUS:
13183: case ASMINUS:
13184: case ASMUL:
13185: case ASDIV:
13186: case ASMOD:
13187: case ASAND:
13188: case ASOR:
13189: case ASER:
13190: case ASLS:
13191: case ASRS:
13192: nin++;
13193: if(e->e1->not_simple())
13194: error('s',"overly complex %k of %k",b,e->base);
13195: nin--;
13196: e = new expr(G_CM,e,e->e1->typ(tbl));
13197: if (e1) e1=e; else e2=e;
13198: // e1?e1:e2 = e;
13199: return typ(tbl);
13200: }
13201: }
13202:
13203: r1 = t->num_ptr(b);
13204: if (r1='P' && t->check(Pvoid_type,0)==0) error("%k of void*",b);
13205: tp = t;
13206: return this;
13207:
13208: }
13209:
13210: if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b);
13211: switch (b) {
13212: case MUL:
13213: case DIV:
13214: r1 = t1->numeric(b);
13215: r2 = t2->numeric(b);
13216: nppromote(b);
13217: break;
13218:
13219: case PLUS:
13220: r2 = t2->num_ptr(PLUS);
13221: r1 = t1->num_ptr(PLUS);
13222: nppromote(PLUS);
13223: goto void_check;
13224:
13225: case MINUS:
13226: r2 = t2->num_ptr(MINUS);
13227: r1 = t1->num_ptr(MINUS);
13228: if (r2=='P' && r1!='P' && r1!='A') error("nonP - P");
13229: nppromote(MINUS);
13230: void_check:
13231: if ((r1='P' && t1->check(Pvoid_type,0)==0)
13232: || (r2='P' && t2->check(Pvoid_type,0)==0))
13233: error("%k of void*",b);
13234: tp = t;
13235: break;
13236:
13237: case LS:
13238: case RS:
13239: case AND:
13240: case OR:
13241: case ER:
13242: switch (e1->base) {
13243: case LT:
13244: case LE:
13245: case GT:
13246: case GE:
13247: case EQ:
13248: case NE:
13249: error('w',"%kE as operand for%k",e1->base,b);
13250: }
13251: switch (e2->base) {
13252: case LT:
13253: case LE:
13254: case GT:
13255: case GE:
13256: case EQ:
13257: case NE:
13258: error('w',"%kE as operand for%k",e2->base,b);
13259: }
13260: case MOD:
13261: r1 = t1->integral(b);
13262: r2 = t2->integral(b);
13263: nppromote(b);
13264: break;
13265:
13266: case LT:
13267: case LE:
13268: case GT:
13269: case GE:
13270: case EQ:
13271: case NE:
13272: r1 = t1->num_ptr(b);
13273: r2 = t2->num_ptr(b);
13274: if (r1=='P' && r2=='I') { // allow things like:
13275: // if (p==2-2)
13276: // YUCK!
13277: Neval = 0;
13278: long i = e2->eval();
13279: if (Neval==0 && i==0) {
13280: DEL(e2);
13281: e2 = zero;
13282: r2 = 'Z';
13283: }
13284: }
13285: else if (r2=='P' && r1=='I') {
13286: Neval = 0;
13287: long i = e1->eval();
13288: if (Neval==0 && i==0) {
13289: DEL(e1);
13290: e1 = zero;
13291: r1 = 'Z';
13292: }
13293: }
13294:
13295: if (b!=EQ && b!=NE) {
13296: if (r1=='P' && r2=='Z') error("P%k 0",b);
13297: if (r2=='P' && r1=='Z') error("P%k 0",b);
13298: }
13299:
13300: // make sure functions are properly converted to pointers to
13301: // functions and make sure overloaded functions are rejected
13302: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl);
13303: if (r1 == FCT) e1 = ptof(0,e1,tbl);
13304: if (r2 == FCT) e2 = ptof(0,e2,tbl);
13305:
13306: npcheck(b);
13307:
13308: if (r1=='P') { // need cast for pointers to virtual and second bases
13309: Pptr p1 = t1->is_ptr();
13310: Pptr p2 = t2->is_ptr();
13311: Pname cn = p1?p1->typ->is_cl_obj():0;
13312: Pname cn2 = p2?p2->typ->is_cl_obj():0;
13313:
13314: if (cn && cn2) {
13315: Pclass cl = Pclass(cn->tp);
13316: Pclass cl2 = Pclass(cn2->tp);
13317:
13318: if (cl->has_base(cl2)) {
13319: e1 = cast_cptr(cl2,e1,tbl,0);
13320: e1 = new cast(p2,e1);
13321: }
13322: else if (cl2->has_base(cl)) {
13323: e2 = cast_cptr(cl,e2,tbl,0);
13324: e2 = new cast(p1,e2);
13325: }
13326: }
13327: }
13328:
13329: if (r1=='P' && t1->memptr()) {
13330: mpmp:
13331: if (r2=='Z') {
13332: e2 = zero;
13333: e1 = new mdot("i",e1);
13334: e1->i1 = 9;
13335: }
13336: else if (r2=='P' && t2->memptr()) {
13337: // ERROR: no check for sideeffects
13338: Pexpr i1 = new mdot("i",e1);
13339: Pexpr i2;
13340: i1->i1 = 9;
13341:
13342: i2 = e2;
13343: while ( i2->base == CAST )
13344: i2 = i2->e1;
13345: if ( i2->base == ILIST )
13346: e2 = i2;
13347:
13348: if (e2->base==ILIST)
13349: i2 = e2->e1->e2;
13350: else {
13351: i2 = new mdot("i",e2);
13352: i2->i1 = 9;
13353: }
13354:
13355: Pexpr f1 = new mdot("f",e1);
13356: Pexpr f2;
13357: f1->i1 = 9;
13358: if (e2->base == ILIST)
13359: // f2 = new cast(Pfct_type,e2->e2);
13360: f2 = e2->e2;
13361: else {
13362: f2 = new mdot("f",e2);
13363: f2->i1 = 9;
13364: }
13365:
13366: Pexpr ei = new expr(base,i1,i2);
13367: Pexpr fi = new expr(base,f1,f2);
13368:
13369: base = ANDAND;
13370: e1 = ei;
13371: e2 = fi;
13372: } else if (r2=='P') {
13373: error('s',"%t %k %t",t1,base,t2);
13374: }
13375: }
13376: else if (r2=='P' && t2->memptr()) {
13377: Pexpr ee = e1; // swap
13378: e1 = e2;
13379: e2 = ee;
13380: int rr = r1;
13381: r1 = r2;
13382: r2 = rr;
13383: Ptype tt = t1;
13384: t1 = t2;
13385: t2 = tt;
13386: goto mpmp;
13387: }
13388: t = int_type;
13389: break;
13390:
13391: case ANDAND:
13392: case OROR:
13393: e1 = check_cond(e1,b,tbl);
13394: e2 = check_cond(e2,b,tbl);
13395: t = int_type;
13396: break;
13397:
13398: case QUEST:
13399: {
13400: Pname c1, c2;
13401: cond = check_cond(cond,b,tbl);
13402: //error('d',"cond %k %t",cond->base,cond->tp);
13403: //error('d',"t1 %t t2 %t",t1,t2);
13404:
13405: // still doesn't do complete checking for possible conversions...
13406:
13407: bit MPTR = 0; // local hack
13408:
13409: extern int suppress_error; // global hack
13410: suppress_error++;
13411: r1 = t1->num_ptr(b);
13412: r2 = t2->num_ptr(b);
13413: suppress_error--;
13414: if (r1=='P' && r2=='P' && t1->memptr() && t2->memptr()) {
13415:
13416: ++MPTR; // prevent later sorry
13417:
13418: // watch for casts
13419: Pexpr tt = e1;
13420: while ( tt->base == CAST ) tt = tt->e1;
13421: if ( tt->base == ILIST ) e1 = tt;
13422:
13423: tt = e2;
13424: while ( tt->base == CAST ) tt = tt->e1;
13425: if ( tt->base == ILIST ) e2 = tt;
13426:
13427: // cannot have sides return (expr?{}:{})
13428: // reuse same temp for both sides ?:
13429: Pname temp = make_tmp( 'A', mptr_type, tbl );
13430:
13431: e1 = mptr_assign( temp, e1 );
13432: e1 = new expr( G_CM, e1, temp );
13433: e1->tp = temp->tp;
13434:
13435: e2 = mptr_assign( temp, e2 );
13436: e2 = new expr( G_CM, e2, temp );
13437: e2->tp = temp->tp;
13438: }
13439:
13440: if (t1==t2
13441: || ( (c1=t1->is_cl_obj())
13442: && (c2=t2->is_cl_obj())
13443: && (c1->tp==c2->tp)
13444: ))
13445: t = t1;
13446: else {
13447: r1 = t1->num_ptr(b);
13448: r2 = t2->num_ptr(b);
13449:
13450: if (r1=='P' && r2=='P') {
13451: Pptr p1 = t1->is_ptr();
13452: Pptr p2 = t2->is_ptr();
13453: //error('d',"p1 %t p2 %t",p1,p2);
13454: if ((c1 = p1->typ->is_cl_obj())
13455: && (c2 = p2->typ->is_cl_obj())) {
13456: Pclass cl1 = Pclass(c1->tp);
13457: Pclass cl2 = Pclass(c2->tp);
13458: if (cl1==cl2 || cl2->has_base(cl1)) {
13459: t = t1;
13460: goto caca;
13461: }
13462: else if (cl1->has_base(cl2)) {
13463: t = t2;
13464: goto caca;
13465: }
13466: }
13467: }
13468:
13469: if (r1==FCT && r2==FCT) { // fudge
13470: if (t1->check(t2,ASSIGN))
13471: error("badTs in ?:E: %t and %t",t1,t2);
13472: else if (Pfct(t1)->memof) error('s',"conditionalE with%t",t1);
13473: t = t1;
13474: }
13475: else
13476: nppromote(b);
13477: caca:
13478: //error('d',"?: t %t t1 %t t2 %t",t,t1,t2);
13479: if (t!=t1 && t->check(t1,0)) {
13480: PERM(t);
13481: e1 = new cast(t,e1);
13482: }
13483:
13484: if (t!=t2 && t->check(t2,0)) {
13485: PERM(t);
13486: e2 = new cast(t,e2);
13487: }
13488:
13489: Pptr pt = t->is_ptr();
13490: //if (pt && pt->base==PTR && pt->memof) error('s',"conditionalE with%t",t);
13491: if (pt && pt->base==PTR && pt->memof && MPTR == 0) error('s',"conditionalE with%t",t);
13492: }
13493: }
13494: break;
13495:
13496: case ASPLUS:
13497: r1 = t1->num_ptr(ASPLUS);
13498: r2 = t2->num_ptr(ASPLUS);
13499: nppromote(ASPLUS);
13500: goto ass;
13501:
13502: case ASMINUS:
13503: r1 = t1->num_ptr(ASMINUS);
13504: r2 = t2->num_ptr(ASMINUS);
13505: if (r2=='P' && r1!='P' && r1!='A') error("P -= nonP");
13506: nppromote(ASMINUS);
13507: goto ass;
13508:
13509: case ASMUL:
13510: case ASDIV:
13511: r1 = t1->numeric(b);
13512: r2 = t1->numeric(b);
13513: nppromote(b);
13514: goto ass;
13515:
13516: case ASMOD:
13517: r1 = t1->integral(ASMOD);
13518: r2 = t2->integral(ASMOD);
13519: nppromote(ASMOD);
13520: goto ass;
13521:
13522: case ASAND:
13523: case ASOR:
13524: case ASER:
13525: case ASLS:
13526: case ASRS:
13527: r1 = t1->integral(b);
13528: r2 = t2->integral(b);
13529: npcheck(b);
13530: t = int_type;
13531: goto ass;
13532: ass:
13533: if (r1='P' && t1->check(Pvoid_type,0)==0) error("%k of void*",b);
13534: tp = t;
13535: as_type = t; /* the type of the rhs */
13536: t2 = t;
13537:
13538: case ASSIGN:
13539: //error('d',"assign %k: %t %t %s",b,t1,t2,ignore_const?"ignore const":"");
13540: //error('d'," e1 %d %k e1 %d %k",e1,e1->base,e2,e2->base);
13541: if (ignore_const) { // handle static initializers
13542: // represented as assignments
13543: // ignore consts.
13544: tp = e1->tp;
13545: return this;
13546: }
13547:
13548: switch (e1->base) {
13549: case G_CM:
13550: case CM: // (a,b)=c => *(a,&b)=c
13551: {
13552: e1->e2 = new expr(G_ADDROF,0,e1->e2);
13553: e1->tp = 0;
13554: e1 = new expr(DEREF,e1,0);
13555: return typ(tbl);
13556: }
13557: case QUEST: // (a?b:c)=d => *(a?&b:&c)=c
13558: {
13559: e1->e1 = new expr(G_ADDROF,0,e1->e1);
13560: e1->e2 = new expr(G_ADDROF,0,e1->e2);
13561: e1->tp = 0;
13562: e1 = new expr(DEREF,e1,0);
13563: return typ(tbl);
13564: }
13565: case ASSIGN: // (a*=b)=c => a*=b,a=c
13566: case ASPLUS:
13567: case ASMINUS:
13568: case ASMUL:
13569: case ASDIV:
13570: case ASMOD:
13571: case ASAND:
13572: case ASOR:
13573: case ASER:
13574: case ASLS:
13575: case ASRS:
13576: {
13577: base = G_CM;
13578: nin++;
13579: if (e1->e1->not_simple()) error('s',"lvalue %k too complicated",b);
13580: nin--;
13581: Pexpr aa = new expr(e1->base,e1->e1,e1->e2);
13582: Pexpr bb = new expr(b,e1->e1,e2);
13583: e1 = aa;
13584: e2 = bb;
13585: return typ(tbl);
13586: }
13587: case INCR:
13588: case DECR: // ++a=b => ++a,a=b
13589: {
13590: if(!e1->e2) break ;
13591: base = G_CM;
13592: nin++;
13593: if (e1->e2->not_simple()) error('s',"lvalue %k too complicated",b);
13594: nin--;
13595: Pexpr aa = new expr(e1->base,0,e1->e2);
13596: Pexpr bb = new expr(b,e1->e2,e2);
13597: e1 = aa;
13598: e2 = bb;
13599: return typ(tbl);
13600: }
13601: case REF:
13602: {
13603: Pexpr r = e1;
13604: // hack to prevent
13605: // f().i = j
13606: // transformed into
13607: // ((t=f()),&t)->i = j
13608: if (r->e1->base==G_CM
13609: && r->e1->e2->base==G_ADDROF
13610: && r->e1->e2->e2->base==NAME) {
13611: char* s = r->e1->e2->e2->string;
13612: if (s[0]=='_' && s[1]=='_')
13613: error("left hand side not lvalue");
13614: }
13615: }
13616: }
13617:
13618: if (e1->lval(b) == 0) {
13619: tp = any_type;
13620: return this;
13621: }
13622: lkj:
13623: switch (t1->base) {
13624: case TYPE:
13625: t1 = Pbase(t1)->b_name->tp;
13626: goto lkj;
13627: case INT:
13628: case CHAR:
13629: case SHORT:
13630: // if (e2->base==ICON && e2->tp==long_type)
13631: // error('w',"long constant assigned to%k",t1->base);
13632: { Ptype t = e2->tp;
13633: csi:
13634: switch (t->base) {
13635: case TYPE:
13636: t = Pbase(t)->b_name->tp; goto csi;
13637: case LONG:
13638: case FLOAT:
13639: case DOUBLE:
13640: case LDOUBLE:
13641: error('w',"%t assigned to %t",e2->tp,t1);
13642: }
13643: }
13644: // no break
13645: case LONG:
13646: if (b==ASSIGN
13647: && Pbase(t1)->b_unsigned
13648: && e2->base==UMINUS
13649: && e2->e2->base==ICON)
13650: error('w',"negative assigned to unsigned");
13651: break;
13652: case PTR:
13653: if (b == ASSIGN) {
13654: //error('d',"ptr t1 %t %d %t",t1,t1->memptr(),t2);
13655: //?? if (t1->memptr() && t2->base!=OVERLOAD) break;
13656: e2 = ptr_init(Pptr(t1),e2,tbl);
13657: t2 = e2->tp;
13658: //error('d',"pchecked %d",Pchecked);
13659: if (Pchecked) {
13660: tp = e1->tp;
13661: return this;
13662: }
13663: }
13664: break;
13665: case COBJ:
13666: { Pname c1 = t1->is_cl_obj();
13667: // test of c1->tp necessary for ``fake classes''
13668: // _Sdd generated for vector assignemnts
13669: if (c1
13670: && c1->tp
13671: /* && Pclass(c1->tp)->memtbl->look("__as",0)==0*/) {
13672: //&& Pclass(c1->tp)->has_oper(ASSIGN)==0) {
13673: Pname c2 = t2->is_cl_obj();
13674: // error('d', "expr::typ: c1: %n c2: %n", c1, c2 );
13675: if (c1 != c2) {
13676: /*
13677: consider:
13678:
13679: struct A { A(B&); };
13680: struct B : A {};
13681:
13682: A aa;
13683: B bb;
13684:
13685: aa = bb; // aa.operator=(A(bb));
13686: // optimize to aa.A(bb) when possible
13687: // avoid temporary where aa = *(A*)&bb is legal
13688: */
13689: // error('d',"expr::typ c1 %n %d c2 %n %d",c1,c1?c1->tp:0,c2,c2?c2->tp:0);
13690: if (c2
13691: && c2->tp
13692: && can_coerce(t1,t2)==0
13693: //&& Pclass(c2->tp)->has_base(Pclass(c1->tp))
13694: //&& (1<is_unique_base(Pclass(c2->tp),c1->string,0))
13695: && (vcllist->clear(),vcllist=0,1<is_unique_base(Pclass(c2->tp),c1->string,0))
13696: && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
13697: // error('d',"aaa");
13698: if (make_assignment(c1)) return try_to_overload(tbl);
13699: }
13700: // optimize
13701: else {
13702: e2 = new expr(ELIST,e2,0);
13703: e2 = new texpr(VALUE,t1,e2);
13704: if (Pclass(c1->tp)->has_dtor()==0 &&
13705: Pclass(c1->tp)->has_oper(ASSIGN)==0) {
13706: // optimize
13707: // error('d',"bbb");
13708: e2->e2 = e1;
13709: e2 = e2->typ(tbl);
13710: if (e2->base==DEREF && e2->e1->base==G_CALL ||
13711: e2->base==ASSIGN && e2->e1==e1) {
13712: // error('d',"ccc");
13713: *this = *e2;
13714: }
13715: tp = t1;
13716: return this;
13717: }
13718: return typ(tbl);
13719: }
13720: }
13721: // test of c1->tp necessary for ``fake classes''
13722: // _Sdd generated for vector assignemnts
13723: else if (c1->tp && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
13724: if (make_assignment(c1)) return try_to_overload(tbl);
13725: }
13726: }
13727: (void) t1->tsizeof();
13728: break;
13729: }
13730: }
13731:
13732: //error('d',"check(%t,%t) -> %d",e1->tp,t2,try_to_coerce(t1,e2,"assignment",tbl));
13733: { Pexpr x = try_to_coerce(t1,e2,"assignment",tbl);
13734: if (x)
13735: e2 = x;
13736: else if (e1->tp->check(t2,ASSIGN))
13737: error("bad assignmentT:%t =%t",e1->tp,t2);
13738: else if ((t1 = t1->is_ptr()) && t1->memptr()) {
13739: if (t2 == zero_type) {
13740: Pexpr ee = new expr(ELIST,zero,zero);
13741: e2 = new expr(ILIST,ee,zero);
13742: }
13743: else if (t2->base==PTR && t2->memptr()) {
13744: // do nothing: structure assignment
13745: }
13746: else {
13747: Pexpr x = ptr_init(Pptr(t1),e2,tbl);
13748: if (x != e2) e2 = x;
13749: }
13750: }
13751: }
13752: t = e1->tp; // the type of the lhs
13753: break;
13754: case CM:
13755: case G_CM:
13756: t = t2;
13757: break;
13758: default:
13759: error('i',"unknown operator%k",b);
13760: }
13761:
13762: tp = t;
13763: return this;
13764: }
13765: 0707071010112044271004440001630000160000010200100466055401400001000000130600expr2.c /*ident "@(#)ctrans:src/expr2.c 1.5" */
13766: /***************************************************************************
13767:
13768: C++ source for cfront, the C++ compiler front-end
13769: written in the computer science research center of Bell Labs
13770:
13771: Copyright (c) 1984 AT&T, Inc. All rights Reserved
13772: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
13773:
13774: expr2.c:
13775:
13776: type check expressions
13777:
13778: ************************************************************************/
13779:
13780: #include "cfront.h"
13781: #include "size.h"
13782:
13783: extern Pname conv_dominates(Pname,Pname);
13784: static int const_obj1,const_obj2;
13785:
13786: Pname really_dominate(Pname on1, Pname on2, bit tc)
13787: {
13788: Pfct f1 = on1->tp->base==FCT ? Pfct(on1->tp) :
13789: Pfct(Pgen(on1->tp)->fct_list->f->tp);
13790: Pfct f2 = on2->tp->base==FCT ? Pfct(on2->tp) :
13791: Pfct(Pgen(on2->tp)->fct_list->f->tp);
13792:
13793: // const check
13794: int c1 = f1->f_const;
13795: int c2 = f2->f_const;
13796:
13797: if(c1 == c2) ;
13798: else if(c1 && !c2) return tc ? on1 : on2;
13799: else if(c2 && !c1) return tc ? on2 : on1;
13800:
13801: // hierarchy check
13802: Pname on = conv_dominates(on1,on2);
13803: if(on) return on;
13804: else return 0;
13805: }
13806:
13807: void name::assign()
13808: {
13809: if (n_assigned_to++ == 0) {
13810: switch (n_scope) {
13811: case FCT:
13812: if (n_used && n_addr_taken==0) {
13813: Ptype t = tp;
13814: ll:
13815: switch (t->base) {
13816: case TYPE:
13817: t=Pbase(t)->b_name->tp; goto ll;
13818: case VEC:
13819: break;
13820: default:
13821: if (curr_loop)
13822: error('w',&where,"%n may have been used before set",this);
13823: else
13824: error('w',&where,"%n used before set",this);
13825: }
13826: }
13827: }
13828: }
13829: }
13830:
13831: void name::take_addr()
13832: {
13833: // error('d', "%n->take_addr tp: %t", this, tp?tp:0 );
13834: // error('d', "%n->take_addr tp: %d %d", this, tp?tp:0, tp?tp->base:0 );
13835: if ( (warning_opt) && (! n_addr_taken) && (tp) && (tp->base==FCT) && Pfct (tp)->f_inline)
13836: error('w',"can't take address of inline function %n, %n not inlined", this, this);
13837: n_addr_taken++;
13838: if ( n_sto == EXTERN && tp ) {
13839: Ptype t = tp;
13840: while ( t->base == TYPE )
13841: t = Pbase(t)->b_name->tp;
13842: switch ( t->base ) {
13843: case COBJ:
13844: t = Pbase(t)->b_name->tp; // no break
13845: case CLASS: {
13846: Pclass cl = Pclass(t);
13847: if ( cl->c_body == 1 )
13848: cl->dcl_print(0);
13849: }
13850: }
13851: }
13852: }
13853:
13854: int ignore_const; // for use by ref_init
13855: static is_dataMemPtr(Pexpr);
13856:
13857: int expr::lval(TOK oper)
13858: {
13859: register Pexpr ee = this;
13860: register Pname n;
13861: int deref = 0;
13862: char* es;
13863:
13864: //error('d',"%k expr::lval %k",base,oper);
13865:
13866: switch (oper) {
13867: case ADDROF:
13868: case G_ADDROF: es = "address of"; break;
13869: case DEREF: es = "dereference of"; break;
13870: case INCR: es = "increment of"; goto def;
13871: case DECR: es = "decrement of"; goto def;
13872: default: es = "assignment to";
13873: def:
13874: if (ignore_const==0 && tp->tconst()) {
13875: if (oper) {
13876: if (base == NAME) {
13877: if (vec_const && Pname(this)->n_scope==ARG) break;
13878: error("%s constant%n",es,this);
13879: }
13880: else
13881: error("%s constant",es);
13882: }
13883: return 0;
13884: }
13885: }
13886:
13887: for(;;) {
13888: //error('d',"loop %k",ee->base);
13889: switch (ee->base) {
13890: // case G_CALL:
13891: // case CALL:
13892: default:
13893: defa:
13894: if (deref == 0) {
13895: if (oper) error("%s%k (not an lvalue)",es,ee->base);
13896: return 0;
13897: }
13898: return 1;
13899: case ZERO:
13900: case CCON:
13901: case ICON:
13902: case FCON:
13903: if (oper) error("%s numeric constant",es);
13904: return 0;
13905: case STRING:
13906: if (oper) error('w',"%s string constant",es);
13907: return 1;
13908: case CAST:
13909: switch( oper ) {
13910: case 0:
13911: case ADDROF:
13912: case G_ADDROF:
13913: case DEREF:
13914: goto defa;
13915: default:
13916: if ( ee->tp->base == PTR
13917: && is_dataMemPtr(ee) )
13918: { // check for const class object
13919: Pexpr te;
13920: te = ee->e1->e1->e1;
13921: if ( te->base == G_ADDROF )
13922: te = te->e2;
13923: if ( te->base == NAME ) {
13924: Ptype pt = te->tp;
13925: if ( pt->base == PTR )
13926: pt = Pptr(pt)->typ;
13927: if ( pt->tconst() )
13928: error("%sCMP of const%n",es,te);
13929: return 0;
13930: }
13931: }
13932: goto defa;
13933: }
13934:
13935: case DEREF:
13936: {
13937: Pexpr ee1 = ee->e1;
13938: // error( 'd', "ee1: %k", ee1->base );
13939: switch (ee1->base) { // *& vanishes
13940: case ADDROF: // *&
13941: return 1;
13942: case G_CM:
13943: case CM: // look for *(a,&b)
13944: if (ee1->e2->base==G_ADDROF
13945: || ee1->e2->base==ADDROF)
13946: return 1;
13947: goto defaa;
13948: case QUEST: // look for *(q?&a:&b)
13949: if ((ee1->e1->base==G_ADDROF
13950: || ee1->e1->base==ADDROF)
13951: && (ee1->e2->base==G_ADDROF
13952: || ee1->e2->base==ADDROF))
13953: return 1;
13954: // no break
13955: default:
13956: defaa:
13957: ee = ee1;
13958: deref = 1;
13959: }
13960: break;
13961: }
13962:
13963: case QUEST:
13964: { int x1 = ee->e1->lval(deref?0:oper);
13965: int x2 = ee->e2->lval(deref?0:oper);
13966: if (ee->e1->tp->check(ee->e2->tp,0)) return 0;
13967: if (deref) return 1;
13968: return x1 && x2;
13969: }
13970:
13971: case INCR:
13972: case DECR:
13973: if (e1) goto defa; // postfix does not preserve lval
13974: case ASSIGN:
13975: case ASPLUS:
13976: case ASMINUS:
13977: case ASMUL:
13978: case ASDIV:
13979: case ASMOD:
13980: case ASAND:
13981: case ASOR:
13982: case ASER:
13983: case ASLS:
13984: case ASRS:
13985: return 1;
13986:
13987: case CM:
13988: case G_CM:
13989: if (ee->e2->lval(deref?0:oper)==0) return deref;
13990: return 1;
13991:
13992: case MEMPTR:
13993: ee = ee->e2;
13994: break;
13995:
13996: case MDOT:
13997: ee = ee->mem;
13998: break;
13999:
14000: case DOT:
14001: {
14002: // error('d',"dot %k oper %k",ee->e1->base,oper);
14003: Pexpr e = 0;
14004: int e_const = 0; // to catch x.y.val = 1, where x is const
14005:
14006: switch (ee->e1->base) { // update use counts, etc.
14007: case NAME:
14008: switch (oper) {
14009: case ADDROF:
14010: case G_ADDROF: Pname(ee->e1)->take_addr();
14011: case 0: break;
14012: case ASSIGN: Pname(ee->e1)->n_used--;
14013: default: Pname(ee->e1)->assign(); // asop
14014: }
14015: break;
14016: case DOT:
14017: e = ee->e1;
14018: do e=e->e1; while (e->base==DOT);
14019: if (e->base == NAME) {
14020: e_const = e->tp->tconst();
14021: switch (oper) {
14022: case ADDROF:
14023: case G_ADDROF: Pname(e)->take_addr();
14024: case 0: break;
14025: case ASSIGN: Pname(e)->n_used--;
14026: default: Pname(e)->assign(); // asop
14027: }
14028: }
14029: }
14030:
14031: n = Pname(ee->mem);
14032: while (n->base == MDOT) n = Pname(Pref(n)->mem);
14033:
14034: if (deref==0 &&
14035: (ee->e1->tp->tconst() || e_const)) {
14036:
14037: switch (oper) {
14038: case 0:
14039: case ADDROF:
14040: case G_ADDROF:
14041: case DEREF:
14042: break;
14043: default:
14044: error("%sM%n of%t",es,n,e_const?e->tp:ee->e1->tp);
14045: }
14046: return 0;
14047: }
14048: }
14049: goto xx;
14050:
14051: case REF:
14052: n = Pname(ee->mem);
14053: while (n->base == MDOT) n = Pname(Pref(n)->mem);
14054:
14055: if (deref==0 && ee->e1) { //BR
14056: Ptype p = ee->e1->tp;
14057: zxc:
14058: switch (p->base) {
14059: case TYPE: p = Pbase(p)->b_name->tp; goto zxc;
14060: case PTR:
14061: case VEC: break;
14062: default: error('i',"expr::lval %t->%n",p,n);
14063: }
14064: if (Pptr(p)->typ->tconst()) {
14065: switch (oper) {
14066: case 0:
14067: case G_ADDROF:
14068: case DEREF:
14069: break;
14070: case ADDROF:
14071: if ( cm_const_save == 0 && const_ptr == 0 )
14072: error(strict_opt?0:'w',"%sM%n of%t",es,n,Pptr(p)->typ);
14073: break;
14074: default:
14075: error("%sM%n of%t",es,n,Pptr(p)->typ);
14076: }
14077: return 0;
14078: }
14079: }
14080: goto xx;
14081:
14082: case NAME:
14083: n = Pname(ee);
14084: xx:
14085: // error('d',"name xx: %n oper %d lex_level: %d",n,oper,n->lex_level);
14086: if (deref) return 1;
14087: if (oper==0) return n->n_stclass != ENUM ;
14088:
14089: if (n->tp->base==FIELD && Pbase(n->tp)->b_bits==0) {
14090: error("%s 0-length field%n",es,n);
14091: return 0;
14092: }
14093:
14094: switch (oper) {
14095: case ADDROF:
14096: case G_ADDROF:
14097: { Pfct f = (Pfct)n->tp;
14098:
14099: if (n->n_sto == REGISTER) {
14100: if (warning_opt) error('w',"& register%n",n);
14101: // return 0;
14102: n->n_sto = 0;
14103: n->n_stclass = AUTO;
14104: }
14105:
14106: if (f == 0) {
14107: error("& label%n",n);
14108: return 0;
14109: }
14110:
14111: if (n->n_stclass == ENUM) {
14112: error("& enumerator%n",n);
14113: return 0;
14114: }
14115:
14116: if (n->tp->base == FIELD) {
14117: error("& field%n",n);
14118: return 0;
14119: }
14120:
14121: n->n_used--;
14122: if (n->n_qualifier) { // oops, not the real one
14123: Pname tn = Pclass(n->n_table->t_name->tp)->memtbl->look(n->string,0);
14124: n = tn ? tn : n;
14125: }
14126: n->take_addr();
14127:
14128: // suppress hoisting of local consts
14129: int statmem = n->n_scope==0 || n->n_scope==PUBLIC || n->n_scope == FCT;
14130: if (n->n_evaluated && n->n_scope!=ARG) { // &const
14131: if (statmem == 0 && n->n_dcl_printed==0) {
14132: n->n_initializer = new ival(n->n_val);
14133: n->dcl_print(0);
14134: }
14135: }
14136: else if (f->base==FCT && n->n_dcl_printed==0)
14137: n->dcl_print(0);
14138: break;
14139: }
14140:
14141: case ASSIGN:
14142: //error('d',"ass %n %d",n,n->n_used);
14143: n->n_used--;
14144: n->assign();
14145: break;
14146: // goto check_void;
14147: default: /* incr ops, and asops */
14148: if (cc->tot && n==cc->c_this) {
14149: error("%n%k",n,oper);
14150: return 0;
14151: }
14152: // check_void:
14153: // { Ptype t = n->tp;
14154: // while (t->base==TYPE) t = Pbase(t)->b_name->tp;
14155: // if (t==Pvoid_type) {
14156: // error("%s%t",es,n->tp);
14157: // return 0;
14158: // }
14159: // }
14160: n->assign();
14161: }
14162: return 1;
14163: }
14164: }
14165: }
14166:
14167: int char_to_int(char* s)
14168: /* assume s points to a string:
14169: 'c'
14170: or '\c'
14171: or '\0'
14172: or '\ddd'
14173: or multi-character versions of the above
14174: (hex constants have been converted to octal by the parser)
14175: */
14176: {
14177: register int i = 0;
14178: register char c, d, e;
14179:
14180: switch (*s) {
14181: default:
14182: error('i',"char constant store corrupted");
14183: case '`':
14184: error("bcd constant");
14185: return 0;
14186: case '\'':
14187: break;
14188: }
14189:
14190: for(;;) /* also handle multi-character constants */
14191: switch (c = *++s) {
14192: case '\'':
14193: return i;
14194: case '\\': /* special character */
14195: switch (c = *++s) {
14196: case '0': case '1': case '2': case '3': case '4':
14197: case '5': case '6': case '7': /* octal representation */
14198: c -= '0';
14199: switch (d = *++s) { /* try for 2 */
14200:
14201: case '0': case '1': case '2': case '3': case '4':
14202: case '5': case '6': case '7':
14203: d -= '0';
14204: switch (e = *++s) { /* try for 3 */
14205:
14206: case '0': case '1': case '2': case '3': case '4':
14207: case '5': case '6': case '7':
14208: c = c*64+d*8+e-'0';
14209: break;
14210: default:
14211: c = c*8+d;
14212: s--;
14213: }
14214: break;
14215: default:
14216: s--;
14217: }
14218: break;
14219: case 'a':
14220: c = '\a';
14221: break;
14222: case 'b':
14223: c = '\b';
14224: break;
14225: case 'f':
14226: c = '\f';
14227: break;
14228: case 'n':
14229: c = '\n';
14230: break;
14231: case 'r':
14232: c = '\r';
14233: break;
14234: case 't':
14235: c = '\t';
14236: break;
14237: case 'v':
14238: c = '\v';
14239: break;
14240: case '\\':
14241: c = '\\';
14242: break;
14243: case '\'':
14244: c = '\'';
14245: break;
14246: }
14247: /* no break */
14248: default:
14249: if (i) i <<= BI_IN_BYTE;
14250: i += c;
14251: }
14252: }
14253:
14254: const A10 = 'A'-10;
14255: const a10 = 'a'-10;
14256:
14257: long str_to_long(register const char* p)
14258: {
14259: register c;
14260: register unsigned long i= 0;
14261: const char* pp = p;
14262:
14263: // error( 'd', "str_to_long: %s", p );
14264:
14265: if ((c=*p++) == '0') {
14266: switch (c = *p++) {
14267: case 0:
14268: return 0;
14269:
14270: case 'l':
14271: case 'L': /* long zero */
14272: return 0;
14273:
14274: case 'x':
14275: case 'X': /* hexadecimal */
14276: while (c=*p++) {
14277: switch (c) {
14278: case 'l':
14279: case 'L':
14280: case 'U':
14281: case 'u':
14282: return i;
14283: case 'A':
14284: case 'B':
14285: case 'C':
14286: case 'D':
14287: case 'E':
14288: case 'F':
14289: i = i*16 + c-A10;
14290: break;
14291: case 'a':
14292: case 'b':
14293: case 'c':
14294: case 'd':
14295: case 'e':
14296: case 'f':
14297: i = i*16 + c-a10;
14298: break;
14299: default:
14300: i = i*16 + c-'0';
14301: }
14302: }
14303: return i;
14304:
14305: default: /* octal */
14306: do
14307: switch (c) {
14308: case 'l':
14309: case 'L':
14310: case 'U':
14311: case 'u':
14312: return i;
14313: default:
14314: i = i*8 + c-'0';
14315: }
14316: while (c=*p++);
14317: return i;
14318: }
14319: }
14320: /* decimal */
14321: i = c-'0';
14322: while (c=*p++)
14323: switch (c) {
14324: case 'l':
14325: case 'L':
14326: case 'U':
14327: case 'u':
14328: return i;
14329: default:
14330: { unsigned long ii = i;
14331: i = i*10 + c-'0';
14332: if (i<ii) goto bad;
14333: }
14334: }
14335: return i;
14336: bad:
14337: error("integer constant %s larger than the largest long",pp);
14338: return i;
14339:
14340:
14341: }
14342:
14343: bit type::is_unsigned()
14344: {
14345: Ptype t = this;
14346: while (t->base==TYPE) t = Pbase(t)->b_name->tp;
14347: if (t->base == PTR) return 0;
14348: return Pbase(t)->b_unsigned;
14349: }
14350:
14351: char* Neval;
14352: bit binary_val;
14353:
14354: unsigned long expr::ueval(long x1, long x2)
14355: {
14356: unsigned long i1 = (unsigned long) x1;
14357: unsigned long i2 = (unsigned long) x2;
14358: //error('d',"ueval %k %ld %ld",base,x1,x2);
14359: switch (base) {
14360: case UMINUS: return -i2;
14361: case UPLUS: return i2;
14362: case NOT: return !i2;
14363: case COMPL: return ~i2;
14364: case CAST: return i1;
14365: case PLUS: return i1+i2;
14366: case MINUS: return i1-i2;
14367: case MUL: return i1*i2;
14368: case LS: return i1<<i2;
14369: case RS: return i1>>i2;
14370: case NE: return i1!=i2;
14371: case EQ: return i1==i2;
14372: case LT: return i1<i2;
14373: case LE: return i1<=i2;
14374: case GT: return i1>i2;
14375: case GE: return i1>=i2;
14376: case AND: return i1&i2;
14377: case ANDAND: return i1&&i2;
14378: case OR: return i1|i2;
14379: case OROR: return i1||i2;
14380: case ER: return i1^i2;
14381: case MOD: if (i2 == 0) {
14382: if (Neval == 0) {
14383: Neval = "mod zero";
14384: error("mod zero");
14385: }
14386: return 1;
14387: }
14388: return i1%i2;
14389: case QUEST: return (cond->eval()) ? i1 : i2;
14390: case DIV: if (i2 == 0) {
14391: if (Neval == 0) {
14392: Neval = "divide by zero";
14393: error("divide by zero");
14394: }
14395: return 1;
14396: }
14397: return i1/i2;
14398: case CM:
14399: case G_CM:
14400: return i2;
14401: }
14402:
14403: Neval = "unsigned expression";
14404: return 0;
14405: }
14406:
14407: long expr::eval()
14408: {
14409: if (Neval) return 1;
14410: // error('d',"eval %k",base);
14411:
14412: static int targno=0;
14413: static int icallflag=0;
14414:
14415: switch (base) {
14416: case ZERO: return 0;
14417: case IVAL: return i1;
14418: case ICON: return str_to_long(string);
14419: case CCON: return char_to_int(string);
14420: case FCON: Neval = "float in constant expression"; return 1;
14421: case STRING: Neval = "string in constant expression"; return 1;
14422: case EOBJ: return Pname(this)->n_val;
14423: case SIZEOF:
14424: extern no_sizeof;
14425: if (no_sizeof) Neval = "sizeof";
14426: return tp2->tsizeof();
14427:
14428: case NAME:
14429: { Pname n = Pname(this);
14430: // error('d',"eval %n eval %d %d",n,n->n_evaluated,n->n_val);
14431: // error('d',"eval tp->tconst() %d, n->n_initializer: %k", n->tp->tconst(), n->n_initializer?n->n_initializer->base:0 );
14432: if (n->n_evaluated && n->n_scope!=ARG) return n->n_val;
14433: if (binary_val && strcmp(string,"_result")==0) return 8888;
14434: Neval = "cannot evaluate constant";
14435: return 1;
14436: }
14437: case ICALL:
14438: if (e1) {
14439: icallflag=1;
14440: targno=0;
14441: il->i_next = curr_icall;
14442: curr_icall = il;
14443: long i = e1->eval();
14444: curr_icall = il->i_next;
14445: icallflag=0;
14446: return i;
14447: }
14448: Neval = "void inlineF";
14449: return 1;
14450: case ANAME:
14451: { Pname n = (Pname)this;
14452:
14453: /*
14454: int argno;
14455: if (icallflag) {
14456: argno=targno;
14457: targno++;
14458: }
14459: */
14460: int argno = (int) n->n_val;
14461:
14462: Pin il;
14463: for (il=curr_icall; il; il=il->i_next)
14464: if (il->i_table == n->n_table) goto aok;
14465: goto bok;
14466: aok:
14467: if (il->i_args[argno].local) {
14468: bok:
14469: Neval = "inlineF call too complicated for constant expression";
14470: return 1;
14471: }
14472: Pexpr aa = il->i_args[argno].arg;
14473: return aa->eval();
14474: }
14475: case CAST:
14476: { if (e1->base==FCON && tp2->base!=FLOAT && tp2->base!=DOUBLE) {
14477: char* p = e1->string;
14478: while (*p!='.') p++;
14479: if (p==e1->string) *p++ = '0';
14480: *p = 0;
14481: e1->base = ICON;
14482: }
14483: long i = e1->eval();
14484: Ptype tt = tp2;
14485: strip:
14486: switch (tt->base) {
14487: default:
14488: Neval = "cast to non-integral type in constant expression";
14489: break;
14490: case TYPE:
14491: tt = Pbase(tt)->b_name->tp;
14492: goto strip;
14493: case EOBJ:
14494: case LONG:
14495: case INT:
14496: case CHAR:
14497: case SHORT:
14498: i &= ~(((~(unsigned long)0)<<(BI_IN_BYTE*(tp2->tsizeof()-1)))<<BI_IN_BYTE);
14499: break;
14500: }
14501: return i;
14502: }
14503: case UMINUS:
14504: case UPLUS:
14505: case NOT:
14506: case COMPL:
14507: case PLUS:
14508: case MINUS:
14509: case MUL:
14510: case LS:
14511: case RS:
14512: case NE:
14513: case LT:
14514: case LE:
14515: case GT:
14516: case GE:
14517: case AND:
14518: case OR:
14519: case ER:
14520: case DIV:
14521: case MOD:
14522: case QUEST:
14523: case EQ:
14524: case ANDAND:
14525: break;
14526: case OROR:
14527: if (binary_val) { // a||b, don't evaluate b if a!=0
14528: long i1 = (e1) ? e1->eval() : 0;
14529: if (Neval==0 && i1 && e1->tp->is_unsigned()==0) return i1;
14530: }
14531: break;
14532: case CM:
14533: case G_CM:
14534: break;
14535: case G_ADDROF:
14536: case ADDROF:
14537: if (binary_val) { // beware of &*(T*)0
14538: switch (e2->base) {
14539: case NAME:
14540: case DOT:
14541: case REF: return 9999;
14542: }
14543: }
14544: default:
14545: Neval = "bad operator in constant expression";
14546: return 1;
14547: }
14548:
14549: long i1 = (e1) ? e1->eval() : 0;
14550: long i2 = (e2) ? e2->eval() : 0;
14551:
14552: if (binary_val && i1==9999 && i2==9999) {
14553: Neval = "";
14554: return 1;
14555: }
14556:
14557: if (Neval==0
14558: && ((e1&&e1->tp->is_unsigned()) || (e2&&e2->tp->is_unsigned())))
14559: return (long) ueval(i1,i2);
14560:
14561: switch (base) {
14562: case UMINUS: return -i2;
14563: case UPLUS: return i2;
14564: case NOT: return !i2;
14565: case COMPL: return ~i2;
14566: case CAST: return i1;
14567: case PLUS: return i1+i2;
14568: case MINUS: return i1-i2;
14569: case MUL: return i1*i2;
14570: case LS: return i1<<i2;
14571: case RS: return i1>>i2;
14572: case NE: return i1!=i2;
14573: case EQ: return i1==i2;
14574: case LT: return i1<i2;
14575: case LE: return i1<=i2;
14576: case GT: return i1>i2;
14577: case GE: return i1>=i2;
14578: case AND: return i1&i2;
14579: case ANDAND: return i1&&i2;
14580: case OR: return i1|i2;
14581: case OROR: return i1||i2;
14582: case ER: return i1^i2;
14583: case MOD: if (i2 == 0) {
14584: if (Neval == 0) {
14585: Neval = "mod zero";
14586: error("mod zero");
14587: }
14588: return 1;
14589: }
14590: return i1%i2;
14591: case QUEST: return (cond->eval()) ? i1 : i2;
14592: case DIV: if (i2 == 0) {
14593: if (Neval == 0) {
14594: Neval = "divide by zero";
14595: error("divide by zero");
14596: }
14597: return 1;
14598: }
14599: return i1/i2;
14600: case CM:
14601: case G_CM:
14602: return i2;
14603: }
14604: }
14605: bit classdef::baseof(Pname f)
14606: /*
14607: is ``this'' class a public base class of "f"'s class
14608: or its immediate base class
14609: */
14610: {
14611: Ptable ctbl = f->n_table;
14612: Pname b = ctbl->t_name;
14613:
14614: if (b == 0) return 0;
14615: Pclass cl = Pclass(b->tp);
14616: if (cl == 0) return 0;
14617: if (cl == this) return 1;
14618: ppbase = PUBLIC;
14619: Pclass bcl = is_base(cl->string);
14620: return (bcl && ppbase==PUBLIC);
14621: }
14622:
14623: bit classdef::baseof(Pclass cl)
14624: /*
14625: is ``this'' class a public base class of "cl"
14626: */
14627: {
14628: if (cl == 0) return 0;
14629: if (cl == this) return 1;
14630: ppbase = PUBLIC;
14631: Pclass bcl = is_base(cl->string);
14632: return (bcl && ppbase==PUBLIC);
14633: }
14634:
14635: static int mem_match(Pfct f1, Pfct f2)
14636: /*
14637: check class membership.
14638:
14639: For some reason checking f_this==0 works and f_static doesn't
14640: */
14641: {
14642: // if (f1->memof) return f2->f_this ?f2->memof==f1->memof : 0;
14643: // if (f1 && f1->memof) return f2->f_this?f2->memof==f1->memof : 0;
14644: // return f2->f_this==0;
14645: if (f1==0 || f2==0) return 0;
14646: if (f1->memof && f2->f_this && f2->memof!=f1->memof) return 0;
14647: if (f2->f_this) return 0;
14648: if (f1->memof && f2->f_static) return 0;
14649: if (f1->check(f2,ASSIGN)) return 0;
14650: return 1;
14651: }
14652:
14653: int Pchecked;
14654:
14655: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl)
14656: /*
14657: a kludge: initialize/assign-to pointer to function
14658: */
14659: {
14660: Pfct f;
14661: Pname n = 0;
14662: eee:
14663: //error('d',"ptof %t %t %k",ef,e->tp,e->base);
14664: switch (e->base) {
14665: case QUEST:
14666: e->e1 = ptof(ef,e->e1,tbl);
14667: e->e2 = ptof(ef,e->e2,tbl);
14668: return e;
14669: case CM:
14670: case G_CM:
14671: e->e2 = ptof(ef,e->e2,tbl);
14672: return e;
14673: case NAME:
14674: f = Pfct(e->tp);
14675: Pname nn = Pname(e);
14676:
14677: switch (f->base) {
14678: case OVERLOAD:
14679: e = Pgen(f)->find(ef,0);
14680: if (e == 0) {
14681: error("cannot deduceT for &overloaded%n",nn);
14682: return e;
14683: }
14684: // e = n;
14685: // no break
14686: case FCT:
14687: Pchecked = mem_match(ef,Pfct(e->tp));
14688: e = new expr(G_ADDROF,0,e);
14689: return e->typ(tbl); // handle &B::f
14690: //e->tp = f;
14691: }
14692: goto ad;
14693:
14694: case ZERO:
14695: if (ef->memof) {
14696: e = new expr(ELIST,zero,zero);
14697: e = new expr(ILIST,e,zero);
14698: e->tp = zero_type;
14699: return e;
14700: }
14701: break;
14702:
14703: case MDOT:
14704: // ?? error('s',"P toM of not firstB");
14705: do e = e->mem; while (e->base == MDOT);
14706: goto eee;
14707:
14708: case DOT:
14709: case REF:
14710: f = Pfct(e->mem->tp);
14711:
14712: switch (f->base) {
14713: case OVERLOAD:
14714: n = Pgen(f)->find(ef,0);
14715: if (n == 0) error("cannot deduceT for &overloaded%n",e->mem);
14716: else e = n;
14717: // no break
14718: case FCT:
14719: Pchecked = mem_match(ef,Pfct(e->tp));
14720: e = new expr(G_ADDROF,0,e);
14721: return e->typ(tbl); // handle &B::f
14722: // n = Pname(e->mem);
14723: // e = n->address();
14724: }
14725: goto ad;
14726:
14727: case ADDROF:
14728: case G_ADDROF:
14729: f = Pfct(e->e2->tp);
14730: ad:
14731: if (f->base == OVERLOAD) {
14732: n = Pgen(f)->find(ef,0);
14733: if (n == 0) error("cannot deduceT for &overloaded %s()",Pgen(f)->fct_list->f->string);
14734: Pchecked = mem_match(ef,Pfct(n->tp));
14735: e->e2 = n;
14736: e->tp = n->tp;
14737: }
14738: if (n) n->lval(ADDROF);
14739: break;
14740:
14741: case CAST:
14742: {
14743: Pexpr te = e->e1;
14744: if (e->e1->base == G_ADDROF) te = e->e1->e2;
14745: (void) ptof(ef,te,tbl);
14746: }
14747: }
14748: return e;
14749: }
14750:
14751: Pexpr ptr_init(Pptr p, Pexpr init, Ptable tbl)
14752: /*
14753: check for silly initializers
14754:
14755: char* p = 0L; ?? fudge to allow redundant and incorrect `L'
14756: char* p = 2 - 2; ?? worse
14757: */
14758: {
14759: // error('d',"ptr_init: p=%t init->tp=%t init->base %k",p,init->tp,init->base);
14760:
14761: Pchecked = 0;
14762:
14763: Ptype it = init->tp;
14764: itl:
14765: switch (it->base) {
14766: case TYPE:
14767: it = Pbase(it)->b_name->tp; goto itl;
14768: case ZTYPE:
14769: // if (init == zero) break;
14770: break;
14771: case EOBJ:
14772: case INT:
14773: case CHAR:
14774: case SHORT:
14775: case LONG:
14776: { Neval = 0;
14777: long i = init->eval();
14778: if (Neval)
14779: error("badPIr: %s",Neval);
14780: else
14781: if (i)
14782: error("badPIr value %d",i);
14783: else {
14784: DEL(init);
14785: init = zero;
14786: }
14787: break;
14788: }
14789: }
14790:
14791: Pclass c1 = p->memof;
14792:
14793: if (c1) {
14794: if (init==zero)
14795: ;
14796: else {
14797: Pclass c2;
14798: // error('d',"it %t %d",it,it->base);
14799: switch (it->base) {
14800: case FCT:
14801: c2 = Pfct(it)->memof;
14802: break;
14803: case OVERLOAD:
14804: c2 = Pfct(Pgen(it)->fct_list->f->tp)->memof;
14805: break;
14806: case PTR:
14807: case RPTR:
14808: c2 = Pptr(it)->memof;
14809: break;
14810: default:
14811: c2 = 0;
14812: }
14813:
14814: if (c2 == 0) {
14815: // initialization by &A::f
14816: //error('d',"curious");
14817: }
14818: else if (c1 != c2) {
14819: Nptr = 0;
14820: Noffset = 0;
14821: vcllist->clear();
14822: vcllist=0;
14823: int u1 = is_unique_base(c1,c2->string,0);
14824: //error('d',"c1 %t c2 %t u1 %d off %d",c1,c2,u1,Noffset);
14825: if (u1 && (Nptr || Noffset)) {
14826: // requires offset manipulation
14827: int bad = 0;
14828: if (u1 == 1 && !Nptr) {
14829: if (init->base==ILIST) {
14830: // d = d+Noffset;
14831: switch (init->e1->e1->base) {
14832: case IVAL:
14833: init->e1->e1->i1 += Noffset;
14834: break;
14835: case ZERO:
14836: init->e1->e1 = new ival(Noffset);
14837: break;
14838: default:
14839: bad = 1;
14840: }
14841:
14842: // if (i<0) f = vptroffset
14843: switch (init->e1->e2->base) {
14844: case IVAL:
14845: if (0<init->e1->e2->i1) {
14846: // extern Ptype Pfct_type;
14847: // store vptr offset
14848: // init->e2=new cast(Pfct_type,zero);
14849: }
14850: else
14851: break;
14852: default:
14853: bad = 1;
14854: }
14855: } // end if (init->base==ILIST)
14856: else
14857: bad = 1;
14858: } // end if (u1 == 1 ...
14859: else
14860: bad = 1;
14861:
14862: if (bad) error('s',"%t assigned to %t (too complicated)",init->tp,p);
14863: } // end if (u1 && ...
14864:
14865: Nptr = 0;
14866: Noffset = 0;
14867: vcllist->clear();
14868: vcllist=0;
14869: int u2 = is_unique_base(c2,c1->string,0);
14870: //error('d',"c1 %t c2 %t u2 %d off %d",c1,c2,u2,Noffset);
14871: if (u2 && (Nptr || Noffset)) {
14872: // requires offset manipulation
14873: error('s',"%t assigned to %t",init->tp,p);
14874: }
14875: } // end if (c1 != c2
14876: } // end else
14877: } // end if (c1)
14878:
14879: Ptype pit = p->typ;
14880: lll:
14881: // error('d',"p %t pit %t",p,pit);
14882: switch (pit->base) {
14883: case TYPE:
14884: pit = Pbase(pit)->b_name->tp;
14885: goto lll;
14886: case FCT:
14887: return ptof(Pfct(pit),init,tbl);
14888: case COBJ:
14889: { Pptr r;
14890: // error('d',"cobj: ptr %t, ref %t",it->is_ptr(),it->is_ref());
14891: if (r=it->is_ptr_or_ref()) {
14892: Pchecked = 1;
14893: TOK b = p->base; // could be REF
14894: TOK bb = r->base;
14895: if (b==RPTR) p->base = PTR;
14896: if (bb==RPTR) r->base = PTR;
14897: if (p->check(r,ASSIGN)) {
14898: if ( cc && cc->nof &&
14899: Pfct(cc->nof->tp)->f_const &&
14900: cc->c_this == init )
14901: error("%n const: assignment of%n (%t) to%t",cc->nof,init,init->tp,p);
14902: else
14903: error("no standard conversion of %t to %t",init->tp,p);
14904: }
14905: p->base = b;
14906: r->base = bb;
14907: Pexpr cp = cast_cptr(Pclass(Pbase(pit)->b_name->tp),init,tbl,0);
14908: if (cp != init) {
14909: PERM(p); // or else it will be deleted twice!
14910: return new cast(p,cp);
14911: }
14912: }
14913: // no break
14914: }
14915: default:
14916: return init;
14917: }
14918: }
14919:
14920: static Pname Lcoerce, Rcoerce;
14921: extern int suppress_error;
14922:
14923: int try_to_demote(TOK oper, Ptype t1, Ptype t2)
14924: /*
14925: look at t1 and t2 and see if there are ``demotions'' of t1 and/or t2
14926: so that ``t1 oper t2'' can be made legal
14927:
14928: return 0 is not
14929: 1 if there is exactly one way
14930: >1 if there is more than one way (if in doubt return 2)
14931: */
14932: {
14933: //error('d',"try_to_demote(%k : %t : %t)",oper,t1,t2);
14934:
14935: Pname n1 = t1 ? t1->is_cl_obj() : 0;
14936: Pclass c1 = n1 ? Pclass(n1->tp) : 0;
14937: Pname n2 = t2 ? t2->is_cl_obj() : 0;
14938: Pclass c2 = n2 ? Pclass(n2->tp) : 0;
14939:
14940: Ptype lt = t1;
14941: Ptype rt = t2;
14942:
14943: Lcoerce = Rcoerce = 0;
14944:
14945: // if (oper == DOT) return 0;
14946:
14947: if (c1)
14948: switch (oper) {
14949: case ASSIGN:
14950: case ASPLUS:
14951: case ASMINUS:
14952: case ASMUL:
14953: case ASDIV:
14954: case ASMOD:
14955: case ASAND:
14956: case ASOR:
14957: case ASER:
14958: case ASLS:
14959: case ASRS: // don't coerce left hand side of assignment
14960: // c1 = 0;
14961: if (c1->memtbl->look("__as",0)) return 0;
14962: }
14963: else
14964: switch (oper) {
14965: case ADDROF:
14966: case INCR:
14967: case DECR: // don't coerce unary requiring an lval
14968: return 0;
14969: }
14970:
14971: if (c1) {
14972: //error('d',"c1 %t",c1);
14973: for (Pname on1 = c1->conv; on1; on1=on1->n_list) {
14974: // error( 'd', "on1: %s tp: %k", on1->string, on1->tp->base );
14975: Pfct f = Pfct(on1->tp);
14976: lt = f->base==FCT ? f->returns :
14977: Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns;
14978: Pname cn = lt->is_cl_obj();
14979:
14980: if (cn && (Lcoerce==0 || Lcoerce->tp->check(f,0))) {
14981: Pclass cl = Pclass(cn->tp);
14982: Pname n = cl->has_oper(oper);
14983: if (n == 0) continue;
14984: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem) ;
14985: Pfct nf = Pfct(n->tp);
14986: // error( 'd', "nf: %d %k", nf->base, nf->base );
14987: if (nf->base == FCT) {
14988: if (nf->nargs==1
14989: && t2
14990: && (nf->argtype->tp->check(t2,ARG)==0
14991: || can_coerce(nf->argtype->tp,t2)==1)
14992: ) {
14993: if (Lcoerce) return 2;
14994: Lcoerce = on1;
14995: }
14996: }
14997: else {
14998: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) {
14999: Pfct nf = Pfct(gl->f->tp);
15000: if (nf->nargs==1
15001: && t2
15002: && (nf->argtype->tp->check(t2,ARG)==0
15003: || can_coerce(nf->argtype->tp,t2)==1)
15004: ) {
15005: if (Lcoerce) return 2;
15006: Lcoerce = on1;
15007: }
15008: }
15009: }
15010: continue;
15011: }
15012: //if (lt->is_cl_obj()) continue;
15013: if (c2) {
15014: //error('d',"c2 %t",c2);
15015: for (Pname on2 = c2->conv; on2; on2=on2->n_list) {
15016: Pfct f = Pfct(on2->tp);
15017: rt = f->base==FCT ? f->returns :
15018: Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns;
15019: if (rt->is_cl_obj()) continue;
15020:
15021: suppress_error = 1;
15022: int r1 = lt->kind(oper,0);
15023: int r2 = rt->kind(oper,0);
15024: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
15025: Pname sn = on1;
15026: if (Lcoerce) {
15027: Pname tn = really_dominate(
15028: Lcoerce,
15029: on1,
15030: const_obj1
15031: );
15032: if(!tn) {
15033: suppress_error = 0;
15034: return 2;
15035: }
15036: else sn = tn;
15037: }
15038: Lcoerce = sn;
15039: Rcoerce = on2;
15040:
15041: }
15042: suppress_error = 0;
15043: }
15044:
15045: }
15046: else if (rt) {
15047: suppress_error = 1;
15048: int r1 = lt->kind(oper,0);
15049: int r2 = rt->kind(oper,0);
15050: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
15051: Pname sn = on1;
15052: if (Lcoerce) {
15053: Pname tn = really_dominate(
15054: Lcoerce,
15055: on1,
15056: const_obj1
15057: );
15058: if(!tn) {
15059: suppress_error = 0;
15060: return 2;
15061: }
15062: else sn = tn;
15063: }
15064: Lcoerce = sn;
15065: }
15066: suppress_error = 0;
15067: }
15068: else {
15069: Pname sn = on1;
15070: if (Lcoerce) {
15071: Pname tn = really_dominate(
15072: Lcoerce,
15073: on1,
15074: const_obj1
15075: );
15076: if(!tn) return 2;
15077: else sn = tn;
15078: }
15079: Lcoerce = sn;
15080: }
15081: }
15082: }
15083: else if (c2) {
15084: //error('d',"c2 %n",c2);
15085: for (Pname on = c2->conv; on; on=on->n_list) {
15086: Pfct f = Pfct(on->tp);
15087: rt = f->base==FCT ? f->returns :
15088: Pfct(Pgen(on->tp)->fct_list->f->tp)->returns;
15089: Pname cn = rt->is_cl_obj();
15090: //error('d',"cn %n",cn);
15091: if (cn && (Rcoerce==0 || Rcoerce->tp->check(f,0))) {
15092: Pclass cl = Pclass(cn->tp);
15093: Pname n = cl->has_oper(oper);
15094: if (n == 0) continue;
15095:
15096: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem);
15097: Pfct nf = Pfct(n->tp);
15098: if (nf->base == FCT) {
15099: if (nf->nargs == 0) {
15100: if (Lcoerce || Rcoerce) return 2;
15101: Rcoerce = on;
15102: }
15103: }
15104: else {
15105: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l)
15106: if (Pfct(gl->f->tp)->nargs == 0) {
15107: if (Lcoerce || Rcoerce) return 2;
15108: Rcoerce = on;
15109: }
15110: }
15111: continue;
15112: }
15113: //if (rt->is_cl_obj()) continue;
15114: if( lt ) {
15115: suppress_error = 1;
15116: int r1 = lt->kind(oper,0);
15117: int r2 = rt->kind(oper,0);
15118:
15119: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
15120: Pname sn = on;
15121: if (Lcoerce || Rcoerce) {
15122: Pname tn = really_dominate(
15123: Rcoerce,
15124: on,
15125: const_obj2
15126: );
15127: if(!tn) {
15128: suppress_error = 0;
15129: return 2;
15130: }
15131: else sn = tn;
15132: }
15133: Rcoerce = sn;
15134: }
15135: suppress_error = 0;
15136: }
15137: }
15138: }
15139:
15140: //error('d',"->%d || %d",Lcoerce,Rcoerce);
15141: return (Lcoerce || Rcoerce);
15142: }
15143:
15144: Pexpr expr::try_to_overload(Ptable tbl)
15145: {
15146: // TOK bb = (base==DEREF && e2==0) ? MUL : base;
15147: // error('d',"try_to_overload %k %d",base,base);
15148:
15149: Pname n1 = 0;
15150: Ptype t1 = 0;
15151: const_obj1 = 0;
15152: const_obj2 = 0;
15153:
15154: if (e1) {
15155: t1 = e1->tp;
15156: Ptype tpx = t1;
15157: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
15158: n1 = tpx->is_cl_obj();
15159: const_obj1 = t1->tconst();
15160:
15161: Pexpr ee = e1;
15162: while (ee && (ee->base==DOT || ee->base==REF)) {
15163: Pexpr m = ee->mem;
15164: if ( ee->base==REF && m->tp && m->tp->is_ptr())
15165: break;
15166: ee = ee->e1;
15167: }
15168: if (ee) {
15169: int tc;
15170: Ptype ttt = ee->tp;
15171: switch (e1->base) {
15172: case REF:
15173: Pptr p = ttt?ttt->is_ptr():0;
15174: if (p && p->typ->tconst())
15175: const_obj1 = 1;
15176: break;
15177: case DOT:
15178: tc = ttt ? ttt->tconst() : 0;
15179: if (ttt && tc && (!strict_opt || tc!=2))
15180: const_obj1 = 1;
15181: }
15182: }
15183: }
15184:
15185: TOK bb = base;
15186: switch (bb) {
15187: case DEREF:
15188: if (e2 == 0) bb = MUL;
15189: // no break;
15190: case CALL:
15191: case G_CALL:
15192: if (n1 == 0) return 0; // ignore type of argument list
15193: }
15194:
15195: Pname n2 = 0;
15196: Ptype t2 = 0;
15197:
15198: if (e2 && e2->base!=ELIST) {
15199: t2 = e2->tp;
15200: Ptype tpx = t2;
15201: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
15202: n2 = tpx->is_cl_obj();
15203: const_obj2 = t2->tconst();
15204: Pexpr ee = e2;
15205: while (ee && (ee->base==DOT || ee->base==REF)) {
15206: Pexpr m = ee->mem;
15207: if ( ee->base==REF && m->tp && m->tp->is_ptr())
15208: break;
15209: ee = ee->e1;
15210: }
15211: if (ee) {
15212: int tc;
15213: Ptype ttt = ee->tp;
15214: switch (e2->base) {
15215: case REF:
15216: Pptr p = ttt?ttt->is_ptr():0;
15217: if (p && p->typ->tconst())
15218: const_obj2 = 1;
15219: break;
15220: case DOT:
15221: tc = ttt ? ttt->tconst() : 0;
15222: if (ttt && tc && (!strict_opt || tc!=2))
15223: const_obj2 = 1;
15224: }
15225: }
15226: }
15227:
15228: if (n1==0 && n2==0) return 0;
15229: if (n1 && n1->tp == 0) return 0; // make_assign() fudge
15230: // error('d',"e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0 );
15231: // error('d',"t1 %t t2 %t",t1,t2);
15232: // error('d',"n1 %n n2 %n",n1,n2);
15233: /* first try for non-member function: op(e1,e2) or op(e2) or op(e1) */
15234: Pexpr oe2 = e2;
15235: Pexpr ee2 = (e2 && e2->base!=ELIST) ? e2 = new expr(ELIST,e2,0) : 0;
15236: Pexpr ee1 = e1 ? new expr(ELIST,e1,e2) : ee2;
15237: char* obb = oper_name(bb);
15238: Pname gname = tbl->look(obb,0);
15239: // if necessary check for ambiguities
15240: int go = gname ? over_call(gname,ee1) : 0;
15241: //error('d',"go %d",go);
15242: if (go) gname = Nover;
15243:
15244: if (n1) {
15245: if (bb == ASSIGN) {
15246: Pclass c1 = Pclass(n1->tp);
15247: //error('d',"look %k %d",bb,c1->memtbl->look(obb,0));
15248: if (c1->memtbl->look(obb,0)==0) {
15249: Pclass bcl = c1->baselist?c1->baselist->bclass:0;
15250: if (n2==0
15251: || (Pclass(n2->tp)!=c1
15252: && Pclass(n2->tp)->has_base(c1)==0)) {
15253: // if legal, a=1 can be optimized to a.ctor(1)
15254: if (2 < go) goto glob;
15255: return 0;
15256: }
15257:
15258: if (bcl
15259: && c1->obj_size!=bcl->obj_size
15260: && bcl->memtbl->look(obb,0)) {
15261: // cannot inherit from smaller base class
15262: // make_assignment(n1);
15263: // return try_to_overload(tbl);
15264: goto mkas;
15265: }
15266:
15267: if (c1->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
15268: // make operator=() if
15269: // no base (shouldn't happen
15270: // different (smaller) sized base
15271: // two bases
15272: mkas:
15273: if (2 < go) goto glob;
15274: // make_assignment(n1);
15275: // return try_to_overload(tbl);
15276: return make_assignment(n1) ? try_to_overload(tbl) : 0;
15277: }
15278: // error('d',"n2 %n",n2);
15279: // if (n2 && Pclass(n2->tp)==c1)
15280: return 0;
15281: }
15282: // now take care of other assignments,
15283: }
15284:
15285: int dbconv = 0;
15286: Pclass ccl = Pclass(n1->tp);
15287: // Pexpr mn = Pclass(n1->tp)->memtbl->look(obb,0);
15288: Pexpr mn = ccl->memtbl->look(obb,0);
15289: // error('d', "tcl %d %t cl %d %t", tcl, tcl, ccl, ccl);
15290: if(strcmp(obb,"__as")) {
15291: tcl = ccl; // ugh!!!
15292: if(!mn) dbconv = 2;
15293: }
15294: // tcl = ccl; // ugh!!!
15295: mn = ccl->find_name(obb,0);
15296:
15297: Pname mname = Pname(mn);
15298: // error('d',"mn %n %d %k %s",mname,mn,mn?mn->base:0,obb);
15299: if (mname == 0) goto glob;
15300:
15301: zaq:
15302: switch (mname->base) {
15303: case REF:
15304: case MDOT:
15305: mname = Pname(Pexpr(mname)->mem);
15306: goto zaq;
15307: }
15308:
15309: int mo = over_call(mname,e2);
15310: int smo = mo;
15311: if(mo && dbconv && mo >= dbconv) mo = dbconv;
15312: //error('d',"mo %d (go %d)",mo,go);
15313: if (mo==0 || mo<go)
15314: goto glob;
15315: else if (mo && mo==go) {
15316: //error('d',"t1 %t t2 %t",t1,t2);
15317: if (gname->tp->base == OVERLOAD) { // find right version
15318: for (Plist l = Pgen(gname->tp)->fct_list; l; l=l->l) {
15319: Pname n = l->f;
15320: int x = over_call(n,ee1);
15321: if (x == go) {
15322: gname = n;
15323: break;
15324: }
15325: }
15326: }
15327: //error('d',"gname %n: %t",gname,gname->tp);
15328: Pname aa = Pfct(gname->tp)->argtype;
15329: Pptr p;
15330: Ptype gt1 = aa->tp;
15331: if (p = gt1->is_ref()) gt1 = p->typ;
15332: Ptype gt2 = aa->n_list->tp;
15333: //error('d',"gt1 %t gt2 %t",gt1,gt2);
15334: if (mname->tp->base == OVERLOAD) { // find right version
15335: for (Plist l = Pgen(mname->tp)->fct_list; l; l=l->l) {
15336: Pname n = l->f;
15337: int x = over_call(n,e2);
15338: if (x == smo) {
15339: mname = n;
15340: break;
15341: }
15342: }
15343: }
15344: //error('d',"mname %n: %t",mname,mname->tp);
15345: Ptype mt1 = Pfct(mname->tp)->f_this->tp;
15346: mt1 = Pptr(mt1)->typ;
15347: Ptype mt2 = Pfct(mname->tp)->argtype->tp;
15348: //error('d',"mt1 %t mt2 %t",mt1,mt2);
15349: Pname mm = new name;
15350: Pname a1 = new name;
15351: a1->tp = mt1;
15352: Pname a2 = new name;
15353: a2->tp = mt2;
15354: a1->n_list = a2;
15355: mm->tp = new fct(void_type,a1,2);
15356: Pname gg = new name;
15357: Pname a3 = new name;
15358: a3->tp = gt1;
15359: Pname a4 = new name;
15360: a4->tp = gt2;
15361: a3->n_list = a4;
15362: gg->tp = new fct(void_type,a3,1);
15363: extern Pname dominate(Pname,Pname,Pexpr,int,int);
15364: aa = dominate(gg,mm,ee1,0,1);
15365: delete a1;
15366: delete a2;
15367: delete a3;
15368: delete a4;
15369: DEL( gg->tp );
15370: DEL( mm->tp );
15371: //delete gg->tp;
15372: //delete mm->tp;
15373: if (aa == 0) {
15374: delete gg;
15375: delete mm;
15376: error("ambiguous operandTs%n and%t for%k",n1,t2,bb);
15377: tp = any_type;
15378: return this;
15379: }
15380: else if (aa == gg) {
15381: delete gg;
15382: delete mm;
15383: goto glob;
15384: }
15385: delete gg;
15386: delete mm;
15387: }
15388: else if (mo < 2) { // user-defined conversion user
15389:
15390: if (try_to_demote(bb,t1,t2))
15391: error("ambiguous use of overloaded%k",bb);
15392: }
15393:
15394: base = G_CALL; // e1.op(e2) or e1.op()
15395: Pname xx = new name(mname->string); // do another lookup
15396: // . suppresses virtual
15397: e1 = new ref(DOT,e1,xx);
15398: if (ee1) delete ee1;
15399: return typ(tbl);
15400: }
15401:
15402: if (n2 && e1==0) { /* look for unary operator */
15403: suppress_error++;
15404: Pexpr mn = Pclass(n2->tp)->find_name(obb,0);
15405: suppress_error--;
15406: Pname mname = Pname(mn);
15407: if (mname == 0) goto glob;
15408: zaqq:
15409: switch (mname->base) {
15410: case REF:
15411: case MDOT:
15412: mname = Pname(Pexpr(mname)->mem);
15413: goto zaqq;
15414: }
15415:
15416: switch (mname->n_scope) {
15417: default: goto glob;
15418: case 0:
15419: case PUBLIC: break; // try e2.op()
15420: }
15421:
15422: int mo = over_call(mname,0);
15423: //error('d',"e2 mo %d (go %d)",mo,go);
15424: if (mo==0 || mo<go)
15425: goto glob;
15426: else if (mo==go) {
15427: error("ambiguous operandT%n for%k",n2,bb);
15428: tp = any_type;
15429: return this;
15430: }
15431: else if (mo < 2) { // user-defined conversion user
15432: if (try_to_demote(bb,t1,t2))
15433: error("ambiguous use of overloaded%k",bb);
15434: }
15435: base = G_CALL; // e2.op()
15436: Pname xx = new name(Nover->string); // do another lookup
15437: // . suppresses virtual
15438: e1 = new ref(DOT,oe2,xx);
15439: e2 = 0;
15440: if (ee2) delete ee2;
15441: if (ee1 && ee1!=ee2) delete ee1;
15442: return typ(tbl);
15443: }
15444:
15445: glob:
15446: // error('d',"glob %d",go);
15447:
15448: if (go) {
15449: if (go < 2) { // user-defined conversion necessary => binary
15450: if (try_to_demote(bb,t1,t2))
15451: error("ambiguous use of overloaded%k: %t and %t",bb,t1,t2);
15452: }
15453:
15454: base = gname->n_table == gtbl ? G_CALL : CALL;
15455: //error('d',"gname %n %t",gname,gname->tp);
15456: e1 = new name(gname->string);
15457: // if global scope, look only for globals
15458: if(gname->n_table == gtbl) Pname(e1)->n_qualifier = sta_name;
15459: e2 = ee1;
15460: return typ(tbl);
15461: }
15462:
15463: if (ee2) delete ee2;
15464: if (ee1 && ee1!=ee2) delete ee1;
15465: e2 = oe2;
15466:
15467: // error('d',"bb %d %k",bb,bb);
15468: switch (bb) {
15469: case CM:
15470: case G_CM:
15471: case G_ADDROF:
15472: return 0;
15473: case ASSIGN:
15474: if (n1
15475: && n2
15476: && (n1->tp==n2->tp || Pclass(n2->tp)->has_base(Pclass(n1->tp)))) {
15477: if (make_assignment(n1))
15478: return try_to_overload(tbl);
15479: else
15480: return 0;
15481: }
15482: case DEREF:
15483: case CALL:
15484: if (n1 == 0) break;
15485:
15486: default: /* look for conversions to basic types */
15487: if (n1
15488: && Pclass(n1->tp)->conv
15489: && (bb==ANDAND || bb==OROR)) {
15490: e1 = check_cond(e1,bb,tbl);
15491: return 0;
15492: }
15493:
15494: if (n2
15495: && Pclass(n2->tp)->conv
15496: && (bb==ANDAND || bb==OROR || bb==NOT ||
15497: bb==UMINUS || bb==UPLUS || bb==COMPL)) {
15498: e2 = check_cond(e2,bb,tbl);
15499: return 0;
15500: }
15501:
15502: // error( 'd', "bb: %k t1: %k t2: %k", bb, t1?t1->base:0, t2?t2->base:0 );
15503: switch (try_to_demote(bb,t1,t2)) {
15504: default:
15505: if (Lcoerce) error("ambiguous conversion of%n",n1);
15506: if (Rcoerce) error("ambiguous conversion of%n",n2);
15507: case 0:
15508: break;
15509: case 1:
15510: if (Lcoerce) {
15511: Pname xx = new name(Lcoerce->string);
15512: Pref r = new ref(DOT,e1,xx);
15513: e1 = new expr(G_CALL,r,0);
15514: }
15515:
15516: if (Rcoerce) {
15517: Pname xx = new name(Rcoerce->string);
15518: Pref r = new ref(DOT,e2,xx);
15519: e2 = new expr(G_CALL,r,0);
15520: }
15521: return typ(tbl);
15522: }
15523:
15524: switch (bb) {
15525: case CM:
15526: case ADDROF: // has legal built-in meaning
15527: return 0;
15528: }
15529:
15530: if (t1 && t2)
15531: error("bad operandTs%t%t for%k",t1,t2,bb);
15532: else
15533: error("bad operandT%t for%k",t1?t1:t2,bb);
15534:
15535: tp = any_type;
15536: return this;
15537: }
15538:
15539: return 0;
15540: }
15541:
15542: Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast)
15543: /*
15544: "ee" is being cast to pointer object of class "ccl"
15545: if necessary modify "ee"
15546: */
15547: {
15548:
15549: // Ptype etp = ee->tp;
15550: // error('d',"cast_cptr %k ccl %t ee->tp %t",ee->tp->base,ccl,ee->tp);
15551: // if (etp->base!=PTR && etp->base!=RPTR) return ee;
15552: Ptype etp = ee->tp->is_ptr_or_ref();
15553: if (etp == 0) return ee;
15554:
15555: Pname on = Pptr(etp)->typ->is_cl_obj();
15556: if (on == 0) return ee;
15557:
15558: Pclass ocl = Pclass(on->tp);
15559: if (ocl==ccl || ccl==0 || ocl==0) return ee;
15560:
15561: // error('d',"cast_cptr %t(%t) real %d",ccl,ocl,real_cast);
15562: int oo = 0;
15563: Pexpr r = 0;
15564:
15565: if (ocl->baselist
15566: && (ocl->baselist->bclass!=ccl || ocl->baselist->base!=NAME)) {
15567: // casting derived to second or virtual base?
15568: Nptr = 0;
15569: Nvis = 0;
15570: Nalloc_base = 0;
15571: vcllist->clear();
15572: vcllist=0;
15573: int x = is_unique_base(ocl,ccl->string,0);
15574: if (Nvis) {
15575: if (real_cast==0)
15576: error("cast:%n* ->B%t*; privateBC",on,ccl);
15577: else if (warning_opt)
15578: error('w',"cast:%n* ->B%t*; privateBC",on,ccl);
15579: real_cast = 1; // suppress further error mesages
15580: Nvis = 0;
15581: }
15582:
15583: switch (x) {
15584: default:
15585: error("cast:%n* ->B%t*;%t isB more than once",on,ccl,ccl);
15586: case 0: // unrelated;
15587: break;
15588: case 1:
15589: oo = Noffset;
15590: break;
15591: }
15592:
15593: if (Nptr) { // => ee?Nptr:0
15594: if (ocl->c_body==1) ocl->dcl_print(0);
15595: Nptr->mem = ee; // ee->Pbase_class
15596: if ( Nalloc_base ) {
15597: // error('d', "cast_cptr: nalloc_base: %s", Nalloc_base);
15598: Nptr->i1 = 5;
15599: Nptr->string4 = new char[strlen(Nalloc_base)];
15600: strcpy(Nptr->string4,Nalloc_base);
15601: Nalloc_base = 0;
15602: }
15603: else Nptr->i1 = 3;
15604:
15605: if (ee->base==ADDROF || ee->base==G_ADDROF)
15606: ee = Nptr;
15607: else {
15608: Pexpr p = new expr(QUEST,Nptr,zero);
15609: nin = 1;
15610: if (ee->not_simple()) { // need temp
15611: Ptype t = ee->tp;
15612: Pname pp = make_tmp('N',t,tbl);
15613: Pname(pp)->n_assigned_to = 1;
15614: ee = new expr(ASSIGN,pp,ee);
15615: ee->tp = t;
15616: Nptr->mem = pp;
15617: }
15618: nin = 0;
15619: p->cond = ee;
15620: p->tp = ee->tp;
15621: ee = p;
15622: }
15623: }
15624: }
15625:
15626: if (ccl->baselist
15627: && (ccl->baselist->bclass!=ocl || ccl->baselist->base!=NAME)) {
15628: // casting second or virtual base to derived?
15629: Nptr = 0;
15630: vcllist->clear();
15631: vcllist=0;
15632: int x = is_unique_base(ccl,ocl->string,0);
15633: switch (x) {
15634: default:
15635: error("cast:%n* ->derived%t*;%n isB more than once",on,ccl,on);
15636: case 0: // unrelated;
15637: break;
15638: case 1:
15639: oo = -Noffset;
15640: if (Nptr)
15641: error("cast:%n* ->derived%t*;%n is virtualB",on,ccl,on);
15642: break;
15643: }
15644: Nvis = 0; // visibility no concern when converting from base to derived
15645: }
15646: // error('d',"oo %d ee %k",oo,ee->base);
15647: if (oo) { // => ee?ee+offset:0
15648: if (ee->base==ADDROF || ee->base==G_ADDROF)
15649: ee = rptr(ee->tp,ee,oo);
15650: else {
15651: Pexpr p;
15652: nin = 1;
15653: if (ee->not_simple()) { // need temp
15654: Ptype t = ee->base==MDOT?ee->mem->tp:ee->tp;
15655: Pname pp = make_tmp('M',t,tbl);
15656: Pname(pp)->n_assigned_to = 1;
15657: ee = new expr(ASSIGN,pp,ee);
15658: ee->tp = t;
15659: p = rptr(t,pp,oo);
15660: }
15661: else
15662: p = rptr(ee->base==MDOT?ee->mem->tp:ee->tp,ee,oo);
15663: nin = 0;
15664: Pexpr pp = new expr(QUEST,p,zero);
15665: pp->tp = ee->tp;
15666: pp->cond = ee;
15667: ee = pp;
15668: }
15669: }
15670:
15671: Nvis = 0; // Nvis set by has_base()
15672: if (ocl->has_base(ccl) && Nvis) {
15673: if (real_cast==0)
15674: error("cast:%n* ->B%t*; privateBC",on,ccl);
15675: else if (warning_opt)
15676: error('w',"cast:%n* ->B%t*; privateBC",on,ccl);
15677: Nvis = 0;
15678: }
15679:
15680: // error('d',"return %d %k %t",ee,ee->base,ee->tp);
15681: return ee;
15682: }
15683:
15684: Pexpr expr::donew(Ptable tbl)
15685: {
15686: Ptype tt = tp2;
15687: Ptype tpx = tt;
15688: bit v = 0;
15689: bit old = new_type;
15690: int init = 0; // non-constructor initialization
15691: new_type = 1;
15692:
15693: tt->dcl(tbl);
15694: new_type = old;
15695: // error('d',"donew %d %d (%k) tt %t",e1,e2,e2?e2->base:0,tt);
15696: if (e1) e1 = e1->typ(tbl);
15697: if (e2) e2 = e2->typ(tbl);
15698: ll:
15699: //error('d',"ll %d",tt->base);
15700: switch (tt->base) {
15701: default:
15702: if ( e1) {
15703: if (v) {
15704: error("Ir for array created using \"new\"");
15705: break;
15706: }
15707: init = 1;
15708: }
15709: // if (e1) {
15710: // error("Ir for nonCO created using \"new\"");
15711: // e1 = 0;
15712: // }
15713: break;
15714: case VEC:
15715: if (v && Pvec(tt)->dim) error("only 1st array dimension can be non-constant");
15716: if (Pvec(tt)->size==0 && Pvec(tt)->dim==0) error("array dimension missing in `new'");
15717: // if (Pvec(tt)->dim==zero) {
15718: // Pvec(tt)->size = 0;
15719: // Pvec(tt)->dim = 0;
15720: // }
15721: v++;
15722: tt = Pvec(tt)->typ;
15723: goto ll;
15724: case TYPE:
15725: tt = Pbase(tt)->b_name->tp;
15726: goto ll;
15727: case VOID:
15728: error("badT for `new': void");
15729: break;
15730: case COBJ:
15731: { Pname cn = Pbase(tt)->b_name;
15732: Pclass cl = Pclass(cn->tp);
15733: Pname icn = 0;
15734:
15735: if ( e1 ) { // arguments
15736: if ( e1->e2 == 0 && e1->base == ELIST ) {
15737: e1 = e1->e1;
15738: e1 = e1->typ(tbl);
15739: }
15740: icn = (e1->base!=ELIST)?e1->tp->is_cl_obj():0;
15741: }
15742: //Pname icn = (e1 && e1->base!=ELIST)?e1->tp->is_cl_obj() : 0;
15743:
15744: Pclass icl = icn ? Pclass(icn->tp) : 0;
15745:
15746: if (cl->c_abstract) {
15747: error("`new' of abstractC%t",cl);
15748: break;
15749: }
15750:
15751: if (v && e1) {
15752: error("Ir for array ofCO created using \"new\"");
15753: break;
15754: }
15755:
15756: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
15757: error("new%n;%n isU",cn,cn);
15758: break;
15759: }
15760:
15761: Pname ctor = cl->has_ctor();
15762:
15763: if (ctor) {
15764: if (v) {
15765: Pname ic;
15766: if ((ic = cl->has_ictor())==0) {
15767: error("array ofC%n that does not have aK taking noAs",cn);
15768: break;
15769: }
15770:
15771: if (Pfct(ic->tp)->nargs) {
15772: error("defaultAs forK for array ofC%n",cn);
15773: break;
15774: }
15775: }
15776:
15777: if (icl
15778: && cl->has_itor()==0 // incomplete:
15779: // what if X(Y&) exists
15780: // for class Y : X ?
15781: && (icl==cl || icl->has_base(cl))) {
15782: init = 1;
15783: break;
15784: }
15785: e1 = call_ctor(tbl,0,ctor,e1);
15786: }
15787: else if (e1) {
15788: if (icl==cl || icl->has_base(cl))
15789: init = 1;
15790: else
15791: error("new%n(As ); %n does not have aK",cn,cn);
15792: }
15793: }
15794: }
15795:
15796: if (init) {
15797: Pname tmp = make_tmp('N',tt->addrof(),tbl);
15798: e1 = e1->typ(tbl);
15799: if (tt->check(e1->tp,ASSIGN))
15800: error("badIrT %t for new operator (%t X)",e1->tp,tt);
15801: e1 = new expr(0,tmp,e1);
15802: tmp->assign();
15803: }
15804:
15805: // tp = (v) ? tpx : tpx->addrof();
15806: switch (v) {
15807: case 0:
15808: tp = tpx->addrof();
15809: break;
15810: case 1:
15811: tp = tpx;
15812: break;
15813: default:
15814: tp = tpx;
15815: }
15816: //error('d',"donew(%d) -> %t",v,tp);
15817: return this;
15818: }
15819:
15820: static is_dataMemPtr( Pexpr ee )
15821: /* this is utterly implementation dependent
15822: * called by expr::lval to determine
15823: * const objects bounds to pointers to data members
15824: */
15825: {
15826: Pexpr te = ee->e1;
15827: if ( te == 0 ) return 0;
15828: if ( te->base != PLUS ) return 0;
15829: if ( (te = te->e2) == 0 ) return 0;
15830: if ( te->base != MINUS ) return 0;
15831: if ( (te = te->e1) == 0 ) return 0;
15832: if ( te->base != CAST ) return 0;
15833: if ( (te = te->e1) == 0 ) return 0;
15834: if ( te->tp->base != PTR ) return 0;
15835: if ( Pptr(te->tp)->memof == 0 ) return 0;
15836: return 1;
15837: }
15838: 0707071010112044301004440001630000160000010200700466055402100001000000162346expr3.c /*ident "@(#)ctrans:src/expr3.c 1.6" */
15839: /***************************************************************************
15840:
15841: C++ source for cfront, the C++ compiler front-end
15842: written in the computer science research center of Bell Labs
15843:
15844: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
15845: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
15846:
15847: expr3.c:
15848:
15849: type check function calls, casts, and explicit coercions
15850:
15851: ************************************************************************/
15852:
15853: #include "cfront.h"
15854: #include "size.h"
15855:
15856: int pr_dominate(Ptype t1, Ptype t2)
15857: /*
15858: */
15859: {
15860: Pname cn1 = t1->is_cl_obj();
15861: Pname cn2 = t2->is_cl_obj();
15862: //error('d',"pr_dominate(%t,%t)",t1,t2);
15863:
15864: if (cn1==0 || cn2==0) {
15865: Ptype p1 = t1->is_ptr();
15866: Ptype p2 = t2->is_ptr();
15867: if (p1 && p2) { // pointers
15868: cn1 = Pptr(p1)->typ->is_cl_obj();
15869: cn2 = Pptr(p2)->typ->is_cl_obj();
15870: if (cn1==0 || cn2==0) return 0;
15871: }
15872: else {
15873: p1 = t1->is_ref();
15874: p2 = t2->is_ref();
15875: if (p1 && p2) { // references
15876: cn1 = Pptr(p1)->typ->is_cl_obj();
15877: cn2 = Pptr(p2)->typ->is_cl_obj();
15878: if (cn1==0 || cn2==0) return 0;
15879: }
15880: // else if (p1 && cn2) {
15881: // cn1 = Pptr(p1)->typ->is_cl_obj();
15882: // }
15883: else
15884: return 0; // not the same and not classes
15885: }
15886: }
15887: Pclass c1 = Pclass(cn1->tp);
15888: Pclass c2 = Pclass(cn2->tp);
15889: //error('d'," c1 : c2 %d; c2 : c1 %d",c1->has_base(c2),c2->has_base(c1));
15890: if (c1->has_base(c2)) return 1;
15891: if (c2->has_base(c1)) return 2;
15892: return 0;
15893: }
15894:
15895: int exact1(Pname,Ptype);
15896: static exact2(Pname,Ptype);
15897: static exact3(Pname,Ptype);
15898:
15899: static Pname user_dominate(Pname n1, Pname n2, Pexpr arg)
15900: {
15901: Pfct f1 = Pfct(n1->tp);
15902: Pfct f2 = Pfct(n2->tp);
15903:
15904: Pname a1 = f1->argtype;
15905: Pname a2 = f2->argtype;
15906: //error('d',"user_dominate: %n %t %t",n1,f1,f2);
15907:
15908: for(; a1 && a2; a1 = a1->n_list, a2 = a2->n_list) {
15909: Ptype t1 = a1->tp;
15910: Ptype t2 = a2->tp;
15911: }
15912:
15913: if (a1 && !a1->n_evaluated) return n1;
15914: if (a2 && !a2->n_evaluated) return n2;
15915:
15916: a1 = f1->argtype;
15917: a2 = f2->argtype;
15918:
15919: Pname prev = 0;
15920: Pexpr e = arg;
15921:
15922: for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
15923: Ptype t1 = a1->tp;
15924: Ptype t2 = a2->tp;
15925: Ptype at = e->e1->tp;
15926:
15927: int j = can_coerce(t1,at);
15928: Ptype tt1 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
15929: j = can_coerce(t2,at);
15930: Ptype tt2 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
15931: if(!tt1 || !tt2 || tt1->check(tt2,OVERLOAD))
15932: return 0;
15933:
15934: int one = 0, two = 0;
15935: if(exact1(a1,tt1)) one = 4;
15936: else if(exact2(a1,tt1)) one = 3;
15937: else if(exact3(a1,tt1)) one = 2;
15938: else one = 1;
15939: if(exact1(a2,tt1)) two = 4;
15940: else if(exact2(a2,tt1)) two = 3;
15941: else if(exact3(a2,tt1)) two = 2;
15942: else two = 1;
15943:
15944: if(one > two && (!prev || prev==n1)) prev = n1;
15945: else if(two > one && (!prev || prev==n2)) prev = n2;
15946: else if(one == two && one) ;
15947: else return 0;
15948: }
15949: if(prev) return prev;
15950:
15951: return 0;
15952: }
15953:
15954: Pname dominate(Pname n1, Pname n2, Pexpr arg, int const_obj, int level)
15955: /*
15956: the two functions n1 and n2 can each respond to a call using
15957: standard conversions. Does the one dominate the other in the
15958: sense that all its arguments are identical to the other or
15959: classes defived from the class of the corresponding argument
15960: of the other.
15961:
15962: If so return it, otherwise return 0;
15963: */
15964: {
15965: Pname res = 0;
15966:
15967: Pfct f1 = Pfct(n1->tp);
15968: Pfct f2 = Pfct(n2->tp);
15969:
15970: Pname a1 = f1->argtype;
15971: Pname a2 = f2->argtype;
15972: Pexpr e = arg;
15973: //error('d',"dominate: %n %t %t e %d",n1,f1,f2,e);
15974:
15975: if (e == 0) {
15976: if (const_obj) {
15977: if (f1->f_const && f2->f_const==0) return n1;
15978: if (f2->f_const && f1->f_const==0) return n2;
15979: }
15980: else {
15981: if (f1->f_const==0 && f2->f_const) return n1;
15982: if (f2->f_const==0 && f1->f_const) return n2;
15983: }
15984: return 0;
15985: }
15986:
15987: for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
15988: Ptype t1 = a1->tp;
15989: Ptype t2 = a2->tp;
15990: Ptype at = e->e1->tp;
15991: //error('d',"t1 %t t2 %t at %t",t1,t2,at);
15992: if (t1==t2 || t1->check(t2,0)==0 )
15993: continue;
15994: Pptr r1 = t1->is_ref();
15995: Pptr r2 = t2->is_ref();
15996: //error('d',"const_problem %t %t %t %d",t1,t2,at,const_problem);
15997: if (const_problem) { // t1 and t1 differs only in const
15998: Pname rr;
15999: if (at->check(t1,0)==0 && const_problem==0) {
16000: if (t1->is_ptr())
16001: rr = n1;
16002: else
16003: goto nc;
16004: }
16005: else if (at->check(t2,0)==0 && const_problem==0) {
16006: if (t2->is_ptr())
16007: rr = n2;
16008: else
16009: goto nc;
16010: }
16011: else if (r1 && r1->typ->check(at,0)==0 && const_problem==0)
16012: rr = n1;
16013: else if (r2 && r2->typ->check(at,0)==0 && const_problem==0)
16014: rr = n2;
16015: else
16016: goto nc;
16017:
16018: if (res && res!=rr) return 0; // mutual dominace
16019: res = rr;
16020: continue; // identical
16021: }
16022: nc:
16023: if (r2 && (t1==r2 || t1->check(r2->typ,0)==0)) continue;
16024: if (r1 && (t2==r1 || t2->check(r1->typ,0)==0)) continue;
16025:
16026: Pname rr = 0;
16027: if (t1==at || exact1(a1,at))
16028: rr = n1;
16029: else if (t2==at || exact1(a2,at))
16030: rr = n2;
16031: else if (1<level) { // try integral promotion
16032: if (exact2(a1,at))
16033: rr = n1;
16034: if (exact2(a2,at)) {
16035: if (rr) rr = 0;
16036: else rr = n2;
16037: }
16038: }
16039: if (!rr && 2<level) { // try standard conversions
16040: if (exact3(a1,at))
16041: rr = n1;
16042: if (exact3(a2,at)) {
16043: if (rr) rr = 0;
16044: else rr = n2;
16045: }
16046: }
16047: if (rr) {
16048: if (res && res!=rr) return 0; // mutual dominance
16049: res = rr;
16050: continue;
16051: }
16052:
16053: int r = pr_dominate(t1,t2);
16054: //error('d',"pr1 %d",r);
16055: if (r) {
16056: Pname rr = r==1?n1:n2;
16057: if (res && res!=rr) return 0; // mutual dominace
16058: res = rr;
16059: continue;
16060: }
16061:
16062: r = pr_dominate(t1,at);
16063: //error('d',"pr2 %d",r);
16064: if (r==2) {
16065: if (res && res!=n1) return 0; // mutual dominace
16066: res = n1;
16067: r = pr_dominate(t2,at);
16068: if (r==2) return 0; // mutual dominace
16069: continue;
16070: }
16071:
16072: r = pr_dominate(t2,at);
16073: //error('d',"pr3 %d",r);
16074: if (r==2) {
16075: if (res && res!=n2) return 0; // mutual dominace
16076: res = n2;
16077: continue;
16078: }
16079:
16080: }
16081: //if (a1==0 && a2 && a2->n_initializer==0) return 0; // wrong number of arguments
16082: //if (a2==0 && a1 && a1->n_initializer==0) return 0; // wrong number of arguments
16083:
16084: if (e) {
16085: //error('d',"more args %t a1 %t a2 %t",e->e1->tp,a1?a1->tp:0,a2?a2->tp:0);
16086: int k1 = f1->nargs_known!=ELLIPSIS;
16087: int k2 = f2->nargs_known!=ELLIPSIS;
16088: if (a1 && a1->tp->check(e->e1->tp,ASSIGN)==0) return n1;
16089: if (a2 && a2->tp->check(e->e1->tp,ASSIGN)==0) return n2;
16090: if (k1 && k2) return 0;
16091: }
16092:
16093: if (a1==0 && a2 && a2->n_initializer==0) return 0;
16094: if (a2==0 && a1 && a1->n_initializer==0) return 0;
16095: if (res==0)
16096: if (const_obj) {
16097: if (f1->f_const && f2->f_const==0) return n1;
16098: if (f2->f_const && f1->f_const==0) return n2;
16099: }
16100: else {
16101: if (f1->f_const==0 && f2->f_const) return n1;
16102: if (f2->f_const==0 && f1->f_const) return n2;
16103: }
16104: //error('d'," -> %n %t",res,res?res->tp:0);
16105: return res;
16106: }
16107:
16108: Pname Ntmp;
16109:
16110: static refd; // initialization routine called by ref_init, do not apply itor
16111: static no_sti;
16112: extern int stat_init;
16113:
16114: Pname make_tmp(char c, Ptype t, Ptable tbl)
16115: {
16116: int dt = 0;
16117: Pname tn = tbl->t_name;
16118: Pname cn = t->is_cl_obj();
16119:
16120: if (tn && tn->tp) error('s',"defaultA too complicated");
16121: if (cn && Pclass(cn->tp)->has_dtor()) dt = 1;
16122: if (Ntmp == 0 && dt ) Ntmp = cn;
16123:
16124: //error('d',"tbl %d cstmt %d %d sti %d",tbl,Cstmt,Cstmt?Cstmt->memtbl:0,sti_tbl);
16125: if (Cstmt) { // make Cstmt into a block
16126: if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0);
16127: tbl = Cstmt->memtbl;
16128: }
16129: else if (tbl == gtbl && no_sti == 0) {
16130: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
16131: tbl = sti_tbl;
16132: }
16133:
16134: Pname tmpx = new name(make_name(c));
16135: tmpx->where = no_where;
16136: tmpx->tp = t;
16137: (void) t->tsizeof();
16138: if ( t->base == COBJ ) {
16139: Pclass cl = Pclass(Pbase(t)->b_name->tp);
16140: if ( cl->lex_level ) tmpx->lex_level = cl->lex_level;
16141: }
16142:
16143: TOK scop = ARG;
16144: if (stat_init && dt) {
16145: tmpx->n_sto = STATIC; scop = ARGS;
16146: }
16147:
16148: // ARG[S]: no init; ARGS: static dtor
16149: Pname tmp = tmpx->dcl(tbl,scop);
16150: delete tmpx;
16151:
16152: // n_scope == ARGS sets static dtor in simpl2.c
16153: tmp->n_scope = (scop==ARG) ? FCT : ARGS;
16154: return tmp;
16155: }
16156:
16157: Pexpr init_tmp(Pname tmp, Pexpr init, Ptable tbl)
16158: {
16159: Pname cn = tmp->tp->is_cl_obj();
16160: Pname ct = cn ? Pclass(cn->tp)->has_itor() : 0;
16161:
16162: tmp->n_assigned_to = 1;
16163: //error('d',"init_tmp %n ct %n refd %d",tmp,ct,refd);
16164: if (ct) { // must initialize
16165: if (refd) {
16166: //error('d',"'orrible %k",init->e1->base);
16167: switch (init->e1->base) { // 'orrible 'ack
16168: case NAME:
16169: case REF:
16170: case DEREF:
16171: if (init->e1->tp->is_ptr())
16172: init = init->e1;
16173: else
16174: init = new expr(G_CM,init,init->e1->address());
16175:
16176: }
16177: if (ct->tp->base == OVERLOAD) ct = Pgen(ct->tp)->fct_list->f; // first fct
16178: tbl = 0;
16179: }
16180: return call_ctor(tbl,tmp,ct,init,DOT);
16181: }
16182: Pexpr ass = new expr(ASSIGN,tmp,init); // no ctor: can assign
16183: ass->tp = tmp->tp;
16184: return ass;
16185: }
16186: /*
16187: int exact0(Pname nn, Ptype at)
16188: // return 1 if
16189: // exact match
16190:
16191: {
16192: if (nn == 0) return 0; //known==ELLIPSIS;
16193: Ptype nt = nn->tp;
16194: if (at == nt) return 1;
16195: //error('d',"exact0 %d",nt->check(at,0));
16196: return nt->check(at,0)==0;
16197: }
16198: */
16199:
16200: int exact3(Pname nn, Ptype at)
16201: /*
16202: return 1 if
16203: match with standard conversions
16204: */
16205: {
16206: if (nn == 0) return 0; //known==ELLIPSIS;
16207: Ptype nt = nn->tp;
16208:
16209: while(nt->base == TYPE)
16210: nt = Pbase(nt)->b_name->tp;
16211:
16212: if (at == nt) return 1;
16213:
16214: switch (nt->base) {
16215: case RPTR:
16216: if (at==zero_type && Pptr(nt)->typ->is_ptr()==0) return 0; //break;
16217: if (nt->check(at,COERCE)) {
16218: Pptr pt = at->addrof();
16219: nt->base = PTR; // handle derived classes
16220: if (nt->check(pt,COERCE)) {
16221: nt->base = RPTR;
16222: delete pt;
16223: return 0;
16224: }
16225: nt->base = RPTR;
16226: delete pt;
16227: }
16228: break;
16229: default:
16230: switch (at->base) {
16231: default:
16232: if (nt->check(at,COERCE)) return 0;
16233: break;
16234: case OVERLOAD:
16235: // the actual argument is an overloaded function
16236: // we'll try each instance until one matches
16237: register Plist gl;
16238: int no_match = 1;
16239:
16240: for (gl = Pgen(at)->fct_list; gl; gl=gl->l) {
16241: if (nt->check(gl->f->tp,COERCE)==0) {
16242: no_match = 0;
16243: break;
16244: }
16245: }
16246:
16247: if ( no_match ) return 0;
16248: }
16249: }
16250: return 1;
16251: }
16252:
16253: int exact1(Pname nn, Ptype at)
16254: /*
16255: return 1 if
16256: exact match with
16257: T <-> const T
16258: X -> X&
16259: T* -> const T*
16260: T* -> T*const
16261: taken into account
16262: */
16263: {
16264: if (nn == 0) return 0;//known==ELLIPSIS;
16265: Ptype nt = nn->tp;
16266: if (at == nt) return 1;
16267:
16268: //error('d',"exact1 nt %t at %t",nt,at);
16269: if (nt->check(at,0)) {
16270: //error('d',"nt %t at %t cp %d",nt,at,const_problem);
16271: if (const_problem) return 1; // handle T <-> const T
16272:
16273: Pptr rt = nt->is_ref(); //handle X -> X&
16274: if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1;
16275:
16276: Pptr art = at->is_ptr();
16277: if (rt && art) return 0; // ptrs do not match refs
16278:
16279: // handle T* -> const T* and
16280: // T* -> T*const
16281: if (rt || (rt = nt->is_ptr())) {
16282: if (art == 0) art = at->is_ref();
16283: if (art) {
16284: //error('d',"art %t %t",art->typ,rt->typ);
16285: if (art->typ->check(rt->typ,0)) {
16286: if (const_problem) return 1;
16287: }
16288: else // T* -> T*const
16289: return 1;
16290: }
16291: }
16292: return 0;
16293: }
16294: return 1;
16295: }
16296:
16297: Pexpr Ninit; // default argument used;
16298: int Nstd; // standard coercion used (derived* =>base* or int=>long or ...)
16299:
16300: bit exact_match(Pname n, Pexpr arg)
16301: /*
16302: look for an exact match between "n" and the argument list "arg"
16303: This function goes through three stages:
16304: (1) exact match (no coercions at all)
16305: (2) do integral promotions and float->double and re-try exact match
16306: (3) try for unique standard conversions
16307:
16308: */
16309: {
16310: Pfct f = Pfct(n->tp);
16311: register Pexpr e;
16312: register Pname nn;
16313:
16314: // error('d',"exact_match(%n) %t",n,n->tp);
16315:
16316: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
16317: Pexpr a = e->e1;
16318: Ptype at = a->tp;
16319: if (at->base == ANY) return 0;
16320: if (at->base == ZTYPE) at = int_type;
16321: if (exact1(nn,at)==0) return 0;
16322: }
16323:
16324: //error('d',"exact %d -> %d",nn,nn?nn->n_initializer!=0:1);
16325: if (nn) {
16326: Ninit = nn->n_initializer;
16327: return Ninit!=0;
16328: }
16329:
16330: //error('d',"return 1");
16331: return 1; // exact match without any promotions
16332: }
16333:
16334: int exact2(Pname nn, Ptype at)
16335: /*
16336: return 1 if
16337: do integral promotion and float->double on at, then match
16338: */
16339: {
16340: //error('d',"exact2 nt %t at %t",nn?nn->tp:0,at);
16341: while(at->base == TYPE)
16342: at = Pbase(at)->b_name->tp;
16343:
16344: switch (at->base) {
16345: case EOBJ:
16346: at = Penum(Pbase(at)->b_name->tp)->e_type;
16347: break;
16348: case ZTYPE:
16349: at = int_type;
16350: break;
16351: case CHAR:
16352: case SHORT:
16353: at = (Pbase(at)->b_unsigned && at->tsizeof()==SZ_INT) ? uint_type : int_type;
16354: break;
16355: case FLOAT:
16356: at = double_type;
16357: }
16358:
16359: if (nn == 0) return 0;//known==ELLIPSIS;
16360: Ptype nt = nn->tp;
16361: //error('d'," exact2 nt %t at %t",nt,at);
16362: if (at == nt) return 1;
16363: if (nt->check(at,0)) {
16364: if (const_problem) return 1;
16365:
16366: Pptr rt = nt->is_ref(); // handle X -> X&
16367: if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1;
16368:
16369: Pptr art = at->is_ptr();
16370: if (rt && art) return 0; // ptrs do not match refs
16371:
16372: // handle T* -> const T* and
16373: // T* -> T*const
16374: if (rt || (rt = nt->is_ptr())) {
16375: if (art == 0) art = at->is_ref();
16376: if (art) {
16377: if (art->typ->check(rt->typ,0)) {
16378: if (const_problem) return 1;
16379: }
16380: else // T* -> T*const
16381: return 1;
16382: }
16383: }
16384: return 0;
16385: }
16386: return 1;
16387: }
16388:
16389: bit prom_match(Pname n, Pexpr arg)
16390: /*
16391: look for an exact match between "n" and the argument list "arg"
16392: using integral promotions and float->double
16393:
16394: */
16395: {
16396: Pfct f = Pfct(n->tp);
16397: register Pexpr e;
16398: register Pname nn;
16399:
16400: // error('d',"prom_match(%n) %t",n,n->tp);
16401:
16402: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
16403: Pexpr a = e->e1;
16404: Ptype at = a->tp;
16405: if (at->base == ANY) return 0;
16406:
16407: if (exact2(nn,at)==0) return 0;
16408: }
16409:
16410: if (nn) {
16411: Ninit = nn->n_initializer;
16412: return Ninit!=0;
16413: }
16414:
16415: return 1; // exact match with promotions
16416: }
16417:
16418: bit std_match(Pname n, Pexpr arg)
16419: /*
16420: look for an exact match between "n" and the argument list "arg"
16421: using standard conversions
16422:
16423: */
16424: {
16425: Pfct f = Pfct(n->tp);
16426: register Pexpr e;
16427: register Pname nn;
16428:
16429: // error('d',"std_match(%n) %t",n,n->tp);
16430:
16431: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
16432: Pexpr a = e->e1;
16433: Ptype at = a->tp;
16434:
16435: if (at->base == ANY) return 0;
16436: if ( exact3(nn,at) == 0) return 0;
16437: }
16438:
16439: if (nn) {
16440: Ninit = nn->n_initializer;
16441: return Ninit!=0;
16442: }
16443:
16444: return 1;
16445: }
16446:
16447: Pname Ncoerce;
16448: int ref_cast;
16449:
16450: bit can_coerce(Ptype t1, Ptype t2)
16451: /* return number of possible coercions of t2 into t1,
16452: Ncoerce holds a coercion function (not constructor), if found
16453: */
16454: {
16455: int zz = 0;
16456: Ncoerce = 0;
16457: if (t2->base == ANY) return 0;
16458: // error('d',"can_coerce t1 %t t2 %t",t1, t2);
16459:
16460: while(t1->base == TYPE)
16461: t1 = Pbase(t1)->b_name->tp;
16462:
16463: switch (t1->base) {
16464: case RPTR:
16465: while(t2->base == TYPE)
16466: t2 = Pbase(t2)->b_name->tp;
16467:
16468: switch (t2->base) {
16469: // case VEC:
16470: // case PTR:
16471: // case RPTR:
16472: // if (t1->check(t2,COERCE) == 0) return 1;
16473: default:
16474: { Ptype tt2 = t2->addrof();
16475: if (t1->check(tt2,COERCE) == 0) return 1;
16476: if (ref_cast) break;//return 0; // (T&): no coercions
16477: // except operator T&()
16478: Ptype tt1 = Pptr(t1)->typ;
16479: while (tt1->base==TYPE) tt1 = Pbase(tt1)->b_name->tp;
16480: int bc;
16481: if ( tt1->base != PTR && tt1->base != RPTR ) {
16482: bc = Pbase(tt1)->b_const;
16483: Pbase(tt1)->b_const = 0;
16484: }
16485: int i = can_coerce(tt1,t2);
16486: if ( tt1->base != PTR && tt1->base != RPTR )
16487: Pbase(tt1)->b_const = bc;
16488: if (i) return i;
16489: zz = 1;
16490: }
16491: }
16492: }
16493:
16494: Pname c1 = t1->is_cl_obj();
16495: Pname c2 = t2->is_cl_obj();
16496: int val = 0;
16497: if (ref_cast || zz) goto oper_coerce;
16498: if (c1) {
16499: Pclass cl = Pclass(c1->tp);
16500: if (c2 && c2->tp==cl) return 1;
16501:
16502: // A more comprehensive test for template classes
16503: if (c2 && (Pclass(c1->tp)->same_class(Pclass(c2->tp))))
16504: return 1 ;
16505:
16506: /* look for constructor
16507: with one argument
16508: or with default for second argument
16509: of acceptable type
16510: */
16511: Pname ctor = cl->has_ctor();
16512: if (ctor == 0) goto oper_coerce;
16513: register Pfct f = Pfct(ctor->tp);
16514: //error('d',"ctor %n f %t",ctor,f);
16515: switch (f->base) {
16516: case FCT:
16517: switch (f->nargs) {
16518: case 1:
16519: one:
16520: { Ptype tt = f->argtype->tp;
16521: if (tt->check(t2,COERCE)==0)
16522: val = 1;
16523: else if (const_problem) {
16524: Pptr p1 = tt->is_ptr_or_ref();
16525: if (p1==0 || p1->typ->tconst()) val = 1;
16526: }
16527: if (tt = tt->is_ref()) {
16528: Pptr pt = t2->addrof(); // handle derived classed
16529: tt->base = PTR;
16530: if (tt->check(pt,COERCE) == 0) val = 1;
16531: tt->base = RPTR;
16532: delete pt;
16533: }
16534: goto oper_coerce;
16535: }
16536: default:
16537: if (f->argtype->n_list->n_initializer) goto one;
16538: case 0:
16539: goto oper_coerce;
16540: }
16541: case OVERLOAD:
16542: { register Plist gl;
16543:
16544: for (gl=Pgen(f)->fct_list; gl; gl=gl->l) { // look for match
16545: Pname nn = gl->f;
16546: Pfct ff = Pfct(nn->tp);
16547:
16548: switch (ff->nargs) {
16549: case 0:
16550: break;
16551: case 1:
16552: over_one:
16553: { Ptype tt = ff->argtype->tp;
16554: //error('d',"over one %t %t -> %d %d",tt,t2,tt->check(t2,COERCE),const_problem);
16555: if (tt->check(t2,COERCE)==0)
16556: val = 1;
16557: else if (const_problem) {
16558: Pptr p1 = tt->is_ptr_or_ref();
16559: if (p1==0 || p1->typ->tconst()) val = 1;
16560: }
16561: if (tt=tt->is_ref()) {
16562: Pptr pt = t2->addrof(); // handle derived classed
16563: tt->base = PTR;
16564: if (tt->check(pt,COERCE) == 0) {
16565: tt->base = RPTR;
16566: delete pt;
16567: val = 1;
16568: goto oper_coerce;
16569: }
16570: tt->base = RPTR;
16571: delete pt;
16572: }
16573: break;
16574: }
16575: default:
16576: if (ff->argtype->n_list->n_initializer) goto over_one;
16577: }
16578: }
16579: goto oper_coerce;
16580: }
16581: default:
16582: error('i',"cannot_coerce(%k)\n",f->base);
16583: }
16584: }
16585:
16586: oper_coerce:
16587: //error('d',"oper_coerce %d",val);
16588: if (c2) {
16589: Pclass cl = Pclass(c2->tp);
16590: int std = 0;
16591: int oval = val;
16592: extern Pname conv_dominates(Pname,Pname);
16593: for (Pname ox, on=cl->conv; on; on=ox) {
16594: ox = on->n_list;
16595: // error( 'd', "can_coerce: ox: %s on: %s tp: %k", ox?ox->string:"", on->string, on->tp->base );
16596: Plist gl = 0;
16597: if ( on->tp->base == OVERLOAD ) {
16598: gl = Pgen(on->tp)->fct_list;
16599: on = gl->f;
16600: gl = gl->l;
16601: }
16602:
16603: overlist:
16604: // error( 'd', "can coerce: on: %n tp: %t gl: %d", on, on->tp, gl );
16605:
16606: Pfct f = Pfct(on->tp);
16607: Nstd = 0;
16608: if (t1->check(f->returns,COERCE) == 0) {
16609: if (Nstd==0) { // forget solutions involving standard conversions
16610: Pname old = Ncoerce;
16611: if (std) { // forget
16612: val = oval+1;
16613: std = 0;
16614: Ncoerce = on;
16615: }
16616: else if (Ncoerce == 0) {
16617: // val = 1;
16618: val++;
16619: Ncoerce = on;
16620: }
16621: else if ((Ncoerce = conv_dominates(Ncoerce,on))==0) {
16622: if (val == 1) {
16623: //error('d',"val==1 on %n old %n",on,old);
16624: Ptype ton = Pfct(on->tp)->returns;
16625: Ptype tco = Pfct(old->tp)->returns;
16626: if (t1->check(ton,0)==0)
16627: ;
16628: else if (t1->check(tco,0)==0)
16629: on = old;
16630: else
16631: val++;
16632: }
16633: else
16634: val++;
16635: Ncoerce = on;
16636: }
16637: }
16638: else { // take note only if no exact match seen
16639: if (Ncoerce==0 || on->tp->check(Ncoerce->tp,0)) {
16640: if (val==0 || std) {
16641:
16642: if (Ncoerce) Ncoerce = conv_dominates(Ncoerce,on);
16643: if (Ncoerce == 0) {
16644: Ncoerce = on;
16645: val++;
16646: std = 1;
16647: }
16648: }
16649: }
16650: }
16651: }
16652: // error( 'd', "can_coerce: gl: %d", gl );
16653: if ( gl ) {
16654: on = gl->f;
16655: gl = gl->l;
16656: goto overlist; // must walk list of overloaded instances
16657: }
16658: }
16659: }
16660: //error('d',"val %d",val);
16661: if (val) return val;
16662: if (c1 && Pclass(c1->tp)->has_itor()) return 0;
16663: //error('d',"%t->check(%t) -> %d",t1,t2,t1->check(t2,COERCE));
16664: if (t1->check(t2,COERCE)) return 0;
16665: return 1;
16666: }
16667:
16668: int gen_coerce(Pname n, Pexpr arg)
16669: /*
16670: look to see if the argument list "arg" can be coerced into a call of "n"
16671: 1: it can
16672: 0: it cannot or it can be done in more than one way
16673: */
16674: {
16675: Pfct f = (Pfct) n->tp;
16676: register Pexpr e;
16677: register Pname nn;
16678:
16679: //error('d',"gen_coerce(%n,%d) %t",n,arg,n->tp);
16680: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
16681: if (nn == 0) return f->nargs_known==ELLIPSIS;
16682: Pexpr a = e->e1;
16683: Ptype at = a->tp;
16684: int i = can_coerce(nn->tp,at);
16685: if (i != 1) return 0;
16686: }
16687: if (nn && nn->n_initializer==0) return 0;
16688: return 1;
16689: }
16690:
16691:
16692: Pname Nover;
16693: // int Nover_coerce;
16694:
16695: int over_call(Pname n, Pexpr arg)
16696: /*
16697: return 4 if n(arg) can be performed without coercion of arg
16698: return 3 if n(arg) can be performed only with promotion coercion of arg
16699: return 2 if n(arg) can be performed only with standard coercion of arg
16700: return 1 if n(arg) can be performed only with user defined coercion of arg
16701: return 0 if n(arg) is an error
16702: Nover is the function found, if any
16703: Nstd is the number of standard coercions used
16704: */
16705: {
16706: register Plist gl;
16707: Pgen g = Pgen(n->tp);
16708: if (arg && arg->base!= ELIST) error('i',"ALX");
16709:
16710: //error('d',"over_call(%n) %k",n,n->tp->base);
16711: extern suppress_error;
16712: suppress_error = 1;
16713: // Nover_coerce = 0;
16714: Nstd = 0;
16715: switch (g->base) {
16716: default: error('i',"over_call(%t)\n",g);
16717: case OVERLOAD: break;
16718: case FCT:
16719: Nover = n;
16720: Ninit = 0;
16721: if (exact_match(n,arg)) {suppress_error = 0; return 4;}
16722: if (prom_match(n,arg)) {suppress_error = 0; return 3;}
16723: if (std_match(n,arg) && Ninit==0) {suppress_error = 0; return 2;}
16724: Nstd = 0;
16725: suppress_error = 0;
16726: return gen_coerce(n,arg);
16727: }
16728:
16729: Pname exact = 0;
16730: int no_exact = 0;
16731: int ret = 0;
16732: Pname nret;
16733: for (gl=g->fct_list; gl; gl=gl->l) { /* look for match */
16734: Nover = gl->f;
16735: Ninit = 0;
16736: Nstd = 0;
16737: if (exact_match(Nover,arg)) {suppress_error = 0; return 4;} // no coercion
16738: // if (prom_match(Nover,arg)) return 3; // only promotion
16739: // if (std_match(Nover,arg) && Ninit==0) return 2; // only built-in conversion
16740: if (ret<3 && prom_match(Nover,arg)) {
16741: nret = Nover;
16742: ret = 3;
16743: }
16744: if (ret<2 && std_match(Nover,arg) && Ninit==0) {
16745: nret = Nover;
16746: ret = 2;
16747: }
16748: }
16749:
16750: suppress_error = 0;
16751: if (ret) {
16752: Nover = nret;
16753: return ret;
16754: }
16755:
16756: Nover = 0;
16757: for (gl=g->fct_list; gl; gl=gl->l) { /* look for coercion */
16758: Pname nn = gl->f;
16759: if (gen_coerce(nn,arg)) {
16760: Nover = nn;
16761: return 1;
16762: }
16763: }
16764: return 0;
16765:
16766: }
16767:
16768: Ptype expr::call_fct(Ptable tbl)
16769: /*
16770: check "this" call:
16771: e1(e2)
16772: e1->typ() and e2->typ() has been done
16773: */
16774: {
16775: Pfct f;
16776: Pname fn;
16777: int x;
16778: int k;
16779: Pname nn;
16780: Pexpr e;
16781: Ptype t;
16782: Pexpr arg = e2;
16783: Ptype t1 = e1?e1->tp:0;
16784: int argno;
16785: Pexpr etail = 0;
16786: bit no_change = 0;
16787: Pname no_virt = 0; // set if explicit qualifier was used: c::f()
16788: Pname chk = 0; // set if visibility check is needed
16789: // that is if function name might have been
16790: // found without use of find_name()
16791: int const_obj = 0;
16792:
16793: if (t1 == any_type) return any_type;
16794:
16795: switch (base) {
16796: case CALL:
16797: case G_CALL: break;
16798: default: error('i',"call_fct(%k)",base);
16799: }
16800:
16801: // error('d',"call %d %k %n arg %d",this,e1->base,e1->base==NAME?e1:0,arg);
16802: if (t1 == 0) error('i',"call_fct(e1=%d,e1->tp=%t)",e1,t1);
16803: if (arg && arg->base!=ELIST) error('i',"badAL%d%k",arg,arg->base);
16804:
16805: switch (e1->base) {
16806: case NAME:
16807: fn = Pname(e1);
16808: //error('d',"name %n %k",fn,fn->n_oper);
16809: switch (fn->n_oper) {
16810: case 0:
16811: case CTOR:
16812: case DTOR:
16813: case TYPE:
16814: case NEW:
16815: case DELETE:
16816: break;
16817: default: // real operator: check for operator+(1,2);
16818: if (arg == 0) break;
16819: Pexpr a = arg->e1; // first operand
16820:
16821: if (Pfct(fn->tp)->memof // obj.operator(1) is OK
16822: || a->tp->is_cl_obj()
16823: || a->tp->is_ref()) break;
16824: a = arg->e2;
16825: if (a == 0) // unary
16826: error("%k of basicT",fn->n_oper);
16827: else { // binary
16828: a = a->e1; // second operand
16829: if (a->tp->is_cl_obj() || a->tp->is_ref()) break;
16830: error("%k of basicTs",fn->n_oper);
16831: }
16832: break;
16833: }
16834: break;
16835: case REF:
16836: case DOT:
16837: no_virt = Pname(e1->n_initializer);
16838: e1->n_initializer = 0;
16839: if (e1 && e1->e1) {
16840: Ptype t = e1->e1->tp;
16841: Pptr tt = t->is_ptr_or_ref();
16842: Ptype ft = tt ? tt->typ : t;
16843: Pexpr ee = e1->e1;
16844: const_obj = ft->tconst();
16845: while (ee && (ee->base==DOT || ee->base==REF)) {
16846: Pexpr m = ee->mem;
16847: if ( ee->base==REF && m->tp && m->tp->is_ptr())
16848: break;
16849: ee = ee->e1;
16850: }
16851: if (ee) {
16852: Ptype ttt = ee->tp;
16853: int tc;
16854: switch (e1->base) {
16855: case REF:
16856: Pptr p = ttt?ttt->is_ptr():0;
16857: if (p && p->typ->tconst())
16858: const_obj = 1;
16859: break;
16860: case DOT:
16861: tc = ttt ? ttt->tconst() : 0;
16862: if(ttt && tc && (!strict_opt || tc!=2))
16863: const_obj = 1;
16864: }
16865: }
16866: }
16867: case MDOT:
16868: { Pexpr n = e1->mem;
16869: lxlx:
16870: switch (n->base) {
16871: case MDOT:
16872: // reverse mdot (see expr::print())
16873: // p->a.b() => (&p->a)->b() => b(&p->a)
16874: // or p->a->b() => (p->a)->b() => b(p->a)
16875: // or oo.a.b() => (&oo.a)->b() => b(&oo.a)
16876: // or oo.a->b() => (oo.a)->b() => b(oo.a)
16877: {
16878: Pexpr r = e1;
16879: Pexpr p = r->e1;
16880: for (Pexpr m = r->mem; m->base==MDOT; m = r->mem) {
16881: p = new mdot(m->string2,p);
16882: p->i1 = m->i1+2;
16883: p->tp = p->mem->tp;
16884: r->mem = m->mem;
16885: r->e1 = p;
16886: }
16887: }
16888: case REF:
16889: case DOT:
16890: n = n->mem;
16891: goto lxlx;
16892: case NAME:
16893: break;
16894: default:
16895: error('i',"ref %k",n->base);
16896: }
16897: fn = Pname(n);
16898: //error('d',"mem %n",fn);
16899: break;
16900: }
16901: case MEMPTR:
16902: default:
16903: fn = 0;
16904: };
16905:
16906: lll:
16907: //error('d',"lll: %t %k",t1,t1->base);
16908: switch (t1->base) {
16909: case TYPE:
16910: t1 = Pbase(t1)->b_name->tp;
16911: goto lll;
16912:
16913: case PTR: // pf() allowed as shorthand for (*pf)()
16914: switch (Pptr(t1)->typ->base) {
16915: case FCT:
16916: case OVERLOAD:
16917: if (Pptr(t1)->memof) error("O missing in call throughP toMF");
16918: t1 = Pptr(t1)->typ;
16919: fn = 0;
16920: goto lll;
16921: }
16922:
16923: default:
16924: if (fn)
16925: error("call of%n;%n is a%t",fn,fn,e1->tp);
16926: else
16927: error("call of%kE ofT%t",e1->base,e1->tp);
16928:
16929: case ANY:
16930: return any_type;
16931:
16932: case OVERLOAD:
16933: { register Plist gl;
16934: Pgen g = Pgen(t1);
16935: Pname found = 0;
16936: Pname exact = 0;
16937: int no_exact = 0;
16938: int no_gen = 0;
16939:
16940: for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match
16941: register Pname nn = gl->f;
16942: if (exact_match(nn,arg)) {
16943: //error('d',"found exact %n %t",nn,nn->tp);
16944: if (found) {
16945: // check if one fct dominates the other
16946: Pname d = dominate(found,nn,arg,const_obj,0);
16947: if (d)
16948: nn = d;
16949: else
16950: error("two exact matches for%n:%t and%t",nn,nn->tp,found->tp);
16951: }
16952: found = nn;
16953: }
16954: }
16955: //error('d',"found exact2 %n",found);
16956: if (found) goto fnd;
16957:
16958: Pname mvec[20];
16959:
16960: /****************************************************************************
16961: the next 2 loops have been commented out to eliminate the rule that calls
16962: requiring only promotions and standard conversions are preferred over
16963: calls requiring user-defined conversions.
16964:
16965: for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match
16966: register Pname nn = gl->f;
16967:
16968: if (prom_match(nn,arg)) {
16969: if (found) {
16970: // check if one fct dominates the other
16971: Pname d = dominate(found,nn,arg,const_obj,1);
16972: if (d)
16973: nn = d;
16974: else
16975: error("two exact matches (after integral promotions) for%n:%t and%t",nn,nn->tp,found->tp);
16976: }
16977: found = nn;
16978: }
16979: }
16980: //error('d',"found exact2 %n",found);
16981: if (found) goto fnd;
16982:
16983: // for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match
16984: // register Pname nn = gl->f;
16985: //
16986: // if (exact_match(nn,arg) || prom_match(nn,arg)) {
16987: // found = nn;
16988: // goto fnd;
16989: // }
16990: // }
16991:
16992: for (gl=g->fct_list; gl; gl=gl->l) { // look for match
16993: // with standard conversion
16994: register Pname nn = gl->f;
16995: Ninit = 0;
16996: Nstd = 0;
16997: if (std_match(nn,arg)) {
16998: // if (Nstd == 0) {
16999: // found = nn;
17000: // goto fnd;
17001: // }
17002: if (exact) {
17003: // check if one fct dominates the other
17004: Pname d = dominate(exact,nn,arg,const_obj,2);
17005: if (d == 0) {
17006: mvec[no_exact++] = nn;
17007: // no_exact++;
17008: // error("two standard conversions possible for%n: %t and %t",fn,exact->tp,nn->tp);
17009: }
17010: else
17011: exact = d;
17012: }
17013: else
17014: exact = nn;
17015: }
17016:
17017: }
17018:
17019: //error('d',"excact %n",exact);
17020: if (exact) {
17021: if (no_exact) {
17022: while (no_exact) {
17023: Pname d = dominate(exact,mvec[--no_exact],arg,const_obj,2);
17024: if (d)
17025: exact = d;
17026: else
17027: error("two standard conversions possible for%n: %t and %t",fn,exact->tp,mvec[no_exact]->tp);
17028: }
17029:
17030: }
17031: //error('d',"found exact3 %n",found);
17032: found = exact;
17033: goto fnd;
17034: }
17035:
17036: this is the end of the commented out section.
17037: ************************************************************************/
17038:
17039: for (gl=g->fct_list; gl; gl=gl->l) { /* look for coercion */
17040: register Pname nn = gl->f;
17041: if (prom_match(nn,arg) ||
17042: std_match(nn,arg) ||
17043: gen_coerce(nn,arg)) {
17044: //error('d',"user2 %n %t",nn,nn->tp);
17045: if (found) {
17046: // check if one fct dominates the other
17047: Pname d = dominate(found,nn,arg,const_obj,3);
17048: //error('d',"dom d %d",d);
17049: if (d == 0) d = user_dominate(found,nn,arg);
17050: if (d == 0) {
17051: mvec[no_gen++] = nn;
17052: }
17053: else
17054: found = d;
17055: }
17056: else
17057: found = nn;
17058: }
17059: }
17060: if(found) {
17061: while(no_gen) {
17062: Pname d = dominate(found,mvec[--no_gen],arg,const_obj,3);
17063: if(d==0) d = user_dominate(found,mvec[no_gen],arg);
17064: if(d)
17065: found = d;
17066: else {
17067: //error("ambiguousA for%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
17068: error("ambiguous call of%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
17069: }
17070: }
17071: }
17072: fnd:
17073: //error('d',"fnd %t",found?found->tp:0);
17074: if (found) {
17075: overFound = chk = fn = found;
17076: f = Pfct(fn->tp);
17077: }
17078: else {
17079: error("badAL for%n (no match against any %n)",fn,fn);
17080: return any_type;
17081: }
17082: break;
17083: }
17084: case FCT:
17085: f = Pfct(t1);
17086: if (fn) {
17087: switch (fn->n_oper) {
17088: case CTOR:
17089: case TYPE:
17090: chk = fn;
17091: }
17092: }
17093: }
17094:
17095: //error('d',"chk %n",chk);
17096: if (chk) {
17097: Ptype t = 0;
17098: Pexpr ee = e1->e1;
17099:
17100: switch (e1->base) {
17101: case REF: // ptr->chk()
17102: if (ee == 0) { // 0->x() fudge handling new x()
17103: check_visibility(chk,no_virt,Pclass(chk->n_table->t_name->tp),tbl,cc->nof);
17104: break;
17105: };
17106: t = ee->tp;
17107: while(t->base==TYPE) t = Pbase(t)->b_name->tp;
17108: t = Pptr(t)->typ;
17109: break;
17110: case DOT: // obj.chk()
17111: t = ee->tp;
17112: }
17113:
17114: Pname cn = t?t->is_cl_obj():0;
17115: Pclass cl = cn?Pclass(cn->tp):0; // class of ``this'' for chk
17116:
17117: if (cl) {
17118: if (chk->n_oper==CTOR
17119: && chk->n_protect
17120: && cc->nof
17121: && cc->nof->n_oper==CTOR)
17122: // BUG: cannot handle protected base
17123: // class constructor
17124: ;
17125: else {
17126: check_visibility(chk,no_virt,cl,tbl,cc->nof);
17127: }
17128: }
17129: }
17130:
17131: if (fn && f->returns->is_cl_obj() && f->f_result==0) {
17132: // protect against class cn; cn f(); ... class cn { cn(cn&); ... };
17133: make_res(f);
17134: //error('d',"returns %t",f->returns);
17135: f->returns->tsizeof(); // make sure it is declared
17136: }
17137:
17138: //error('d',"fn %n %t printed %d",fn,fn?fn->tp:0,fn?fn->n_dcl_printed:0);
17139: if (fn && fn->n_dcl_printed==0) {
17140: if (f->f_inline==0 && f->f_imeasure) {
17141: extern void uninline(Pname fn);
17142: uninline(fn);
17143: }
17144:
17145: // ensure printout of class declaration:
17146: for (Pname nn=f->argtype; nn; nn=nn->n_list)
17147: if (nn->tp->is_cl_obj()) (void) nn->tp->tsizeof();
17148:
17149: fn->dcl_print(0);
17150: }
17151:
17152: if (no_virt && f->f_static==0) {
17153: if (e1->base==REF || e1->base==DOT) e1->n_initializer = fn;
17154: }
17155: else
17156: fct_name = fn;
17157: //error('d',"fn %n %t %d %d",fn,f,f->f_this,f->f_static);
17158: if (f->f_this) { //SSS call of non-static memberfunction
17159: switch (e1->base) {
17160: case MEMPTR:
17161: case REF:
17162: case DOT:
17163: break;
17164: default:
17165: error("O orP missing for%n ofT %t",fct_name,f);
17166: }
17167: }
17168: else if (fn) { //SSS call of static function
17169: sss:
17170: switch (e1->base) {
17171: case REF:
17172: case DOT:
17173: e1 = e1->mem;
17174: goto sss;
17175: }
17176: }
17177:
17178: if (fn) fn->use(); // a patch: ctors are sometimes not use()d
17179:
17180: if (f->f_const==0
17181: && (fn==0 || (fn->n_oper!=CTOR && fn->n_oper!=DTOR))) { //CCC
17182: Pexpr ee = e1->e1;
17183: // while (ee && (ee->base==DOT || ee->base==REF)) ee = ee->e1;
17184: while (ee && (ee->base==DOT || ee->base==REF)) {
17185: Pexpr m = ee->mem;
17186: // error('d', "m: %k tp %t", m?m->base:0, m?m->tp:0 );
17187: if ( ee->base==REF && m->tp && m->tp->is_ptr())
17188: break;
17189: ee = ee->e1;
17190: }
17191: // error('d', "ee: %k tp %k", ee?ee->base:0, ee?ee->tp->base:0);
17192:
17193: if (ee) {
17194: Ptype tt = ee->tp;
17195: switch (e1->base) {
17196: case REF:
17197: { Pptr p = tt?tt->is_ptr():0;
17198: if (p && p->typ->tconst())
17199: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
17200: // is really an error, but only warn to help transition
17201: break;
17202: }
17203: case DOT:
17204: int tc = tt ? tt->tconst() : 0;
17205: if (tt && tc && (!strict_opt || tc!=2))
17206: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
17207: // is really an error, but only warn to help transition
17208: }
17209: }
17210: }
17211:
17212: t = f->returns;
17213: x = f->nargs;
17214: k = f->nargs_known;
17215:
17216: e = arg;
17217: if (k == 0) goto rlab;
17218:
17219: for (nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) {
17220: Pexpr a;
17221: int save_base = 0;
17222: char* save_name = 0;
17223:
17224: if (e) {
17225: a = e->e1;
17226: etail = e;
17227:
17228: if (nn) { /* type check */
17229: Ptype t1 = nn->tp;
17230: //error('d',"argtp %t etp %t a %k",t1,a->tp,a->base);
17231:
17232: while(t1->base == TYPE)
17233: t1 = Pbase(t1)->b_name->tp;
17234:
17235: switch (t1->base) {
17236: case RPTR:
17237: { Ptype pt = Pptr(t1)->typ;
17238: if (pt->base != FCT ||
17239: ( pt->base == FCT &&
17240: pt->check(a->tp,0)))
17241: a = ref_init(Pptr(nn->tp),a,tbl);
17242: goto cbcb;
17243: }
17244: case COBJ:
17245: if (a->base!=G_CM
17246: || nn->tp->check(a->tp,ASSIGN))
17247: a = class_init(0,t1,a,tbl);
17248: else
17249: a->e2=class_init(0,t1,a->e2,tbl);
17250: if (nn->n_xref) {
17251: // (temp.ctor(arg),&arg)
17252: a = a->address();
17253: }
17254: else {
17255: // defend against:
17256: // int f(X); ... X(X&);
17257: Pname cln = Pbase(t1)->b_name;
17258: if (cln && Pclass(cln->tp)->has_itor()) {
17259: // mark X(X&) arguments
17260: nn->n_xref = 1;
17261: a = a->address();
17262: }
17263: }
17264: cbcb:
17265: //error('d',"cbcb: a %d %k %t",a->base,a->base,a->tp);
17266: if (a->base==G_CM) {
17267: if (a->e1->base==DEREF) a->e1 = a->e1->e2; // (*e1,e2) => (e1,e2)
17268: //error('d'," a %d %k",a->e1->base,a->e1->base);
17269: if (a->e1->base==G_CALL
17270: && Pname(a->e1->fct_name)
17271: && Pname(a->e1->fct_name)->n_oper==CTOR
17272: && (a->e2->base==G_ADDROF || a->e2->base==ADDROF)) {
17273: a = a->e1; // (ctor(&tmp),&tmp) => ctor(&tmp)
17274: //error('d',"tmp %k %n",a->e2->base,a->e2->e2);
17275: goto cccc;
17276: }
17277: else if (a->e2->base==G_ADDROF
17278: && a->e2->e2->base==NAME) {
17279: cccc:
17280: //error('d',"cccc: a %d %k %t",a->base,a->base,a->tp);
17281: if (t1->base==RPTR
17282: && Pptr(t1)->typ->tconst()==0) { // temporary used
17283: if (warning_opt)
17284: error('w',"temporary used for non-const%tA",nn->tp);
17285: else {
17286: Ptype atp = a->tp;
17287: if (atp==void_type
17288: && a->base==G_CALL
17289: && a->e1->tp->base==FCT)
17290: atp = Pfct(a->e1->tp)->s_returns;
17291:
17292: Ptype tt = t1->is_ref();
17293: //error('d',"tt %t atp %t",tt,atp);
17294: if (tt) {
17295: if (Pptr(tt)->typ->tsizeof()!=atp->tsizeof()) { // sliced
17296: Ptype aat = atp->is_ptr_or_ref();
17297: if (aat==0
17298: || Pptr(tt)->typ->tsizeof()!=Pptr(aat)->typ->tsizeof())
17299: error('w',"temporary used for non-const%tA",nn->tp);
17300: }
17301: }
17302: else if (t1->tsizeof()!=atp->tsizeof()) // sliced
17303: error('w',"temporary used for non-const%tA",nn->tp);
17304: }
17305:
17306: // if (warning_opt // blabber
17307: // || t1->tsizeof()!=a->tp->tsizeof())) // sliced
17308: // error('w',"temporary used for non-const%tA",nn->tp);
17309:
17310: }
17311: }
17312: }
17313: e->e1 = a;
17314: break;
17315: case ANY:
17316: goto rlab;
17317: case PTR:
17318: {
17319: save_base = e->e1->base;
17320: if(a->tp->base==OVERLOAD)
17321: save_name = Pgen(a->tp)->fct_list->f->string;
17322: Pexpr te_a = a;
17323: e->e1 = a = ptr_init(Pptr(t1),a,tbl);
17324: no_change = (te_a == a);
17325: // if (x==a || x==a->e2) goto def; // needs checking
17326: if (Pchecked == 0) goto def;
17327: break;
17328: }
17329: // e->e1 = a = ptr_init(Pptr(t1),a,tbl);
17330: // goto def;
17331: case CHAR:
17332: case SHORT:
17333: case INT:
17334: // if (a->base==ICON && a->tp==long_type)
17335: // error('w',"long constantA for%n,%kX",fn,t1->base);
17336: { Ptype t = a->tp;
17337: while(t->base == TYPE)
17338: t = Pbase(t)->b_name->tp;
17339:
17340: switch (t->base) {
17341: case LONG:
17342: case FLOAT:
17343: case DOUBLE:
17344: case LDOUBLE:
17345: error('w',"A%d: %t passed as %t",argno,a->tp,t1);
17346: }
17347: }
17348: // no break
17349: case LONG:
17350: if (Pbase(t1)->b_unsigned
17351: && a->base==UMINUS
17352: && a->e2->base==ICON)
17353: error('w',"negativeA for%n, unsignedX",fn);
17354: default:
17355: def:
17356: { Pexpr x = try_to_coerce(t1,a,"argument",tbl);
17357: //error('d',"x %d t1 %t nn %t a1 %t",x,t1,nn->tp,a->tp);
17358: if (x) {
17359: if (Pchecked == 0 && no_change) {
17360: Pexpr te_x = ptr_init(Pptr(t1), x, tbl);
17361:
17362: if ( te_x != x ) e->e1 = a = te_x; else e->e1=x;
17363: }
17364: else
17365: e->e1 = x;
17366: }
17367: else if (nn->tp->check(a->tp,ARG)) {
17368: error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp);
17369: return any_type;
17370: }
17371: }
17372: }
17373:
17374: Pexpr tt = e->e1;
17375: while ( tt->base == CAST )
17376: tt = tt->e1;
17377: if ( tt->base == ILIST )
17378: e->e1 = tt;
17379:
17380: if (e->e1->base == ILIST) {
17381: // memptr constant
17382: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
17383: if(save_base == REF) {
17384: Pptr m = Pptr(a->tp);
17385: error(strict_opt?0:'w',
17386: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
17387: m->memof->string,
17388: m->memof->string,
17389: save_name
17390: );
17391: }
17392: Pname temp = make_tmp('A',mptr_type,tbl);
17393: e->e1 = mptr_assign(temp,e->e1);
17394: e->e1 = a = new expr(G_CM,e->e1,temp);
17395: a->tp = temp->tp;
17396: }
17397:
17398: }
17399: else {
17400: if (k != ELLIPSIS) {
17401: error("unexpected %dA for%n",argno,fn);
17402: return any_type;
17403: }
17404: Pexpr te=e;
17405: while(e) {
17406: if (e->e1->base == ILIST) {
17407: // memptr constant
17408: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
17409: Pname temp = make_tmp('A',mptr_type,tbl);
17410: e->e1 = mptr_assign(temp,e->e1);
17411: e->e1 = a = new expr(G_CM,e->e1,temp);
17412: a->tp = temp->tp;
17413: }
17414: e = e->e2;
17415: }
17416: e = te;
17417: goto rlab;
17418: }
17419: }
17420: else { /* default argument? */
17421: a = nn->n_initializer;
17422: if (a == 0) {
17423: error("A %d ofT%tX for%n",argno,nn->tp,fn);
17424: return any_type;
17425: }
17426: if (a->base == ILIST) {
17427: // memptr constant
17428: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
17429: Pname temp = make_tmp('A',mptr_type,tbl);
17430: a = mptr_assign(temp,a);
17431: a = new expr(G_CM,a,temp);
17432: a->tp = temp->tp;
17433: }
17434: a->permanent = 2; // ought not be necessary, but it is
17435: e = new expr(ELIST,a,0);
17436: if (etail)
17437: etail->e2 = e;
17438: else
17439: e2 = e;
17440: etail = e;
17441: }
17442: }
17443:
17444: rlab:
17445: //error('d',"rlab fct_name %n %t",fct_name,fct_name?fct_name->tp:0);
17446: for (; e; e = e->e2) { // unchecked arguments
17447: Pexpr a = e->e1;
17448: Pname cn;
17449:
17450: if (a->base==NAME && a->tp->base==FCT) {
17451: // function name that escaped the type system:
17452: // update use count
17453: a->lval(ADDROF);
17454: }
17455: else if (warning_opt && (cn = a->tp->is_cl_obj())) {
17456: Pclass cl = Pclass(cn->tp);
17457: if (cl->has_ctor() || cl->memtbl->look("__as",0))//cl->has_oper(ASSIGN)
17458: {
17459: if (fct_name)
17460: error('w',"O ofC%t withK or = copied asA to%n (%t)",cl,fct_name,fct_name->tp);
17461: else
17462: error('w',"O ofC%t withK or = copied asA to `...'",cl);
17463: }
17464: }
17465: else if (a->tp->is_ref())
17466: e->e1 = a->contents();
17467: }
17468:
17469: if (f->f_result) { // f(args) => (f(&temp,args),temp)
17470: Pname tn = make_tmp('R',f->returns,tbl);
17471: e2 = new expr(ELIST,tn->address(),e2);
17472: // error('d',"result %n refd: %d",fn, refd);
17473: Pexpr ee = new expr(0,0,0);
17474: *ee = *this;
17475: base = G_CM; // (f(&temp,args),temp)
17476: e1 = ee;
17477: if (refd == 2)
17478: e2 = tn->address();
17479: else e2 = tn;
17480: tp = tn->tp;
17481: }
17482:
17483: return t;
17484: }
17485:
17486: int cm_const_save;
17487:
17488: Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl)
17489: /*
17490: initialize the "p" with the "init"
17491: remember to call ptr_init to ensure that pointers to second bases
17492: are handled correctly.
17493: */
17494: {
17495: register Ptype it = init->tp;
17496: Pptr px = p;
17497: while (px->base == TYPE) px = Pptr(Pbase(px)->b_name->tp);
17498: Ptype p1 = px->typ;
17499: Pname c1 = p1->is_cl_obj();
17500: // error('d',"ref_init: p %t, p1 %t, px %t, init->tp %t",p,p1,px,it);
17501: // error('d', "ref_init: nof: %n f_const: %d", cc?cc->nof:0, cc?(cc->nof?Pfct(cc->nof->tp)->f_const:0):0);
17502:
17503: if (init->base == ILIST) error("IrL as RIr");
17504:
17505: if (init->base==NAME
17506: && Pname(init)->n_scope==ARG
17507: && init->tp->base==FLOAT)
17508: error('w',"initializing a float& with floatA is non-portable");
17509:
17510: while(it->base == TYPE)
17511: it = Pbase(it)->b_name->tp;
17512:
17513: switch (it->base) {
17514: default:
17515: { Ptype tt = it->addrof();
17516: px->base = PTR; // allow &x for y& when y : public x
17517: // but not &char for int&
17518: int x = px->check(tt,COERCE);
17519:
17520: if (x == 0) { //CCC type is fine check for constness:
17521: if (init->tp->tconst()
17522: && vec_const==0
17523: && fct_const==0) {
17524: // not ``it''
17525: if (init->base == ELIST) init = init->e1;
17526: if (px->typ->tconst() == 0) error("R to constO");
17527: px->base = RPTR;
17528: // if we have a const lvalue we can still pass its address
17529: ignore_const++;
17530: if (init->lval(0)) {
17531: init->lval(ADDROF); // force output
17532: ignore_const--;
17533: //error('d',"in1 %t",init->tp);
17534: return ptr_init(px,init->address(),tbl);//return init->address();
17535: }
17536: ignore_const--;
17537: goto xxx;
17538: }
17539: px->base = RPTR;
17540: if (init->lval(0)) { // can pass the address // no temporary needed
17541: init->lval(ADDROF); // force output
17542: //error('d',"px %t init %t init %t",px,init->tp,init->tp);
17543: return ptr_init(px,init->address(),tbl);
17544: }
17545: goto xxx;
17546: }
17547:
17548: px->base = RPTR;
17549: }
17550: }
17551:
17552: //error('d',"c1 %n",c1);
17553: if (c1) { // assigning to a const X & is fine
17554: ref_cast++;
17555: Pexpr x = try_to_coerce(p,init,"reference initialization",tbl);
17556: ref_cast--;
17557: if (x) {
17558: init = x;
17559: goto xxx;
17560: }
17561: while (p1->base==TYPE) p1 = Pbase(p1)->b_name->tp;
17562: int bc = Pbase(p1)->b_const;
17563: Pbase(p1)->b_const = 0;
17564: // refd = 1;
17565: switch ( init->base ) {
17566: case STRING: case ZERO: case CCON:
17567: case ICON: case FCON: case IVAL:
17568: case NAME:
17569: refd = 1;
17570: break;
17571: default:
17572: refd = (init->e1 && init->e1->base == NAME &&
17573: init->e1->tp->base != RPTR &&
17574: Pname(init->e1)->n_xref == 0) ? 2: 1;
17575: break;
17576: }
17577: // error('d', "***** refd: %d", refd );
17578: Pexpr a = class_init(0,p1,init,tbl);
17579: Pbase(p1)->b_const = bc;
17580: refd = 0;
17581: if (a==init && init->tp!=any_type) goto xxx;
17582: // error('d',"ri a %d %k",a->base,a->base);
17583: switch (a->base) {
17584: case G_CALL:
17585: // case CM:
17586: // case G_CM:
17587: init = a;
17588: goto xxx;
17589: }
17590: a = a->address();
17591: a = ptr_init(px,a,tbl);
17592: return a;
17593: // return ptr_init(px,a->address(),tbl);//a->address();
17594: }
17595:
17596: //error('d',"p1 %t it %t",p1,it);
17597: if (p1->check(it,0)) {
17598:
17599: if (p1->check(it,ASSIGN) == 0) {
17600: // if (p1->is_ptr()) // check for base* = derived*
17601: // goto xxx;
17602:
17603: // things like ``double& rr = 1;'' temporary needed
17604: // warn in case of ``slightly wrong lvalue'', e.g.
17605: // int i; double& r = i;
17606: if (init->lval(0) && p1->tconst()==0)
17607: error('w',"temporary used toIR; no changes will be propagated to actualA");
17608: goto def;
17609: }
17610:
17611: Pexpr x = try_to_coerce(p1,init,"reference",tbl); // x==init
17612: if (x==0) x = try_to_coerce(px,init,"reference",tbl); // x&=init
17613: if (x) {
17614: init = x;
17615: goto def;
17616: }
17617:
17618: error("badIrT:%t (%tX)",it,p);
17619: if (init->base != NAME) init->tp = any_type;
17620: return init;
17621: }
17622:
17623: xxx: /*
17624: here comes the test of a ``fundamental theorem'':
17625: a structure valued expression is
17626: (1) an lvalue of type T (possibly const)
17627: or (2) the result of a function (a _result if X(X&) is defined)
17628: or (3) a * or [] or ? or , expression
17629: */
17630: //error('d',"xxx %k %d %t",init->base,init->base,init->tp);
17631:
17632: switch (init->base) {
17633: case NAME:
17634: case DEREF:
17635: case REF:
17636: case DOT: // init => &init
17637: if (it->tconst() && vec_const==0 && fct_const==0) goto def;
17638: if ( cc && cc->nof &&
17639: Pfct(cc->nof->tp)->f_const )
17640: cm_const_save = Pbase(p->typ)->b_const;
17641: init->lval(ADDROF);
17642: cm_const_save = 0;
17643:
17644: if (vec_const) return init;
17645: if (fct_const && p1->is_ptr()) goto def; // fptr& = fct
17646: // no break
17647: case CM:
17648: case G_CM: // & (f(&temp), temp)
17649: return ptr_init(px,init->address(),tbl);//init->address();
17650: default:
17651: def:
17652: {
17653: // error('d',"def: init->tp %t p1 %t ",init->tp,p1);
17654: // error('d',"p1: %t const_ptr: %d", p1, const_ptr);
17655: if (const_ptr == 0) {
17656: if (tbl == gtbl || strict_opt)
17657: error("Ir for%snon-constR not an lvalue", strict_opt?"":" global ");
17658: else
17659: if (warning_opt)
17660: error('w', "Ir for non-constR not an lvalue (anachronism)");
17661: }
17662:
17663: Pname tcl = p1->is_cl_obj ();
17664: if(tcl && Pclass(tcl->tp)->c_abstract)
17665: error("a temporary is needed for a parameter, but the argument type is abstract class %t.", tcl->tp);
17666:
17667: Pname n = make_tmp('I',p1,tbl);
17668: Pexpr a;
17669: Pname ic = init->tp->is_cl_obj();
17670:
17671: if (p1->tconst()==0
17672: && (init->tp->tconst() && vec_const==0 && fct_const==0)
17673: && p1->check(it,ASSIGN)==0)
17674: error('w',"constIr: temporary used toI reference");
17675:
17676: switch (p1->base) {
17677: case INT:
17678: case CHAR:
17679: case SHORT:
17680: switch (it->base) {
17681: case LONG:
17682: case FLOAT:
17683: case DOUBLE:
17684: case LDOUBLE:
17685: error('w',"%t assigned to %t inRIr",it,p1);
17686: }
17687: }
17688:
17689: if (ic!=c1 && Pclass(ic->tp) != Pclass(c1->tp)) {
17690: // derived class1 => must cast: ``it Ix; (Ix=init,(p)&Ix);''
17691: n->tp = init->tp;
17692: a = ptr_init(px,n->address(),tbl);//n->address();
17693: PERM(p);
17694: a = new texpr(CAST,p,a);
17695: a->tp = p;
17696: }
17697: else
17698: a = n->address();
17699:
17700: refd = 1;
17701: Pexpr as = init_tmp(n,init,tbl);
17702: refd = 0;
17703: a = new expr(G_CM,as,a);
17704: a->tp = a->e2->tp;
17705: return a;
17706: }
17707: }
17708: }
17709:
17710: Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl)
17711: /*
17712: initialize "nn" of type "tt" with "init"
17713: if nn==0 make a temporary,
17714: nn may not be a name
17715: */
17716: {
17717: if (init == dummy) return 0;
17718: //error('d',"class_init %t with %t init %k refd %d",tt,init->tp,init->base,refd);
17719: Pname c1 = tt->is_cl_obj();
17720:
17721: if (init == 0) {
17722: error("emptyIr");
17723: return dummy;
17724: }
17725:
17726: if (c1) {
17727: Pclass cl = Pclass(c1->tp);
17728: Pname c2 = init->tp->is_cl_obj();
17729:
17730: if (c1!=c2 || (refd==0 && cl->has_itor())) {
17731: /* really ought to make a temp if refd,
17732: but ref_init can do that
17733: */
17734: int i = can_coerce(tt,init->tp);
17735: //error('d',"i %d nn %n",i,nn);
17736: switch (i) {
17737: default:
17738: error("%d ways of making a%n from a%t",i,c1,init->tp);
17739: init->tp = any_type;
17740: return init;
17741: case 0:
17742: if (c2 && Pclass(c2->tp)->has_base(cl)) {
17743: init = init->address();
17744: Pexpr x = cast_cptr(cl,init,tbl,0);
17745:
17746: if (x == init) {
17747: Ptype pt = tt->addrof();
17748: PERM(pt);
17749: x = new cast(pt,init);
17750: }
17751:
17752: return x->contents();
17753: }
17754: error("cannot make a%n from a%t",c1,init->tp);
17755: init->tp = any_type;
17756: return init;
17757: case 1:
17758: //error('d',"ncoerce %n %k %d",Ncoerce,init->base,init->base);
17759: if (Ncoerce == 0) {
17760: Pexpr a = new expr(ELIST,init,0);
17761: a = new texpr(VALUE,tt,a);
17762: a->e2 = nn;
17763: // return a->typ(tbl);
17764: a = a->typ(tbl);
17765: //error('d',"ci a %k %d %t",a->base,a->base,a->tp);
17766: return a;
17767: }
17768:
17769: switch (init->base) {
17770: case CM:
17771: case G_CM: //ddd
17772: case NAME: /* init.coerce() */
17773: /* *ref */ case DEREF:
17774: { Pref r = new ref(DOT,init,Ncoerce);
17775: Pexpr rr = r->typ(tbl);
17776: init = new expr(G_CALL,rr,0);
17777: init->fct_name = Ncoerce;
17778: break;
17779: }
17780: default: // (temp=init,temp.coerce())
17781: { Pname tmp = make_tmp('U',init->tp,tbl);
17782: int x = refd;
17783: refd = 0; // ??
17784: Pexpr ass = init_tmp(tmp,init,tbl);
17785: refd = x;
17786: Pref r = new ref(DOT,tmp,Ncoerce);
17787: Pexpr rr = r->typ(tbl);
17788: Pexpr c = new expr(G_CALL,rr,0);
17789: c->fct_name = Ncoerce;
17790: c = c->typ(tbl);
17791: init = new expr(CM,ass,c);
17792: init->tp = c->tp;
17793: if (refd) { // &f() => (t=f(), &t)
17794: Pname tmp2 = make_tmp('L',c->tp,tbl);
17795: ass = init_tmp(tmp2,init,tbl);
17796: init = new expr(G_CM,ass,tmp2);
17797: }
17798: }
17799: }
17800: //error('d',"nn %n",nn);
17801: if (nn) {
17802: Pexpr a = new expr(ELIST,init,0);
17803: a = new texpr(VALUE,tt,a);
17804: a->e2 = nn;
17805: return a->typ(tbl);
17806: }
17807: }
17808: //error('d',"c1 %n c2 %n",c1,c2);
17809: return init->typ(tbl);
17810: }
17811: return init;
17812: }
17813: //error('d',"ci check tt %t init->tp %t",tt,init->tp);
17814: if (tt->check(init->tp,ASSIGN) && refd==0) {
17815: error("badIrT:%t (%tX)",init->tp,tt);
17816: init->tp = any_type;
17817: }
17818:
17819: return init;
17820: }
17821:
17822: extern int bound; // fudge for bound pointers to functions
17823:
17824: Pexpr expr::docast(Ptable tbl)
17825: {
17826: // check cast against value, INCOMPLETE
17827:
17828: //error('d',"docast %d %t %k",this,tp2,e1->base);
17829: if (e1 == dummy) {
17830: error("E missing for cast");
17831: tp = any_type;
17832: return this;
17833: }
17834:
17835: int pmf = 0;
17836: int ptom_cast = 0;
17837: Pexpr ee = e1;
17838:
17839: //error('d',"ee %k %d",ee->base,ee->base);
17840: switch (ee->base) {
17841: case ADDROF:
17842: ee = ee->e2;
17843: switch (ee->base) {
17844: case NAME: goto nm;
17845: case REF: goto rf;
17846: }
17847: break;
17848:
17849: case NAME:
17850: nm:
17851: if (Pname(ee)->n_qualifier) pmf = 1;
17852: break;
17853:
17854: case REF:
17855: rf:
17856: if (ee->e1->base == THIS) bound = 1;
17857: break;
17858: }
17859:
17860: e1 = e1->typ(tbl);
17861:
17862: int b = bound; // distinguish between explicit and implicit THIS
17863: bound = 0;
17864: pmf = pmf && e1->base==CAST;
17865:
17866: Ptype etp = e1->tp;
17867: Ptype tt = tp2;
17868: Ptype t = tt;
17869: tt->dcl(tbl);
17870:
17871: while (etp->base == TYPE) etp = Pbase(etp)->b_name->tp;
17872: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
17873:
17874: //error('d',"e1 %k etp %t tt %t",e1->base,etp,tt);
17875:
17876: switch (etp->base) {
17877: case PTR:
17878: case RPTR:
17879: if (Pptr(etp)->typ->base == OVERLOAD) goto over;
17880:
17881: if (warning_opt && i2==0 && Pptr(etp)->typ->tconst()) {
17882: switch (tt->base) {
17883: case FCT:
17884: break;
17885: case PTR:
17886: case RPTR:
17887: if (Pptr(tt)->typ->tconst()) break;
17888: default:
17889: // casting away const
17890: // should be an error
17891: // but ANSI says OK so I chicken out
17892: // to be able to compile strtok(), etc.
17893: error('w',"const cast away:%t->%t",e1->tp,tp2);
17894: }
17895: }
17896: else
17897: i2 = 0; // to allow cfront to escape its own checking
17898: break;
17899: case COBJ:
17900: { ref_cast = 1;
17901: Pexpr x = try_to_coerce(tt,e1,"cast",tbl);
17902: ref_cast = 0;
17903: //error('d',"x %k %t tt %d %t",x?x->base:0,x?x->tp:0,tt,tt);
17904: if (x) {
17905: if (x!=e1 && x->base==DEREF && tt->is_ref()) x = x->e1;
17906: if (tt==x->tp || tt->check(x->tp,0)==0 || const_problem)
17907: return x;
17908: else
17909: return new cast(tt,x);
17910: }
17911: // else if (e1->base==DEREF && tt->is_ref()) return e1;
17912: break;
17913: }
17914: case VOID:
17915: if (tt->base == VOID) {
17916: tp = t;
17917: return this;
17918: }
17919: error("cast of void value");
17920: // no break;
17921: case ANY:
17922: any:
17923: tp = any_type;
17924: return this;
17925: case FCT:
17926: if (tt->base == PTR && Pptr(tt)->typ->base != FCT)
17927: error('w',"P toF cast toP to nonF");
17928: break;
17929: case OVERLOAD:
17930: over:
17931: error("cast of overloaded");
17932: goto any;
17933: }
17934:
17935: //error('d',"tt %t",tt);
17936: switch (tt->base) {
17937: case PTR:
17938: if (Pptr(tt)->typ->base==FCT && Pptr(tt)->memof) {
17939: if (etp->base!=PTR
17940: || Pptr(etp)->typ->base!=FCT
17941: || Pptr(etp)->memof==0)
17942: error("cast toP toM %t",tt);
17943: else { // adjust delta in MI case
17944: // for the moment just suppress the cast
17945: // all pmfs are the same to cc
17946: /*
17947: Pclass c1 = Pptr(tt)->memof;
17948: Pclass c2 = Pptr(etp)->memof;
17949: */
17950: ptom_cast = 1;
17951: tp2 = void_type;
17952: }
17953: }
17954:
17955: switch (etp->base) {
17956: case COBJ:
17957: error("cannot castCO toP");
17958: break;
17959: case FCT:
17960: e1 = new expr(G_ADDROF,0,e1);
17961: bound = b;
17962: e1 = e1->typ(tbl);
17963: bound = 0;
17964: if (e1->base == CAST)
17965: pmf = 1;
17966: else
17967: break;
17968: // no break;
17969:
17970: case PTR:
17971: { Pname cn = Pptr(tt)->typ->is_cl_obj();
17972: if (cn) {
17973: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
17974:
17975: if (x == e1) {
17976: PERM(tt);
17977: e1 = new cast(tt,e1);
17978: e1->i2 = i2;
17979: }
17980: else
17981: e1 = x;
17982: }
17983: if (pmf) {
17984: while(tt->base == TYPE)
17985: tt = Pbase(tt)->b_name->tp;
17986:
17987: switch (tt->base) {
17988: case PTR:
17989: if (Pptr(tt)->memof) break;
17990: default:
17991: error("%t cast to%t (%t is not aP toM)",e1->tp,tp2,tp2);
17992: }
17993: }
17994: }
17995: }
17996: break;
17997:
17998: case RPTR: // (x&)e: pretend e is an x
17999: { Ptype er = etp;
18000: Ptype cr = tt;
18001: do {
18002: if (er = er->is_ptr_or_ref()) er = Pptr(er)->typ;
18003: if (cr = cr->is_ptr_or_ref()) cr = Pptr(cr)->typ;
18004: } while (er && cr);
18005: int pp = er!=0; // if `e' is a suitable pointer cast it:
18006: // (x&)e => (x*)e, otherwise
18007: // (x&)e => *(x*)&e
18008: // error('d',"rptr tt %t e1->base %k e1->tp %t",tt,e1->base,e1->tp);
18009: // if (Pptr(tt)->typ->tsizeof()>etp->tsizeof()) goto zse;
18010: // we need to be able to ``raise the type'' from base to derived
18011: // if (etp->is_cl_obj() && Pptr(tt)->typ->is_cl_obj()==0) goto zse;
18012:
18013: if (e1->base==G_CM
18014: || e1->base==CALL
18015: || e1->base==G_CALL
18016: || e1->lval(0))
18017: ;
18018: else if (e1->tp->tconst()) {
18019: // casting away const
18020: // should be an error
18021: // but ANSI says OK so I chicken out
18022: // to be able to compile strtok(), etc.
18023: if (warning_opt && Pptr(tt)->typ->tconst()==0)
18024: error('w',"const cast away:%t->%t",e1->tp,tp2);
18025:
18026: }
18027: else
18028: error("cannot cast%t to%t",etp,t);
18029: //error('d',"e1 %k %t %d",e1->base,e1->tp,pp);
18030: if (pp == 0) e1 = e1->address(); // *(x*)&e
18031: tp = t;
18032:
18033: // do proper pointer manipulation for multiple inheritance
18034: Pname cn = Pptr(tt)->typ->is_cl_obj();
18035: if (cn) {
18036: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
18037:
18038: if (x == e1) {
18039: PERM(tt);
18040: e1 = new cast(tt,e1);
18041: e1->i2 = i2;
18042: }
18043: else
18044: e1 = x;
18045: }
18046:
18047: return pp ? this : contents();
18048: // zse:
18049: // error("cannot cast%t to%t",etp,t);
18050: // tp2 = tt = any_type;
18051: // break;
18052: }
18053: case COBJ:
18054: base = VALUE; // (x)e => x(e): construct an x from e
18055: e1 = new expr(ELIST,e1,0);
18056: return typ(tbl);
18057:
18058: case CHAR:
18059: case INT:
18060: case SHORT:
18061: case LONG:
18062: switch (etp->base) {
18063: case FCT:
18064: e1 = new expr(ADDROF,0,e1);
18065: e1 = e1->typ(tbl);
18066: //etp = e1->tp;
18067: case PTR:
18068: if(!e1->tp->memptr() && e1->tp->tsizeof()>tt->tsizeof())
18069: error("type ``%t'' not large enough for values of ``%t ''",tt,etp);
18070: break;
18071: case COBJ:
18072: error("cannot castCO to%k",tt->base);
18073: break;
18074: }
18075: break;
18076:
18077: case FLOAT:
18078: case DOUBLE:
18079: case LDOUBLE:
18080: switch (etp->base) {
18081: case FLOAT:
18082: case DOUBLE:
18083: case LDOUBLE:
18084: case CHAR:
18085: case INT:
18086: case SHORT:
18087: case LONG:
18088: case EOBJ:
18089: case ZTYPE:
18090: break;
18091: default:
18092: error("cannot cast ``%t '' to ``%t''",etp,tt);
18093: break;
18094: }
18095: break;
18096:
18097: case FCT:
18098: error("cannot cast toFT");
18099: break;
18100: }
18101:
18102: tp = t;
18103:
18104: if (e1->base==ILIST && ptom_cast==0) { // pointer to member constant
18105: Pexpr ee = e1->e1; // ELIST
18106: int i;
18107: switch (ee->e2->base) {
18108: case IVAL:
18109: i = int(ee->e2->i1);
18110: break;
18111: case ZERO:
18112: i = 0;
18113: }
18114:
18115: if (i<0)
18116: e1 = e1->e2; // just the function
18117: else
18118: e1 = ee->e2; // just the index
18119: return this;
18120: }
18121:
18122: if (etp->base==PTR && Pptr(etp)->memof && Pptr(etp)->typ->base==FCT) {
18123: Pclass cl = Pptr(etp)->memof;
18124:
18125: if (Pptr(tt)->memof==0 && b == 0 ) {
18126: Pexpr y = new mdot("f",e1);
18127: y->i1 = 9;
18128: y = new cast(tt,y);
18129: if (cl->virt_count && b==0) {
18130: // ERROR: no check for side effects
18131: Pexpr z = new mdot("i",e1);
18132: Pexpr x = new mdot("i",e1);
18133: x->i1 = 9;
18134: x = new cast(tt,x);
18135: z->i1 = 9;
18136: Pexpr q = new expr (QUEST,x,y);
18137: q->cond = new expr(LE,zero,z);
18138: q->tp = tt;
18139: delete this;
18140: return q;
18141: }
18142: delete this;
18143: return y;
18144: }
18145: }
18146:
18147: return this;
18148: }
18149:
18150: Pexpr expr::dovalue(Ptable tbl)
18151: {
18152: Ptype tt = tp2;
18153: Pclass cl;
18154: Pname cn;
18155:
18156: //error('d',"value %d %t e1 %d e2 %d",tt,tt,e1,e2);
18157:
18158: tt->dcl(tbl);
18159:
18160: while(tt->base == TYPE)
18161: tt = Pbase(tt)->b_name->tp;
18162:
18163: switch (tt->base) {
18164: case EOBJ:
18165: default:
18166: if (e1 == 0) {
18167: error("value missing in conversion to%t",tt);
18168: return dummy;
18169: }
18170: base = CAST;
18171: e1 = e1->e1; // strip ELIST
18172: return typ(tbl);
18173:
18174: case CLASS:
18175: cl = Pclass(tt);
18176: tp2 = Pptr(cl->this_type)->typ;
18177: break;
18178:
18179: case COBJ:
18180: cn = Pbase(tt)->b_name;
18181: cl = Pclass(cn->tp);
18182: }
18183:
18184: //error('d',"e1 %k e1->e2 %k",e1->base,e1?e1->e2->base:0);
18185: if (e1 && e1->e2==0) { // single argument
18186: if (e1->e1->base==ELIST) e1->e1 = e1->e1->e1; // spurious elist
18187: e1->e1 = e1->e1->typ(tbl);
18188: if (tt->base==COBJ) {
18189: Pexpr x = try_to_coerce(tt,e1->e1,"type conversion",tbl);
18190: if (x) return x;
18191: }
18192:
18193: Pname acn = e1->e1->tp->is_cl_obj();
18194: //error('d',"acn %n %d",acn,cl->has_itor());
18195: if (acn && cl->has_itor()==0) {
18196: Pclass acl = Pclass(acn->tp);
18197: int hb = acl->has_base(cl);
18198:
18199: if (acl==cl || hb) {
18200: vcllist->clear();
18201: vcllist=0;
18202: if (1<is_unique_base(acl,cl->string,0)) error("ambiguous assignment to base %t",cl);
18203: Pexpr ee = e1->e1;
18204: if (ee->base == ELIST) ee = ee->e1; // ???
18205: if (hb) { // ee => *(tp2*)&ee
18206: // remember = may be overloaded
18207: //error('d',"hb %k %t %d",ee->base,ee->tp,ee->lval(0));
18208: ignore_const++;
18209: if (ee->lval(0)==0) {
18210: Pname tmp = make_tmp('T',ee->tp,tbl);
18211: ee = init_tmp(tmp,ee,tbl);
18212: ee = new expr(G_CM,ee,tmp->address());
18213: }
18214: else
18215: ee = ee->address();
18216: ignore_const--;
18217: ee = new texpr(CAST,new ptr(PTR,tp2),ee); //new cast(new ptr(PTR,tp2),ee);
18218: ee = ee->contents();
18219: ee->typ(tbl);
18220: }
18221:
18222: if (e2) { // x(x_obj) => e2=x_obj
18223: base = ASSIGN;
18224: e1 = e2;
18225: e2 = ee;
18226: tp = tp2;
18227: return this;
18228: }
18229: return ee; // strip ELIST: x(x_obj) => x_obj
18230: }
18231: }
18232: }
18233:
18234:
18235: /* x(a) => obj.ctor(a); where e1==obj */
18236: Pname ctor = cl->has_ctor();
18237: if (ctor == 0) {
18238: error("cannot make a%t",cl);
18239: return dummy;
18240: }
18241:
18242: // error('d',"e2 %k",e2?e2->base:0);
18243: // error('d',"refd: %d const_ptr: %d", refd, const_ptr);
18244: if (e2 == 0) { // x(a) => x temp; (temp.x(a),temp)
18245: /* incomplete condition
18246: if ( refd && const_ptr == 0) {
18247: if ( tbl == gtbl ) {
18248: error("Ir forG non-constCR not an lvalue");
18249: }
18250: else
18251: if (strict_opt)
18252: error("Ir for non-constCR not an lvalue");
18253: else
18254: if (warning_opt)
18255: error('w', "Ir for non-constR not an lvalue (anachronism)");
18256: }
18257: */
18258:
18259: no_sti = 1;
18260: Pname n = make_tmp('V',tp2,tbl);
18261: no_sti = 0;
18262: n->assign();
18263: if (tbl == gtbl) n->dcl_print(0); // a hack
18264: Pexpr c = call_ctor(tbl,n,ctor,e1,DOT);
18265: c = new expr(G_CM,c,n);
18266: c->tp = n->tp;
18267: //error('d',"tp1 %t",c->tp);
18268: return c;
18269: }
18270: else {
18271: Pexpr c = call_ctor(tbl,e2,ctor,e1,DOT);
18272: c = new expr(DEREF,c,0); // deref value returned by constructor
18273: c->tp = c->e1->tp;
18274: //error('d',"tp2 %t",c->tp);
18275: return c;
18276: }
18277: }
18278:
18279: 0707071010112044311004440001630000160000010201300466055402500000700000074341find.c /*ident "@(#)ctrans:src/find.c 1.5" */
18280: /******************************************************************
18281:
18282: C++ source for cfront, the C++ compiler front-end
18283: written in the computer science research center of Bell Labs
18284:
18285: Copyright (c) 1986 AT&T, Inc. All Rights Reserved
18286: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
18287:
18288: find.c:
18289:
18290: name lookup and visibility checks
18291:
18292: *******************************************************************/
18293:
18294: #include "cfront.h"
18295:
18296: Pname undef(Pname n, Ptable tbl, TOK f)
18297: {
18298: switch (f) {
18299: case CCON:
18300: error("illegalF call: explicit call ofK %s()",n->string);
18301: break;
18302: case 0: error("%nU",n); break;
18303: case CALL: error("UF%n called",n); break;
18304: case REF:
18305: case DOT: error("M%nU",n); break;
18306: case ADDROF: error("address ofU%n",n); break;
18307: }
18308:
18309: if (tbl == gtbl) {
18310: Pname nn = tbl->insert(n,0);
18311: if (f == CALL) {
18312: nn->tp = new fct(defa_type,0,0);
18313: nn->n_sto = nn->n_scope = EXTERN;
18314: }
18315: else
18316: nn->tp = any_type;
18317: delete n;
18318: return nn;
18319: }
18320:
18321: n->n_table = tbl;
18322: n->tp = any_type;
18323: return n;
18324: }
18325:
18326:
18327:
18328: static int mptr; // &C::m
18329: static Pname me; // name of fct requesting access to name using find_name()
18330: static Pfct mef; // fct requesting access to name using find_name()
18331: Pclass tcl; // class of original ``this''
18332: Pclass mec; // class requesting access to name using find_name()
18333: int mex;
18334:
18335: Ptable lcl_tbl = 0; // handle local function reference of local const for dimen size
18336:
18337:
18338: Pexpr find_name(Pname n, Pclass cl, Ptable tbl, int f, Pname m)
18339: /*
18340: in function ``m'' find the true name for "n",
18341: implicitly define if undefined
18342:
18343: f==CALL: n() cl == cc->cot
18344: f==REF: p->n cl == class of *p
18345: f==DOT: obj.n cl == class of obj
18346: f==ADDROF: &n cl == cc->cot
18347: f==0 n (none of the above)
18348:
18349: "tbl" defines local scope (block or global)
18350:
18351: */
18352: {
18353: if ( n == 0 ) error('i',"find_name(n==0,cl==%t,tbl==%d,f==%k,m==%n)",cl,tbl,f,m);
18354: Pname q = n->n_qualifier;
18355: char* s = n->string;
18356: Pexpr ee;
18357: DB( if(Ddebug>=3) {
18358: error('d',"find_name %s::%s cl %t",q?q->string:"",s,cl);
18359: error('d'," f %d m %n",f,m);
18360: if(q&&q->tp&&q->tp->base==COBJ)
18361: fprintf(stderr," -- cb==%d\n",Pclass(q->tp)->c_body);
18362: });
18363:
18364: tcl = cl;
18365:
18366: //if (n) {
18367: mex = 1;
18368: if (me = m) {
18369: mef = Pfct(me->tp);
18370: if (mef->base!=FCT)
18371: error('i',"mef %d %k",mef,mef->base);
18372: mec = mef->memof;
18373: }
18374: else {
18375: mef = 0;
18376: mec = cl;
18377: }
18378: //}
18379: //else
18380: // mex = 0;
18381:
18382: if (n->base == MDOT) error('i',"find (mdot %n)",n);
18383:
18384: if (n->n_table) { me = 0; return n; }
18385:
18386: //error('d',"q %n %t f %k",q,q?q->tp:0,f);
18387: if (q) { // qualified name: q::s
18388:
18389: if (q == sta_name) { // explicitly global: ::s
18390: Pname nn = gtbl->look(s,0);
18391: if (nn == 0) { me = 0; return undef(n,gtbl,f); }
18392: nn->use();
18393: delete n;
18394: me = 0;
18395: return nn;
18396: }
18397:
18398: {
18399: Pname aq = q; // actual q
18400: while ( aq->tp->base == TYPE ) aq = Pbase(aq->tp)->b_name;
18401: if (aq->tp->base != COBJ) {
18402: error("Qr%nnot aCN",q);
18403: me = 0;
18404: return undef(n,gtbl,f);
18405: }
18406: q = aq;
18407: }
18408: Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
18409:
18410: Pclass bcl = cl;
18411:
18412: if (cl==0 || f==ADDROF)
18413: bcl = cl = qcl; // Pclass(Pbase(q->tp)->b_name->tp);
18414: else {
18415: // if (strcmp(q->string,cl->string)) { // really a base?
18416: // bcl = cl->is_base(q->string);
18417: if (strcmp(qcl->string,cl->string)) { // really a base?
18418: bcl = cl->is_base(qcl->string);
18419: if (bcl == 0) {
18420: if (f==REF || f==DOT) {
18421: error("%s is not aBC of %t",q->string,cl);
18422: me = 0;
18423: return undef(n,cl->memtbl,7);
18424: }
18425: goto sss;
18426: }
18427: // else try in base or for static
18428: }
18429: }
18430:
18431: if (f == ADDROF) mptr = 1; // &C::m
18432: ee = cl->find_name(s,bcl==cl?0:bcl); // really a member?
18433: mptr = 0;
18434:
18435: if (ee == 0) {
18436: sss:
18437: //error('d',"sss %k",f);
18438: if (f!=REF && f!=DOT) {
18439: // try for static member of other class:
18440: Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
18441: mptr = 1;
18442: if ( cl && cl->csu == ANON ) {
18443: mec = (cc-1)->cot;
18444: ee = qcl->find_name(s,qcl);
18445: } else
18446: ee = qcl->find_name(s,qcl);
18447: mptr = 0;
18448: if (ee && ee->base==NAME) {
18449: // switch (ee->tp->base) {
18450: // case FCT:
18451: // case OVERLOAD:
18452: // break;
18453: // default:
18454: delete n;
18455: me = 0;
18456: return ee;
18457: // }
18458: }
18459: }
18460: error("QdN%n::%n not found in %t",q,n,cl);
18461: me = 0;
18462: return undef(n,bcl?bcl->memtbl:cl->memtbl,7);
18463: }
18464:
18465: if (ee->base==REF && ee->e1==0) { // &C::f, no ``this''
18466: //error('d',"ee %k %d f %k",ee->base,ee->e1,f);
18467: switch (f) {
18468: case 0:
18469: case CALL: //SSS
18470: { Pexpr mm = ee->mem;
18471: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
18472: if (mm->base==NAME)
18473: switch (mm->tp->base) {
18474: case FCT:
18475: case OVERLOAD:
18476: goto addrof;
18477: default:
18478: if (Pname(mm)->n_stclass == STATIC) goto addrof;
18479: }
18480: }
18481: error("O orOP missing forM%n",n);
18482:
18483: case ADDROF:
18484: addrof:
18485: Pexpr x = ee;
18486: ee = ee->mem;
18487: delete x;
18488: case REF:
18489: case DOT:
18490: break;
18491: default:
18492: error("QdN%n::%n used in nonC context",q,n);
18493: }
18494: }
18495:
18496: delete n;
18497: me = 0;
18498: return ee;
18499: }
18500:
18501: if (f!=DOT && f!=REF) { // not .s or ->s: look for local, global, and member
18502:
18503: Pname nn = tbl->look(s,0);
18504: if (nn) { // local, global, or member
18505: if (nn->n_table->t_name) { // global or member
18506: if (cl) { // might be member
18507: if ((ee = cl->find_name(s,0))==0 &&
18508: cl->in_class)
18509: { // nested class
18510: Pclass nstd_cl = cl->in_class;
18511: for (; nstd_cl; nstd_cl=nstd_cl->in_class)
18512: {
18513: // error( 'd', "find_name( %s ): nested class %t",s,nstd_cl );
18514: if (ee=nstd_cl->find_name(s,0))
18515: {
18516: if ( cl->nested_sig == 0 ) {
18517: error('w',"%s, accessed within nestedC%t, is visible bothGly and within enclosingC%t -- using %n (anachronism)", s, cl, nstd_cl, nn );
18518: ee = 0;
18519: }
18520: break;
18521: }
18522: }
18523: } // nested class
18524:
18525: if ( ee )
18526: { // class member name
18527: if (ee->base==REF && ee->e1==0 )
18528: {
18529: Pexpr mm = ee->mem;
18530: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
18531: if (mm->base==NAME)
18532: switch (mm->tp->base) {
18533: default:
18534: if (Pname(mm)->n_stclass != STATIC)
18535: break;
18536: case FCT:
18537: case OVERLOAD:
18538: delete n;
18539: me = 0;
18540: return mm;
18541: }
18542: error("O orOP missing for%n",Pref(ee)->mem);
18543: }
18544: delete n;
18545: me = 0;
18546: return ee;
18547: } // if ee
18548: } // if cl
18549: } // else local, global, or member
18550:
18551: nn->use();
18552: delete n;
18553: me = 0;
18554: return nn;
18555: }
18556:
18557: if (cl) {
18558: if ( cl->csu == ANON ) {
18559: mec = (cc-1)->cot;
18560: ee = (cc-1)->cot->find_name(s,0);
18561: } else
18562: ee = cl->find_name(s,0);
18563: if (ee) {
18564: if (ee->base==REF && ee->e1==0) {
18565: Pexpr mm = ee->mem;
18566: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
18567: if (mm->base==NAME)
18568: switch (mm->tp->base) {
18569: default:
18570: if (Pname(mm)->n_stclass != STATIC)
18571: break;
18572: case FCT:
18573: case OVERLOAD:
18574: delete n;
18575: me = 0;
18576: return mm;
18577:
18578: }
18579: error("O orOP missing for%n",Pref(ee)->mem);
18580: }
18581: delete n;
18582: me = 0;
18583: return ee;
18584: }
18585: }
18586:
18587: if ( lcl_tbl && (nn=lcl_tbl->look(s,0)) ) {
18588: nn->use();
18589: delete n;
18590: me = 0;
18591: return nn;
18592: }
18593:
18594: if (nn = gtbl->look(s,0)) { // global
18595: nn->use();
18596: delete n;
18597: me = 0;
18598: return nn;
18599: }
18600:
18601: me = 0;
18602: return undef(n,gtbl,f);
18603: }
18604:
18605: if (ee = cl->find_name(s,cl)) { // .s or ->s
18606: delete n;
18607: me = 0;
18608: return ee;
18609: }
18610:
18611: if(!strcmp(s,cl->string)) {
18612: me = 0;
18613: return undef(n,gtbl,CCON);
18614: }
18615:
18616: me = 0;
18617: return undef(n,gtbl,f);
18618: }
18619:
18620: int classdef::check_dup(Pclass cl, TOK bb)
18621: /*
18622: see if cl is a base of this; return 0 if no clash
18623: */
18624: {
18625: for (Pbcl b = baselist; b; b=b->next) {
18626: if (cl == b->bclass) {
18627: if (bb!=VIRTUAL) {
18628: if (b->base==VIRTUAL)
18629: error('w',"%t inaccessible because of virtual%t in%t",cl,cl,this);
18630: else
18631: error('w',"%t inaccessible because of%t in%t",cl,cl,this);
18632: return 1;
18633: }
18634: else if (b->base!=VIRTUAL) {
18635: error('w',"virtual %t inaccessible because of%t in%t",cl,cl,this);
18636: return 1;
18637: }
18638: }
18639: if (b->bclass->check_dup(cl,bb)) return 1;
18640: }
18641: return 0;
18642: }
18643:
18644:
18645: int Nvis;
18646: TOK Nvirt;
18647: TOK ppbase;
18648:
18649: Pclass classdef::is_base(char* s)
18650: /*
18651: is "s" a public base class of this?
18652: */
18653: {
18654: //error('d',"%s->is_base(%s) %k",string,s,ppbase);
18655: TOK pp = ppbase;
18656: for (Pbcl b = baselist; b; b=b->next) {
18657: /*
18658: if (b->ppp!=PUBLIC
18659: && cc->cot!=this
18660: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
18661: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
18662: */
18663: if (strcmp(s,b->bclass->string) == 0) {
18664: if (b->ppp!=PUBLIC
18665: && cc->cot!=this
18666: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
18667: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
18668: Nvirt = b->base;
18669: return b->bclass;
18670: }
18671: else {
18672: Pclass bc = b->bclass->is_base(s);
18673: if (bc) {
18674: if (b->ppp!=PUBLIC
18675: && cc->cot!=this
18676: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
18677: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
18678: return bc;
18679: }
18680: }
18681: }
18682: ppbase = pp;
18683: return 0;
18684: }
18685:
18686: bit classdef::has_base(Pclass cl)
18687: /*
18688: is "cl" a base of this?
18689: */
18690: {
18691: // error('d', "%t->has_base( %t ) cc->cot: %t", this, cl, cc->cot?cc->cot:0 );
18692:
18693: if (this == 0) return 0;
18694: for (Pbcl b = baselist; b; b=b->next) {
18695: // error('d', "b: %t ppp: %k", b->bclass, b->ppp );
18696: if (b->bclass==cl) {
18697: if (b->ppp!=PUBLIC
18698: && cc->cot!=this
18699: && (cc->nof==0 ||
18700: this->has_friend(Pfct(cc->nof->tp))==0)
18701: && this->has_friend(cc->cot)==0)
18702: Nvis = 1; // no standard coercion
18703: Nvirt = b->base;
18704: return 1;
18705: }
18706: if (b->bclass->has_base(cl)) return 1;
18707: }
18708: return 0;
18709: }
18710:
18711: int Noffset;
18712: Pexpr Nptr;
18713: char *Nalloc_base;
18714: clist* vcllist;
18715:
18716: int clist::onlist(Pclass c)
18717: {
18718: for (clist* p = this; p; p = p->next)
18719: if (p->cl == c) return 1;
18720: return 0;
18721: }
18722:
18723: void clist::clear()
18724: {
18725: if (this == 0) return;
18726: clist* p = next;
18727: while (p) {
18728: clist* q = p->next;
18729: delete p;
18730: p = q;
18731: };
18732: delete this;
18733: }
18734:
18735: Pbcl Nvbc_alloc;
18736: int is_unique_base(Pclass cl, char* s, int offset, int in_base )
18737: /*
18738: is "s" a unique base class of this?
18739: */
18740: {
18741: int i = 0;
18742: static Pclass priSeen = 0;
18743: // error('d',"is_unique_base(cl: %t, s: %s,%d,%d)",cl,s,offset,in_base);
18744: for (Pbcl b = cl->baselist; b; b=b->next) {
18745: int no = 0;
18746: if (b->base!=VIRTUAL)
18747: no = offset + b->obj_offset;
18748: else if (in_base)
18749: continue;
18750: if (strcmp(s,b->bclass->string) == 0) {
18751: Noffset = no;
18752: i++;
18753: if ((b->ppp!=PUBLIC || priSeen )
18754: && (cc->cot!=cl || cc->cot != priSeen )
18755: && (cc->nof==0 || cl->has_friend(Pfct(cc->nof->tp))==0)
18756: || (priSeen && priSeen->has_friend(Pfct(cc->nof->tp))==0))
18757: Nvis = 1; // no standard coercion
18758:
18759: if (b->base==VIRTUAL) {
18760: Nptr = new mdot(s,0);
18761: if (b->allocated == 0) {
18762: Nvbc_alloc = 0;
18763: Nalloc_base = cl->has_allocated_base(s);
18764: }
18765: }
18766: }
18767: else {
18768: if (b->base==VIRTUAL) {
18769: if (vcllist->onlist(b->bclass) )continue;
18770: vcllist = new clist(b->bclass,vcllist);
18771: }
18772:
18773: Pclass clscope = 0;
18774: if ( cc && cc->c_this ) {
18775: Ptype t = Pptr(cc->c_this->tp)->typ;
18776: clscope = Pclass(Pbase(t)->b_name->tp);
18777: }
18778: // error('d', "cl: %t %d clscope: %t %d", cl, cl, clscope, clscope);
18779: if (b->ppp != PUBLIC &&
18780: cl != clscope && priSeen == 0 ) priSeen = cl;
18781:
18782: int ii = is_unique_base(b->bclass,s,no,1);
18783: if (in_base == 0) priSeen = 0;
18784: // error('d',"base %t i %d ii %d",b->bclass,i,ii);
18785: // error('d',"base %t %k allocated: %d", b->bclass, b->base, b->allocated);
18786: i += ii;
18787: if (ii==1 && b->base==VIRTUAL) {
18788: Nptr = new mdot(b->bclass->string,0);
18789: if (b->allocated == 0) {
18790: Nvbc_alloc = 0;
18791: Nalloc_base = cl->has_allocated_base(b->bclass->string);
18792: }
18793: }
18794: }
18795: }
18796:
18797: return i;
18798: }
18799:
18800: /*
18801: int classdef::has_allocated_base(Pclass bcl)
18802:
18803: search the list of !first base classes for this virtual base
18804: space will have been allocated in !first bases for virtual bases
18805: declared in !first classes
18806:
18807: in addition bcl may bave been specified explicitly as a base
18808:
18809: {
18810: int off;
18811: for (Pbcl l = baselist; l; l=l->next) {
18812: if (l->base == VIRTUAL) continue; // another non-allocated virtual base
18813: if (l==baselist) continue; // first base
18814:
18815: Pclass bc = l->bclass;
18816: off = l->obj_offset;
18817:
18818: for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
18819: // cannot share non-virtual base
18820: if (ll->base != VIRTUAL) continue;
18821: if (ll->bclass==bcl) return off + ll->obj_offset;
18822: }
18823: }
18824: return 0;
18825: }
18826: */
18827:
18828: int classdef::has_allocated_base(Pclass bcl)
18829: /*
18830: search the list of base classes for this virtual base
18831: space will be allocated in first virtual version found.
18832: return offset.
18833:
18834: A virtual base cannot have offset 0 (its pointer at least is ahead)
18835: */
18836: {
18837: //error('d',"%t->has_allocated_base(%t) ",this,bcl);
18838: for (Pbcl l = baselist; l; l=l->next) {
18839: if (l->base==VIRTUAL
18840: && l->bclass==bcl
18841: && l->obj_offset)
18842: return l->obj_offset;
18843:
18844: if (l->base==VIRTUAL || l!=baselist) {
18845: // allocated as an object,
18846: // not unravelled as a set of members
18847: int i = l->bclass->has_allocated_base(bcl);
18848: if (i) return l->obj_offset + i;
18849: }
18850: }
18851: return 0;
18852: }
18853:
18854: char *classdef::has_allocated_base(char *str)
18855: /*
18856: * str is an unallocated virtual base class of this
18857: * return the name of the second or subsequent base class
18858: * containing the member ``struct str *P<str>''
18859: */
18860: {
18861: // error('d',"%t::has_allocated_base(%s) baselist: %t",this,str,baselist->bclass);
18862: for (Pbcl l = baselist; l; l=l->next) {
18863: if (l->base == VIRTUAL) {
18864: if ( l->allocated ) Nvbc_alloc = l;
18865: continue;
18866: }
18867:
18868: Pclass bc = l->bclass;
18869: for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
18870: if (ll->base != VIRTUAL) continue;
18871: if (ll->allocated &&
18872: strcmp( str, ll->bclass->string) == 0 )
18873: {
18874: if (bc == baselist->bclass) {
18875: // NfirstBase=1;
18876: return 0;
18877: }
18878: return bc->string;
18879: }
18880: }
18881: }
18882: return 0;
18883: }
18884:
18885: /*
18886: int allocated_base(Pclass cl,Pclass bcl)
18887: {
18888: static second;
18889: int s2 = second;
18890: for (Pbcl l = cl->baselist; l; l=l->next) {
18891: if (l->base==VIRTUAL
18892: && l->bclass==bcl
18893: && l->obj_offset
18894: && (second || l!=cl->baselist)) return (second=s2,1);
18895: int i = allocated_base(l->bclass,bcl);
18896: if (i) return (second=s2,1);
18897: second = 1;
18898: }
18899: second = s2;
18900: return 0;
18901: }
18902: */
18903: Pname vfct(Pclass cl, char* s)
18904: /*
18905: Called for each name "s" in a vtbl for "cl"
18906: Find the "s" to go in the vtbl.
18907: The "s" that caused the vtbl entry to be created
18908: is found if nothing else is
18909: */
18910: {
18911: Pname n = cl->memtbl->look(s,0);
18912: if (n) return n;
18913:
18914: for (Pbcl b = cl->baselist; b; b=b->next) {
18915: Pname nn = vfct(b->bclass,s);
18916: if (nn) {
18917: //error('d',"nn %nn",nn);
18918: if (n && n!=nn) {
18919: Pclass ncl = Pclass(n->n_table->t_name->tp);
18920: Pclass nncl = Pclass(nn->n_table->t_name->tp);
18921: //error('d',"ncl %t nncl %t",ncl,nncl);
18922: if (nncl->is_base(ncl->string))
18923: n = nn; // use nn
18924: }
18925: else
18926: n = nn;
18927: }
18928: }
18929:
18930: return n;
18931: }
18932:
18933: Pexpr rptr(Ptype t, Pexpr p, int offset)
18934: /*
18935: return rvalue of offset off pointer:
18936: (t)((char*)p+offset)
18937: */
18938: {
18939: if ( t == 0 ) error( 'i', "rptr(), t==0 (type passed for cast)" );
18940: Pexpr pp = p;
18941: //error('d',"rptr %t %d",t,offset);
18942: if (offset) {
18943: Pexpr i = new ival(offset);
18944: // pp = new texpr(CAST,Pchar_type,pp);
18945: pp = new cast(Pchar_type,pp);
18946: pp = new expr(PLUS,pp,i);
18947: }
18948: pp = new cast(t,pp);
18949: return pp;
18950: }
18951: /*
18952: Pexpr lptr(Ptype t, Pexpr p, int offset)
18953:
18954: return lvalue of offset off pointer:
18955: *(t*)((char*)p+offset)
18956:
18957: {
18958: Pexpr pp = p;
18959: if (offset) {
18960: Pexpr i = new ival(offset);
18961: // pp = new texpr(CAST,Pchar_type,pp);
18962: pp = new cast(Pchar_type,pp);
18963: pp = new expr(PLUS,pp,i);
18964: }
18965: pp = new cast(t->addrof(),pp);
18966: pp = new expr(DEREF,pp,0);
18967: pp->tp = t;
18968: return pp;
18969: }
18970: */
18971: int friend_check(Pclass start,Pclass stop, Pfct f)
18972: /*
18973: is `f' a friend of a class between `start' and `stop'
18974: in a class DAG?
18975: */
18976: {
18977: //error('d',"friend_check(%t,%t)",start,stop);
18978:
18979: if (start->has_friend(f)) return 1;
18980: if (stop == start) return 0;
18981: for (Pbcl b = start->baselist; b; b = b->next) {
18982: if (b->bclass->has_friend(f)) return 1;
18983: if (friend_check(b->bclass,stop,f)) return 1;
18984: }
18985: return 0;
18986: }
18987:
18988: bit classdef::has_friend(Pfct f)
18989: /*
18990: does this class have function "f" as its friend?
18991: */
18992: {
18993: // error('d',"%t->has_friend(%t) %d %d ",this,f,f,f->base);
18994:
18995: for (Plist l=friend_list; l; l=l->l) {
18996: Pname fr = l->f;
18997: Ptype frt = fr->tp;
18998: //error('d',"frt %t %d %d",frt,frt,frt->base);
18999: switch (frt->base) {
19000: case FCT:
19001: if (f == frt) return 1;
19002: break;
19003: case OVERLOAD:
19004: l->f = fr = Pgen(frt)->fct_list->f; // first fct
19005: if (fr->tp == f) return 1;
19006: case CLASS:
19007: break;
19008: default:
19009: error('i',"bad friend %k",fr->tp->base);
19010: }
19011: }
19012: return 0;
19013: }
19014:
19015: bit classdef::has_friend(Pclass cl)
19016: /*
19017: does this class have class "cl" as its friend?
19018: */
19019: {
19020: // error('d',"%t->has_friend(%t) ",this,cl);
19021:
19022: for (Plist l=friend_list; l; l=l->l) {
19023: Pname fr = l->f;
19024: Ptype frt = fr->tp;
19025: switch (frt->base) {
19026: case CLASS:
19027: // error('d',"class friend: %t", frt);
19028: if ((frt == cl) || cl->same_class(Pclass(frt)))
19029: return 1;
19030: case FCT:
19031: case OVERLOAD:
19032: break;
19033: default:
19034: {error('i',"bad friend %k",frt->base);}
19035: }
19036: }
19037: return 0;
19038: }
19039:
19040: Pname find_virtual(Pclass cl, Pname s)
19041: /*
19042: does ``cl'' have a virtual function ``s'' in some base class
19043: */
19044: {
19045: for (Pbcl b = cl->baselist; b; b = b->next) {
19046: Pclass bcl = b->bclass;
19047: Pname n;
19048: if (n = bcl->memtbl->look(s->string,0)) {
19049: // error('d', "find_virtual: n: %d base: %k", n, n->base );
19050: if ( n->base == PUBLIC ) // x::foo;
19051: continue;
19052: Pfct f = Pfct(n->tp);
19053: if (f->base == OVERLOAD) {
19054: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
19055: n = gl->f;
19056: // if (f != s->tp) continue;
19057: // Replaced by:
19058: if (n->tp->check(s->tp,VIRTUAL)) continue;
19059: if (Pfct(n->tp)->f_virtual) return n;
19060: }
19061: }
19062: // else if (f->f_virtual)
19063: else if (f->f_virtual && n->tp->check(s->tp,VIRTUAL)==0)
19064: return n;
19065: }
19066: else if (n = find_virtual(bcl,s))
19067: return n;
19068: }
19069: return 0;
19070: }
19071:
19072: Pname dummy_fct;
19073:
19074: static int
19075: is_accessible(Pname n, Pclass this_class, bit noCdcl = 0)
19076: // 0 means n is not accessible to this_class
19077: {
19078: // error('d',"is_accessible(%n,%t)", n, this_class
19079: // error('d',"%n: %k mef %t",n,n->n_protect,mef);
19080: // error('d'," this_class %d %t",this_class,this_class);
19081: // error('d'," mec %d %t",mec,mec);
19082: // error('d'," tcl %d %t",tcl,tcl);
19083: // error('d',"mec->has_base(this_class) %d",mec?mec->has_base(this_class):0);
19084: // error('d',"tcl->has_base(mec) %d",tcl?tcl->has_base(mec):0);
19085: // error('d',"tcl->has_base(this_class) %d",tcl?tcl->has_base(this_class):0);
19086: // error('d',"tcl->has_friend(mef) %d",tcl?tcl->has_friend(mef):0);
19087:
19088: if (this_class==mec ||
19089: (mec && this_class->has_friend(mec)) ||
19090: (mef && this_class->has_friend(mef)))
19091: return 1;
19092:
19093: if ( n->n_protect && tcl ) {
19094: if ( mec )
19095: {
19096: if ( tcl->has_friend(mec) ||
19097: ( mec->has_base(this_class) &&
19098: (tcl==mec || tcl->has_base(mec))))
19099: return 1;
19100: }
19101:
19102: if ( mef )
19103: {
19104: if ( tcl->has_base(this_class) &&
19105: // && tcl->has_friend(mef))
19106: friend_check(tcl,this_class,mef))
19107: return 1;
19108: }
19109: }
19110:
19111: // call from check_visibility
19112: if ( noCdcl ) return 0;
19113:
19114: if ( Cdcl && Cdcl->base == NAME &&
19115: Cdcl->n_stclass == STATIC &&
19116: Cdcl->n_initializer &&
19117: Cdcl->n_qualifier )
19118: {
19119: Pbase bn = Pbase(Cdcl->n_qualifier->tp);
19120: Pclass cl = Pclass(bn->b_name->tp);
19121:
19122: if ( cl == this_class ||
19123: (n->n_protect && cl->has_base(this_class)) ||
19124: cl->has_friend(this_class))
19125: return 1;
19126: }
19127:
19128: return 0;
19129: }
19130:
19131: Pexpr classdef::find_name(char* s, Pclass cl, int access_only)
19132: /*
19133: look for "s" in "this" class and its base classes
19134: if (cl)
19135: accept only a member of "cl" or "cl"'s base classes
19136: (that is cl::s was seen)
19137:
19138: complicated by hiding rules: private, protected, friend
19139:
19140: */
19141: {
19142: // error('d',"%s->find_name(%s,%s) memtbl %d",string,s,cl?cl->string:"",memtbl);
19143: Pname n = memtbl->look(s,0);
19144:
19145: if (n) {
19146: if (n->tp) {
19147: switch (n->tp->base) {
19148: case OVERLOAD:
19149: break;
19150: case FCT:
19151: if (Pfct(n->tp)->f_virtual==0) {
19152: if (n->n_dcl_printed==0) n->dcl_print(0);
19153: break;
19154: }
19155: default:
19156: if (c_body==1) dcl_print(0);
19157: }
19158: }
19159:
19160: if (n->base == PUBLIC) {
19161: if (mex && n->n_scope==0) {
19162: if ( is_accessible(n,this) == 0 )
19163: {
19164: if ( me == dummy_fct )
19165: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
19166: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
19167: mex = 0; // suppress further error messages
19168: }
19169: }
19170: mex = 0; // don't have find_in_base complain about n
19171: return find_in_base(s, cl);
19172: }
19173:
19174: if (cl==0 || cl==this) {
19175: if (mptr==0
19176: && n->n_stclass!=STATIC
19177: && n->n_stclass!=ENUM) {
19178: Ptype t = n->tp;
19179:
19180: // error('d',"cl %d this %d",cl,this);
19181:
19182: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
19183: if ( is_accessible(n,this)==0 )
19184: {
19185: if ( me == dummy_fct )
19186: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
19187: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
19188: mex = 0; // suppress further error messages
19189: }
19190: }
19191:
19192: Pname th = cc->c_this;
19193: Pexpr r = new ref(REF,th,n);
19194:
19195: if ( access_only == 0 ) {
19196: if (th) th->use();
19197: n->use();
19198: }
19199: r->tp = t;
19200: return r;
19201: }
19202:
19203: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
19204: if ( is_accessible(n,this)==0 )
19205: {
19206: if ( me == dummy_fct )
19207: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
19208: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
19209: mex = 0; // suppress further error messages
19210: }
19211: }
19212: n->use();
19213: return n;
19214: }
19215: }
19216:
19217: if ((cl==0 || cl==this) // not qualified to a base class
19218: && csu!=UNION
19219: && csu!=ANON
19220: && strcmp(s,"__as")==0) { // assignment is special: you cannot inherit it
19221: if (baselist==0
19222: || (baselist && baselist->bclass->obj_size!=obj_size)) {
19223: Pname cn = ktbl->look(string,0);
19224: if (cn->tp->base == COBJ) cn = Pbase(cn->tp)->b_name;
19225: Pname x = gtbl->look("__as",0);
19226: if (x) { // what if there is an (illegal) global assignment operation?
19227: // hack hack don't declare global assignment operations!
19228: Pfct f = Pfct(x->tp);
19229: if (f->base == FCT) {
19230: Pptr r = f->argtype->tp->is_ref();
19231: if (r) {
19232: Pname cnn = r->typ->is_cl_obj();
19233: if (cnn && cn==cnn) return 0;
19234: }
19235: } else {
19236: for (Plist gl = Pgen(f)->fct_list; gl; gl=gl->l) {
19237: Pptr r = Pfct(gl->f)->argtype->tp->is_ref();
19238: if (r) {
19239: Pname cnn = r->typ->is_cl_obj();
19240: if (cnn &&cn==cnn) return 0;
19241: }
19242: }
19243: }
19244: }
19245: return make_assignment(cn) ? find_name(s,cl) : 0;
19246: }
19247: }
19248:
19249: return find_in_base(s, cl);
19250: }
19251:
19252: static Pclass rootClass;
19253: static Pbcl pubVClass;
19254: static struct PendingMessage {
19255: Pbcl bc;
19256: Pname mf;
19257: char *nm;
19258: } *pM;
19259:
19260: Pexpr classdef::find_in_base(char* s, Pclass cl)
19261: {
19262: Pbcl bc = 0;
19263: Pexpr e = 0;
19264:
19265: // error('d',"%s->find_in_base(%s %s)",string,s,cl?cl->string:"");
19266:
19267: if ( me == 0 ) mef = 0;
19268: if (rootClass == 0) rootClass = this;
19269: for (Pbcl b=baselist; b; b=b->next) {
19270: Pclass ccl = cl==this?0:cl;
19271: // error('d',"try %t %s %k",b->bclass,b->bclass?b->bclass->string:"?", b->base);
19272: Pexpr ee = b->bclass->find_name(s,ccl);
19273:
19274: if (ee) {
19275: if (c_body == 1) { // look for first use (through this)
19276: if (b!=baselist || b->base==VIRTUAL)
19277: dcl_print(0);
19278: else {
19279: Pexpr ex = ee;
19280: while ((ex->base==MDOT && ex->i1==1)
19281: || (ex->base==REF && ex->e1==cc->c_this)) ex = ex->mem;
19282: switch (ex->tp->base) {
19283: case OVERLOAD:
19284: break;
19285: case FCT:
19286: if (Pfct(ex->tp)->f_virtual==0) break;
19287: default:
19288: dcl_print(0);
19289: }
19290: }
19291: }
19292:
19293: if (e) {
19294: // error( 'd', "find_in_base: b( %s ): %k %k ",b->bclass->string,b->base,b->ppp);
19295: Pexpr ex = e;
19296: int evb = 0; // number of vbase indirections
19297: int eb = 0;
19298:
19299: // note that this does not catch enum members
19300: while (ex->base == MDOT
19301: || (ex->base==REF && ex->e1==cc->c_this)) {
19302: if (ex->base==MDOT) evb += int(ex->i1);
19303: ex = ex->mem;
19304: }
19305:
19306: Pexpr eex = ee;
19307: int eevb = b->base==VIRTUAL; // number of vbase indirections (incl. possibly this one)
19308: int eeb = b->base!=VIRTUAL;
19309:
19310: while (eex->base == MDOT
19311: || (eex->base==REF && eex->e1==cc->c_this)) {
19312: if (eex->base==MDOT) eevb += int(eex->i1);
19313: eex = eex->mem;
19314: }
19315:
19316: // error('d', "find_in_base: ex: %k eex: %k, eevb: %d evb: %d", ex->base, eex->base, eevb, evb );
19317: // relying on simple counts for sub-object identification isn't good enough
19318:
19319: if (ex != eex) {
19320: // error('d',"ex %k tp %k eex %k tp %k", ex->base, ex->tp->base, eex->base, eex->tp->base );
19321: // if (!mqua) {
19322: Pclass ocl, ncl;
19323: if ( ex->tp->base == FCT )
19324: ocl = Pfct(ex->tp)->memof;
19325: else
19326: if ( ex->tp->base == OVERLOAD )
19327: ocl = Pfct(Pgen(ex->tp)->fct_list->f->tp)->memof;
19328: else ocl = Pclass(ex->n_table->t_name->tp);
19329: // else ocl = 0;
19330:
19331: if ( eex->tp->base == FCT )
19332: ncl = Pfct(eex->tp)->memof;
19333: else
19334: if ( eex->tp->base == OVERLOAD )
19335: ncl = Pfct(Pgen(eex->tp)->fct_list->f->tp)->memof;
19336: else ncl = Pclass(eex->n_table->t_name->tp);
19337: // else ncl = 0;
19338:
19339: // Pclass ocl = Pfct(ex->tp)->memof;
19340: // Pclass ncl = Pfct(eex->tp)->memof;
19341: int eb = ocl?ocl->has_base(ncl):0;
19342: int eeb = ncl?ncl->has_base(ocl):0;
19343:
19344: //error('d',"eb %d eeb %d evb %d eevb %d",eb,eeb,evb,eevb);
19345: if (eb==0 && eeb==0) {
19346: // different
19347: error("ambiguous%n and%n",ex,eex);
19348: break;
19349: }
19350: else if (eb) { // ex dominates
19351: if (eevb<evb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
19352: }
19353: else { // eex dominates
19354: e = ee;
19355: bc = b;
19356: if (evb<eevb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
19357: }
19358: if (evb==0 && eevb==0) {
19359: error("ambiguous%n and%n (different sub-objects)",ex,eex);
19360: }
19361: // }
19362: // else {
19363: // // different
19364: // error("ambiguous%n and%n",ex,eex);
19365: // break;
19366: // }
19367: }
19368: else if (ex->base==NAME
19369: && (Pname(ex)->n_evaluated || Pname(ex)->n_sto==EXTERN)) {
19370: //error('d',"enum");
19371: }
19372: else if (evb==0 && eevb==0) {
19373: //error('d',"e %k",e->base);
19374: // no virtual base => different
19375: error("ambiguous%n and%n (no virtualB)",ex,eex);
19376: break;
19377: }
19378: else if ((evb && eevb==0) || (eevb && evb==0)) {
19379: // only one virtual base => different
19380: error("ambiguous%n and%n (one not in virtualB)",ex,eex);
19381: break;
19382: }
19383: }
19384: else {
19385: e = ee;
19386: bc = b;
19387: }
19388: }
19389: }
19390:
19391: if (rootClass == this ) {
19392: if ( pM ) {
19393: // deferred until all base classes of ``this'' examined
19394: error("%n cannot access %s: %s is a privateBC",pM->mf,pM->nm,pM->bc->bclass->string);
19395: delete pM; pM=0;
19396: }
19397: rootClass = 0;
19398: pubVClass = 0;
19399: }
19400:
19401: if (e == 0) return 0;
19402:
19403: if (mex) {
19404: if ( bc->ppp==PRIVATE ) { // private base
19405: if (this==mec ||
19406: (mec && has_friend(mec)) ||
19407: (mef && has_friend(mef)))
19408: ;
19409: else
19410: if ( bc->base == VIRTUAL &&
19411: rootClass != this ) {
19412: // if one instance is public, it dominates
19413: if ( pubVClass == 0 ||
19414: strcmp(pubVClass->bclass->string,bc->bclass->string)) {
19415: pM = (PendingMessage *) new char[sizeof(*pM)];
19416: pM->bc = bc; pM->mf = me; pM->nm = s;
19417: }
19418: }
19419: else {
19420: if ( me == dummy_fct )
19421: error("G scope cannot access %s: %s is a privateBC",s,bc->bclass->string);
19422: else error("%n cannot access %s: %s is a privateBC",me,s,bc->bclass->string);
19423: mex = 0;
19424: }
19425: }
19426: else { // public base class
19427: if ( bc->base == VIRTUAL ) {
19428: if ( pM &&
19429: strcmp(bc->bclass->string,pM->bc->bclass->string)==0 ) {
19430: delete pM;
19431: pM=0;
19432: pubVClass = bc;
19433: } // previous private member becomes public
19434: else pubVClass = bc; // ignore subsequent private instances
19435: }
19436: }
19437: }
19438:
19439: if (e->base==NAME
19440: && Pname(e)->n_stclass==STATIC) { // static member
19441: Pname(e)->use();
19442: return e;
19443: }
19444: if (e->base != NAME)
19445: if (bc->base == VIRTUAL) { // this->mem => this->Pbclass->mem
19446: e->mem = new mdot(bc->bclass->string,e->mem);
19447: e->mem->i1 = 1;
19448: e->mem->tp = e->mem->mem->tp;
19449: }
19450: else if (bc!=baselist) { // not first base
19451: if (e->e1 == cc->c_this) { // this->mem => this->Obcl.mem
19452: e->mem = new mdot(bc->bclass->string,e->mem);
19453: e->mem->tp = e->mem->mem->tp;
19454: }
19455: else { // this->p->mem => this->Obcl.p->mem
19456: Pexpr ee = e;
19457: while (ee->e1->base == REF) ee = ee->e1;
19458: ee->mem = new mdot(bc->bclass->string,ee->mem);
19459: ee->mem->tp = ee->mem->mem->tp;
19460: }
19461: }
19462:
19463: return e;
19464: }
19465:
19466: int has_virt(Pclass cl)
19467: {
19468: if (cl->virt_count) return 1;
19469: for (Pbcl b = cl->baselist; b; b = b->next)
19470: if (b->bclass->virt_count || has_virt(b->bclass)) return 1;
19471: return 0;
19472: }
19473:
19474: Pname find_vptr(Pclass cl)
19475: /*
19476: find virtual function table
19477: in memtbl or memtbl of ``first bases''
19478: */
19479: {
19480: //error('d',"find_vptr %t",cl);
19481: while (cl) {
19482: Pname vp = cl->memtbl->look("__vptr",0);
19483: if (vp) return vp;
19484: Pbcl b = cl->baselist;
19485: cl = 0;
19486: for (; b; b = b->next)
19487: if (b->base == NAME) {
19488: cl = b->bclass;
19489: break;
19490: }
19491: }
19492: //error('d',"return 0");
19493: return 0;
19494: }
19495:
19496: void make_dummy()
19497: /* a function with no special privileges */
19498: {
19499: Pname x = new name(".." /*"__static_initializer"*/);
19500: x->tp = new fct(Pvoid_type,0,1);
19501: dummy_fct = x->dcl(gtbl,EXTERN);
19502: // dummy_fct->string = "";
19503: delete x;
19504: }
19505:
19506: void check_visibility(Pname n, Pname q, Pclass cl, Ptable tbl, Pname fn)
19507: /*
19508: "fn" calls "n" a member function of "cl"
19509: fn can be zero (for functions called in arguments to static constructors)
19510: */
19511: {
19512: // error('d',"check_visibility(%n, %t, %d, %n)",n,cl,tbl,fn);
19513: if (fn==0) {
19514: if (dummy_fct == 0) make_dummy();
19515: fn = dummy_fct;
19516: }
19517: Pname nn = new name;
19518: char* s = n->n_gen_fct_name; // overloaded name
19519: nn->string = s?s:n->string;
19520: nn->n_qualifier = q;
19521: Pname nx = Pname(find_name(nn,cl,tbl,REF,fn)); // nn deleted by find_name
19522: if (nx->tp->base != OVERLOAD) return;
19523:
19524: // can we get here?
19525:
19526: // overloaded not checked by find_name()
19527: // (since it looks for NAMEs not functions)
19528:
19529: for (Plist gl=Pgen(nx->tp)->fct_list; gl; gl=gl->l) {
19530: Pname nn = gl->f;
19531: if (n == nn) {
19532: if (nn->n_scope) return; // public member
19533:
19534: Pfct omef = mef;
19535: Pclass omec = mec;
19536: Pclass otcl = tcl;
19537:
19538: Pclass ncl = Pclass(nn->n_table->t_name->tp);
19539: Pname fncn = fn->n_table->t_name;
19540:
19541: mec = fncn?Pclass(fncn->tp):0;
19542: Pfct f = mef = Pfct(fn->tp);
19543: tcl = cl;
19544:
19545: int ok = is_accessible( n, ncl, 1 );
19546:
19547: // restore global values
19548: mef = omef; mec = omec; tcl = otcl;
19549:
19550: if ( ok ) return;
19551:
19552: if ( Cdcl && Cdcl->base == NAME &&
19553: Cdcl->n_stclass == STATIC &&
19554: Cdcl->n_initializer &&
19555: Cdcl->n_qualifier )
19556: {
19557: Pbase bn = Pbase(Cdcl->n_qualifier->tp);
19558: Pclass ccl = Pclass(bn->b_name->tp);
19559:
19560: if ( ccl == cl || ccl->has_friend(f) ||
19561: (n->n_protect && ccl->has_base(ncl)))
19562: return;
19563: }
19564:
19565: if ( fn == dummy_fct )
19566: error("G scope cannot access%n: %sM",nn,nn->n_protect?"protected":"private");
19567: else error("%n cannot access%n: %sM",fn,nn,nn->n_protect?"protected":"private");
19568: return;
19569: }
19570: }
19571: error('i',"visibility check failed");
19572: }
19573: 0707071010112044321004440001630000160000010202000466055403200000700000150132gram.y /*ident "@(#)ctrans:src/gram.y 1.11" */
19574: /*************************************************************************
19575:
19576: C++ source for cfront, the C++ compiler front-end
19577: written in the computer science research center of Bell Labs
19578:
19579: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
19580: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
19581:
19582: gram.y:
19583:
19584: This is the C++ syntax analyser.
19585:
19586: Syntax extensions for error handling:
19587: nested functions
19588: any expression can be empty
19589: any expression can be a constant_expression
19590:
19591: A call to error() does not change the parser's state
19592:
19593: ***************************************************************************/
19594:
19595: %{
19596: #include "cfront.h"
19597: #include "size.h"
19598: #include "template.h"
19599: #include <string.h>
19600: // include tqueue.h after YYSTYPE is defined ...
19601:
19602:
19603: struct parstate {
19604: Ptype intypedef;
19605: int defercheck;
19606: Pname intag;
19607: } pstate[BLMAX];
19608: static int px;
19609: static void
19610: SAVE_STATE()
19611: {
19612: if ( px++ >= BLMAX ) error('i',"maximum scope depth exceeded");
19613: pstate[px].intypedef = in_typedef;
19614: in_typedef = 0;
19615: pstate[px].defercheck = defer_check;
19616: defer_check = 0;
19617: pstate[px].intag = in_tag;
19618: in_tag = 0;
19619: }
19620: static void
19621: RESTORE_STATE()
19622: {
19623: if ( --px < 0 ) error('i',"scope stack underflow");
19624: in_typedef = pstate[px].intypedef;
19625: defer_check = pstate[px].defercheck;
19626: in_tag = pstate[px].intag;
19627: }
19628:
19629: #define copy_if_need_be(s) ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : s)
19630: #define YYMAXDEPTH 600
19631:
19632: #ifdef DBG
19633: #ifndef YYDEBUG
19634: #define YYDEBUG 1
19635: #endif
19636: #endif
19637:
19638: static init_seen = 0;
19639: static cdi = 0;
19640: static Pnlist cd = 0, cd_vec[BLMAX];
19641: static char stmt_seen = 0, stmt_vec[BLMAX];
19642:
19643: //local class
19644: static Plist tn_vec[BLMAX], lcl_tn_vec[BLMAX], lcl_blk_vec[BLMAX];
19645: extern void local_restore();
19646: extern void local_name();
19647:
19648: //nested class
19649: static Plist nested_tn_vec[BLMAX], nested_type_vec[BLMAX];
19650: extern void nested_restore();
19651:
19652: static Pname err_name = 0;
19653:
19654: // fcts put into norm2.c just to get them out of gram.y
19655: void sig_name(Pname);
19656: Ptype tok_to_type(TOK);
19657: void memptrdcl(Pname, Pname, Ptype, Pname);
19658:
19659: static Pptr doptr(TOK p, TOK t)
19660: {
19661: Pptr r = new ptr(p,0);
19662: switch (t) {
19663: case CONST:
19664: r->rdo = 1;
19665: // if (p == RPTR) error('w',"redundant `const' after &");
19666: break;
19667: case VOLATILE:
19668: error('w',"\"volatile\" not implemented (ignored)");
19669: break;
19670: default:
19671: error("syntax error: *%k",t);
19672: }
19673: return r;
19674: }
19675:
19676: static Pbcl dobase(TOK pr, Pname n, TOK v = 0)
19677: {
19678: Pbcl b = new basecl(0,0);
19679:
19680: if (pr == PROTECTED) {
19681: pr = PUBLIC;
19682: error("protectedBC");
19683: }
19684: b->ppp = pr; // save protection indicator
19685:
19686: if (n) {
19687: if (n->base != TNAME) {
19688: error("BN%n not aTN",n);
19689: return 0;
19690: }
19691:
19692: Pbase bt = Pbase(n->tp);
19693: while (bt->base == TYPE) bt = Pbase(bt->b_name->tp);
19694:
19695: if (bt->base != COBJ) {
19696: error("BN%n not aCN",n);
19697: return 0;
19698: }
19699:
19700: if (v) {
19701: if (v != VIRTUAL) error("syntax error:%k inBCD",v);
19702: b->base = VIRTUAL;
19703: }
19704: else
19705: b->base = NAME;
19706:
19707: b->bclass = Pclass(bt->b_name->tp);
19708: }
19709:
19710: return b;
19711: }
19712:
19713:
19714: #define Ndata(a,b) b->normalize(Pbase(a),0,0)
19715: #define Ncast(a,b) b->normalize(Pbase(a),0,1)
19716: #define Nfct(a,b,c) b->normalize(Pbase(a),Pblock(c),0)
19717: #define Ncopy(n) (n->base==TNAME)?new name(n->string):n
19718:
19719: #define Finit(p) Pfct(p)->f_init
19720: #define Fargdcl(p,q,r) Pfct(p)->argdcl(q,r)
19721: #define Freturns(p) Pfct(p)->returns
19722: #define Vtype(v) Pvec(v)->typ
19723: #define Ptyp(p) Pptr(p)->typ
19724:
19725: /* avoid redefinitions */
19726: #undef EOFTOK
19727: #undef ASM
19728: #undef BREAK
19729: #undef CASE
19730: #undef CONTINUE
19731: #undef DEFAULT
19732: #undef DELETE
19733: #undef DO
19734: #undef ELSE
19735: #undef ENUM
19736: #undef FOR
19737: #undef FORTRAN
19738: #undef FRIEND
19739: #undef GOTO
19740: #undef IF
19741: #undef NEW
19742: #undef OPERATOR
19743: #undef RETURN
19744: #undef SIZEOF
19745: #undef SWITCH
19746: #undef THIS
19747: #undef WHILE
19748: #undef LP
19749: #undef RP
19750: #undef LB
19751: #undef RB
19752: #undef REF
19753: #undef DOT
19754: #undef NOT
19755: #undef COMPL
19756: #undef MUL
19757: #undef AND
19758: #undef PLUS
19759: #undef MINUS
19760: #undef ER
19761: #undef OR
19762: #undef ANDAND
19763: #undef OROR
19764: #undef QUEST
19765: #undef COLON
19766: #undef ASSIGN
19767: #undef CM
19768: #undef SM
19769: #undef LC
19770: #undef RC
19771: #undef ID
19772: #undef STRING
19773: #undef ICON
19774: #undef FCON
19775: #undef CCON
19776: #undef ZERO
19777: #undef ASOP
19778: #undef RELOP
19779: #undef EQUOP
19780: #undef DIVOP
19781: #undef SHIFTOP
19782: #undef ICOP
19783: #undef TYPE
19784: #undef TNAME
19785: #undef EMPTY
19786: #undef NO_ID
19787: #undef NO_EXPR
19788: #undef FDEF
19789: #undef ELLIPSIS
19790: #undef AGGR
19791: #undef MEM
19792: #undef MEMPTR
19793: #undef PR
19794: #undef TSCOPE
19795: #undef DECL_MARKER
19796: #undef REFMUL
19797: #undef LDOUBLE
19798: #undef LINKAGE
19799: #undef LOCAL
19800: #undef TEMPLATE
19801:
19802: #undef XVIRT
19803: #undef XNLIST
19804: #undef XILINE
19805: #undef XIA
19806: #undef STATEMENT
19807: #undef EXPRESSION
19808: #undef SM_PARAM
19809: #undef TEMPLATE_TEST
19810: #undef PTNAME
19811: #undef NEW_INIT_KLUDGE
19812: %}
19813:
19814: %union {
19815: char* s;
19816: TOK t;
19817: int i;
19818: loc l;
19819: Pname pn;
19820: Ptype pt;
19821: Pexpr pe;
19822: Pstmt ps;
19823: Pbase pb;
19824: Pnlist nl;
19825: Pslist sl;
19826: Pelist el;
19827: Pbcl pbc;
19828: Pptr pp;
19829: PP p; // fudge: pointer to all class node objects
19830: Plist pl;
19831: toknode* q; // token queue
19832: }
19833: %{
19834: #include "tqueue.h"
19835: extern YYSTYPE yylval, yyval;
19836: extern int yyparse();
19837:
19838: // in_typedef should allow for nested in_typedef
19839: extern int declTag; // !1: inline, virtual mod permitted
19840: int in_sizeof = 0;
19841: Ptype in_typedef = 0; // catch redefinition of TNAME
19842: Pname in_tag = 0; // handle complex typedefs: int (*)()
19843: extern int defer_check; // redefinition typedef check delay
19844: Pname curr_scope;
19845:
19846: extern int must_be_id; // !0, TNAME => ID, i.e., int X
19847: int DECL_TYPE = 0; // lalex() wants this set for global x(*fp)()
19848: int in_arg_list=0; // !0 when parsing argument list
19849: static int in_binit_list=0;
19850: int in_class_decl=0; // !0 when processing class definition
19851: int parsing_class_members=0; // !0 when parsing class def but not member function body
19852: int in_mem_fct=0; // !0 when parsing member function definition
19853:
19854: #define yylex lalex
19855: #define NEXTTOK() ( (yychar==-1) ? (yychar=yylex(),yychar) : yychar )
19856: #define EXPECT_ID() must_be_id = 1
19857: #define NOT_EXPECT_ID() must_be_id = 0
19858:
19859: Pname syn()
19860: {
19861: ll:
19862: switch (yyparse()) {
19863: case 0: return 0; // EOF
19864: case 1: goto ll; // no action needed
19865: default: return yyval.pn;
19866: }
19867: }
19868:
19869: %}
19870: /*
19871: the token definitions are copied from token.h,
19872: and all %token replaced by %token
19873: */
19874: /* keywords in alphabetical order */
19875: %token EOFTOK 0
19876: %token ASM 1
19877: %token AUTO 2
19878: %token BREAK 3
19879: %token CASE 4
19880: %token CONTINUE 7
19881: %token DEFAULT 8
19882: %token DELETE 9
19883: %token DO 10
19884: %token ELSE 12
19885: %token ENUM 13
19886: %token FOR 16
19887: %token FORTRAN 17
19888: %token FRIEND 18
19889: %token GOTO 19
19890: %token IF 20
19891: %token NEW 23
19892: %token OPERATOR 24
19893: %token RETURN 28
19894: %token SIZEOF 30
19895: %token SWITCH 33
19896: %token THIS 34
19897: %token WHILE 39
19898:
19899: /* operators in priority order (sort of) */
19900: %token LP 40
19901: %token RP 41
19902: %token LB 42
19903: %token RB 43
19904: %token REF 44
19905: %token DOT 45
19906: %token NOT 46
19907: %token COMPL 47
19908: %token MUL 50
19909: %token AND 52
19910: %token PLUS 54
19911: %token MINUS 55
19912: %token LT 58
19913: %token GT 60
19914: %token ER 64
19915: %token OR 65
19916: %token ANDAND 66
19917: %token OROR 67
19918: %token QUEST 68
19919: %token COLON 69
19920: %token ASSIGN 70
19921: %token CM 71
19922: %token SM 72
19923: %token LC 73
19924: %token RC 74
19925:
19926: /* = constants etc. */
19927: %token ID 80
19928: %token STRING 81
19929: %token ICON 82
19930: %token FCON 83
19931: %token CCON 84
19932: %token NAME 85
19933: %token ZERO 86
19934: /* groups of tokens */
19935: %token ASOP 90 /* op= */
19936: %token RELOP 91 /* LE GE LT GT */
19937: %token EQUOP 92 /* EQ NE */
19938: %token DIVOP 93 /* DIV MOD */
19939: %token SHIFTOP 94 /* LS RS */
19940: %token ICOP 95 /* INCR DECR */
19941: %token TYPE 97
19942: /* TYPE = INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO
19943: LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */
19944:
19945: %token TNAME 123
19946: %token EMPTY 124
19947: %token NO_ID 125
19948: %token NO_EXPR 126
19949: %token FDEF 127
19950:
19951: %token ELLIPSIS 155
19952: %token AGGR 156
19953: %token MEM 160
19954: %token MEMPTR 173
19955: %token PR 175 /* PUBLIC PRIVATE PROTECTED */
19956: %token TSCOPE 178 /* TNAME :: */
19957: %token DECL_MARKER 179
19958: %token REFMUL 180 /* ->*, .* */
19959: %token LDOUBLE 181
19960: %token LINKAGE 182 /* extern "asdf" */
19961: %token LOCAL 183 /* local class */
19962: %token TEMPLATE 185 /* local class */
19963:
19964: /* "tokens" for aux data structures */
19965:
19966: %token XVIRT 200 /* class virt */
19967: %token XNLIST 201 /* struct name_list */
19968: %token XILINE 202
19969: %token XIA 203
19970: %token STATEMENT 205
19971: %token EXPRESSION 206
19972: %token SM_PARAM 207
19973: %token TEMPLATE_TEST 208
19974: %token PTNAME 209
19975: %token NEW_INIT_KLUDGE 210
19976: %token XDELETED_NODE 211
19977: %token DUMMY_LAST_NODE 212
19978:
19979: %type <p> external_def fct_dcl fct_def att_fct_def arg_dcl_list
19980: base_init init_list binit
19981: data_dcl ext_def vec ptr
19982: type tp enum_dcl moe_list moe
19983: tag ttag enumtag class_head class_dcl cl_mem_list
19984: cl_mem dl decl_list
19985: fname decl initializer stmt_list
19986: caselab_stmt caselablist
19987: block statement simple ex_list elist e ee term prim
19988: term_elist
19989: cast_decl cast_type c_decl c_type c_tp
19990: arg_decl formal_decl at arg_type arg_list arg_type_list
19991: new_decl new_type
19992: condition
19993: TSCOPE tscope TNAME tn_list MEMPTR
19994: qualified_tname
19995: PTNAME tname ptname template_def
19996: %type <l> LC RC SWITCH CASE DEFAULT FOR IF DO WHILE GOTO RETURN DELETE
19997: BREAK CONTINUE
19998: %type <t> oper ellipsis_opt
19999: EQUOP DIVOP SHIFTOP ICOP RELOP GT LT ASOP
20000: ANDAND OROR PLUS MINUS MUL ASSIGN OR ER AND
20001: LP LB NOT COMPL AGGR
20002: TYPE PR REFMUL
20003: STATEMENT EXPRESSION stmt_or_expr
20004: %type <s> CCON ZERO ICON FCON STRING LINKAGE
20005: %type <pn> ID FDEF inline_fct_def identifier
20006: %type <pbc> base_list base_unit_list base_unit
20007: %type <q> EMPTY
20008: %type <i> fct_attributes
20009: %type <pl> arg_lp
20010: %type <pe> temp_inst_parm
20011: %type <el> temp_inst_parms
20012:
20013: %left EMPTY
20014: %left NO_ID
20015: %left RC LC ID BREAK CONTINUE RETURN GOTO DELETE DO IF WHILE FOR CASE DEFAULT
20016: AGGR ENUM TYPE TNAME TSCOPE
20017: %left NO_EXPR
20018:
20019: %left CM
20020: %right ASOP ASSIGN
20021: %right QUEST COLON
20022: %left OROR
20023: %left ANDAND
20024: %left OR
20025: %left ER
20026: %left AND
20027: %left EQUOP
20028: %left RELOP GT LT
20029: %left SHIFTOP
20030: %left PLUS MINUS
20031: %left MUL DIVOP MEMPTR
20032: %left REFMUL
20033: %right NOT COMPL NEW
20034: %right ICOP SIZEOF
20035: %left LB LP DOT REF MEM
20036:
20037: %start ext_def
20038:
20039: %%
20040: /*
20041: this parser handles declarations one by one,
20042: NOT a complete .c file
20043: */
20044:
20045:
20046: /************** DECLARATIONS in the outermost scope: returns Pname (in yylval) ***/
20047:
20048: ext_def : external_def { return 2; }
20049: | SM { return 1; }
20050: | EOFTOK { return 0; }
20051: | LINKAGE LC
20052: {
20053: set_linkage($<s>1);
20054: bl_level--;
20055: return 1;
20056: }
20057: | RC
20058: {
20059: set_linkage(0);
20060: bl_level++;
20061: return 1;
20062: }
20063: | template { return 1; }
20064: | template_test { return 1 ;}
20065: ;
20066:
20067:
20068: template_test : TEMPLATE_TEST identifier LT temp_inst_parms GT SM
20069: { Ptreet t = tree_template::get($<pn>2->string) ;
20070: Pexpr e = 0 ;
20071: if (t)
20072: e = t->expand(expr_unlist($<el>4)) ;
20073: else error ("%s wasn't an expression template",
20074: $<pn>2->string) ;
20075: } ;
20076:
20077: template : TEMPLATE
20078: { templp->start() ; }
20079: LT template_parm_list GT
20080: {templp->enter_parameters() ; }
20081: template_def
20082: {templp->end($<pn>7);
20083: templp->in_progress = false ;
20084: goto mod;}
20085: ;
20086:
20087: template_def : att_fct_def
20088: { goto mod; }
20089: | fct_def
20090: { goto mod; }
20091: | class_dcl SM
20092: { Pname pn = $<pb>1->aggr();
20093: /* basetype:aggr() does not return the name for a forward */
20094: /* declaration, so extract it directly */
20095: $$ = (pn ? pn : $<pb>1->b_name) ;
20096: DECL_TYPE = 0; }
20097: /* internal template specification productions*/
20098: | STATEMENT
20099: {templp->curr_tree_template = $1 ; }
20100: identifier COLON statement
20101: {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */
20102: $<pn>$ = $<pn>3; }
20103: | EXPRESSION
20104: {templp->curr_tree_template = $1 ; }
20105: identifier COLON ee SM
20106: {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */
20107: $<pn>$ = $<pn>3 ; }
20108: ;
20109:
20110: identifier : ID
20111: | qualified_tname
20112: { $<pn>$ = Ncopy($<pn>1) ;} ;
20113: ;
20114:
20115: external_def : data_dcl
20116: {
20117: /* if function declartion with arguments
20118: * need to make sure modified_tn is traversed */
20119: if ( $<pn>1 != 0
20120: && $<pn>1->tp->base == FCT
20121: && Pfct($<pn>1->tp)->nargs !=0 )
20122: goto mod;
20123: else {
20124: modified_tn = 0;
20125: curr_scope = 0;
20126: if ($<pn>1==0) $<i>$ = 1;
20127: }
20128: }
20129: | att_fct_def
20130: { goto mod; }
20131: | fct_def
20132: { goto mod; }
20133: | fct_dcl
20134: { mod: if (modified_tn) {
20135: restore();
20136: modified_tn = 0;
20137: }
20138: local_blk = 0;
20139: curr_scope = 0;
20140: if (local_tn) {
20141: local_restore();
20142: local_tn = 0;
20143: }
20144:
20145: if (nested_tn) { // x::f(){}
20146: nested_restore();
20147: nested_tn = 0;
20148: nested_type = 0;
20149: }
20150: }
20151: | ASM LP STRING RP SM
20152: { Pname n = new name(make_name('A'));
20153: n->tp = new basetype(ASM,0);
20154: Pbase(n->tp)->b_name = Pname($<s>3);
20155: $$ = n;
20156: }
20157: ;
20158:
20159: fct_dcl : decl ASSIGN initializer SM
20160: {
20161: err_name = $<pn>1;
20162: if(err_name) err_name->n_initializer = $<pe>3;
20163: goto fix;
20164: }
20165: | decl SM
20166: {
20167: Ptype t;
20168: err_name = $<pn>1;
20169: fix:
20170: if (err_name == 0) {
20171: error("syntax error:TX");
20172: $$ = Ndata(defa_type,err_name);
20173: }
20174: else if ((t=err_name->tp) == 0) {
20175: error("TX for%n",err_name);
20176: $$ = Ndata(defa_type,err_name);
20177: }
20178: else if (t->base==FCT) {
20179: if (Pfct(t)->returns==0)
20180: $$ = Nfct(defa_type,err_name,0);
20181: else
20182: $$ = Ndata(0,err_name);
20183: }
20184: else {
20185: error("syntax error:TX for%k%n",t->base,err_name);
20186: $$ = Ndata(defa_type,err_name);
20187: }
20188: }
20189: ;
20190:
20191: att_fct_def : type decl arg_dcl_list check_inline base_init block
20192: { Pname n = Nfct($1,$<pn>2,$6);
20193: Fargdcl(n->tp,name_unlist($<nl>3),n);
20194: Finit(n->tp) = $<pn>5;
20195: $$ = n;
20196: NOT_EXPECT_ID();
20197: //???POP_SCOPE(); // undef arg names
20198: }
20199: | type decl arg_dcl_list check_inline EMPTY
20200: {
20201: Pname n = Nfct($1,$<pn>2,dummy);
20202: Fargdcl(n->tp,name_unlist($<nl>3),n);
20203: $<q>5->retval.pn = n;
20204: $$ = n;
20205: NOT_EXPECT_ID();
20206: }
20207: | type decl arg_dcl_list check_inline NO_ID /*syntax error*/
20208: {
20209: error(&$<pn>2->where,"syntax error -- did you forget a ';'?");
20210: Pname n = Nfct($1,$<pn>2,0);
20211: $$ = n;
20212: NOT_EXPECT_ID();
20213: //???POP_SCOPE(); // undef arg names
20214: }
20215: ;
20216:
20217: fct_def : decl arg_dcl_list check_inline base_init block
20218: { Pname n = Nfct(defa_type,$<pn>1,$5);
20219: Fargdcl(n->tp,name_unlist($<nl>2),n);
20220: if ( $<pn>4 && $<pn>4->n_list &&
20221: ccl && ccl->csu == UNION )
20222: error( "multiple initializers in unionK %s::%n", $<pn>1->string, $<pn>1 );
20223: Finit(n->tp) = $<pn>4;
20224: $$ = n;
20225: NOT_EXPECT_ID();
20226: //???POP_SCOPE(); // undef arg names
20227: }
20228: | decl arg_dcl_list check_inline EMPTY
20229: {
20230: Pname n = Nfct(defa_type,$<pn>1,dummy);
20231: Fargdcl(n->tp,name_unlist($<nl>2),n);
20232: $<q>4->retval.pn = n;
20233: $$ = n;
20234: NOT_EXPECT_ID();
20235: }
20236: | decl arg_dcl_list check_inline NO_ID /*syntax error*/
20237: {
20238: error(&$<pn>1->where,"badD of%n -- did you forget a ';'?",$<pn>1);
20239: Pname n = Nfct(defa_type,$<pn>1,0);
20240: $$ = n;
20241: NOT_EXPECT_ID();
20242: //???POP_SCOPE(); // undef arg names
20243: }
20244: ;
20245:
20246: inline_fct_def : FDEF
20247: {//PUSH_ARG_SCOPE
20248: arg_redec($<pn>1);
20249: }
20250: base_init block
20251: {
20252: Finit($1->tp) = $<pn>3;
20253: Pfct($1->tp)->body = Pblock($4);
20254: $$ = $1;
20255: NOT_EXPECT_ID();
20256: //???POP_SCOPE(); // undef arg names
20257: }
20258: ;
20259:
20260:
20261: check_inline : /* empty */
20262: {
20263: // if parsing implicit inline def, save body
20264: // of function for parsing after class def
20265: switch ( NEXTTOK() ) {
20266: case LC: case COLON:
20267: if ( in_class_decl ) {
20268: // mem or friend inline def
20269: // save text of mem_init & ftn
20270: la_backup(yychar,yylval);
20271: // yylval used as dummy...
20272: la_backup(FDEF, yylval);
20273: if ( yylval.q = save_text() )
20274: yychar = EMPTY;
20275: else { // syntax error
20276: // just parse in place
20277: yylex(); // FDEF
20278: yychar = yylex();
20279: }
20280: } // if in_class_decl
20281: break;
20282: default:
20283: la_backup(yychar,yylval);
20284: yychar = NO_ID; // 'graceful' recovery
20285: break;
20286: }
20287: }
20288: ;
20289:
20290: base_init : COLON { ++in_binit_list; } init_list
20291: {
20292: $$ = $3;
20293: in_arg_list = 0;
20294: --in_binit_list;
20295: }
20296: | %prec EMPTY
20297: { $$ = 0; }
20298: ;
20299:
20300: init_list : binit
20301: { $$ = $1; }
20302: | init_list CM binit
20303: { $<pn>$ = $<pn>3; $<pn>$->n_list = $<pn>1; }
20304: ;
20305:
20306: binit : LP elist RP
20307: {
20308: $<pn>$ = new name;
20309: $<pn>$->n_initializer = $<pe>2;
20310: }
20311: | ttag LP elist RP
20312: {
20313: Pname n = Ncopy($<pn>1);
20314: n->base = $<pn>1->base;
20315: n->tp = $<pn>1->tp;
20316: n->n_initializer = $<pe>3;
20317: $<pn>$ = n;
20318: }
20319:
20320: /*
20321: | NEW LP elist RP
20322: { Pname n = new name;
20323: n->base = NEW;
20324: n->n_initializer = $<pe>3;
20325: $<pn>$ = n;
20326: }
20327: */
20328: ;
20329:
20330:
20331:
20332:
20333: /*************** declarations: returns Pname ********************/
20334:
20335: arg_dcl_list : arg_dcl_list data_dcl
20336: { if ($<pn>2 == 0)
20337: error("badAD");
20338: else if ($<pn>2->tp->base == FCT)
20339: error("FD inAL (%n)",$<pn>2);
20340: else if ($1)
20341: $<nl>1->add_list($<pn>2);
20342: else
20343: $<nl>$ = new nlist($<pn>2);
20344: }
20345: | %prec EMPTY
20346: {
20347: $$ = 0;
20348: }
20349: ;
20350:
20351: dl : decl
20352: | ID COLON
20353: {
20354: if ( in_typedef ) {
20355: error("Tdef field");
20356: in_typedef = 0;
20357: }
20358: // ENTER_NAME($<pn>1);
20359: }
20360: e %prec CM
20361: { $$ = $<pn>1;
20362: $<pn>$->tp = new basetype(FIELD,$<pn>4);
20363: }
20364: | COLON e %prec CM
20365: { $$ = new name;
20366: $<pn>$->tp = new basetype(FIELD,$<pn>2);
20367: if ( in_typedef ) {
20368: error("Tdef field");
20369: in_typedef = 0;
20370: }
20371: }
20372: | decl ASSIGN
20373: {
20374: // ENTER_NAME($<pn>1);
20375: }
20376: initializer
20377: { Pexpr e = $<pe>4;
20378: if (e == dummy) error("emptyIr");
20379: $<pn>1->n_initializer = e;
20380: init_seen = 0;
20381: }
20382: ;
20383:
20384: decl_list : dl
20385: {
20386: if ($1) $<nl>$ = new nlist($<pn>1);
20387: if ( NEXTTOK() == CM && la_look() == TNAME )
20388: EXPECT_ID();
20389: }
20390: | decl_list CM dl
20391: { if ($1)
20392: if ($3)
20393: $<nl>1->add($<pn>3);
20394: else
20395: error("DL syntax");
20396: else {
20397: if ($3) $<nl>$ = new nlist($<pn>3);
20398: error("DL syntax");
20399: }
20400: if ( NEXTTOK() == CM && la_look() == TNAME )
20401: EXPECT_ID();
20402: }
20403: ;
20404:
20405: data_dcl : type decl_list SM
20406: {
20407: extern int co_hack;
20408: co_hack = 1;
20409: /*$$ = Ndata($1,name_unlist($<nl>2));*/
20410: Pname n = Ndata($1,name_unlist($<nl>2));
20411: if ( in_typedef && in_tag ) {
20412: if ( n->tp->check( in_tag->tp, 0 ))
20413: error("%nredefined: previous: %t now: %t", in_tag, in_tag->tp, n->tp );
20414: }
20415: in_typedef = 0;
20416: in_tag = 0;
20417: co_hack = 0;
20418: DECL_TYPE = 0;
20419: $$ = n;
20420: }
20421: | type SM
20422: {
20423: $$ = $<pb>1->aggr();
20424: in_typedef = 0;
20425: in_tag = 0;
20426: DECL_TYPE = 0;
20427: }
20428:
20429: ;
20430:
20431: /* This is where parametrized types, and regular types come together. */
20432:
20433: lt : LT { templp->parameters_in_progress++; };
20434: gt : GT { templp->parameters_in_progress--; };
20435:
20436: tname : qualified_tname { $<pn>$ = templp->check_tname($<pn>1) ; }
20437: | qualified_tname lt temp_inst_parms gt
20438: {
20439: $<pn>$ = parametrized_typename($<pn>1,
20440: (expr_unlist($<el>3))) ;
20441: }
20442: | NAME LT temp_inst_parms GT
20443: { extern Pbase any_type;
20444: error("%n was not a parametrized type.", $<pn>$) ;
20445: $<pn>$= $<pn>1->tdef() ;
20446: $<pn>$->tp = any_type ; } ;
20447:
20448:
20449:
20450: tp : TYPE
20451: {
20452: $$ = new basetype($<t>1,0);
20453: if ( $<t>1 == TYPEDEF ) in_typedef = $<pt>$;
20454: if (DECL_TYPE == -1) DECL_TYPE = 0;
20455: }
20456: | LINKAGE
20457: { $$ = new basetype(EXTERN,0);
20458: $<pb>$->b_linkage = $<s>1;
20459: if (DECL_TYPE == -1) DECL_TYPE = 0;
20460: }
20461: | qualified_tname
20462: {
20463: templp->check_tname($<pn>1);
20464: $$ = new basetype(TYPE,$<pn>1);
20465: if (DECL_TYPE == -1) DECL_TYPE = 0;
20466: }
20467: /*XXX*/ | tn_list DECL_MARKER
20468: { // modified tn_list TNAME
20469: $$ = new basetype(TYPE,$<pn>2);
20470: //xxx qualifier currently ignored...
20471: if (DECL_TYPE == -1) DECL_TYPE = 0;
20472: }
20473: | qualified_tname lt temp_inst_parms gt
20474: {
20475: $<pb>$ = parametrized_basetype($<pn>1,(expr_unlist($<el>3)));
20476: }
20477: | class_dcl
20478: | enum_dcl
20479: | DECL_MARKER
20480: {
20481: if (DECL_TYPE == TNAME)
20482: $$ = new basetype(TYPE,$<pn>1);
20483: // else if (DECL_TYPE == TSCOPE)
20484: // $$ = 0;
20485: else
20486: if (DECL_TYPE == 0 &&
20487: $<p>1->base == TNAME)
20488: $$ = new basetype(TYPE,$<pn>1);
20489: else
20490: $$ = new basetype($<t>1,0);
20491: DECL_TYPE = -1;
20492: }
20493: ;
20494:
20495: type : tp
20496: | type TYPE
20497: {
20498: if ( DECL_TYPE != -1 ) {
20499: switch ($<pb>1->base) { Pbase bt;
20500: case COBJ: case EOBJ:
20501: bt = new basetype(0,0);
20502: *bt = *$<pb>1;
20503: DEL($<pb>1);
20504: $<pb>1 = bt;
20505: }
20506: $$ = $<pb>1->type_adj($<t>2);
20507: }
20508: DECL_TYPE = 0;
20509: }
20510: | type tname
20511: {
20512: //error('d',"decl_type: %d $1: %t $2: %n",DECL_TYPE,$<pb>1,$<pn>2);
20513: if ( DECL_TYPE != -1 )
20514: $$ = $<pb>1->name_adj($<pn>2);
20515: /*XXX*/ else if($<pb>1==0) $$=new basetype(TYPE,$<pn>2);
20516: DECL_TYPE = 0;
20517: }
20518: | type class_dcl { $$ = $<pb>1->base_adj($<pb>2); }
20519: | type enum_dcl { $$ = $<pb>1->base_adj($<pb>2); }
20520: | type DECL_MARKER
20521: {
20522: if (DECL_TYPE == TYPE) {
20523: switch ($<pb>1->base) { Pbase bt;
20524: case COBJ: case EOBJ:
20525: bt = new basetype(0,0);
20526: *bt = *$<pb>1;
20527: DEL($<pb>1);
20528: $<pb>1 = bt;
20529: }
20530: $$ = $<pb>1->type_adj($<t>2);
20531: }
20532: /*XXX*/ else if (DECL_TYPE == TSCOPE) {
20533: /*XXX*/ error('i',"type decl_marker(tscope)");
20534: /*XXX*/ // $$ = $1;//ignore(?)
20535: /*XXX*/ }
20536: else
20537: $$ = $<pb>1->name_adj($<pn>2);
20538: DECL_TYPE = -1;
20539: }
20540: ;
20541:
20542: temp_inst_parms : temp_inst_parms CM temp_inst_parm
20543: {$<el>1->add(new expr(ELIST,$<pe>3,NULL)) ; }
20544: | temp_inst_parm { $<el>$ =
20545: new elist(new expr(ELIST,$<pe>1,NULL)); } ;
20546:
20547: temp_inst_parm : new_type
20548: {$<pn>1->n_template_arg = template_actual_arg_dummy ;
20549: $<pe>$ = $<pn>1; /* keep yacc happy */ }
20550: | e %prec GT
20551: { $<pe>$ = $<pe>1 ; } ;
20552:
20553: /***************** aggregate: returns Pname *****************/
20554:
20555: enumtag : tag
20556: { enumcheck:
20557: Ptype tx = $<pn>1->tp;
20558: $$ = $1;
20559: if ( tx->base == TYPE ) {
20560: $$ = Pbase(tx)->b_name;
20561: tx = $<pn>$->tp;
20562: if ( tx->base != EOBJ
20563: || strcmp($<pn>$->string,$<pn>1->string)
20564: )
20565: error("%n of type%t redeclared as enum.",$<pn>1,tx);
20566: } else if ( tx->base != EOBJ )
20567: error("%n of type%t redeclared as enum",$<pn>1,tx);
20568: }
20569: | DECL_MARKER { goto enumcheck; }
20570: ;
20571:
20572: enum_dcl : ENUM LC moe_list RC { $$ = end_enum(0,$<nl>3); }
20573: | ENUM enumtag LC moe_list RC { $$ = end_enum($<pn>2,$<nl>4); }
20574: | ENUM enumtag { $<pb>$ = (Pbase)$<pn>2->tp; }
20575: ;
20576:
20577: moe_list : moe
20578: { if ($1) $<nl>$ = new nlist($<pn>1); }
20579: | moe_list CM moe
20580: { if( $3)
20581: if ($1)
20582: $<nl>1->add($<pn>3);
20583: else
20584: $<nl>$ = new nlist($<pn>3);
20585: }
20586: ;
20587:
20588: template_parm_list : template_parm_list CM template_parm
20589: | template_parm
20590: | { $<pn>$ = NULL ;} ;
20591:
20592:
20593: stmt_or_expr : STATEMENT | EXPRESSION ;
20594:
20595: template_parm : AGGR identifier
20596: /* Build the name for the parameter
20597: /* Check that AGGR is indeed CLASS */
20598: { templp->collect($<t>1, $<pn>2) ; }
20599: | stmt_or_expr identifier
20600: { templp->collect($<t>1, $<pn>2) ; }
20601: | type formal_decl
20602: {templp->collect(Ndata($1,$<pn>2)); } ;
20603:
20604:
20605: /* Sam: these productions are a variant of the ones for arg_decl,
20606: verify them against arg_decl for each release. */
20607: formal_decl : ID
20608: { $$ = $<pn>1; }
20609: | ptr formal_decl %prec MUL
20610: { Ptyp($1) = $<pn>2->tp;
20611: $<pn>2->tp = (Ptype)$1;
20612: $$ = $2;
20613: }
20614: | formal_decl vec %prec LB
20615: { Vtype($2) = $<pn>1->tp;
20616: $<pn>1->tp = (Ptype)$2;
20617: }
20618: | formal_decl arg_list
20619: { Freturns($2) = $<pn>1->tp;
20620: $<pn>1->tp = (Ptype)$2;
20621: } ;
20622:
20623:
20624: moe : ID
20625: { $$ = $<pn>1; $<pn>$->tp = moe_type; }
20626: | ID ASSIGN e
20627: { $$ = $<pn>1;
20628: $<pn>$->tp = moe_type;
20629: $<pn>$->n_initializer = $<pe>3;
20630: }
20631: | /* empty: handle trailing CM: enum e { a,b, }; */
20632: { $$ = 0; }
20633: ;
20634:
20635: class_dcl : class_head cl_mem_list RC
20636: { parsing_class_members = 0;
20637: RESTORE_STATE();
20638: switch ( NEXTTOK() ) {
20639: case TYPE: case AGGR: case ENUM: case EOFTOK:
20640: error("`;' or declaratorX afterCD");
20641: la_backup(yychar,yylval);
20642: yychar = SM;
20643: break;
20644: }
20645: la_backup(yychar,yylval);
20646: yychar = -1;
20647: restore_text();
20648: ++bl_level; // scope weirdness!
20649: ++in_mem_fct;
20650: }
20651: inline_mem_defs
20652: {
20653: --in_mem_fct;
20654: --bl_level; // scope weirdness!
20655: if ( yychar == ID ) {
20656: // (yuk!) adjust lex level
20657: --yylval.pn->lex_level;
20658: }
20659: ccl->mem_list = name_unlist($<nl>2);
20660: if ( --in_class_decl ) // nested class
20661: // continue to parse enclosing class
20662: parsing_class_members = 1;
20663: ccl->nest_list = nested_type;
20664: if ( nested_tn ) nested_restore();
20665: nested_type = nested_type_vec[in_class_decl];
20666: nested_tn = nested_tn_vec[in_class_decl];
20667: end_cl();
20668: declTag = 1;
20669: //POP_SCOPE();
20670: }
20671: | AGGR tag
20672: { aggrcheck:
20673: $<pb>$ = (Pbase)$<pn>2->tp;
20674: if ( $$->base == TYPE ) {
20675: Pname nx = $<pb>$->b_name;
20676: $<pb>$ = (Pbase)nx->tp;
20677: if ( $$->base != COBJ
20678: || strcmp(nx->string,$<pn>2->string)
20679: )
20680: error("%n of type%t redeclared as%k.",$<pn>2,$<pb>$,$<t>1);
20681: } else if ( $$->base != COBJ )
20682: error("%n of type%t redeclared as%k",$<pn>2,$<pb>$,$<t>1);
20683: check_tag();
20684: }
20685: | AGGR qualified_tname lt temp_inst_parms gt
20686: {
20687: Pname p = parametrized_typename($<pn>2, (expr_unlist($<el>4))) ;
20688: $<pb>$ = (Pbase)p->tp;
20689: check_tag();
20690: }
20691: | AGGR DECL_MARKER
20692: {
20693: goto aggrcheck;
20694: }
20695: ;
20696:
20697:
20698: inline_mem_defs : /* empty */
20699: | inline_mem_defs inline_fct_def
20700: ;
20701:
20702: base_list : COLON base_unit_list { $$ = $2; }
20703: | %prec EMPTY { $$ = 0; }
20704: ;
20705:
20706: base_unit_list : base_unit
20707: | base_unit_list CM base_unit
20708: { if ($3) { $$ = $3; $<pbc>$->next = $1; } }
20709: ;
20710:
20711: base_unit : ttag { $$ = dobase(0,$<pn>1); }
20712: | PR ttag { $$ = dobase($<t>1,$<pn>2); }
20713: | TYPE ttag { $$ = dobase(0,$<pn>2,$<t>1); }
20714: | PR TYPE ttag { $$ = dobase($<t>1,$<pn>3,$<t>2); }
20715: | TYPE PR ttag { $$ = dobase($<t>2,$<pn>3,$<t>1); }
20716: ;
20717:
20718: class_head : AGGR LC
20719: {//PUSH_CLASS_SCOPE(0);
20720: parsing_class_members = 1;
20721: $$ = start_cl($<t>1,0,0);
20722: nested_tn_vec[in_class_decl] = nested_tn;
20723: nested_type_vec[in_class_decl++] = nested_type;
20724: nested_tn = nested_type = 0;
20725: SAVE_STATE();
20726: }
20727:
20728: | AGGR tag base_list LC
20729: { //PUSH_CLASS_SCOPE($<pn>2->string);
20730: parsing_class_members = 1;
20731: $$ = start_cl($<t>1,$<pn>2,$<pbc>3);
20732: nested_tn_vec[in_class_decl] = nested_tn;
20733: nested_type_vec[in_class_decl++] = nested_type;
20734: nested_tn = nested_type = 0;
20735: SAVE_STATE();
20736: }
20737: ;
20738:
20739: tag : ID { $$ = $1; }
20740: | qualified_tname { $$=$1; }
20741: ;
20742:
20743: ttag : ID { $$ = $1; }
20744: | tname { $$=$1; }
20745: ;
20746:
20747: cl_mem_list : cl_mem_list cl_mem
20748: {
20749: if ($2) {
20750: if ($1)
20751: $<nl>1->add_list($<pn>2);
20752: else
20753: $<nl>$ = new nlist($<pn>2);
20754: }
20755: }
20756: | %prec EMPTY { $$ = 0; }
20757: | cl_mem_list TEMPLATE
20758: {
20759: error( "ZizedTD must be atG, notC scope" );
20760: error('i', "cannot recover from previous error" );
20761: }
20762: ;
20763:
20764: cl_mem : data_dcl
20765: | att_fct_def SM
20766: | fct_def SM
20767: | fct_def
20768: | att_fct_def
20769: | fct_dcl
20770: | PR COLON
20771: { $$ = new name;
20772: $<pn>$->base = $<t>1;
20773: }
20774: /*XXX | tn_list TNAME SM
20775: * { Pname n = Ncopy($<pn>2);
20776: * n->n_qualifier = $<pn>1;
20777: * n->base = PR;
20778: * $$ = n;
20779: * }
20780: */ | tn_list fname SM
20781: { Pname n = Ncopy($<pn>2);
20782: if (n->n_oper == TYPE) {
20783: error('s',"visibilityD for conversion operator");
20784: // n->tp = Ptype(n->n_initializer);
20785: n->tp = Ptype(n->cond);
20786: n->cond = 0;
20787: // n->n_initializer = 0;
20788: n->n_oper = 0;
20789: sig_name(n);
20790: }
20791: n->n_qualifier = $<pn>1;
20792: n->base = PR;
20793: $$ = n;
20794: }
20795: ;
20796:
20797: /************* declarators: returns Pname **********************/
20798: /* a ``decl'' is used for function and data declarations,
20799: and for member declarations
20800: (it has a name)
20801: an ``arg_decl'' is used for argument declarations
20802: (it may or may not have a name)
20803: an ``cast_decl'' is used for casts
20804: (it does not have a name)
20805: a ``new_decl'' is used for type specifiers for the NEW operator
20806: (it does not have a name, and PtoF and PtoV cannot be expressed)
20807: */
20808:
20809: fname : ID
20810: { $$ = $<pn>1; }
20811: | COMPL TNAME /* qualified_tname? */
20812: { $$ = Ncopy($<pn>2);
20813: $<pn>$->n_oper = DTOR;
20814: }
20815: | OPERATOR oper
20816: { $$ = new name(oper_name($2));
20817: $<pn>$->n_oper = $<t>2;
20818: }
20819: | OPERATOR c_type
20820: { Pname n = $<pn>2;
20821: n->string = "_type";
20822: n->n_oper = TYPE;
20823: n->cond = Pexpr(n->tp);
20824: // n->n_initializer = Pexpr(n->tp);
20825: n->tp = 0;
20826: $$ = n;
20827: }
20828: ;
20829:
20830: oper : PLUS
20831: | MINUS
20832: | MUL
20833: | AND
20834: | OR
20835: | ER
20836: | SHIFTOP
20837: | EQUOP
20838: | DIVOP
20839: | RELOP
20840: | LT
20841: | GT
20842: | ANDAND
20843: | OROR
20844: | LP RP { $$ = CALL; }
20845: | LB RB { $$ = DEREF; }
20846: | NOT
20847: | COMPL
20848: | ICOP
20849: | ASOP
20850: | ASSIGN
20851: | NEW { $$ = NEW; }
20852: | DELETE { $$ = DELETE; }
20853: | REF { $$ = REF; }
20854: | CM { $$ = CM; }
20855: | REFMUL { $$ = REFMUL;
20856: if ($<t>1 == DOT) error(".* cannot be overloaded");
20857: }
20858: ;
20859:
20860: tn_list : tscope
20861: /*XXX*/ { if ( $<pn>1 != sta_name ) {
20862: // error('d',"tn_list: tscope: pn1: %s", $<pn>1->string);
20863: Ptype t = $<pn>1->tp;
20864: while ( t->base == TYPE )
20865: t = Pbase(t)->b_name->tp;
20866: Pname n = Pbase(t)->b_name;
20867: if (NEXTTOK() == TNAME
20868: && strcmp(n->string,yylval.pn->string)==0){
20869: // ctor -- change to ID to avoid
20870: // parsing as type spec
20871: yychar = ID;
20872: yylval.pn = Ncopy(yylval.pn);
20873: yylval.pn->n_oper = TNAME;
20874: }
20875: }
20876: $<pn>$ = $<pn>1;
20877: }
20878: /* YYY | tn_list tscope { $<pn>$ = $<pn>1; } */
20879: | tn_list tscope { error('s', "CNs do not nest, use typedef x::y y_in_x"); };
20880: /*XXX | tn_list ID DOT { error("CNs do not nest"); } */
20881: ;
20882:
20883: qualified_tname : tn_list TNAME
20884: { $<pn>$ = $<pn>2;
20885: //xxx qualifier currently ignored...
20886: // $<pn>$ = Ncopy( $<pn>2 );
20887: // $<pn>$->n_oper = TNAME;
20888: // $<pn>$->n_qualifier = $<pn>1;
20889: }
20890: | TNAME
20891: { $<pn>$ = $<pn>1;
20892: // $<pn>$ = Ncopy( $<pn>1 );
20893: // $<pn>$->n_oper = TNAME;
20894: }
20895: ;
20896:
20897: fct_attributes : /* empty */
20898: { $$ = 0; }
20899: | fct_attributes TYPE
20900: { /* const/volatile function */
20901: switch ( $<t>2 ) {
20902: case VOLATILE:
20903: error('s',"volatile functions");
20904: break;
20905: case CONST:
20906: $$ = ($1 | 1);
20907: break;
20908: default:
20909: if ( NEXTTOK() != SM
20910: && yychar != COLON
20911: && yychar != LC ) {
20912: la_backup(yychar,yylval);
20913: yylval.t = $<t>2;
20914: la_backup(TYPE,yylval);
20915: yylval.t = SM;
20916: yychar = SM;
20917: error("syntax error: unexpected%k (did you forget a `;'?)",$<t>2);
20918: } else error("FD syntax: unexpected%k",$<t>2);
20919: break;
20920: }
20921: }
20922: ;
20923:
20924: decl : decl arg_list
20925: { Freturns($2) = $<pn>1->tp;
20926: $<pn>1->tp = $<pt>2;
20927: }
20928: | decl LP RP fct_attributes
20929: { /* function with no argument */
20930: $<pn>1->tp = new fct($<pn>1->tp,0,1);
20931: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
20932: }
20933: | tname arg_list
20934: { Pname n = $<pn>1;
20935: $$ = Ncopy(n);
20936: //??? what if tname is qualified ???
20937: if (ccl && strcmp(n->string,ccl->string)) n->hide();
20938: $<pn>$->n_oper = TNAME;
20939: Freturns($2) = $<pn>$->tp;
20940: $<pn>$->tp = $<pt>2;
20941: }
20942: | decl arg_lp elist RP
20943: /* may be class object initializer,
20944: class object vector initializer,
20945: if not elist will be a CM or an ID
20946: */
20947: {
20948: $<pn>1->tp = new fct($<pn>1->tp,$<pn>3,1);
20949: in_arg_list = 0;
20950: end_al($2,0);
20951: RESTORE_STATE();
20952: //POP_SCOPE(); // similar to end_al()
20953: }
20954: | tname LP MUL ID RP arg_list
20955: {
20956: Pptr p = new ptr( PTR, 0 );
20957: Ptyp(p) = new basetype(TYPE,$<pn>1);
20958: Freturns( $6 ) = Ptype(p);
20959: $<pn>4->tp = $<pt>6;
20960: $$ = $4;
20961: if (DECL_TYPE == -1) DECL_TYPE = 0;
20962: }
20963: | tname LP elist RP
20964: { $$ = Ncopy($<pn>1);
20965: $<pn>$->n_oper = TNAME;
20966: $<pn>$->tp = new fct(0,$<pn>3,1);
20967: }
20968: | tname LP RP fct_attributes
20969: { /* function with no argument */
20970: $$ = Ncopy($<pn>1);
20971: $<pn>$->n_oper = TNAME;
20972: $<pn>$->tp = new fct(0,0,1);
20973: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
20974: }
20975: | tname LP MEMPTR decl RP arg_list
20976: { memptrdcl($<pn>3,$<pn>1,$<pt>6,$<pn>4);
20977: $$ = $4;
20978: }
20979: | fname
20980: | ID DOT fname
20981: { $$ = Ncopy($<pn>3);
20982: $<pn>$->n_qualifier = $1;
20983: error(strict_opt?0:'w',"`.' used for qualification; please use `::' (anachronism)");
20984: }
20985: | tn_list fname
20986: { $$ = $2;
20987: if ( $<pn>1 != sta_name ) {
20988: set_scope($<pn>1);
20989: $<pn>$->n_qualifier = $<pn>1;
20990: }
20991: }
20992: /*XXX*/ | tn_list ID DOT fname
20993: { $$ = Ncopy($<pn>4);
20994: $<pn>$->n_qualifier = $2;
20995: error(ansi_opt?0:'w',"anachronism `.' used for qualification; please use `::'");
20996: if ( $<pn>1 != sta_name ) {
20997: set_scope($<pn>1);
20998: $<pn>2->n_qualifier = $<pn>1;
20999: }
21000: }
21001: /*XXX | tn_list TNAME
21002: * {
21003: * if ( $<pn>1 == sta_name )
21004: * error( ":: applied to CN%n", $<pn>2 );
21005: * $$ = Ncopy($<pn>2);
21006: * set_scope($<pn>1);
21007: * $<pn>$->n_oper = TNAME;
21008: * $<pn>$->n_qualifier = $<pn>1;
21009: * }
21010: */ | ptr decl %prec MUL
21011: { Ptyp($1) = $<pn>2->tp;
21012: $<pn>2->tp = $<pt>1;
21013: $$ = $2;
21014: }
21015: | ptr tname %prec MUL
21016: { $$ = Ncopy($<pn>2);
21017: $<pn>$->n_oper = TNAME;
21018: // cannot evaluate at this point: defer until data_dcl
21019: if ( in_typedef ) {
21020: defer_check = 1;
21021: in_tag = $<pn>2;
21022: }
21023: $<pn>2->hide();
21024: defer_check = 0;
21025: $<pn>$->tp = $<pt>1;
21026: }
21027: | tname vec %prec LB
21028: { $$ = Ncopy($<pn>1);
21029: $<pn>$->n_oper = TNAME;
21030: if ( in_typedef ) {
21031: defer_check = 1;
21032: in_tag = $<pn>1;
21033: }
21034: $<pn>1->hide();
21035: defer_check = 0;
21036: $<pn>$->tp = $<pt>2;
21037: }
21038: | decl vec %prec LB
21039: { Vtype($2) = $<pn>1->tp;
21040: $<pn>1->tp = $<pt>2;
21041: }
21042: /*
21043: | LP decl RP arg_list
21044: {
21045: Freturns($4) = $<pn>2->tp;
21046: $<pn>2->tp = $<pt>4;
21047: $$ = $2;
21048: }
21049: | LP decl RP vec
21050: { Vtype($4) = $<pn>2->tp;
21051: $<pn>2->tp = $<pt>4;
21052: $$ = $2;
21053: }
21054: */
21055: | arg_lp decl RP
21056: {
21057: $$ = $2;
21058: in_arg_list = 0;
21059: end_al($1,0);
21060: RESTORE_STATE();
21061: //POP_SCOPE(); // similar to end_al()
21062: }
21063: ;
21064:
21065: arg_decl : ID
21066: { $$ = $<pn>1; }
21067: | ptr qualified_tname %prec MUL
21068: { $$ = Ncopy($<pn>2);
21069: $<pn>$->n_oper = TNAME;
21070: $<pn>2->hide();
21071: $<pn>$->tp = $<pt>1;
21072: }
21073: | %prec NO_ID
21074: {
21075: $$ = new name;
21076: NOT_EXPECT_ID();
21077: }
21078: | ptr arg_decl %prec MUL
21079: { Ptyp($1) = $<pn>2->tp;
21080: $<pn>2->tp = (Ptype)$1;
21081: $$ = $2;
21082: }
21083: | arg_decl vec %prec LB
21084: { Vtype($2) = $<pn>1->tp;
21085: $<pn>1->tp = (Ptype)$2;
21086: }
21087: | arg_decl arg_list
21088: { Freturns($2) = $<pn>1->tp;
21089: $<pn>1->tp = (Ptype)$2;
21090: }
21091: /*
21092: | LP arg_decl RP arg_list
21093: { Freturns($4) = $<pn>2->tp;
21094: $<pn>2->tp = (Ptype)$4;
21095: $$ = $2;
21096: }
21097: | LP arg_decl RP vec
21098: { Vtype($4) = $<pn>2->tp;
21099: $<pn>2->tp = (Ptype)$4;
21100: $$ = $2;
21101: }
21102: */
21103: | arg_lp arg_decl RP
21104: {
21105: // error('d', "arg_lp arg_decl rp in_arg_list: %d", in_arg_list );
21106: $$ = $2;
21107: in_arg_list = 0;
21108: end_al($1,0);
21109: RESTORE_STATE();
21110: //POP_SCOPE(); // similar to end_al()
21111: }
21112: ;
21113:
21114: new_decl : %prec NO_ID
21115: { $$ = new name; }
21116: | ptr new_decl %prec MUL
21117: { Ptyp($1) = $<pn>2->tp;
21118: $<pn>2->tp = (Ptype)$1;
21119: $$ = $2;
21120: NOT_EXPECT_ID();
21121: }
21122: | new_decl vec %prec LB
21123: { Vtype($2) = $<pn>1->tp;
21124: $<pn>1->tp = (Ptype)$2;
21125: }
21126: ;
21127:
21128: cast_decl : %prec NO_ID { $$ = new name; }
21129: | ptr cast_decl %prec MUL
21130: { Ptyp($1) = $<pn>2->tp;
21131: $<pn>2->tp = (Ptype)$1;
21132: $$ = $2;
21133: NOT_EXPECT_ID();
21134: }
21135: | cast_decl vec %prec LB
21136: { Vtype($2) = $<pn>1->tp;
21137: $<pn>1->tp = (Ptype)$2;
21138: }
21139: | LP cast_decl RP arg_list
21140: { Freturns($4) = $<pn>2->tp;
21141: $<pn>2->tp = $<pt>4;
21142: $$ = $2;
21143: }
21144: | LP cast_decl RP vec
21145: { Vtype($4) = $<pn>2->tp;
21146: $<pn>2->tp = $<pt>4;
21147: $$ = $2;
21148: }
21149: ;
21150:
21151: c_decl : %prec NO_ID
21152: { $$ = new name; }
21153: | ptr c_decl %prec MUL
21154: { Ptyp($1) = $<pn>2->tp;
21155: $<pn>2->tp = (Ptype)$1;
21156: $$ = $2;
21157: }
21158: ;
21159:
21160:
21161:
21162: /***************** statements: returns Pstmt *****************/
21163: stmt_list : /* empty */
21164: {
21165: $$ = 0;
21166: }
21167: | stmt_list TEMPLATE
21168: {
21169: error( "ZizedTD must be atG, not local scope" );
21170: error('i', "cannot recover from previous error" );
21171: }
21172: | stmt_list caselab_stmt
21173: {
21174: if ($2)
21175: if ($1)
21176: $<sl>1->add($<ps>2);
21177: else {
21178: $<sl>$ = new slist($<ps>2);
21179: stmt_seen = 1;
21180: }
21181: }
21182: ;
21183: caselab_stmt : caselablist statement
21184: {
21185: $$ = $2;
21186: if ($2) stmt_seen = 1;
21187: }
21188: ;
21189:
21190: caselablist : /* empty */
21191: {
21192: $$ = 0;
21193: check_decl();
21194: }
21195: ;
21196:
21197: condition : LP e RP
21198: { $$ = $2;
21199: /* if ($<pe>$ == dummy) error("empty condition");*/
21200: stmt_seen = 1;
21201: }
21202: ;
21203:
21204: block : LC
21205: {//PUSH_BLOCK_SCOPE
21206: cd_vec[cdi] = cd;
21207: stmt_vec[cdi] = stmt_seen;
21208: tn_vec[cdi] = modified_tn;
21209: lcl_blk_vec[cdi++] = local_blk;
21210: lcl_tn_vec[cdi] = local_tn;
21211: local_blk = 0;
21212: local_tn = 0;
21213: cd = 0;
21214: stmt_seen = 0;
21215: modified_tn = 0;
21216: }
21217: stmt_list RC
21218: { Pname n = name_unlist(cd);
21219: Pstmt ss = stmt_unlist($<sl>3);
21220: $$ = new block($<l>1,n,ss,$<l>4);
21221: if ( local_tn ) local_restore();
21222: if ( local_blk ) local_name();
21223: if (modified_tn) restore();
21224: cd = cd_vec[--cdi];
21225: stmt_seen = stmt_vec[cdi];
21226: modified_tn = tn_vec[cdi];
21227: local_tn = lcl_tn_vec[cdi];
21228: local_blk = lcl_blk_vec[cdi];
21229: if (cdi < 0) error('i',"block level(%d)",cdi);
21230: NOT_EXPECT_ID();
21231: //POP_SCOPE(); // similar to end_al()
21232: }
21233: | LC RC
21234: { $$ = new block($<l>1,0,0,$<l>2); NOT_EXPECT_ID();}
21235: | LC error RC
21236: { $$ = new block($<l>1,0,0,$<l>3); NOT_EXPECT_ID();}
21237: ;
21238:
21239: simple : ee
21240: { $$ = new estmt(SM,curloc,$<pe>1,0); }
21241: | BREAK
21242: { $$ = new stmt(BREAK,$<l>1,0); }
21243: | CONTINUE
21244: { $$ = new stmt(CONTINUE,$<l>1,0); }
21245: | GOTO ID
21246: { $$ = new lstmt(GOTO,$<l>1,$<pn>2,0); }
21247: | DO { stmt_seen=1; } caselab_stmt WHILE condition
21248: { $$ = new estmt(DO,$<l>1,$<pe>5,$<ps>3); }
21249: | ASM LP STRING RP
21250: {
21251: if (stmt_seen)
21252: $$ = new estmt(ASM,curloc,(Pexpr)$<s>3,0);
21253: else {
21254: Pname n = new name(make_name('A'));
21255: n->tp = new basetype(ASM,(Pname)$<s>3);
21256: if (cd)
21257: cd->add_list(n);
21258: else
21259: cd = new nlist(n);
21260: $$ = 0;
21261: }
21262: }
21263: ;
21264:
21265: sm : {
21266: if ( NEXTTOK() != SM ) {
21267: error("`;' missing afterS");
21268: la_backup(yychar,yylval);
21269: yychar = SM;
21270: }
21271: } SM
21272: ;
21273:
21274: statement : simple sm
21275: | SM
21276: { $$ = new estmt(SM,$<l>1,dummy,0); }
21277: | RETURN e SM
21278: { $$ = new estmt(RETURN,$<l>1,$<pe>2,0); }
21279: | TYPE STRING block
21280: {
21281: error("local linkage specification");
21282: $$ = $<pn>3;
21283: }
21284: | data_dcl
21285: { Pname n = $<pn>1;
21286: if (n) {
21287: //error('d',"adding local dcl of%n%t ll %d in_typedef%t",n,n->tp,n->lex_level,in_typedef);
21288: if (stmt_seen) {
21289: $$ = new block(n->where,n,0);
21290: $<ps>$->base = DCL;
21291: }
21292: else {
21293: if (cd)
21294: cd->add_list(n);
21295: else
21296: cd = new nlist(n);
21297: $$ = 0;
21298: }
21299: } // if n
21300: }
21301: | att_fct_def
21302: {
21303: Pname n = $<pn>1;
21304: error(&n->where,"%n's definition is nested (did you forget a ``}''?)",n);
21305: if (cd)
21306: cd->add_list(n);
21307: else
21308: cd = new nlist(n);
21309: $$ = 0;
21310: }
21311: | block
21312: | IF condition caselab_stmt
21313: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,0); }
21314: | IF condition caselab_stmt ELSE caselab_stmt
21315: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,$<ps>5); }
21316: | WHILE condition caselab_stmt
21317: { $$ = new estmt(WHILE,$<l>1,$<pe>2,$<ps>3); }
21318: | FOR LP { stmt_seen=1; } caselab_stmt e SM e RP caselab_stmt
21319: { $$ = new forstmt($<l>1,$<ps>4,$<pe>5,$<pe>7,$<ps>9); }
21320: | SWITCH condition caselab_stmt
21321: { $$ = new estmt(SWITCH,$<l>1,$<pe>2,$<ps>3); }
21322: | ID COLON { $$ = $1; stmt_seen=1; } caselab_stmt
21323: { Pname n = $<pn>3;
21324: $$ = new lstmt(LABEL,n->where,n,$<ps>4);
21325: }
21326: | TNAME COLON { $$ = new name($<pn>1->string); stmt_seen=1; } caselab_stmt
21327: { Pname n = $<pn>3;
21328: $$ = new lstmt(LABEL,n->where,n,$<ps>4);
21329: }
21330: | CASE { stmt_seen=1; } e COLON caselab_stmt
21331: { if ($<pe>3 == dummy) error("empty case label");
21332: $$ = new estmt(CASE,$<l>1,$<pe>3,$<ps>5);
21333: }
21334: | DEFAULT COLON { stmt_seen=1; } caselab_stmt
21335: { $$ = new stmt(DEFAULT,$<l>1,$<ps>4); }
21336: ;
21337:
21338:
21339:
21340: /********************* expressions: returns Pexpr **************/
21341: elist : ex_list
21342: { Pexpr e = expr_unlist($<el>1);
21343: while (e && e->e1==dummy) {
21344: register Pexpr ee2 = e->e2;
21345: if (ee2) error("EX inEL");
21346: delete e;
21347: e = ee2;
21348: }
21349: $$ = e;
21350: }
21351: ;
21352:
21353: ex_list : initializer %prec CM
21354: { $<el>$ = new elist(new expr(ELIST,$<pe>1,0)); }
21355: | ex_list CM initializer
21356: { $<el>1->add(new expr(ELIST,$<pe>3,0)); }
21357: ;
21358:
21359: initializer : e %prec CM
21360: | LC elist RC
21361: {
21362: if ( in_arg_list )
21363: error( "syntax error: IrL not permitted in AL" );
21364: else if ( in_binit_list )
21365: error( "syntax error: IrL not permitted inMIr" );
21366: else
21367: init_seen = 1;
21368: Pexpr e;
21369: if ($2)
21370: e = $<pe>2;
21371: else
21372: e = new expr(ELIST,dummy,0);
21373: $$ = new expr(ILIST,e,0);
21374: }
21375: ;
21376:
21377: ee : ee ASSIGN ee
21378: { bbinop: $$ = new expr($<t>2,$<pe>1,$<pe>3); }
21379: | ee PLUS ee { goto bbinop; }
21380: | ee MINUS ee { goto bbinop; }
21381: | ee MUL ee { goto bbinop; }
21382: | ee AND ee { goto bbinop; }
21383: | ee OR ee { goto bbinop; }
21384: | ee ER ee { goto bbinop; }
21385: | ee SHIFTOP ee { goto bbinop; }
21386: | ee EQUOP ee { goto bbinop; }
21387: | ee DIVOP ee { goto bbinop; }
21388: | ee RELOP ee { goto bbinop; }
21389: | ee GT ee { goto bbinop; }
21390: | ee LT ee { goto bbinop; }
21391: | ee ANDAND ee { goto bbinop; }
21392: | ee OROR ee { goto bbinop; }
21393: | ee ASOP ee { goto bbinop; }
21394: | ee CM ee { goto bbinop; }
21395: | ee QUEST ee COLON ee
21396: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
21397: | DELETE term
21398: { $$ = new expr(DELETE,$<pe>2,0); }
21399: | DELETE LB e RB term
21400: {
21401: if($<pe>3 != dummy) {
21402: if ( warning_opt || strict_opt )
21403: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
21404: }
21405: $$ = new expr(DELETE,$<pe>5,$<pe>3);
21406: }
21407: | MEM DELETE term
21408: { $$ = new expr(GDELETE,$<pe>3,0); }
21409: | MEM DELETE LB e RB term
21410: {
21411: if($<pe>4 != dummy) {
21412: if ( warning_opt || strict_opt )
21413: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
21414: }
21415: $$ = new expr(DELETE,$<pe>6,$<pe>4);
21416: }
21417: | term
21418: ;
21419:
21420: e : e ASSIGN e
21421: { binop: $$ = new expr($<t>2,$<pe>1,$<pe>3); }
21422: | e PLUS e { goto binop; }
21423: | e MINUS e { goto binop; }
21424: | e MUL e { goto binop; }
21425: | e AND e { goto binop; }
21426: | e OR e { goto binop; }
21427: | e ER e { goto binop; }
21428: | e SHIFTOP e { goto binop; }
21429: | e EQUOP e { goto binop; }
21430: | e DIVOP e { goto binop; }
21431: | e RELOP e { goto binop; }
21432: | e LT e { goto binop; }
21433: | e GT e { goto binop; }
21434: | e ANDAND e { goto binop; }
21435: | e OROR e { goto binop; }
21436: | e ASOP e { goto binop; }
21437: | e CM e { goto binop; }
21438: | e QUEST e COLON e
21439: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
21440: | DELETE term
21441: { $$ = new expr(DELETE,$<pe>2,0); }
21442: | DELETE LB e RB term
21443: {
21444: if($<pe>3 != dummy) {
21445: if ( warning_opt || strict_opt )
21446: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
21447: }
21448: $$ = new expr(DELETE,$<pe>5,$<pe>3);
21449: }
21450: | MEM DELETE term
21451: { $$ = new expr(GDELETE,$<pe>3,0); }
21452: | MEM DELETE LB e RB term
21453: {
21454: if($<pe>4 != dummy) {
21455: if ( warning_opt || strict_opt )
21456: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
21457: }
21458: $$ = new expr(DELETE,$<pe>6,$<pe>4);
21459: }
21460: | term {
21461: init_seen = 0;
21462: }
21463: | %prec NO_EXPR
21464: { $$ = dummy; }
21465: ;
21466:
21467: term : NEW cast_type { goto new1; }
21468: | NEW new_type
21469: { new1:
21470: Ptype t = $<pn>2->tp;
21471: $$ = new texpr(NEW,t,0);
21472: }
21473: | MEM NEW cast_type { goto new3; }
21474: | MEM NEW new_type
21475: { new3:
21476: Ptype t = $<pn>3->tp;
21477: $$ = new texpr(GNEW,t,0);
21478: }
21479: | term ICOP
21480: { $$ = new expr($<t>2,$<pe>1,0); }
21481: | cast_type term %prec ICOP
21482: { $$ = new texpr(CAST,$<pn>1->tp,$<pe>2); }
21483: | MUL term
21484: { $$ = new expr(DEREF,$<pe>2,0); }
21485: | AND term
21486: { $$ = new expr(ADDROF,0,$<pe>2); }
21487: | MINUS term
21488: { $$ = new expr(UMINUS,0,$<pe>2); }
21489: | PLUS term
21490: { $$ = new expr(UPLUS,0,$<pe>2); }
21491: | NOT term
21492: { $$ = new expr(NOT,0,$<pe>2); }
21493: | COMPL term
21494: { $$ = new expr(COMPL,0,$<pe>2); }
21495: | ICOP term
21496: { $$ = new expr($<t>1,0,$<pe>2); }
21497: | SIZEOF term
21498: {
21499: $$ = new texpr(SIZEOF,0,$<pe>2);
21500: in_sizeof = 0;
21501: }
21502: | SIZEOF cast_type %prec SIZEOF
21503: {
21504: $$ = new texpr(SIZEOF,$<pn>2->tp,0);
21505: in_sizeof = 0;
21506: }
21507: | term LB e RB
21508: { $$ = new expr(DEREF,$<pe>1,$<pe>3); }
21509: | term REF prim
21510: { $$ = new ref(REF,$<pe>1,$<pn>3); }
21511: | term REFMUL term
21512: { $$ = new expr($<t>2,$<pe>1,$<pe>3); }
21513: | term REF qualified_tname
21514: { $$ = new ref(REF,$<pe>1,Ncopy($<pn>3)); }
21515: | term DOT prim
21516: { $$ = new ref(DOT,$<pe>1,$<pn>3); }
21517: | term DOT qualified_tname
21518: { $$ = new ref(DOT,$<pe>1,Ncopy($<pn>3)); }
21519: | prim
21520: | term_elist
21521: {
21522: if ( init_seen )
21523: error( "syntax error:IrL illegal within ()");
21524: }
21525:
21526: | term_lp e RP
21527: {
21528: if ( $2 == dummy )
21529: error("syntax error: nullE");
21530: $$ = $2;
21531: }
21532: | ZERO
21533: { $$ = zero; }
21534: | ICON
21535: { $$ = new expr(ICON,0,0);
21536: $<pe>$->string = copy_if_need_be($<s>1);
21537: }
21538: | FCON
21539: { $$ = new expr(FCON,0,0);
21540: $<pe>$->string = copy_if_need_be($<s>1);
21541: }
21542: | STRING
21543: { $$ = new expr(STRING,0,0);
21544: $<pe>$->string = copy_if_need_be($<s>1);
21545: }
21546: | CCON
21547: { $$ = new expr(CCON,0,0);
21548: $<pe>$->string = copy_if_need_be($<s>1);
21549: }
21550: | THIS
21551: { $$ = new expr(THIS,0,0); }
21552: ;
21553:
21554: term_elist : TYPE LP elist RP
21555: { $$ = new texpr(VALUE,tok_to_type($<t>1),$<pe>3); }
21556: /*
21557: | qualified_tname LP elist RP
21558: */
21559: | tname LP elist RP
21560: { $$ = new texpr(VALUE,$<pn>1->tp,$<pe>3); }
21561: | NEW term_lp elist RP cast_type { goto new2; }
21562: | NEW term_lp elist RP new_type /* allow separate allocation */
21563: { new2:
21564: Ptype t = $<pn>5->tp;
21565: $$=new texpr(NEW,t,0);
21566: $<pe>$->e2 = $<pe>3;
21567: }
21568: | MEM NEW term_lp elist RP cast_type { goto new4; }
21569: | MEM NEW term_lp elist RP new_type /* allow separate allocation */
21570: { new4:
21571: Ptype t = $<pn>6->tp;
21572: $$ = new texpr(GNEW,t,0);
21573: $<pe>$->e2 = $<pe>4;
21574: }
21575: | term LP elist RP
21576: {
21577: Pexpr ee = $<pe>3;
21578: Pexpr e = $<pe>1;
21579: if (e->base==NEW || e->base==GNEW)
21580: e->e1 = ee;
21581: else
21582: $$ = new call(e,ee);
21583: }
21584:
21585: ;
21586:
21587: ptname : PTNAME lt temp_inst_parms gt
21588: {
21589: $<pn>$ =parametrized_typename($<pn>1,(expr_unlist($<el>3)));
21590: }
21591: ;
21592:
21593: tscope : TSCOPE
21594: {
21595: $<pn>$ = $<pn>1;
21596: curr_scope = $<pn>1;
21597: }
21598: | MEM { $<pn>$ = sta_name; }
21599: | ptname TSCOPE { $<pn>$ = $<pn>1; }
21600: ;
21601:
21602:
21603: prim : ID
21604: { $$ = $<pn>1; }
21605: /*XXX*/ | tn_list ID
21606: { $$ = Ncopy($<pn>2);
21607: $<pn>$->n_qualifier = $<pn>1;
21608: }
21609: | OPERATOR oper
21610: { $$ = new name(oper_name($2));
21611: $<pn>$->n_oper = $<t>2;
21612: }
21613: | tn_list OPERATOR oper
21614: { $$ = new name(oper_name($3));
21615: $<pn>$->n_oper = $<t>3;
21616: $<pn>$->n_qualifier = $<pn>1;
21617: }
21618: | OPERATOR c_type
21619: { $$ = $2;
21620: sig_name($<pn>$);
21621: }
21622: | tn_list OPERATOR c_type
21623: { $$ = $3;
21624: sig_name($<pn>$);
21625: $<pn>$->n_qualifier = $<pn>1;
21626: }
21627: | tn_list COMPL tag /* allow explicit call of destructor */
21628: {
21629: if (strcmp($<pn>1->string,$<pn>3->string)) error("syntax error: inconsistent destructor notation");
21630: $$ = new name(oper_name(DTOR));
21631: $<pn>$->n_oper = DTOR;
21632: $<pn>$->n_qualifier = $<pn>1;
21633: }
21634: ;
21635:
21636:
21637:
21638: /****************** abstract types (return type Pname) *************/
21639: cast_type : term_lp type cast_decl RP
21640: { $$ = Ncast($2,$<pn>3); }
21641: ;
21642:
21643: term_lp : LP { check_cast(); }
21644: ;
21645:
21646: c_tp : TYPE
21647: {
21648: TOK t = $<t>1;
21649:
21650: switch (t) {
21651: case FRIEND:
21652: case OVERLOAD:
21653: case REGISTER:
21654: case STATIC:
21655: case EXTERN:
21656: case AUTO:
21657: case VIRTUAL:
21658: error("%k in operatorT",t);
21659: t = INT;
21660:
21661: }
21662:
21663: $$ = new basetype(t,0);
21664:
21665: }
21666: | tname { $$ = new basetype(TYPE,$<pn>1); }
21667: | c_tp TYPE
21668: {
21669: if ( DECL_TYPE != -1 ) {
21670: switch ($<pb>1->base) { Pbase bt;
21671: case COBJ: case EOBJ:
21672: bt = new basetype(0,0);
21673: *bt = *$<pb>1;
21674: DEL($<pb>1);
21675: $<pb>1 = bt;
21676: }
21677: $$ = $<pb>1->type_adj($<t>2);
21678: }
21679: DECL_TYPE = 0;
21680: }
21681: | c_tp tname
21682: {
21683: if ( DECL_TYPE != -1 )
21684: $$ = $<pb>1->name_adj($<pn>2);
21685: DECL_TYPE = 0;
21686: }
21687: ;
21688:
21689: c_type : c_tp c_decl { $$ = Ncast($1,$<pn>2); }
21690: ;
21691:
21692: new_type : type new_decl { $$ = Ncast($1,$<pn>2); };
21693:
21694: arg_type : type arg_decl
21695: {
21696: // ENTER_NAME($<pn>2);
21697: $$ = Ndata($1,$<pn>2);
21698: }
21699: | type arg_decl ASSIGN
21700: {
21701: // ENTER_NAME($<pn>2);
21702: }
21703: initializer
21704: { $$ = Ndata($1,$<pn>2);
21705: $<pn>$->n_initializer = $<pe>5;
21706: }
21707: ;
21708:
21709: arg_lp : LP
21710: {//PUSH_ARG_SCOPE
21711: SAVE_STATE();
21712: check_decl();
21713: in_arg_list=1;
21714: $$ = modified_tn;
21715: modified_tn = 0;
21716: }
21717: ;
21718:
21719: arg_list : arg_lp arg_type_list ellipsis_opt RP fct_attributes
21720: {
21721: $$ = new fct(0,name_unlist($<nl>2),$<t>3);
21722: if ( NEXTTOK() != COLON ) in_arg_list=0;
21723: //in_arg_list=0;
21724: Pfct($<pt>$)->f_const = ($<i>5 & 1);
21725: if ( parsing_class_members
21726: || (NEXTTOK()!=LC && yychar!=COLON)) {
21727: end_al($1,1);
21728: //POP_SCOPE(); // similar to end_al()
21729: } else
21730: end_al($1,0);
21731: RESTORE_STATE();
21732: }
21733: ;
21734:
21735: arg_type_list : arg_type_list CM at
21736: {
21737: if ($3)
21738: if ($1)
21739: $<nl>1->add($<pn>3);
21740: else {
21741: error("AD syntax");
21742: $<nl>$ = new nlist($<pn>3);
21743: }
21744: else
21745: error("AD syntax");
21746: }
21747: | at %prec CM
21748: {
21749: if ($1) $<nl>$ = new nlist($<pn>1);
21750: }
21751: ;
21752:
21753: at : arg_type
21754: | %prec EMPTY { $$ = 0; }
21755: ;
21756:
21757: ellipsis_opt : /* empty */
21758: { $$ = 1; }
21759: | ELLIPSIS
21760: { $$ = ELLIPSIS; }
21761: | CM ELLIPSIS
21762: { $$ = ELLIPSIS; }
21763: ;
21764:
21765: ptr : MUL %prec NO_ID
21766: {
21767: $$ = new ptr(PTR,0);
21768: EXPECT_ID();
21769: }
21770: | AND %prec NO_ID
21771: {
21772: $$ = new ptr(RPTR,0);
21773: EXPECT_ID();
21774: }
21775: | MUL TYPE %prec NO_ID
21776: { $$ = doptr(PTR,$<t>2); }
21777: | ptr TYPE %prec NO_ID
21778: {
21779: switch ( $<t>2 ) {
21780: case CONST:
21781: $<pp>1->rdo = 1; break;
21782: case VOLATILE:
21783: error('w',"\"volatile\" not implemented (ignored)");
21784: break;
21785: default:
21786: error( "syntax error: *%k", $<t>2 );
21787: }
21788: $$ = $<pp>1;
21789: }
21790: | AND TYPE %prec NO_ID
21791: { $$ = doptr(RPTR,$<t>2); }
21792: | ptname MEMPTR %prec NO_ID
21793: { goto memptr1; }
21794: | MEMPTR %prec NO_ID
21795: {
21796: memptr1:
21797: $$ = new ptr(PTR,0);
21798: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
21799: EXPECT_ID();
21800: }
21801: | ptname MEMPTR TYPE %prec NO_ID
21802: {
21803: $<t>2 = $<t>3;
21804: goto memptr2;
21805: }
21806: | MEMPTR TYPE %prec NO_ID
21807: {
21808: memptr2:
21809: $$ = doptr(PTR,$<t>2);
21810: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
21811: }
21812: ;
21813:
21814: vec : LB e RB { $$ = new vec(0,$<pe>2!=dummy?$<pe>2:0 ); }
21815: | NOT %prec LB { $$ = new vec(0,0); }
21816: ;
21817:
21818: %%
21819:
21820: static void
21821: check_tag()
21822: /*
21823: Allow the case of inline/virtual/overload as
21824: modifiers of return type of form struct/class/union x foo()
21825: SM, COLON, LC ==> real class declaration, not return type
21826: */
21827: {
21828: switch ( NEXTTOK() ) {
21829: case SM: case COLON: case LC:
21830: declTag = 1;
21831: break;
21832: default:
21833: declTag = 0;
21834: break;
21835: }
21836: }
21837:
21838: static void
21839: end_al( Plist mtn, int rst )
21840: // unhide type names hidden by arg names
21841: // mtn == saved modified_tn
21842: {
21843: if ( rst == 0 ) {
21844: // not really an arg list, or we are entering a function def
21845: // merge modified_tn and don't restore
21846: if ( modified_tn == 0 ) modified_tn = mtn;
21847: else {
21848: for ( Plist l = modified_tn; l->l; l = l->l ) ;
21849: l->l = mtn;
21850: }
21851: } else {
21852: restore();
21853: modified_tn = mtn;
21854: }
21855: }
21856: static void
21857: arg_redec( Pname fn )
21858: {
21859: if ( fn==0 || fn->tp->base != FCT )
21860: error('i',"bad inline rewrite!");
21861: Pname al = Pfct(fn->tp)->argtype;
21862: Pname n = 0;
21863: for ( ; al; al = al->n_list ) {
21864: DB( if(Ydebug>=1)error('d',"arg_redec: %n %d",al,al->lex_level); );
21865: // nested function args should have lex_level >= 1
21866: if ( al->lex_level==1 && (n=ktbl->look(al->string,0)) )
21867: n->hide();
21868: else if ( al->lex_level>1 && (n=ktbl->look(al->string,LOCAL)) )
21869: n->hide();
21870: DB( if(Ydebug>=1)error('d'," %n",n); );
21871: }
21872: }
21873:
21874:
21875: 0707071010112046011004440001630000160000010211100466055415400000700000014643hash.c /* ident "@(#)ctrans:src/hash.c 1.2" */
21876: /*
21877: $Header: /usr2/odi/libmisc/RCS/hash.C,v 1.11 90/03/22 09:24:07 sam Exp $
21878:
21879: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
21880: All rights reserved.
21881:
21882: */
21883:
21884: #include <stdio.h>
21885: #include "hash.h"
21886: #include <osfcn.h>
21887:
21888: #define EMPTY 0
21889: #define VALID 1
21890: #define DELETED 2
21891:
21892: void default_Hash_error_handler(const char* msg)
21893: {
21894: fprintf(stderr, "Fatal Hash error: %s\n", msg) ;
21895: exit(1) ;
21896: }
21897:
21898: Error_Proc Hash_error_handler = default_Hash_error_handler ;
21899:
21900: Error_Proc set_Hash_error_handler(Error_Proc f)
21901: {
21902: Error_Proc old = Hash_error_handler ;
21903: Hash_error_handler = f ;
21904: return old ;
21905: }
21906:
21907: void Hash::error(const char* msg)
21908: {
21909: (*Hash_error_handler)(msg) ;
21910: }
21911:
21912: Hash::Hash(int sz= DEFAULT_INITIAL_HASH_SIZE)
21913: {
21914: tab = new HashTableEntry[size = sz] ;
21915: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
21916: entry_count = 0 ;
21917: }
21918:
21919: Hash::Hash(Hash& a)
21920: {
21921: tab = new HashTableEntry[size = a.size] ;
21922:
21923: key_hash_function = a.key_hash_function ;
21924: key_key_equality_function = a.key_key_equality_function ;
21925:
21926: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
21927: entry_count = 0 ;
21928: for (HashWalker p(a); p; p.advance())
21929: (*this)[p.key()] = p.get() ;
21930: }
21931:
21932: Hash& Hash::operator = (Hash& a)
21933: {
21934: if (a.tab != tab)
21935: {
21936: clear() ;
21937: delete [size] tab ;
21938: tab = new HashTableEntry[size = a.size] ;
21939: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
21940: entry_count = 0 ;
21941: for (HashWalker p(a); p; p.advance())
21942: (*this)[p.key()] = p.get() ;
21943: }
21944: return *this ;
21945: }
21946:
21947: /*
21948: * hashing method: double hash based on high bits of hash fct,
21949: * followed by linear probe. Can't do too much better if Assoc
21950: * sizes not constrained to be prime.
21951: */
21952:
21953:
21954: static inline doublehashinc(unsigned int h, int s)
21955: {
21956: return ((h / s) % s) >> 1 ;
21957: }
21958:
21959: // IWBNI we knew whether we were being called as an lvalue or rvalue.
21960: // If the former, then we wouldn't have to scan through the whole
21961: // table just to tell if we should rehash or not. Sigh.
21962: int& Hash::operator [](int key)
21963: {
21964: unsigned int hashval = key_hash(key) ;
21965: while (1)
21966: {
21967: int bestspot = -1 ;
21968: int h = hashval % size ;
21969: for (int i = 0; i <= size; ++i)
21970: {
21971: if (tab[h].status == EMPTY)
21972: {
21973: // resize if the hash table is more than 87.5% full
21974: if (entry_count > ((size>>1)+(size>>2)+(size>>3)))
21975: // resize and insert again
21976: break ;
21977: if (bestspot < 0) bestspot = h ;
21978: tab[bestspot].key = key ;
21979: tab[bestspot].status = VALID ;
21980: ++entry_count ;
21981: return tab[bestspot].cont ;
21982: }
21983: else if (tab[h].status == DELETED)
21984: {
21985: if (bestspot < 0) bestspot = h ;
21986: }
21987: else if (key_key_eq(tab[h].key, key))
21988: return tab[h].cont ;
21989: if (i == 0)
21990: h = (h + doublehashinc(hashval, size)) % size ;
21991: else if (++h >= size)
21992: h -= size ;
21993: }
21994: resize(size << 1) ;
21995: }
21996: }
21997:
21998: /* This seems convoluted, but it does whatever you want without
21999: redundant probing of the hash table. */
22000:
22001: void Hash::action (int key, int val, insert_action what,
22002: int& found, int& old_val)
22003: {
22004: unsigned int hashval = key_hash(key) ;
22005: while (1)
22006: {
22007: int bestspot = -1 ;
22008: int h = hashval % size ;
22009: for (int i = 0; i <= size; ++i)
22010: {
22011: if (tab[h].status == EMPTY)
22012: {
22013: // resize if the hash table is more than 87.5% full
22014: if (entry_count > ((size>>1)+(size>>2)+(size>>3)))
22015: // resize and insert again
22016: break ;
22017: if (bestspot < 0) bestspot = h ;
22018: found = 0;
22019: if(what != probe) {
22020: tab[bestspot].key = key ;
22021: tab[bestspot].status = VALID ;
22022: ++entry_count ;
22023: tab[bestspot].cont = val;
22024: }
22025: return;
22026: }
22027: else if (tab[h].status == DELETED)
22028: {
22029: if (bestspot < 0) bestspot = h ;
22030: }
22031: else if (key_key_eq(tab[h].key, key)) {
22032: found = 1;
22033: old_val = tab[h].cont;
22034: if(what == replace)
22035: tab[h].cont = val;
22036: return;
22037: }
22038: if (i == 0)
22039: h = (h + doublehashinc(hashval, size)) % size ;
22040: else if (++h >= size)
22041: h -= size ;
22042: }
22043: resize(size << 1) ;
22044: }
22045: }
22046:
22047: int Hash::contains(int key)
22048: {
22049: unsigned int hashval = key_hash(key) ;
22050: int h = hashval % size ;
22051: for (int i = 0; i <= size; ++i)
22052: {
22053: if (tab[h].status == EMPTY)
22054: return 0 ;
22055: else if (tab[h].status == VALID && key_key_eq(tab[h].key, key))
22056: return 1 ;
22057: if (i == 0)
22058: h = (h + doublehashinc(hashval, size)) % size ;
22059: else if (++h >= size)
22060: h -= size ;
22061: }
22062: return 0 ;
22063: }
22064:
22065: int Hash::del(int key)
22066: {
22067: unsigned int hashval = key_hash(key) ;
22068: int h = hashval % size ;
22069: for (int i = 0; i <= size; ++i)
22070: {
22071: if (tab[h].status == EMPTY)
22072: return 0 ;
22073: else if (tab[h].status == VALID && key_key_eq(tab[h].key, key))
22074: {
22075: tab[h].status = DELETED ;
22076: --entry_count ;
22077: return 1 ;
22078: }
22079: if (i == 0)
22080: h = (h + doublehashinc(hashval, size)) % size ;
22081: else if (++h >= size)
22082: h -= size ;
22083: }
22084: return 0 ;
22085: }
22086:
22087: void Hash::apply(intProc f)
22088: {
22089: for (int i = 0; i < size; ++i)
22090: if (tab[i].status == VALID)
22091: (*f)(tab[i].cont) ;
22092: }
22093:
22094: void Hash::clear()
22095: {
22096: for (int i = 0; i < size; ++i)
22097: tab[i].status = EMPTY ;
22098: entry_count = 0 ;
22099: }
22100:
22101: void Hash::resize(int newsize)
22102: {
22103: if (newsize < entry_count)
22104: error("requested resize too small") ;
22105: HashTableEntry* oldtab = tab ;
22106: int oldsize = size ;
22107: tab = new HashTableEntry[size = newsize] ;
22108: for (int i = 0; i < size; ++i)
22109: tab[i].status = EMPTY ;
22110: entry_count = 0 ;
22111: for (i = 0; i < oldsize; ++i)
22112: if (oldtab[i].status == VALID)
22113: (*this)[oldtab[i].key] = oldtab[i].cont ;
22114: delete [oldsize] oldtab ;
22115: }
22116:
22117: void HashWalker::reset()
22118: {
22119: for (pos = 0; pos < h->size; ++pos)
22120: if (h->tab[pos].status == VALID)
22121: return ;
22122: pos = -1 ;
22123: }
22124:
22125: void HashWalker::advance()
22126: {
22127: if (pos < 0)
22128: return ;
22129: for (pos++; pos < h->size; ++pos)
22130: if (h->tab[pos].status == VALID)
22131: return ;
22132: pos = -1 ;
22133: }
22134:
22135: /*
22136: unsigned int foo(int bar) {return bar;}
22137: int baz(int a, int b) {return a == b;}
22138:
22139: main()
22140: {
22141: Hash vh(10) ;
22142: HashWalker vt(vh) ;
22143: int i ;
22144:
22145: vh.key_hash_function = &foo ;
22146: vh.key_key_equality_function = baz ;
22147: printf("Capacity=%d \n", vh.capacity()) ;
22148: for (i=0; i<500; i+= 5)
22149: {
22150: vh[i] = i * i ;
22151: }
22152: vt.reset() ;
22153: while (vt.valid())
22154: {
22155: printf("key=%d, data=%d\t", vt.key(), vt.get());
22156: vt.advance() ;
22157: }
22158: for (i=0; i<500; i+= 10)
22159: {
22160: vh.del (i) ;
22161: printf("After delete: %d\n", vh[i]);
22162: }
22163: printf("\n-----------------\n") ;
22164: vt.reset() ;
22165: while (vt.valid())
22166: {
22167: printf("key=%d, data=%d\t", vt.key(), vt.get());
22168: vt.advance() ;
22169: }
22170: }
22171:
22172: */
22173: 0707071010112046061004440001630000160000010212400466055420200000700000011465hash.h /* ident "@(#)ctrans:src/hash.h 1.2" */
22174: /* Compiler interface to hash tables from odi library.
22175: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/hash.h,v $ $RCSfile: hash.h,v $
22176: $Revision: 1.1 $ $Date: 89/11/20 08:50:36 $
22177: $Author: benson $ $Locker: $
22178: $State: Exp $
22179:
22180: $Header: /usr2/odi/objectstore.src/libos/RCS/hash.H,v 1.4 89/09/26 09:37:31 benson Exp $
22181:
22182: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
22183: All rights reserved.
22184:
22185: */
22186:
22187: #ifndef _HASH_H
22188: #define _HASH_H
22189:
22190: #include <string.h>
22191:
22192: typedef void (*Error_Proc) (const char*) ;
22193:
22194: extern void default_Hash_error_handler (const char*) ;
22195: extern Error_Proc Hash_error_handler ;
22196: extern Error_Proc set_Hash_error_handler (Error_Proc f) ;
22197:
22198: #ifndef _hash_typedefs
22199: #define _hash_typedefs 1
22200: typedef void (*intProc)(int) ;
22201: #endif
22202:
22203: #define DEFAULT_INITIAL_HASH_SIZE 100
22204:
22205: struct HashTableEntry
22206: {
22207: int key ;
22208: int cont ;
22209: char status ;
22210: } ;
22211:
22212: class HashWalker ;
22213:
22214: class Hash
22215: {
22216: friend class HashWalker ;
22217:
22218: HashTableEntry* tab ;
22219: int size ;
22220: int entry_count ;
22221:
22222: public:
22223: unsigned int (*key_hash_function)(int) ;
22224: int (*key_key_equality_function) (int, int) ;
22225:
22226: unsigned int key_hash(int a) ;
22227: int key_key_eq(int a, int b);
22228:
22229: Hash(int sz) ;
22230: Hash(Hash& a) ;
22231: ~Hash() ;
22232:
22233: Hash& operator= (Hash& a) ;
22234:
22235: int count() ;
22236: int empty() ;
22237: int full() ;
22238: int capacity() ;
22239:
22240: void clear() ;
22241: void resize(int newsize) ;
22242:
22243: enum insert_action { probe, insert, replace };
22244: void action (int key, int val, insert_action what,
22245: int& found, int& old_val);
22246: int& operator [] (int k) ;
22247: int contains(int key) ;
22248: int del(int key) ;
22249:
22250: void apply (intProc f) ;
22251: void error(const char* msg) ;
22252: } ;
22253:
22254: class HashWalker
22255: {
22256: Hash* h ;
22257: int pos ;
22258:
22259: public:
22260: HashWalker(Hash& l) ;
22261: ~HashWalker() ;
22262:
22263: int null() ;
22264: int valid() ;
22265: operator void* () ;
22266: int operator ! () ;
22267: void advance() ;
22268: void reset() ;
22269: void reset(Hash& l) ;
22270: const int& key() ;
22271: int& get() ;
22272: } ;
22273:
22274: inline unsigned int Hash::key_hash(int a)
22275: {
22276: #ifdef HASHFUNCTION
22277: return HASHFUNCTION(a) ;
22278: #else
22279: return (*key_hash_function)(a) ;
22280: #endif
22281: }
22282:
22283: inline int Hash::key_key_eq(int a, int b)
22284: {
22285: #ifdef EQUALITYFUNCTION
22286: return EQUALITYFUNCTION(a, b) ;
22287: #else
22288: return (*key_key_equality_function)(a, b) ;
22289: #endif
22290: }
22291:
22292:
22293: inline Hash::~Hash()
22294: {
22295: delete [size] tab ;
22296: }
22297:
22298: inline int Hash::count()
22299: {
22300: return entry_count ;
22301: }
22302:
22303: inline int Hash::empty()
22304: {
22305: return entry_count == 0 ;
22306: }
22307:
22308: inline int Hash::full()
22309: {
22310: return entry_count == size ;
22311: }
22312:
22313: inline int Hash::capacity()
22314: {
22315: return size ;
22316: }
22317: inline HashWalker::HashWalker(Hash& a)
22318: {
22319: h = &a ;
22320: reset() ;
22321: }
22322:
22323: inline void HashWalker::reset(Hash& a)
22324: {
22325: h = &a ;
22326: reset() ;
22327: }
22328:
22329:
22330: inline HashWalker::~HashWalker() {}
22331:
22332: inline int HashWalker::null()
22333: {
22334: return pos < 0 ;
22335: }
22336:
22337: inline int HashWalker::valid()
22338: {
22339: return pos >= 0 ;
22340: }
22341:
22342: inline HashWalker::operator void* ()
22343: {
22344: return (pos < 0)? 0 : this ;
22345: }
22346:
22347: inline int HashWalker::operator ! ()
22348: {
22349: return (pos < 0) ;
22350: }
22351:
22352:
22353: inline const int& HashWalker::key()
22354: {
22355: if (pos < 0)
22356: h->error("operation on null Walker") ;
22357: return h->tab[pos].key ;
22358: }
22359:
22360: inline int& HashWalker::get()
22361: {
22362: if (pos < 0)
22363: h->error("operation on null Walker") ;
22364: return h->tab[pos].cont ;
22365: }
22366:
22367: inline int pointer_hasheq (int a, int b)
22368: {
22369: return a == b;
22370: };
22371:
22372: inline unsigned int pointer_hash_fcn (int x)
22373: {
22374: unsigned X = (unsigned) x;
22375: return ((X << 16) | (X >> 16)) ^ x;
22376: }
22377:
22378: class pointer_hash : public Hash {
22379: public:
22380: pointer_hash (int sz = 0) : Hash (sz) {
22381: key_hash_function = pointer_hash_fcn;
22382: key_key_equality_function = pointer_hasheq;
22383: }
22384:
22385: pointer_hash (pointer_hash& h) : Hash (h) {};
22386: };
22387:
22388: inline int string_hasheq (int a, int b)
22389: {
22390: return !strcmp((char *)a, (char *) b);
22391: };
22392:
22393: static unsigned int string_hash_fcn (int x)
22394: {
22395: char * str = (char *)x;
22396: int l = strlen(str);
22397:
22398: if(x <= 4) return str[0];
22399: else {
22400: unsigned int * f4 = (unsigned int *) str;
22401: if (l < 8) return ((*f4 << 16) | (*f4 >> 16)) ^ *f4;
22402: else {
22403: unsigned int * s4 = f4 ++;
22404: return ((*f4 << 16) | (*f4 >> 16)) ^ *s4;
22405: }
22406: }
22407: };
22408:
22409:
22410: class string_hash : public Hash {
22411: public:
22412:
22413: string_hash (int sz = 0) : Hash (sz) {
22414: key_hash_function = string_hash_fcn;
22415: key_key_equality_function = string_hasheq;
22416: };
22417:
22418: string_hash (string_hash& h) : Hash (h) {};
22419: };
22420:
22421: #endif
22422: 0707071010112046071004440001630000160000010210470466055420500001500000001056ios_printf.h /* ident "@(#)ctrans:src/ios_printf.h 1.2" */
22423: /* Begin iostream_printf.H -- printf functions that work on ostreams.
22424: someday, perhaps, scanf functions for istreams. */
22425:
22426: #include <stdarg.h>
22427: #include <iostream.h>
22428:
22429: int vostream_printf(const char *format, va_list argp, ostream& fp);
22430: int ostream_printf(ostream& stream, const char * format ...);
22431:
22432: // returns count of characters added.
22433: int printf_to_string (char * string, int length, const char * format ...);
22434:
22435: // returns string which came from malloc.
22436: char * printf_to_alloc_string (const char * format ...);
22437: 0707071010112044331004440001630000160000010202700466055403600001000000134002lalex.c /*ident "@(#)ctrans:src/lalex.c 1.15" */
22438: /**************************************************************************
22439:
22440: C++ source for cfront, the C++ compiler front-end
22441: written in the computer science research center of Bell Labs
22442:
22443: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
22444: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
22445:
22446: lalex.c:
22447:
22448: lookahead
22449:
22450: *****************************************************************************/
22451: #include <stdio.h>
22452:
22453: #ifdef c_plusplus
22454: overload is_empty;
22455: #endif
22456:
22457: #include "cfront.h"
22458: #include "yystype.h"
22459: #include "tqueue.h"
22460: #include "template.h"
22461:
22462: #ifdef DBG
22463: #define LDB(val,a) { if(Ldebug>=val) {a;} }
22464: #else
22465: #define LDB(val,a) /**/
22466: #endif
22467:
22468: #ifdef DBG
22469: static char*
22470: image( int t )
22471: {
22472: if(keys[t]) return keys[t];
22473: else { static char b[20];
22474: sprintf(b,"token(%d)",t);
22475: return b;
22476: }
22477: }
22478: static void
22479: printok( toknode* t )
22480: {
22481: switch(t->tok) {
22482: default:
22483: fprintf(stderr,"\t%s",image(t->tok));
22484: break;
22485: case ID: case ICON: case CCON: case FCON: case STRING:
22486: fprintf(stderr,"ID '%s'",t->retval.s);
22487: break;
22488: case TNAME:
22489: fprintf(stderr,"TNAME '%s'",t->retval.pn->string);
22490: break;
22491: case PTNAME:
22492: fprintf(stderr,"PTNAME '%s'",t->retval.pn->string);
22493: break;
22494: case TSCOPE:
22495: fprintf(stderr,"TSCOPE '%s'::",t->retval.pn->string);
22496: break;
22497: case MEMPTR:
22498: fprintf(stderr,"MEMPTR '%s'::*",t->retval.pn->string);
22499: break;
22500: }
22501: putc(' ',stderr);
22502: t->place.put(stderr);
22503: putc('\n',stderr);
22504: }
22505: static void
22506: showQ( char* where )
22507: /*
22508: display token Q
22509: */
22510: {
22511: fprintf(stderr,"TOKEN Q (%s):\n",where);
22512: for (register toknode* t = front; t; t = t->next) printok(t);
22513: putc('\n',stderr);
22514: }
22515: #endif
22516:
22517: int bl_level;
22518:
22519: static int laexpr( TOK );
22520: static int latype( TOK );
22521: static int la_decl();
22522: static TOK lookahead();
22523:
22524: /* make this a toknode! */
22525: static int lasttk = 0; // one token history
22526: static YYSTYPE lastval; // yylval lasttk value
22527:
22528: int must_be_expr = 0; // handle redundant parentheses
22529: int must_be_id = 0; // !0, TNAME => ID, i.e., int X
22530:
22531: loc curloc;
22532: int curr_file;
22533:
22534: toknode* latok; // current lookahead token
22535: toknode* front = 0;
22536: toknode* rear = 0;
22537:
22538: const TQCHUNK = 16;
22539:
22540: void*
22541: toknode::operator new(size_t)
22542: {
22543: register toknode* p;
22544:
22545: if ((p=free_toks) == 0) {
22546: register toknode* q;
22547: free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) );
22548: p = free_toks;
22549: for (; q != &p[TQCHUNK-1]; q->next = q+1, ++q);
22550: q->next = 0;
22551: }
22552: free_toks = p->next;
22553: return p;
22554: }
22555:
22556: toknode::toknode(TOK t, YYSTYPE r, loc tloc)
22557: {
22558: tok = t;
22559: used = 0;
22560: retval = r;
22561: place = tloc;
22562: next = last = 0;
22563: }
22564:
22565: void
22566: toknode::operator delete(void* vp,size_t)
22567: {
22568: register toknode* p = (toknode*)vp;
22569: p->next = free_toks;
22570: free_toks = p;
22571: vp = 0;
22572: }
22573:
22574: #define USE_TOKEN(T,W) \
22575: LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \
22576: if ( !(T)->used ) use_token(T);
22577:
22578: Ptype
22579: return_nstd_local_type( Pname n, TOK &sw )
22580: {
22581: Ptype tt;
22582: switch ( n->tp->base ) {
22583: case EOBJ:
22584: case COBJ:
22585: tt = Pbase(n->tp)->b_name->tp;
22586: sw = n->tp->base;
22587: break;
22588: default:
22589: tt = n->tpdef;
22590: sw = NESTED; // in repr.c, prints ``typedef''
22591: break;
22592: }
22593: return tt;
22594: }
22595:
22596: static Pname
22597: local_nested_kludge( Pname n, Pname tn )
22598: /*
22599: * for backward compatibility with 2.0
22600: * in transitional model of nested class types
22601: *
22602: * struct T { ... };
22603: * foobar() {
22604: * class X {
22605: * typedef int T;
22606: * // ...
22607: * };
22608: * T t;
22609: * }
22610: *
22611: * pure nested classes, choose global struct T{};
22612: * no nested classes, choose typedef int T
22613: * transitional model: choose typedef, and generate warning
22614: * BUG: local typedefs and enums do not have lex_level set
22615: */
22616: {
22617: // error( 'd', "local_nested_kludge: n: %n", n );
22618: for ( Pname nn = n; nn; nn = nn->n_tbl_list )
22619: {
22620: Pname local_class;
22621: TOK ntd;
22622: if ( nn->n_key != NESTED ) continue;
22623: Ptype tt = return_nstd_local_type(nn,ntd);
22624: Pclass cl = tt->in_class;
22625: while ( cl->in_class ) cl = cl->in_class;
22626: if (cl->lex_level &&
22627: (local_class = ktbl->look(cl->string,LOCAL)))
22628: {
22629: // same typedef at nested and non-nested scope
22630: if (ntd == NESTED && tn && tn->tp == nn->tp )
22631: ;
22632: else
22633: error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string);
22634:
22635: /*
22636: if ( ntd == NESTED && nn->n_dcl_printed != 2 ) {
22637: nn->dcl_print(0);
22638: nn->n_dcl_printed = 2;
22639: }
22640: */
22641: return nn;
22642: }
22643: }
22644: return 0;
22645: }
22646:
22647: enum { one_back, two_back };
22648:
22649: static void
22650: use_token( toknode* T )
22651: /*
22652: lookup TNAMEs here instead of in tlex()
22653: maintain block level
22654: */
22655: {
22656: static TOK last_tokens[2]; // TSCOPE not reduced at this point
22657: static Pname last_tname; // tname :: id, where id is nested class
22658: static Pname tdef_name; // typedef tname tdef_name
22659: T->used = 1;
22660:
22661: DB(if(Ldebug>=1) {
22662: error('d',&T->place,"\n*** use_token(%k )",T->tok);
22663: printok(T);
22664: error('D',&T->place," lasttk%k last_tname%n last tokens%k%k",lasttk,last_tname,last_tokens[one_back],last_tokens[two_back]);
22665: });
22666:
22667: switch ( T->tok ) {
22668: case ID:
22669: Pname n;
22670: // error('d', &T->place, "use_token: %s", T->retval.s );
22671: if ( last_tokens[one_back] == MEM &&
22672: last_tokens[two_back] == TNAME &&
22673: (n=ktbl->look(T->retval.s,NESTED)))
22674: { // TYPEDEF :: ID, nested class ctor
22675: if (tdef_name && tdef_name->n_key==NESTED &&
22676: strcmp(tdef_name->string,n->string)==0)
22677: {
22678: T->tok = TNAME;
22679: T->retval.pn = n;
22680: break;
22681: }
22682: else { // TNAME :: ID, where ID may be nested class
22683: for ( Pname nn = n; nn; nn = nn->n_tbl_list )
22684: {
22685: TOK sw;
22686: if ( nn->n_key != NESTED ) continue;
22687: Ptype tt = return_nstd_local_type(nn,sw);
22688: Pclass cl = tt->in_class;
22689: if (strcmp(last_tname->string,cl->string)==0)
22690: {
22691: T->tok = TNAME;
22692: T->retval.pn = nn;
22693: break;
22694: }
22695: }
22696: }
22697: }
22698: else
22699: if ( bl_level &&
22700: // TNAME:: and :: cannot refer to ``local'' TNAME
22701: last_tokens[one_back] != MEM &&
22702: (n=ktbl->look(T->retval.s,LOCAL)) )
22703: {
22704: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) );
22705: T->tok = TNAME;
22706: T->retval.pn = n;
22707: }
22708: else if ( n=ktbl->look(T->retval.s,0) ) {
22709: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token:GC instance: %n", n ) );
22710: // error( 'd', &T->place, "use_token:GC instance: %n %t", n, n->tp );
22711:
22712: // X:: ?, then n cannot be a global TNAME
22713: // except in the case of a constructor
22714: if (last_tokens[one_back] == MEM &&
22715: last_tokens[two_back] == TNAME &&
22716: strcmp(T->retval.s,last_tname->string))
22717: ; // do nothing; i.e., return ID
22718: else
22719: if ( bl_level && n->tp->base != COBJ &&
22720: last_tokens[one_back] == MEM &&
22721: last_tokens[two_back] != TNAME &&
22722: gtbl->look(T->retval.s,0))
22723: ; // do nothing: local typedefs & enums not implemented
22724: else {
22725: Pname nn = 0;
22726: TOK ntd;
22727: if (bl_level && (nn=ktbl->look(T->retval.s,NESTED)))
22728: {
22729: (void) return_nstd_local_type(n,ntd);
22730: nn = local_nested_kludge(nn,ntd==NESTED?n:0);
22731: }
22732: T->tok = TNAME;
22733: T->retval.pn = nn?nn:n;
22734: }
22735: }
22736: #ifdef DBG
22737: else if(Ldebug>=1)
22738: error('d',&T->place,"use_token: id %s",T->retval.s);
22739: #endif
22740: break;
22741: case LC: ++bl_level; break;
22742: case RC: --bl_level; break;
22743: }
22744:
22745: if (T->tok != COMPL || last_tokens[one_back] != MEM) {
22746: last_tokens[two_back] = last_tokens[one_back];
22747: last_tokens[one_back] = T->tok;
22748: if (T->tok == TNAME) last_tname = T->retval.pn;
22749: if ( last_tname &&
22750: last_tname->tp->base == TYPE )
22751: {
22752: tdef_name = last_tname;
22753: do
22754: tdef_name = Pbase(tdef_name->tp)->b_name;
22755: while ( tdef_name->tp->base == TYPE );
22756: }
22757: }
22758: }
22759:
22760: void
22761: addtok(TOK t, YYSTYPE r, loc tloc)
22762: {
22763: toknode* T = new toknode(t,r,tloc);
22764: if (front == 0)
22765: front = rear = T;
22766: else {
22767: rear->next = T;
22768: T->last = rear;
22769: rear = T;
22770: }
22771: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:"");
22772: //showQ("addtok");
22773: }
22774:
22775: extern TOK
22776: deltok( int noset = 0 )
22777: {
22778: register toknode* T = front;
22779: USE_TOKEN(T,"deltok");
22780: register TOK tk = T->tok;
22781: if ( !noset ) { yylval = T->retval; curloc = T->place; }
22782: curr_file = curloc.file;
22783: if (front = front->next)
22784: front->last = 0;
22785: else
22786: latok = rear = 0;
22787: delete T;
22788: return tk;
22789: }
22790:
22791: static void
22792: add_tokens()
22793: /*
22794: extend lookahead token queue when depleted
22795: */
22796: {
22797: TOK tk = tlex();
22798: if ( tk != ID )
22799: return;
22800:
22801: while (tk == ID || tk == MEM || tk == DOT )
22802: tk = tlex();
22803: }
22804:
22805: extern TOK
22806: la_look()
22807: /*
22808: peek at head of token queue
22809: */
22810: {
22811: LDB(1,fprintf(stderr,"\n*** la_look()"));
22812: if ( front == 0 )
22813: add_tokens();
22814:
22815: latok = front;
22816: USE_TOKEN(latok,"la_look");
22817: LDB(1,fprintf(stderr," -- %s\n",image(latok->tok)));
22818: return latok->tok;
22819: }
22820:
22821: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar )
22822: void
22823: check_decl()
22824: /*
22825: Lookahead to direct parsing of local/arg type declarations
22826: la_decl() returns 1 if lookahead sees a declaration.
22827: */
22828: {
22829: TOK tk2;
22830: switch( NEXTTOK() ) {
22831: default:
22832: break;
22833: case TSCOPE: //XXX
22834: tk2 = la_look();
22835: while ( tk2 == TSCOPE ) tk2 = lookahead();
22836: if ( tk2 == TNAME ) {
22837: toknode* t = latok;
22838: if(t->tok!=TNAME)
22839: error('i',&t->place,"check_decl() token scan");
22840: tk2 = lookahead();
22841: if ( tk2 == LP && la_decl() ) {
22842: t->tok = DECL_MARKER; //TNAME
22843: }
22844: }
22845: break;
22846: case TYPE: case TNAME:
22847: if ( la_look() == LP && la_decl() ) {
22848: must_be_id = 0;
22849: DECL_TYPE=yychar;
22850: yychar = DECL_MARKER;
22851: }
22852: }
22853: }
22854:
22855: void
22856: check_cast()
22857: /*
22858: Lookahead to direct parsing of cast
22859: la_cast() returns 1 if lookahead sees an ambiguous old-style C cast.
22860: */
22861: {
22862: TOK tk2;
22863: switch( NEXTTOK() ) {
22864: case TSCOPE: //XXX
22865: tk2 = la_look();
22866: while ( tk2 == TSCOPE ) tk2 = lookahead();
22867: if ( tk2 == TNAME ) {
22868: toknode* t = latok;
22869: if(t->tok!=TNAME)
22870: error('i',&t->place,"check_cast() token scan");
22871: tk2 = lookahead();
22872: if ( tk2 == LP && la_decl() ) {
22873: t->tok = DECL_MARKER;//TNAME
22874: }
22875: }
22876: break;
22877: case TYPE: case TNAME:
22878: if ( la_look() == LP && la_cast() ) {
22879: must_be_id = 0;
22880: DECL_TYPE = yychar;
22881: yychar = DECL_MARKER;
22882: }
22883: }
22884: }
22885:
22886:
22887: static int
22888: latype( TOK t )
22889: {
22890: switch ( t ) {
22891: default: // includes friend, typedef, storage classes, etc.
22892: return 0;
22893: case CHAR: case SHORT: case INT: case LONG:
22894: case FLOAT: case DOUBLE:
22895: case UNSIGNED:
22896: return 1;
22897: }
22898: }
22899:
22900: static int
22901: laexpr( TOK t )
22902: {
22903: switch ( t ) {
22904: default:
22905: return 0;
22906: case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR:
22907: case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS:
22908: case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP:
22909: case SHIFTOP: case ICOP:
22910: return 1;
22911: }
22912: }
22913:
22914: static toknode *get_next_token(toknode *t) {
22915: if (! t->next)
22916: add_tokens() ;
22917:
22918: return t->next ;
22919: }
22920:
22921:
22922: static int template_tscope(Pname tn, toknode *lt)
22923: /* provide the looakhead for determining TSCOPE tokens when the name is a
22924: * parametrized type name; the lookahead here is non-trivial, because it
22925: * involves stepping over the template arguments.
22926: */
22927: {
22928: int nest = 0 ; // the LT has been fetched
22929:
22930: if (lt->tok != LT) error ('i', "a `<' token was expected") ;
22931:
22932: // assume the worst, ensure that name strings are consed in the heap
22933: templp->parameters_in_progress++ ;
22934:
22935: for (toknode *t = lt;; t = get_next_token(t))
22936: switch (t->tok) {
22937:
22938: case LT:
22939: ++nest;
22940: continue;
22941: case GT:
22942: // ***************
22943: // need to fold in awareness of x::y::z
22944: if (--nest == 0) {
22945: t = get_next_token(t);
22946: if (t->tok == MEM) {
22947: // determine whether it is a memptr
22948: if (t->next == 0) add_tokens();
22949: if (t->next->tok == MUL) {
22950: t->tok = MEMPTR;
22951: t->next = t->next->next ;
22952: } else t->tok = TSCOPE ;
22953: t->retval.pn = tn ;
22954: --templp->parameters_in_progress;
22955: return 1;
22956: }
22957: else return 0 ;
22958: }
22959: continue;
22960:
22961: case SM: case LC: case RC: // a quick exit in case of error
22962: case EOFTOK:
22963: --templp->parameters_in_progress;
22964: return 0 ;
22965:
22966: default:
22967: continue;
22968: }
22969: }
22970:
22971: static TOK
22972: lookahead()
22973: /*
22974: advance lookahead pointer, lexing at end of Q
22975: handle occurrences of TNAME and TSCOPE
22976: (should be kept up to date with lalex())
22977: */
22978: {
22979: TOK tk;
22980: TOK tk2;
22981: TOK prev_tk = 0;
22982: YYSTYPE lastval;
22983:
22984: if ( latok == rear ) {
22985: add_tokens();
22986: if ( latok )
22987: latok = latok->next;
22988: else
22989: latok = front;
22990: }
22991: else
22992: latok = latok->next;
22993:
22994: if ( latok->last ) {
22995: prev_tk = latok->last->tok;
22996: lastval = latok->last->retval;
22997: }
22998:
22999: nexttok:
23000: USE_TOKEN(latok,"lookahead1");
23001: tk = latok->tok;
23002: if ( tk == ID || tk == TNAME )
23003: {
23004: if (latok->next == 0) add_tokens();
23005: USE_TOKEN(latok->next,"lookahead2");
23006: /* TOK */ tk2 = latok->next->tok;
23007: if ( tk == TNAME ) {
23008: if (tk2 == LT) {
23009: // a parametrized type name -- differentiate from TNAME
23010: // so that it can be dealt with in the grammar.
23011: if (template_tscope(latok->retval.pn, latok->next)) tk = PTNAME;
23012: }
23013: else
23014: if ( tk2 == MEM || tk2 == DOT ) {
23015: tscope:
23016: tk = TSCOPE;
23017: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 );
23018: // XXX -- should be modified to loop and do lookup
23019: latok = latok->next;
23020: if (latok->next == 0) add_tokens();
23021: USE_TOKEN(latok->next,"lookahead3");
23022: tk2 = latok->next->tok;
23023: if ( tk2 == MUL ) {
23024: tk = MEMPTR;
23025: latok = latok->next;
23026: }
23027: }
23028: else if (( prev_tk == MUL && tk2 != RP )
23029: || prev_tk == AND )
23030: {
23031: tk = ID;
23032: latok->retval.pn->hide();
23033: latok->tok = ID;
23034: latok->retval.s = latok->retval.pn->string;
23035: }
23036: }
23037: else if ( tk2 == MEM ) {
23038: // ID ::
23039: //XXX latok = latok->next->next;
23040: //XXX goto nexttok;
23041: goto tscope; // treat as tscope
23042: }
23043:
23044: if ( tk == ID &&
23045: ( tk2 == ID ||
23046: ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) {
23047: // ID ID
23048: latok = latok->next;
23049: goto nexttok;
23050: }
23051: }
23052:
23053: if ( tk == ID ) {
23054: Pname nstd = ktbl->look(latok->retval.s,NESTED);
23055: if (nstd && (must_be_id == 0 ||
23056: must_be_id && prev_tk == LP)) {
23057: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too
23058: Pname n = check_for_nested(nstd,prev_tk,lastval,tk2);
23059: if ( n ) {
23060: tk = latok->tok = TNAME;
23061: latok->retval.pn = n;
23062: }
23063: }
23064: }
23065:
23066: return tk;
23067: }
23068:
23069: static Pname mem_sel = 0;
23070:
23071: static Pname
23072: do_local_class( Pname n, int lex_level )
23073: { /*
23074: * modify to ``do_local_type:
23075: * do local types: enums and typedefs
23076: */
23077: Pname nn = n;
23078: if ( n->tp ) { // already a TNAME
23079: Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0;
23080: if ( n->lex_level != lex_level || (cl && cl->lcl) ) {
23081: local_hide( n );
23082: nn = new name( n->string );
23083: nn->lex_level = lex_level>=0?lex_level:0;
23084: }
23085: else
23086: if ( lex_level == n->lex_level && cl->defined ) {
23087: error( "localC %n redefined", n );
23088: return n;
23089: }
23090: }
23091:
23092: nn = nn->tname( lastval.t );
23093: modified_tn = modified_tn->l;
23094: nn->n_key = LOCAL;
23095: local_class = new name_list( nn, local_class );
23096: local_blk = new name_list( nn, local_blk );
23097:
23098: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp));
23099: return nn;
23100: }
23101:
23102: static char*
23103: make_nested_name( char *s, Pclass cl )
23104: { // Q<cnt>_<class_names><space><null>
23105: const nested_depth = 9;
23106: char *str_arr[nested_depth];
23107: int size_arr[nested_depth];
23108: int cnt = 2;
23109: int size = 4; // Q,<cnt>,<_>,<null>
23110:
23111: str_arr[0] = s; str_arr[1] = cl->string;
23112:
23113: size += size_arr[0] = strlen(s);
23114: size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string);
23115:
23116: for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) {
23117: if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth);
23118: size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string);
23119: str_arr[cnt++] = nc->string;
23120: }
23121:
23122: for ( int i=0; i<cnt; i++ ) // <nnn><string>
23123: size += size_arr[i]>99?3:size_arr[i]<10?1:2;
23124:
23125: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size );
23126: char *result = new char[size];
23127: sprintf(result, "Q%d_", cnt );
23128: size = 3;
23129: for ( i=cnt; i; i-- ) {
23130: sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]);
23131: size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2);
23132: }
23133:
23134: //error('d', "size: %d ", size );
23135: result[size] = '\0';
23136: //error('d', "make_nested_name result: %s", result );
23137: return result;
23138: }
23139:
23140: int is_empty( Pclass cl, bit const_chk )
23141: { /* for nested class check, empty means *no* members
23142: * for const object check, means no *data* members
23143: */
23144:
23145: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size );
23146:
23147: int mbr_cnt = cl->memtbl->max();
23148: if ( mbr_cnt == 0 ) return 1;
23149:
23150: if ( cl->baselist == 0 && cl->real_size!=1 )
23151: return 0;
23152:
23153: // empty class to turn on transitional nested class scope
23154: if ( const_chk == 0 &&
23155: ( cl->baselist != 0 || mbr_cnt > 1 )) return 0;
23156:
23157: int i = 1;
23158: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) {
23159: if (nn->base==NAME &&
23160: nn->n_union==0 &&
23161: nn->tp->base!=FCT &&
23162: nn->tp->base!=OVERLOAD &&
23163: nn->tp->base!=CLASS &&
23164: nn->tp->base!=ENUM &&
23165: nn->tp->base!=EOBJ &&
23166: nn->n_stclass != STATIC)
23167: {
23168: if ( nn->string[0]=='_' &&
23169: nn->string[1]=='_' &&
23170: nn->string[2]=='W' )
23171: return 1;
23172: else return 0;
23173: }
23174: }
23175:
23176: return 1; // if here, no data members encountered
23177: }
23178:
23179: static int
23180: is_empty( Penum en )
23181: { // is this an empty enum ??
23182:
23183: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators);
23184: if ( en->no_of_enumerators != 0 )
23185: return 0;
23186:
23187: return 1;
23188: }
23189:
23190: static Pname
23191: check_nested_type( Pname nm )
23192: {
23193: // error('d', "check nested type: %n ccl: %t", nm, ccl );
23194:
23195: Pname nx, n = ktbl->look(nm->string, NESTED);
23196: if ( n == 0 || n == nm ) return nm;
23197:
23198: int cnt = 1;
23199: for (nx = n; n; n=n->n_tbl_list )
23200: if (n->n_key == NESTED) ++cnt;
23201:
23202: if ( cnt > 1 ) {
23203: error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt );
23204: error( 'i', "cannot recover from previous errors" );
23205: }
23206: else {
23207: TOK ntk;
23208: Ptype tt = return_nstd_local_type(nx,ntk);
23209: error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string);
23210: }
23211: return nx;
23212: }
23213:
23214: static int
23215: in_local_class( Pclass cl )
23216: {
23217: if ( cl->lex_level )
23218: return 1;
23219: if ( cl->in_class )
23220: return in_local_class( cl->in_class );
23221: return 0;
23222: }
23223:
23224: Pname
23225: do_nested_type( Pname n )
23226: {
23227: Pname nn = n;
23228: char *str = 0;
23229:
23230: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl );
23231: if ( in_typedef && ccl->string[0]=='_'
23232: && ccl->string[1]=='_'
23233: && ccl->string[2]=='C') return n;
23234:
23235: if ( n->tp )
23236: { // already a TNAME :
23237: // hide existing instance, encode new instance
23238: /*
23239: * need handle the anomaly:
23240: * class x;
23241: * x *p;
23242: * class y {
23243: * class x{ ... }; // oops
23244: * };
23245: */
23246: if (n->tp->base==COBJ) {
23247: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
23248: if (cl->defined == 0 && lasttk == AGGR) {
23249: error('w',"forwardD ofC%n resolved to nested%t::%s",n,ccl,n->string);
23250: cl->lcl = new char[9];
23251: strcpy(cl->lcl,"FUDGE007"); // license to hack
23252: n->lex_level=Pbase(n->tp)->b_name->lex_level=0;
23253: return n;
23254: }
23255: }
23256: else if (n->tp->base==EOBJ) { // watch out for enum x;
23257: Penum en = Penum(Pbase(n->tp)->b_name->tp);
23258: if (en->defined == 0 && lasttk == ENUM) return n;
23259: }
23260:
23261: nested_hide( n );
23262: nn = new name( n->string );
23263: str = make_nested_name( n->string, ccl );
23264: }
23265: else
23266: // make sure we haven't already seen a nested instance
23267: // if so, for transition, this needs to be an error
23268: if (ktbl->look( n->string, NESTED ))
23269: error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string);
23270: if ( in_typedef ) {
23271: if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x;
23272: error( "nested Tdef %s redefines immediately enclosing class", nn->string );
23273: error( 'i', "cannot recover from previous errors" );
23274: }
23275:
23276: // make sure there isn't an identifier at global scope being defined
23277: // by a nested typedef -- previously an error; keep it so for transition
23278: Pname tn;
23279: if ( n->tp == 0 && in_local_class(ccl)==0 &&
23280: (tn=gtbl->look(n->string,0))) {
23281: error( "nested Tdef %s redefinesG %n", n->string, tn );
23282: error( 'i', "cannot recover from previous errors" );
23283: }
23284:
23285: nn->tpdef = new type;
23286: nn->tpdef->nested_sig = str;
23287: nn->tpdef->in_class = ccl;
23288: nn->tpdef->lex_level = NESTED;
23289: PERM(nn->tpdef);
23290: }
23291: else {
23292: nn = nn->tname( lastval.t );
23293: Pname tn = Pbase(nn->tp)->b_name;
23294: Ptype tt = tn->tp;
23295: if ( tt->defined && tt->in_class == ccl) {
23296: error( "nested %t redefines immediately enclosing class", nn->string );
23297: error( 'i', "cannot recover from previous errors" );
23298: }
23299: tt->nested_sig = str;
23300: modified_tn = modified_tn->l;
23301: nn->lex_level = tn->lex_level = 0;
23302: nested_type = new name_list( nn, nested_type );
23303: }
23304: nn->n_key = NESTED;
23305: return nn;
23306: }
23307:
23308: static Pname dtor_seen;
23309: static int in_expr;
23310: extern int in_sizeof;
23311:
23312: extern TOK
23313: lalex()
23314: /* return next token to grammar */
23315: {
23316: register TOK tk;
23317: if ( front == 0 )
23318: add_tokens(); // extend lookahead queue
23319: LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before"));
23320:
23321: gettok:
23322: tk = deltok();
23323: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef);
23324:
23325: if ( tk == ID || tk == TNAME )
23326: {
23327: TOK tk2 = la_look();
23328: int lex_level = bl_level - in_class_decl - (tk2 == LC );
23329:
23330: if ( tk == TNAME )
23331: {
23332: //error('d', "lalex tname %n; lasttk: %k tk2: %k", yylval.pn, lasttk, tk2);
23333: //error('d', " must_be_id: %d must_be_expr %d decl_type %d",must_be_id,must_be_expr,DECL_TYPE);
23334: //error('d', " bl_level: %d parsing_members %d",bl_level,parsing_class_members);
23335: if ( tk2 == LP
23336: && (bl_level == 0 || parsing_class_members)
23337: && ( laexpr(lasttk) == 0 )
23338: && must_be_expr == 0
23339: && DECL_TYPE == 0 ) {
23340: if (la_decl()) {
23341: must_be_id = 0;
23342: DECL_TYPE = tk;
23343: tk = DECL_MARKER;
23344: goto ret;
23345: }
23346: }
23347:
23348: // note: *** can handle local typedefs here, too!
23349: if ( in_typedef &&
23350: in_typedef->base != 0 &&
23351: ccl && in_mem_fct == 0 &&
23352: (tk2 == SM || tk2 == RP || tk2 == LB))
23353: yylval.pn = do_nested_type(yylval.pn);
23354:
23355: if ( lasttk == AGGR || lasttk == ENUM ) {
23356: if ( tk2 == LC || tk2 == COLON ) { // class definition
23357: if ( lex_level
23358: && (in_class_decl==0 || in_mem_fct)
23359: && lasttk != ENUM ) // temporary
23360: yylval.pn = do_local_class( yylval.pn, lex_level );
23361: else
23362: if ( in_class_decl && ccl )
23363: yylval.pn = do_nested_type( yylval.pn );
23364: }
23365: }
23366:
23367: if (tk2 == LT) {
23368: // a parametrized type name
23369: if (template_tscope(yylval.pn,latok))
23370: tk = PTNAME ;
23371: } else
23372: if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) {
23373: if (tk2==DOT)
23374: error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)");
23375: crunch:
23376: tk = TSCOPE;
23377: {//XXX -- should be modified to do lookup and del at each ::
23378: while ( (tk2 = lookahead()) == TSCOPE ) ;
23379: if ( tk2 == TNAME ) {
23380: tk2 = lookahead();
23381: if ( tk2 == LP
23382: && (bl_level == 0 || parsing_class_members)
23383: && ( laexpr(lasttk) == 0 )
23384: && must_be_expr == 0
23385: && DECL_TYPE == 0 ) {
23386: if (la_decl()) {
23387: must_be_id = 0;
23388: //DECL_TYPE = tk;//???
23389: DECL_TYPE = TNAME;
23390: //front should be ::
23391: front->tok = TSCOPE;
23392: front->retval.pn = yylval.pn;
23393: yylval.pn = 0;
23394: tk = DECL_MARKER;
23395: goto ret;
23396: }
23397: }
23398: }
23399: }
23400: tk2 = deltok(1);
23401: tk2 = la_look();
23402: if ( tk2 == MUL ) {
23403: tk = MEMPTR;
23404: tk2 = deltok(1);
23405: }
23406: }
23407: // Have a TNAME. Check to be sure.
23408: else if ( must_be_id ){
23409: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2);
23410: if ( in_class_decl
23411: && lasttk == TYPE
23412: && tk2 == LP
23413: && strcmp(yylval.pn->string,ccl->string) == 0 )
23414: error("%nK with returnT", yylval.pn);
23415:
23416: else if ( lasttk == TYPE && lastval.t == OVERLOAD
23417: && ( tk2 == SM || tk2 == LP ) )
23418: {
23419: tk = ID;
23420: yylval.pn->hide();
23421: yylval.pn = new name( yylval.pn->string );
23422: yylval.pn->n_oper = TNAME;
23423: }
23424: else if ( lasttk == OPERATOR ||
23425: in_typedef && yylval.pn->n_key == NESTED)
23426: must_be_id = 0;
23427: else if ( lasttk != TSCOPE // watch out for X::X
23428: || lastval.pn != yylval.pn
23429: || (in_typedef &&
23430: in_typedef->check( yylval.pn->tp,0) == 0 ))
23431: {
23432: tk = ID;
23433: if ( in_typedef && (lasttk == MUL || lasttk == REF)) {
23434: defer_check = 1;
23435: in_tag = yylval.pn;
23436: }
23437:
23438: if ( lasttk == MEM && yylval.pn->lex_level ) {
23439: Pname nn = gtbl->look( yylval.pn->string, 0 );
23440: if (nn == 0 )
23441: error( "%k%s undeclared", lasttk, yylval.pn->string);
23442: else
23443: yylval.pn = nn;
23444: }
23445: else {
23446: // error('d',"lalex: else: lasttk: %k", lasttk );
23447: if (lasttk!=DOT && lasttk!=REF
23448: && lasttk!=TSCOPE && lasttk != GOTO ) {
23449: // handle typedefs in basetype::check
23450: // when type is available
23451: if (!in_typedef) {
23452: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn);
23453: yylval.pn->hide();
23454: }
23455: yylval.pn = new name(yylval.pn->string);
23456: yylval.pn->n_oper = TNAME;
23457: }
23458: }
23459: if ( defer_check ) defer_check = 0;
23460: }
23461: } // must_be_id
23462:
23463: if ( in_class_decl &&
23464: ccl->lex_level &&
23465: yylval.pn->lex_level != 0 &&
23466: yylval.pn->tp &&
23467: (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ))
23468: {
23469: Pname n = gtbl->look( yylval.pn->string,0);
23470: if ( in_mem_fct ) {
23471: if (n && n->base == TNAME ) {
23472: error('w', "local typedef %n(%t) is not in scope of local class %s members; usingG (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp );
23473: yylval.pn = n;
23474: } else
23475: error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string);
23476: }
23477: }
23478:
23479: // if we still have a TNAME, make sure have the right TNAME
23480: // possibility of ananchronistic reference to nested type
23481: Ptype nbt = yylval.pn->tp;
23482: if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y;
23483: (nbt->base == EOBJ || nbt->base == COBJ))
23484: {
23485: Ptype t = Pbase(nbt)->b_name->tp;
23486: if ( ccl && t->in_class &&
23487: strcmp(t->in_class->string, ccl->string))
23488: {
23489: switch( nbt->base ) {
23490: case COBJ:
23491: if (is_empty(Pclass(t)))
23492: yylval.pn = check_nested_type( yylval.pn );
23493: break;
23494: case EOBJ:
23495: if (is_empty(Penum(t)))
23496: yylval.pn = check_nested_type( yylval.pn );
23497: break;
23498: };
23499: }
23500: }
23501: }
23502: else
23503: { // tk == ID
23504: char *s = yylval.s;
23505: Pname n = ktbl->look( s, HIDDEN );
23506: Pname nstd = ktbl->look( s, NESTED );
23507:
23508: // inside a class definition, ccl, that is nested
23509: // s is a nested class name, and is the name of ccl
23510: if (ccl && ccl->in_class && nstd &&
23511: strcmp(s, ccl->string)==0)
23512: {
23513: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
23514: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
23515: ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
23516: Pclass cl = tt->in_class;
23517: if ( nn->n_key != NESTED ) continue;
23518: if (strcmp(ccl->in_class->string,cl->string) == 0) {
23519: tk = TNAME;
23520: yylval.pn = nn;
23521: n = nstd = nn;
23522: }
23523: }
23524: }
23525:
23526: if (tk2 == MEM) {
23527: // ID ::
23528: if (n) {
23529: yylval.pn = n;
23530: /*XXX*/ goto crunch;
23531: }
23532: else
23533: if (nstd &&
23534: nstd->n_tbl_list==0)
23535: {
23536: yylval.pn = nstd;
23537: tk = TSCOPE;
23538: tk2 = deltok(1);
23539: tk2 = la_look();
23540: if (tk2 == MUL ) {
23541: tk = MEMPTR;
23542: tk2 = deltok(1);
23543: }
23544: }
23545: else {
23546: error( "%s:: %sis not aTN", s, s );
23547: tk2 = deltok(1);
23548: goto gettok;
23549: }
23550: }
23551: else // transitional kludge
23552: if ( n && nstd && n == nstd )
23553: ; // null statement
23554:
23555: // Have an ID. Check last token to be sure.
23556: else if (lasttk==ENUM || lasttk==AGGR &&
23557: // template <class id, class id>
23558: (tk2 != GT && tk2 != CM))
23559: {
23560: int fd = tk2!=LC && tk2!=COLON;
23561: tk = TNAME;
23562: if ( nstd ) {
23563: // in transitional model, need flag this as error
23564: if ( fd == 0 ) { // real definition
23565: if ( ccl == 0 )
23566: error("nested andG%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s);
23567: else
23568: error("multiple nested%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s);
23569: error( 'i', "cannot recover from previous errors" );
23570: }
23571: }
23572: else
23573: // new tag, define it
23574: if (n==0 ||
23575: (n->n_template_arg == template_type_formal))
23576: {
23577: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl);
23578: n = new name( s );
23579: if ( fd ) // struct X*, etc.
23580: n->lex_level=0;
23581: else
23582: n->lex_level=lex_level>=0?lex_level:0;
23583:
23584: if ( ccl && fd == 0 &&
23585: in_class_decl &&
23586: (bl_level == ccl->lex_level + in_class_decl + 1))
23587: n = do_nested_type( n );
23588: else
23589: // note: ***** modify to handle local typedef
23590: // note: ***** add local enums
23591: if ( n->lex_level &&
23592: lasttk != ENUM ) // temporary
23593: n = do_local_class( n, n->lex_level );
23594: else {
23595: n = n->tname( lastval.t );
23596: modified_tn = modified_tn->l;
23597: if (fd && gtbl->look(n->string,0)) statStat = n;
23598: }
23599: }
23600: else {
23601: if (n->tp->base!=COBJ && n->tp->base!=EOBJ) {
23602: error( 'i', "hidden%n:%t",n,n->tp );
23603: goto gettok;
23604: }
23605:
23606: if ( tk2 == LC || tk2 == COLON ) {
23607: // class declared and hidden but not yet defined
23608: // may have ctor defined which invalidates hiding
23609: statStat = n;
23610: n->n_key = 0; // inside class definition it cannot be hidden
23611: }
23612: }
23613: yylval.pn = nstd?nstd:n;
23614: }
23615: else {
23616: tk = ID;
23617: yylval.pn = new name( s );
23618: }
23619:
23620: if ( tk == ID )
23621: {
23622: switch ( tk2 ) {
23623: case ID: case TNAME: case AGGR: case ENUM:
23624: {
23625: Pname n = 0;
23626:
23627: if ((curr_scope||ccl) && nstd) {
23628: // within class scope in which nested class is visible
23629: // curr_scope == set by TSCOPE, X::foo() { ... }
23630: // ccl == parsing class definition ``ccl''
23631:
23632: char *str = curr_scope?curr_scope->string:ccl->string;
23633: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
23634: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
23635: ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
23636: Pclass cl = tt->in_class;
23637: if ( nn->n_key != NESTED ) continue;
23638: if ( strcmp(str,cl->string) == 0){
23639: tk = TNAME;
23640: yylval.pn = nn;
23641: if (lasttk == TYPE &&
23642: lastval.t == TYPEDEF )
23643: in_typedef = yylval.pn->tp;
23644: break;
23645: }
23646: }
23647: }
23648: if (tk == TNAME) break; // found nested class
23649:
23650: n = ktbl->look( s, HIDDEN );
23651: if ( n ) {
23652: Pname nn = n;
23653: switch ( n->tp->base ) {
23654: default:
23655: error("typedef %sis not visible in this scope", s );
23656: break;
23657: case COBJ:
23658: if (is_empty(Pclass(Pbase(n->tp)->b_name->tp)))
23659: n = check_nested_type( nn );
23660: if (nn == n)
23661: error("%sis hidden: use struct %s%s", s,s,front->retval.s);
23662: break;
23663: case EOBJ:
23664: if (is_empty(Penum(Pbase(n->tp)->b_name->tp)))
23665: n = check_nested_type( nn );
23666: if (nn == n)
23667: error("%sis hidden: use enum %s%s", s,s,front->retval.s);
23668: break;
23669: };
23670: tk = TNAME;
23671: yylval.pn = n;
23672: }
23673: else
23674: if (n=ktbl->look(s,NESTED))
23675: {
23676: TOK ntk;
23677: bit ok = 0;
23678: Ptype tt = return_nstd_local_type(n,ntk);
23679: Pclass cl = tt->in_class;
23680: if (ccl) {
23681: // x::y unncessary with in_class,
23682: // a derived class of in_class
23683: // or classes enclosing in_class
23684: if (ccl==cl || ccl->has_base(cl))
23685: ok++;
23686: else {
23687: for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class)
23688: if ( eccl == cl ) { ok++; break; }
23689: }
23690: }
23691: if (!ok)
23692: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string );
23693: tk = TNAME;
23694: yylval.pn = n;
23695: }
23696: else { // probably a typo
23697: if ( tk2 == ID )
23698: error("%s%s: %sis not aTN", s,front->retval.s,s);
23699: else if ( tk2 == TNAME )
23700: error("%s%s: %sis not aTN", s,front->retval.pn->string,s);
23701: else
23702: error("%s%k: %sis not aTN", s,front->retval.t,s);
23703: goto gettok;
23704: }
23705: break;
23706: }
23707: case DOT: case REF:
23708: mem_sel = yylval.pn;
23709: break;
23710: default:
23711: if ( lasttk == TNAME && tk2 == LC )
23712: {
23713: error("T%s %k: %s is unexpected", s, tk2, s );
23714: goto gettok;
23715: }
23716:
23717: // have an ID. lets just make sure it should not be a TNAME
23718: if (curr_scope||ccl||nstd) {
23719: if (ccl && in_typedef &&
23720: in_typedef->base != 0 &&
23721: in_mem_fct == 0 &&
23722: (tk2 == SM || tk2 == RP || tk2 == LB))
23723: {
23724: yylval.pn = do_nested_type( yylval.pn );
23725: tk = TNAME;
23726: }
23727: else
23728: if (nstd && must_be_id == 0 && in_expr == 0) {
23729: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk);
23730: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level);
23731: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
23732: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
23733: TOK ntk;
23734: bit ok = 0;
23735: Ptype tt = return_nstd_local_type(nn,ntk);
23736: Pclass cl = tt->in_class;
23737: // error('d',"xcl: %t ccl: %t", xcl, ccl );
23738: if ( xcl ) {
23739: if (xcl==cl || xcl->has_base(cl) || ccl == cl)
23740: ok++;
23741: else {
23742: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
23743: if ( eccl == cl ) { ok++; break; }
23744: }
23745: }
23746:
23747: if (nn == nstd)
23748: {
23749: if (
23750: // special case: foo(X,
23751: // in_arg_list not set until **after** X is handled
23752: ((in_arg_list || lasttk==LP) && // foo(nestedX
23753: (tk2==CM || tk2==ASSIGN ||
23754: (tk2==RP && lasttk!=MUL && lasttk!=REF)))
23755: || // class x : public nestedX
23756: (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
23757: || // nestedX [*&]
23758: (tk2 == MUL || tk2==AND)
23759: || (lasttk==LP && tk2==RP)
23760: || (lasttk==TSCOPE && lastval.pn == nn)
23761: || (lasttk==COMPL && dtor_seen == nn)
23762: || (lasttk==TYPE && lastval.t == TYPEDEF)
23763: || lasttk == OPERATOR
23764: || lasttk == NEW || in_sizeof )
23765: { // must be type name, and it must be nested:
23766: if ( nstd->n_tbl_list == 0 ) { // only one: ok
23767: if (lasttk != TSCOPE && !ok )
23768: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string);
23769: break;
23770: }
23771: else {
23772: if (lasttk != TSCOPE && lasttk != TYPE && !ok){
23773: error("ambiguous nested type %s, use %t::%s",nn->string,xcl,nn->string);
23774: error( 'i', "cannot recover from previous errors" );
23775: }
23776: }
23777: }
23778:
23779: }
23780: if ( nn->n_key != NESTED ) continue;
23781: if (xcl &&
23782: strcmp(xcl->string,cl->string) == 0) break;
23783: } // end: for nn = nstd
23784:
23785: if (nn) {
23786: tk = TNAME;
23787: yylval.pn = nn;
23788: if (lasttk == TYPE &&
23789: lastval.t == TYPEDEF )
23790: in_typedef = yylval.pn->tp;
23791: }
23792: } // end: if (nstd)
23793: } // end: if (curr_scope||ccl)
23794: break;
23795: } // end: switch tk2
23796: } // end: if (tk == ID)
23797: }
23798:
23799: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk );
23800: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk );
23801: if (lex_level && tk==ID && tk2==LP &&
23802: (lasttk==LC || lasttk==RC || lasttk==RP ||
23803: lasttk == ASSIGN || lasttk == SM))
23804: in_expr = 1;
23805: else in_expr = 0;
23806:
23807: }
23808: if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) )
23809: // XXX || tk == TSCOPE || tk == MEM
23810: || tk == REF || tk == DOT || tk == GOTO
23811: || tk == MEMPTR )
23812: // TNAME cannot immediately follow a type name,
23813: // scope operator, right curly, selection, or goto
23814: must_be_id = 1;
23815: else
23816: must_be_id = 0;
23817:
23818: switch ( tk ) {
23819: case SM:
23820: mem_sel = 0; // no break
23821: in_expr = 0;
23822: case RP: case RC: must_be_expr = 0; break;
23823: case COLON:
23824: if (lasttk == RP ||
23825: (lasttk == TYPE && lastval.t == CONST))
23826: must_be_expr = 1;
23827: break;
23828: case SIZEOF:
23829: in_sizeof = 1;
23830: break;
23831: };
23832: ret:
23833: if ( tk == COMPL && lasttk == TSCOPE )
23834: dtor_seen = lastval.pn;
23835: else dtor_seen = 0;
23836: lasttk = tk;
23837: lastval = yylval;
23838: LDB(1,showQ("after");
23839: fprintf(stderr,"returning '%s'",image(tk));
23840: if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string);
23841: fprintf(stderr,"\n");
23842: );
23843: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen );
23844: return tk;
23845: }
23846:
23847: extern void
23848: la_backup( TOK t, YYSTYPE r )
23849: /*
23850: called by parser to push token back on front of queue
23851: */
23852: {
23853: LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t)));
23854: if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); }
23855: register toknode* T = new toknode(t,r,curloc);
23856: if (front) {
23857: front->last = T;
23858: T->next = front;
23859: T->last = 0;
23860: front = T;
23861: } else
23862: front = rear = T;
23863: lasttk = 0;
23864: }
23865:
23866: extern int
23867: la_sctype( TOK t )
23868: {
23869: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok);
23870: if ( t != latok->tok && t != TSCOPE && t != MEMPTR )
23871: error( 'i', &latok->place, "la_sctype, lalex.c" );
23872:
23873: switch( latok->retval.t ) {
23874: case TYPEDEF:
23875: case EXTERN:
23876: case STATIC:
23877: case AUTO:
23878: case REGISTER:
23879: case OVERLOAD:
23880: case INLINE:
23881: case FRIEND:
23882: case CONST:
23883: case VOLATILE:
23884: return 1;
23885: default:
23886: return 0;
23887: }
23888: }
23889:
23890: extern int
23891: la_cast()
23892: /*
23893: called in reduction of term_lp to check for ambiguous prefix-style cast
23894: if result is 1, caller inserts DECL_MARKER to force reduction of cast
23895: */
23896: {
23897: // yychar already designates TYPE or TNAME
23898: // LP must start the lookahead queue!
23899: LDB(1,fprintf(stderr,"\n*** la_cast()\n"););
23900: int tk, tk2 = latok->tok;
23901:
23902: for ( ; ; ) {
23903: tk = tk2;
23904: tk2 = lookahead();
23905:
23906: switch( tk ) {
23907: case LP:
23908: if ( tk2 == MUL || tk2 == AND ||
23909: tk2 == TSCOPE || tk2 == MEMPTR )
23910: // T ( * ...
23911: // T ( C ::* ...
23912: continue;
23913: else
23914: // T ( exp )
23915: return 0;
23916: case MUL: case AND:
23917: //if ( tk2 == SCTYPE )
23918: if ( la_sctype( tk2 ) )
23919: // T ( * const ...
23920: // T ( * volatile ...
23921: tk2 = lookahead();
23922: continue;
23923: case MEMPTR:
23924: if ( tk2 == RP ) continue;
23925: break;
23926: case TSCOPE:
23927: if ( tk2 == MUL )
23928: // T ( C :: * ...
23929: continue;
23930: else
23931: // T ( exp )
23932: return 0;
23933: case RP: case LB:
23934: // T (*)()
23935: // T (*[])()
23936: return 1;
23937: }
23938:
23939: return 0;
23940: }
23941: }
23942:
23943: static int
23944: la_decl()
23945: /*
23946: handles ambiguities
23947: type (*x) ()
23948: type (*x) []
23949: at start of arg list / statement
23950: return val == 1 if lookahead finds a declaration
23951: (used for error messages only)
23952: if declaration is "ambiguous" (i.e., can't be recognized with
23953: 1-symbol lookahead), insert DECL_MARKER to force reduction
23954: of "type"
23955: */
23956: {
23957:
23958: // LP must start the lookahead queue!
23959: LDB(1,fprintf(stderr,"\n*** la_decl()\n"););
23960: int tk, tk2 = latok->tok;
23961: int paren = 0;
23962: int ptr = 0;
23963:
23964: for ( ; ; ) {
23965:
23966: tk = tk2;
23967: tk2 = lookahead();
23968:
23969: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
23970: switch( tk ) {
23971: case LP:
23972: if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) {
23973: // T ( * ...
23974: ++paren;
23975: ptr = 1;
23976: continue;
23977: } else
23978: if ( tk2 == MEMPTR ) {
23979: // T ( C ::* ...
23980: return 1;
23981: } else
23982: // possible redundant parens
23983: if ( tk2 == ID && lookahead() == RP ) {
23984: TOK tp = lookahead();
23985: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 );
23986: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl );
23987: if ( tp == SM || tp == CM || tp == ASSIGN )
23988: {
23989: // member initialization list
23990: if ( tp != SM && in_arg_list == 0 ) return 1;
23991: }
23992: else
23993: if ( tp == RP && (bl_level-in_class_decl==0))
23994: return 1;
23995: if ( tp != LP )
23996: return 0;
23997: latok=latok->last; // restore lookahead
23998: ++paren;
23999: continue;
24000: }
24001: else
24002: // T ( exp )
24003: return 0;
24004: case MUL: case AND:
24005: //if ( tk2 == SCTYPE )
24006: if ( la_sctype( tk2 ))
24007: // T ( * const ...
24008: // T ( * volatile ...
24009: return 1;
24010: else {
24011: ptr = 0;
24012: continue;
24013: }
24014: case MEMPTR:
24015: // T ( C :: * ...
24016: return 1;
24017: case TSCOPE:
24018: if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!!
24019: // T ( C :: * ...
24020: return 1;
24021: else if ( ptr )
24022: // T ( exp )
24023: return 0;
24024: else if ( tk2 == ID || tk2 == OPERATOR )
24025: // T ( * C :: id ...
24026: continue;
24027: else
24028: // error
24029: return 0;
24030: }
24031:
24032: break;
24033: }
24034:
24035: if ( tk == RP || tk == LB )
24036: // T (*)()
24037: // T (*[])()
24038: return 1;
24039:
24040: if ( tk != ID && tk != OPERATOR )
24041: // T ( exp )
24042: return 0;
24043:
24044: if ( tk == OPERATOR )
24045: switch ( tk2 ) {
24046: case PLUS: case MINUS: case MUL: case REFMUL:
24047: case AND: case OR: case ER: case SHIFTOP: case EQUOP:
24048: case DIVOP: case RELOP: case ANDAND: case OROR:
24049: case NOT: case COMPL: case ICOP: case ASSIGN:
24050: case ASOP: case NEW: case GNEW: case DELETE:
24051: // OPERATOR oper
24052: tk2 = lookahead();
24053: break;
24054: case LP:
24055: // OPERATOR ()
24056: tk2 = lookahead();
24057: if ( tk2 == RP ) {
24058: tk2 = lookahead();
24059: break;
24060: } else
24061: return 0;
24062: case LB:
24063: // OPERATOR []
24064: tk2 = lookahead();
24065: if ( tk2 == LB ) {
24066: tk2 = lookahead();
24067: break;
24068: } else
24069: return 0;
24070: default: // illegal operator
24071: return 0;
24072: }
24073:
24074: int allow_lp = 1;
24075: int allow_rp = 1;
24076: for ( ; ; ) {
24077: tk = tk2;
24078: tk2 = lookahead();
24079:
24080: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
24081: switch( tk ) {
24082: case LP:
24083: if ( !allow_lp )
24084: // T ( * id [ exp ] ( ...
24085: return 0;
24086:
24087: // Current lookahead will be a decl if
24088: // the next lookahead is an arg decl
24089: if ( tk2 == RP || tk2 == ENUM || tk2==AGGR
24090: || tk2==ELLIPSIS || la_sctype( tk2 ))
24091: // T ( * id ()
24092: // T ( * id ) ()
24093: return 1;
24094:
24095: if ( tk2 == TYPE || tk2 == TNAME ) {
24096: // T ( * id ) ( T2 ...
24097: if ( lookahead() == LP && !la_decl() )
24098: return 0;
24099: return 1;
24100: }
24101:
24102: return 0;
24103: case LB:
24104: if ( tk2 == RB || lookahead() == RB )
24105: // T ( * id [] ...
24106: return 1;
24107: else {
24108: // T ( * id [ exp ] ...
24109: allow_lp = 0;
24110: allow_rp = 1;
24111: while ( lookahead() != RB );
24112: tk2 = lookahead();
24113: continue;
24114: }
24115: case RP:
24116: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren );
24117: if ( !allow_rp || !paren )
24118: // T ( * id ) )
24119: return 0;
24120: // permit redundant parentheses
24121: else
24122: if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN )
24123: return 1;
24124: else
24125: if ( tk2 == RP && (bl_level-in_class_decl == 0))
24126: return 1;
24127: else
24128: {
24129: // T ( * id ) ...
24130: allow_lp = 1;
24131: allow_rp = 0;
24132: --paren;
24133: continue;
24134: }
24135: default:
24136: return 0;
24137: }
24138: }
24139: }
24140:
24141:
24142:
24143: /*
24144: ** PROCESSING OF INLINE MEMBER FUNCTIONS
24145: */
24146: static int la_snarf();
24147:
24148: extern toknode*
24149: save_text()
24150: /*
24151: save text of inline def on q of class
24152: */
24153: {
24154: // Q should contain at least the tokens < FDEF, X ... >
24155: // where X is either LC or COLON (start of ftn)
24156: LDB(2,fprintf(stderr,"save_text()"));
24157: LDB(3,fprintf(stderr,"front: %s",image(front->tok)));
24158: LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok)));
24159: latok = front->next;
24160: if ( la_snarf() ) {
24161: // append this set of tokens to
24162: // inline tokenq for class
24163: toknode* t = front; // FDEF
24164: if ( ccl->c_funqf == 0 )
24165: ccl->c_funqf = front;
24166: else {
24167: ccl->c_funqr->next = front;
24168: front->last = ccl->c_funqr;
24169: }
24170: ccl->c_funqr = latok;
24171: front = latok->next;
24172: latok->next = 0;
24173: if (front) front->last = 0;
24174: return t;
24175: }
24176: return 0;
24177: }
24178:
24179:
24180: extern void
24181: restore_text()
24182: /*
24183: restore tokens for member inlines onto token q
24184: */
24185: {
24186: LDB(2,fprintf(stderr,"restore_text()"));
24187: if (ccl->c_funqf == 0) // no inlines on Q
24188: return;
24189: LDB(3,fprintf(stderr," Q present: %d,%d",ccl->c_funqf,ccl->c_funqr));
24190: LDB(3,fprintf(stderr," front==%s",image(ccl->c_funqf->tok)));
24191: LDB(3,fprintf(stderr," rear ==%s",image(ccl->c_funqr->tok)));
24192: ccl->c_funqr->next = front;
24193: if (front) front->last = ccl->c_funqr;
24194: front = ccl->c_funqf;
24195: ccl->c_funqf = ccl->c_funqr = 0;
24196: }
24197:
24198:
24199: static void
24200: del_tokens( toknode* marker )
24201: /*
24202: delete tokens from marker to latok, not inclusive
24203: */
24204: {
24205: if ( marker == 0 || marker == latok || marker->next == 0 )
24206: error('i', "bad token queue");
24207:
24208: LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok)));
24209:
24210: register toknode* tt = marker->next;
24211: if ( tt == latok ) return;
24212: marker->next = latok;
24213: latok->last->next = 0;
24214: latok->last = marker;
24215: register toknode* tx = tt;
24216: do {
24217: LDB(3,fprintf(stderr," deleting %s\n",image(tt->tok)));
24218: tx = tx->next;
24219: delete tt;
24220: tt = tx;
24221: } while ( tx );
24222: }
24223:
24224:
24225: static int
24226: la_snarf()
24227: /*
24228: scan function def without processing declarations
24229: */
24230: {
24231: LDB(2,fprintf(stderr,"la_snarf()"));
24232: loc *L = &latok->place;
24233: //DBPLACE(1,L.l,L.f);
24234: int parens = 0;
24235: int paren_error = 0;
24236: toknode* marker = latok;
24237: switch ( latok->tok ) {
24238: default:
24239: error('i', L, "bad token Q snarfing function: %d", latok->tok);
24240: case COLON:
24241: break;
24242: case LC:
24243: --bl_level;
24244: goto eatf;
24245: }
24246: LDB(2,fprintf(stderr,"\"eat\" member initializers"));
24247: for (;;) {
24248: if (latok->next == 0) add_tokens();
24249: switch ( (latok=latok->next)->tok ) {
24250: case LP:
24251: ++parens;
24252: default:
24253: LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
24254: continue;
24255: case RP:
24256: if ( (--parens < 0) && (paren_error++ == 0) )
24257: error(0,&latok->place,"unbalanced ()");
24258: continue;
24259: case LC:
24260: case RC:
24261: if ( parens <= 0 )
24262: goto eatf;
24263: continue;
24264: case SM:
24265: if ( parens <= 0 ) {
24266: error(0, L, "illegal bit field");
24267: del_tokens( front );
24268: delete front;
24269: front = latok;
24270: front->last = 0;
24271: return 0;
24272: }
24273: continue;
24274: case EOFTOK:
24275: error('i',&latok->place,"unexpected end of file");
24276: } // switch
24277: } // for
24278:
24279: eatf:
24280: int level = 1;
24281: for (;;) {
24282: if (latok->next == 0) add_tokens();
24283: switch ( (latok=latok->next)->tok ) {
24284: case LC:
24285: ++level;
24286: default:
24287: LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
24288: continue;
24289: case RC:
24290: LDB(3,fprintf(stderr,"...RC"));
24291: if (--level <= 0) {
24292: if (level < 0) {
24293: error(0,&latok->place,"unexpected '}'");
24294: goto bad;
24295: }
24296: return 1;
24297: }
24298: break;
24299: case EOFTOK:
24300: error('e', &latok->place, "unbalanced {}");
24301: goto bad;
24302: } // switch
24303: } // for
24304: bad:
24305: del_tokens( marker );
24306: marker->tok = SM;
24307: return 0;
24308: }
24309:
24310: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2)
24311: {
24312: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk);
24313: TOK tk = ID;
24314: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
24315:
24316: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
24317: TOK ntk;
24318: bit ok = 0;
24319: Ptype tt = return_nstd_local_type(nn,ntk);
24320: Pclass cl = tt->in_class;
24321: if ( xcl ) {
24322: if (xcl==cl || xcl->has_base(cl))
24323: ok++;
24324: else {
24325: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
24326: if ( eccl == cl ) { ok++; break; }
24327: }
24328: }
24329:
24330: if (nn == nstd)
24331: {
24332: if ( ((in_arg_list || lasttk==LP) && // foo(nestedX
24333: (tk2==CM || tk2==ASSIGN || tk2==RP))
24334: || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
24335: || (tk2 == MUL || tk2==AND)
24336: || (lasttk==LP && tk2==RP)
24337: || (lasttk==TSCOPE && lastval.pn == nn)
24338: || (lasttk==COMPL && dtor_seen == nn)
24339: || (lasttk==TYPE && lastval.t == TYPEDEF)
24340: || lasttk == NEW || in_sizeof )
24341: {
24342: if ( nstd->n_tbl_list == 0 ) { // only one: ok
24343: break;
24344: } else {
24345: if (lasttk != TSCOPE && !ok){
24346: error("ambiguous nested type %s, use X::%s",nn->string,nn->string);
24347: error( 'i', "cannot recover from previous errors" );
24348: }
24349: }
24350: }
24351: }
24352: if ( nn->n_key != NESTED ) continue;
24353: if (xcl && strcmp(xcl->string,cl->string) == 0) break;
24354: } // end: for nn = nstd
24355: return nn;
24356: }
24357:
24358: 0707071010112044341004440001630000160000010203200466055404200000600000066146lex.c /*ident "@(#)ctrans:src/lex.c 1.4" */
24359: /***************************************************************************
24360:
24361: C++ source for cfront, the C++ compiler front-end
24362: written in the computer science research center of Bell Labs
24363:
24364: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
24365: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
24366:
24367: lex.c:
24368: lexical analyser based on pcc's and cpre's scanners
24369: modified to handle classes:
24370: new keywords: class
24371: public
24372: call
24373: etc.
24374: names are not entered in the symbol table by lex()
24375: names can be of arbitrary length
24376: error() is used to report errors
24377: {} and () must match
24378: numeric constants are not converted into internal representation
24379: but stored as strings
24380:
24381: ****************************************************************************/
24382:
24383: #include "cfront.h"
24384: #include "yystype.h"
24385: #include "size.h"
24386: #include "tqueue.h"
24387: #include "template.h"
24388:
24389: # define CCTRANS(x) x
24390: #define copy_if_need_be(s) ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : (s))
24391:
24392: /* lexical actions */
24393:
24394: #define A_ERR 0 /* illegal character */
24395: #define A_LET 1 /* saw a letter */
24396: #define A_DIG 2 /* saw a digit */
24397: #define A_1C 3 /* return a single character */
24398: #define A_STR 4 /* string */
24399: #define A_CC 5 /* character constant */
24400: #define A_BCD 6 /* GCOS BCD constant */
24401: #define A_SL 7 /* saw a / */
24402: #define A_DOT 8 /* saw a . */
24403: #define A_2C 9 /* possible two character symbol */
24404: #define A_WS 10 /* whitespace (not \n) */
24405: #define A_NL 11 /* \n */
24406: #define A_LC 12 /* { */
24407: #define A_RC 13 /* } */
24408: #define A_L 14 /* ( */
24409: #define A_R 15 /* ) */
24410: #define A_EOF 16
24411: #define A_ASS 17
24412: #define A_LT 18
24413: #define A_GT 19 /* > */
24414: #define A_ER 20
24415: #define A_OR 21
24416: #define A_AND 22
24417: #define A_MOD 23
24418: #define A_NOT 24
24419: #define A_MIN 25
24420: #define A_MUL 26
24421: #define A_PL 27
24422: #define A_COL 28 /* : */
24423: #define A_SHARP 29 /* # */
24424: #define A_DOLL 30 /* $ */
24425:
24426: /* character classes */
24427:
24428: # define LEXLET 01
24429: # define LEXDIG 02
24430: /* no LEXOCT because 8 and 9 used to be octal digits */
24431: # define LEXHEX 010
24432: # define LEXWS 020
24433: # define LEXDOT 040
24434:
24435: const FIRSTCHUNK = 8*1024-8;
24436: const BUFCHUNK = 4*1024-8;
24437:
24438: /* text buffer */
24439: static char inbuf[FIRSTCHUNK/*TBUFSZ*/];
24440: static char* txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1];
24441: static char* txtstart = 0;
24442: static char* txtfree = 0;
24443:
24444: static struct buf* bufhead;
24445: static buf* freebuf;
24446: //static bufs;
24447:
24448: struct buf {
24449: buf* next;
24450: char chars[BUFCHUNK];
24451: // buf() { next=bufhead; bufhead=this; }
24452: };
24453:
24454: new_buf(char c)
24455: {
24456: //fprintf(stderr,"new_buf %d\n",bufs++);
24457: buf* pbuf;
24458: if (freebuf) {
24459: pbuf = freebuf;
24460: freebuf = freebuf->next;
24461: }
24462: else
24463: pbuf = new buf; // allocate and register new chunk
24464: pbuf->next = bufhead;
24465: bufhead = pbuf;
24466:
24467: if (BUFCHUNK < txtmax-txtstart) error('l',"lexical token too long");
24468:
24469: // copy current token:
24470: char* p = txtstart;
24471: txtstart = txtfree = &pbuf->chars[0];
24472: while (p<txtmax) *txtfree++ = *p++;
24473: *txtfree++=c;
24474: txtmax = &pbuf->chars[BUFCHUNK-1];
24475: return 0;
24476: }
24477:
24478:
24479: #define pch(c) ((txtmax<=txtfree)?new_buf(c):(*txtfree++=c))
24480: #define start_txt() txtstart = txtfree
24481: #define del_txt() txtfree = txtstart
24482:
24483: static int Nfile;// = 1;
24484: static char* file_name[MAXFILE*4]; // source file names
24485: // file_name[0] == src_file_name
24486: // file_name[0] == 0 means stdin
24487: static short file_stack[MAXFILE]; // stack of file name indices
24488: static int tcurr_file; // current index in file_stack
24489: // that is current #include nest level
24490:
24491: Linkage linkage = linkage_default; // linkage is default C++
24492: const LINKMAX = 10;
24493: static Linkage lvec[LINKMAX] = { linkage_default };
24494: static int lcount = 0;
24495:
24496: void set_linkage(char* p)
24497: {
24498: if (p==0 || *p == 0) { // resume previous linkage
24499: if (lcount>0) linkage = lvec[--lcount];
24500: }
24501: else {
24502: if (LINKMAX<=++lcount) {
24503: error('l',"linkage directive nested too deep");
24504: --lcount;
24505: } else if (strcmp(p,"C")==0)
24506: lvec[lcount] = linkage = linkage_C;
24507: else if (strcmp(p,"C++")==0)
24508: lvec[lcount] = linkage = linkage_Cplusplus;
24509: else {
24510: error("%s linkage",p);
24511: --lcount;
24512: }
24513: }
24514: }
24515:
24516: static struct loc tloc;
24517: FILE * out_file = stdout;
24518: FILE * in_file = stdin;
24519: Ptable ktbl;
24520: Ptable keyword_table;
24521:
24522: static int p_level = 0; /* number of unmatched ``(''s */
24523: static int b_level = 0; /* number of unmatched ``{''s */
24524:
24525: # ifdef ibm
24526:
24527: # define CSMASK 0377
24528: # define CSSZ 256
24529:
24530: # else
24531:
24532: # define CSMASK 0177
24533: # define CSSZ 128
24534:
24535: # endif
24536:
24537: static short lxmask[CSSZ+1];
24538:
24539: int saved = 0; /* putback character, avoid ungetchar */
24540: static int lxtitle();
24541:
24542: // overload rt;
24543: inline YYSTYPE rt(char* x) { YYSTYPE y; y.s = x; return y; }
24544: inline YYSTYPE rt(int x) { YYSTYPE y; y.t = x; return y; }
24545: inline YYSTYPE rt(loc x) { YYSTYPE y; y.l = x; return y; }
24546: inline YYSTYPE rt(void* x) { YYSTYPE y; y.pn = Pname(x); return y; }
24547:
24548: #define get(c) (c=getc(in_file))
24549: #define unget(c) ungetc(c,in_file)
24550:
24551: #define reti(a,b) { addtok(a, rt(b), tloc); return a; }
24552: #define retn(a,b) { addtok(a, rt((Pnode)b), tloc); return a; }
24553: #define rets(a,b) { addtok(a, rt(b), tloc); return a; }
24554: #define retl(a) { addtok(a, rt(tloc), tloc); return a; }
24555:
24556: // keys[] holds the external form for tokens with fixed representation
24557: // illegal tokens and those with variable representation have 0 entries
24558: char* keys[MAXTOK+1];
24559:
24560: static void
24561: new_key(char* s, TOK toknum, TOK yyclass)
24562: /*
24563: make "s" a new keyword with the representation (token) "toknum"
24564: "yyclass" is the yacc token (for example new_key("int",INT,TYPE); )
24565: "yyclass==0" means yyclass=toknum;
24566: */
24567: {
24568: Pname n = new name(s);
24569:
24570: keys[(toknum==LOC)?yyclass:toknum] = s;
24571: n = new name(s);
24572: Pname nn = keyword_table->insert(n,0);
24573: // if (Nold) error('i',"keyword %sD twice",s);
24574: nn->base = toknum;
24575: nn->syn_class = (yyclass) ? yyclass : toknum;
24576: delete n;
24577: }
24578:
24579: const int keyword_count = 67;
24580: static void
24581: ktbl_init()
24582: /*
24583: enter keywords into keyword table for use by lex()
24584: and into keyword representation table used for output
24585:
24586: ktbl is only for types. We put nothing in it.
24587: keyword_table is for user-defined reserved words
24588: */
24589: {
24590: ktbl = new table(KTBLSIZE,0,0);
24591: keyword_table = new table(keyword_count,0,0);
24592:
24593: new_key("asm",ASM,0);
24594: new_key("auto",AUTO,TYPE);
24595: new_key("break",LOC,BREAK);
24596: new_key("case",LOC,CASE);
24597: new_key("continue",LOC,CONTINUE);
24598: new_key("char",CHAR,TYPE);
24599: new_key("do",LOC,DO);
24600: new_key("double",DOUBLE,TYPE);
24601: new_key("default",LOC,DEFAULT);
24602: new_key("enum",ENUM,0);
24603: new_key("else",LOC,ELSE);
24604: new_key("extern",EXTERN,TYPE);
24605: new_key("float",FLOAT,TYPE);
24606: new_key("for",LOC,FOR);
24607: new_key("goto",LOC,GOTO);
24608: new_key("catch",CATCH,CATCH);
24609: new_key("try",TRY,TRY);
24610: new_key("if",LOC,IF);
24611: new_key("int",INT,TYPE);
24612: new_key("long",LONG,TYPE);
24613: new_key("return",LOC,RETURN);
24614: new_key("register",REGISTER,TYPE);
24615: new_key("static",STATIC,TYPE);
24616: new_key("struct",STRUCT,AGGR);
24617: new_key("sizeof",SIZEOF,0);
24618: new_key("short",SHORT,TYPE);
24619: new_key("switch",LOC,SWITCH);
24620: new_key("typedef",TYPEDEF,TYPE);
24621: new_key("unsigned",UNSIGNED,TYPE);
24622: new_key("union",UNION,AGGR);
24623: new_key("void",VOID,TYPE);
24624: new_key("while",LOC,WHILE);
24625:
24626: new_key("class",CLASS,AGGR);
24627: new_key("const",CONST,TYPE);
24628: new_key("delete",LOC,DELETE);
24629: new_key("friend",FRIEND,TYPE);
24630: new_key("inline",INLINE,TYPE);
24631: new_key("new",NEW,0);
24632: new_key("operator",OPERATOR,0);
24633: new_key("overload",OVERLOAD,TYPE);
24634: new_key("private",PRIVATE,PR);
24635: new_key("protected",PROTECTED,PR);
24636: new_key("public",PUBLIC,PR);
24637: new_key("signed",SIGNED,TYPE);
24638: new_key("template",TEMPLATE,0);
24639: new_key("this",THIS,0);
24640: new_key("virtual",VIRTUAL,TYPE);
24641: new_key("volatile",VOLATILE,TYPE);
24642:
24643: new_key("__statement", STATEMENT, 0) ;
24644: new_key("__expression", EXPRESSION, 0) ;
24645: new_key("__template_test", TEMPLATE_TEST, 0) ;
24646: }
24647:
24648: loc last_line;
24649: loc noloc = { 0, 0 };
24650:
24651: void loc::putline()
24652: {
24653: if (file==0 && line==0) return;
24654: // fix, Nfile, not MAXFILE; Nfile == MAXFILE*4
24655: // if (0<=file && file<MAXFILE) {
24656: if ( 0<=file && file <= Nfile ) {
24657: char* f = file_name[file];
24658: if (f==0) f = src_file_name;
24659: fprintf(out_file,line_format,line,f);
24660: last_line = *this;
24661: }
24662: }
24663:
24664: void loc::put(FILE* p)
24665: {
24666: // fix, Nfile, not MAXFILE; Nfile == MAXFILE*4
24667: // if (0<=file && file<MAXFILE) {
24668: if ( 0<=file && file <= Nfile ) {
24669: char* f = file_name[file];
24670: if (f==0) f = src_file_name;
24671: fprintf(p,"\"%s\", line %d: ",f,line);
24672: }
24673: }
24674:
24675: void lxenter(register char* s, short m)
24676: /* enter a mask into lxmask */
24677: {
24678: register c;
24679:
24680: while( c= *s++ ) lxmask[c+1] |= m;
24681:
24682: }
24683:
24684:
24685: void lxget(register c, register m)
24686: /*
24687: put 'c' back then scan for members of character class 'm'
24688: terminate the string read with \0
24689: txtfree points to the character position after that \0
24690: */
24691: {
24692: pch(c);
24693: while ( (get(c), lxmask[c+1]&m) ) pch(c);
24694: unget(c);
24695: pch('\0');
24696: }
24697:
24698: struct LXDOPE {
24699: short lxch; /* the character */
24700: short lxact; /* the action to be performed */
24701: TOK lxtok; /* the token number to be returned */
24702: } lxdope[] = {
24703: #ifdef apollo
24704: '@', A_ERR, 0, /* illegal characters go here... */
24705: #else
24706: '$', A_DOLL, 0,
24707: // '$', A_ERR, 0, /* illegal characters go here... */
24708: #endif
24709: '_', A_LET, 0, /* letters point here */
24710: '0', A_DIG, 0, /* digits point here */
24711: ' ', A_WS, 0, /* whitespace goes here */
24712: '\n', A_NL, 0,
24713: '"', A_STR, 0, /* character string */
24714: '\'', A_CC, 0, /* ASCII character constant */
24715: '`', A_BCD, 0, /* 'foreign' character constant, e.g. BCD */
24716: '(', A_L, LP,
24717: ')', A_R, RP,
24718: '{', A_LC, LC,
24719: '}', A_RC, RC,
24720: '[', A_1C, LB,
24721: ']', A_1C, RB,
24722: '*', A_MUL, MUL,
24723: '?', A_1C, QUEST,
24724: ':', A_COL, COLON,
24725: '+', A_PL, PLUS,
24726: '-', A_MIN, MINUS,
24727: '/', A_SL, DIV,
24728: '%', A_MOD, MOD,
24729: '&', A_AND, AND,
24730: '|', A_OR, OR,
24731: '^', A_ER, ER,
24732: '!', A_NOT, NOT,
24733: '~', A_1C, COMPL,
24734: ',', A_1C, CM,
24735: ';', A_1C, SM,
24736: '.', A_DOT, DOT,
24737: '<', A_LT, LT,
24738: '>', A_GT, GT,
24739: '=', A_ASS, ASSIGN,
24740: '#', A_SHARP, 0,
24741: EOF, A_EOF, EOFTOK
24742: };
24743: /* note: EOF is used as sentinel, so must be <=0 and last entry in table */
24744:
24745: static struct LXDOPE *lxcp[CSSZ+1];
24746:
24747: void
24748: lex_init()
24749: {
24750: register struct LXDOPE *p;
24751: register i;
24752: register char *cp;
24753: /* set up character classes */
24754:
24755: /* first clear lexmask */
24756: for(i=0; i<=CSSZ; i++) lxmask[i] = 0;
24757:
24758: #ifdef apollo
24759: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
24760: #else
24761: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
24762: #endif
24763: lxenter( "0123456789", LEXDIG );
24764: lxenter( "0123456789abcdefABCDEF", LEXHEX );
24765: /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
24766: lxenter( " \t\r\b\f\013", LEXWS );
24767: lxmask['.'+1] |= LEXDOT;
24768:
24769: /* make lxcp point to appropriate lxdope entry for each character */
24770:
24771: /* initialize error entries */
24772:
24773: for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
24774:
24775: /* make unique entries */
24776:
24777: for( p=lxdope; ; ++p ) {
24778: lxcp[p->lxch+1] = p;
24779: if( p->lxch < 0 ) break;
24780: }
24781:
24782: /* handle letters, digits, and whitespace */
24783: /* by convention, first, second, and third places */
24784:
24785: cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
24786: while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
24787: cp = "123456789";
24788: while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
24789: cp = "\t\b\r\f\013";
24790: while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
24791:
24792: file_name[0] = src_file_name;
24793: // set both curloc and tloc so curloc is valid at program startup
24794: // curloc.file = tloc.file = 0;
24795: curloc.line = tloc.line = 1;
24796:
24797: ktbl_init();
24798: lex_clear();
24799: saved = lxtitle();
24800: }
24801:
24802: void lex_clear()
24803: {
24804: // delete extra buffers:
24805: buf* p = bufhead;
24806: bufhead = 0;
24807: //if (p) {
24808: //fprintf(stderr,"lex_clear\n");
24809: //bufs=0;
24810: //}
24811: while (p) {
24812: buf* pp = p;
24813: p = p->next;
24814: pp->next = freebuf;
24815: freebuf = pp;
24816: }
24817:
24818: // re-set to static buffer:
24819: txtstart = txtfree = inbuf;
24820: txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1];
24821: }
24822:
24823: int int_val(char hex)
24824: {
24825: switch (hex) {
24826: case '0': case '1': case '2': case '3': case '4':
24827: case '5': case '6': case '7': case '8': case '9':
24828: return hex-'0';
24829: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
24830: return hex-'a'+10;
24831: case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
24832: return hex-'A'+10;
24833: }
24834: }
24835:
24836: void hex_to_oct()
24837: /*
24838: \x has been seen on input (in char const or string) and \ printed
24839: read the following hexadecimal integer and replace it with an octal
24840: */
24841: {
24842: int i = 0;
24843: int c;
24844: get(c);
24845: if (lxmask[c+1] & LEXHEX) {
24846: i = int_val(c);
24847: get(c); // try for two
24848: if (lxmask[c+1] & LEXHEX) {
24849: i = (i<<4) + int_val(c);
24850: get(c); // try for three
24851: if (lxmask[c+1] & LEXHEX)
24852: i = (i<<4) + int_val(c);
24853: else
24854: unget(c);
24855: }
24856: else
24857: unget(c);
24858: }
24859: else {
24860: error("hexadecimal digitE after \\x");
24861: unget(c);
24862: }
24863:
24864: // if (0377 < i) error('l',"hexadecimal constant too large");
24865: i &= 0377;
24866:
24867: pch(('0'+(i>>6)));
24868: pch(('0'+((i&070)>>3)));
24869: pch(('0'+(i&7)));
24870: }
24871:
24872:
24873: char * chconst()
24874: /*
24875: read a character constant into inbuf
24876: */
24877: {
24878: register c;
24879: int nch = 0;
24880:
24881: pch('\'');
24882:
24883: for(;;) {
24884: char* p;
24885: char cc = 0;
24886:
24887: switch (get(c)) {
24888: case '\'':
24889: goto ex;
24890: case EOF:
24891: error("eof in char constant");
24892: goto ex;
24893: case '\n':
24894: error("newline in char constant");
24895: goto ex;
24896: case '\\':
24897: if (SZ_INT == nch++) error('l',"char constant too long");
24898: pch(c);
24899: switch (get(c)){
24900: case '\n':
24901: ++tloc.line;
24902: default:
24903: pch(c);
24904: break;
24905: case '4': case '5': case '6': case '7': // octal
24906: p = txtfree;
24907: cc = c-4;
24908: case '0': case '1': case '2': case '3':
24909: pch(c);
24910: get(c); /* try for 2 */
24911: if( lxmask[c+1] & LEXDIG && c<'8'){
24912: pch(c);
24913: get(c); /* try for 3 */
24914: if (lxmask[c+1] & LEXDIG && c<'8') {
24915: if (cc) *p = cc; // zap high bit
24916: pch(c);
24917: }
24918: else
24919: unget(c);
24920: }
24921: else
24922: unget(c);
24923: break;
24924: case 'x': // hexadecimal
24925: hex_to_oct();
24926: break;
24927: };
24928: break;
24929: default:
24930: if (SZ_INT == nch++) error('l',"char constant too long");
24931: pch(c);
24932: }
24933: }
24934: ex:
24935: if(nch==0)
24936: error("empty char constant");
24937: pch('\'');
24938: pch('\0');
24939: return txtstart;
24940: }
24941:
24942: void lxcom()
24943: /* process a "block comment" */
24944: {
24945: register c;
24946:
24947: for(;;)
24948: switch (get(c)) {
24949: case EOF:
24950: error('w',"eof in comment");
24951: return;
24952: case '\n':
24953: tloc.line++;
24954: // Nline++;
24955: break;
24956: case '*':
24957: if (get(c) == '/') return;
24958: unget(c);
24959: break;
24960: case '/':
24961: if (get(c) == '*') error('w',"``/*'' in comment");
24962: unget(c);
24963: break;
24964: }
24965: }
24966:
24967:
24968: void linecom()
24969: // process a "line comment"
24970: {
24971: register c;
24972:
24973: get(c);
24974: #ifdef DBG
24975: if ( c=='@' && get(c)=='!' ) {
24976: while ( get(c) != '\n' && c != EOF ) pch(c);
24977: pch('\0');
24978: process_debug_flags(txtstart);
24979: del_txt();
24980: }
24981: #endif
24982: for(;;get(c))
24983: switch (c) {
24984: case EOF:
24985: error('w',"eof in comment");
24986: return;
24987: case '\n':
24988: tloc.line++;
24989: // Nline++;
24990: saved = lxtitle();
24991: return;
24992: }
24993: }
24994:
24995: char eat_whitespace()
24996: {
24997:
24998: for(;;) {
24999: register c = get(c);
25000: lx:
25001:
25002: switch (c) {
25003: case EOF:
25004: error('w',"unexpected comment");
25005: return EOF;
25006: case '/':
25007: switch (get(c)) {
25008: case '*':
25009: lxcom();
25010: break;
25011: case '/':
25012: linecom();
25013: break;
25014: default:
25015: unget(c);
25016: return '/';
25017: }
25018: break;
25019: case '\n':
25020: ++tloc.line;
25021: c = lxtitle();
25022: goto lx;
25023: case ' ':
25024: case '\t':
25025: break;
25026: default:
25027: return c;
25028: }
25029: }
25030: }
25031:
25032: void get_string()
25033: {
25034: int lxchar;
25035:
25036: for(;;)
25037: switch (get(lxchar)) {
25038: case '\\':
25039: pch('\\');
25040: switch (get(lxchar)){
25041: case '\n':
25042: ++tloc.line;
25043: default:
25044: pch(lxchar);
25045: break;
25046: case 'x': // hexadecimal
25047: hex_to_oct();
25048: break;
25049: };
25050: break;
25051: case '"':
25052: { char* p = txtstart; // eat_whitespace() moves txtstart
25053: if ((lxchar = eat_whitespace()) == '"') {
25054: // string catenation, break with
25055: // newline to avoid merging characters
25056: // (e.g. "\xAB" "C")
25057: pch('\\');
25058: pch('\n');
25059:
25060: continue; // eat '\"' and carry on
25061: };
25062:
25063: txtstart = p;
25064: unget(lxchar);
25065: pch(0);
25066: return;
25067: }
25068: case '\n':
25069: error("newline in string");
25070: pch(0);
25071: return;
25072: case EOF:
25073: error("eof in string");
25074: pch(0);
25075: return;
25076: default:
25077: pch(lxchar);
25078: }
25079: }
25080:
25081: TOK tlex()
25082: {
25083: TOK ret;
25084: Pname n;
25085:
25086: // Ntoken++;
25087:
25088: for(;;) {
25089: register lxchar;
25090: register struct LXDOPE *p;
25091:
25092: start_txt();
25093:
25094: if (saved) {
25095: lxchar = saved;
25096: saved = 0;
25097: }
25098: else
25099: get(lxchar);
25100:
25101: if (lxchar+1 >= CSSZ )
25102: error( "illegal input character encountered: %d", lxchar );
25103:
25104: switch( (p=lxcp[lxchar+1])->lxact ){
25105:
25106: case A_1C: // eat up a single character, and return an opcode
25107: reti(p->lxtok,p->lxtok);
25108:
25109: case A_EOF:
25110: if (p_level || b_level+lcount)
25111: error("'%s' missing at end of input",(b_level+lcount) ? "}" : ")");
25112:
25113: reti(EOFTOK,0);
25114:
25115: case A_SHARP:
25116: // cope with header file not ended with '\n'
25117: unget('#');
25118: saved = lxtitle();
25119: continue;
25120:
25121: case A_ERR:
25122: { if (' '<=lxchar && lxchar<='~') // ASCII printable
25123: error("illegal character '%c' (ignored)",lxchar);
25124: else
25125: error("illegal character '0%o' (ignored)",lxchar);
25126: continue;
25127: }
25128:
25129: case A_DOLL:
25130: { // lex a name of the for $id for template tree formals
25131: Pname fn ;
25132: lxget( lxchar, LEXLET|LEXDIG ) ;
25133:
25134: if (!templp->in_progress || !txtstart[1]) {
25135: // no name string immediately follows, treat it
25136: // like an illegal character
25137: error("illegal character '0%o' (ignored)",lxchar);
25138: continue;
25139: }
25140:
25141: txtstart++ ;
25142: if(fn=templ_compilation::tree_parameter(txtstart)) {
25143: switch (fn->n_template_arg) {
25144: case template_expr_tree_formal:
25145: // retain the $ in the name
25146: retn(ID, strdup(--txtstart)) ;
25147:
25148: case template_stmt_tree_formal:
25149: retn(SM_PARAM, fn) ;
25150: }
25151: }
25152: error("%s wasn't a statement or expression formal", txtstart);
25153: rets(ID, copy_if_need_be(txtstart));
25154: }
25155:
25156: case A_LET: // collect an identifier and check for keyword
25157: {
25158: char ll;
25159: switch (ll = lxchar) {
25160: // case 'l':
25161: case 'L':
25162: switch (get(lxchar)) {
25163: case '\'':
25164: error('s',"wide character constant");
25165: unget(lxchar);
25166: continue;
25167: case '"':
25168: error('s',"wide character string");
25169: unget(lxchar);
25170: continue;
25171: }
25172: unget(lxchar);
25173: lxchar = ll;
25174: }
25175: }
25176:
25177: lxget( lxchar, LEXLET|LEXDIG );
25178: /* look for a keyword or a global type */
25179: if ((n = keyword_table->look(txtstart,0)) /* keyword */
25180: || (n = ktbl->look(txtstart, 0))) /* local type */
25181: {
25182: TOK x;
25183: del_txt();
25184: switch (x=n->base) {
25185: case TNAME:
25186: rets(ID,n->string);
25187: case LOC:
25188: retl(n->syn_class);
25189: case EXTERN:
25190: if ((lxchar = eat_whitespace()) == '\"') {
25191: // linkage directive
25192: get_string();
25193: rets(LINKAGE,txtstart);
25194: }
25195: unget(lxchar);
25196: reti(TYPE,EXTERN);
25197: case CATCH:
25198: // case TEMPLATE:
25199: error('s',"%k",n->syn_class);
25200: continue;
25201: case TRY:
25202: {
25203: static int warn_try;
25204: if (!warn_try) {
25205: Pname n = keyword_table->look("try",0);
25206: n->n_key = DEFAULT;
25207: error('w',&tloc,"%k is a future reserved keyword",n->syn_class);
25208: warn_try++;
25209: }
25210: rets(ID,n->string);
25211: }
25212: default:
25213: reti(n->syn_class,x);
25214: }
25215: }
25216: // rets(ID,txtstart);
25217: rets(ID, copy_if_need_be(txtstart)) ;
25218:
25219: case A_DIG:
25220:
25221: ret = ICON;
25222:
25223: if (lxchar=='0') {
25224: int pkchar;
25225: get(pkchar);
25226: if(pkchar=='x' || pkchar=='X') { // hex
25227: pch(lxchar);
25228: lxget(pkchar,LEXHEX);
25229: txtfree--;
25230: if (txtfree-txtstart<3) // minimum "0Xd\0"
25231: error("hex digitX after \"0x\"");
25232: get(lxchar);
25233: goto getsuffix;
25234: }
25235: unget(pkchar);
25236: }
25237:
25238: lxget(lxchar,LEXDIG);
25239: txtfree--;
25240:
25241: if (get(lxchar) == '.') {
25242: getfp:
25243: lxget('.', LEXDIG );
25244: txtfree--;
25245: ret = FCON;
25246: get(lxchar);
25247: };
25248:
25249: if (lxchar=='e' || lxchar=='E') {
25250: pch(lxchar);
25251: get(lxchar);
25252: if(lxchar=='-' || lxchar=='+') {
25253: pch(lxchar);
25254: get(lxchar);
25255: }
25256: if (lxmask[lxchar+1] & LEXDIG) {
25257: lxget( lxchar, LEXDIG );
25258: txtfree--;
25259: get(lxchar);
25260: }
25261: else
25262: error("missing exponent digits?");
25263: ret = FCON;
25264: };
25265:
25266: if(*txtstart=='0' && ret==ICON) {
25267: char *bch = txtstart;
25268: while (++bch <= txtfree) {
25269: if(*bch=='8' || *bch=='9')
25270: error("%c used as octal digit",*bch);
25271: }
25272: }
25273:
25274: getsuffix:
25275: switch (lxchar) {
25276: case 'f':
25277: case 'F':
25278: if (ret==ICON)
25279: error("%c suffix for integer constant",lxchar);
25280: else
25281: pch(lxchar);
25282: break;
25283: case 'u':
25284: case 'U':
25285: if (ret==FCON) {
25286: error("%c suffix for floating constant",lxchar);
25287: break;
25288: }
25289: pch(lxchar);
25290: switch(get(lxchar)) {
25291: case 'l':
25292: case 'L':
25293: pch(lxchar);
25294: break;
25295: default:
25296: saved=lxchar;
25297: break;
25298: }
25299: break;
25300: case 'l':
25301: case 'L':
25302: pch(lxchar);
25303: if (ret==FCON) {
25304: break;
25305: }
25306: switch(get(lxchar)) {
25307: case 'u':
25308: case 'U':
25309: pch(lxchar);
25310: break;
25311: default:
25312: saved=lxchar;
25313: break;
25314: }
25315: break;
25316: default:
25317: saved = lxchar;
25318: break;
25319: };
25320:
25321: if(*txtstart=='0' && txtfree-txtstart==1)
25322: reti(ZERO,0); // plain zero
25323:
25324: pch(0);
25325: rets(ret,txtstart);
25326:
25327:
25328: case A_DOT:
25329: switch (get(lxchar)) {
25330: case '.': // look for ellipsis
25331: if (get(lxchar) != '.') {
25332: error("token .. ?");
25333: saved = lxchar;
25334: }
25335: reti(ELLIPSIS,0);
25336: case '*':
25337: reti (REFMUL,DOT);
25338: }
25339:
25340: if (lxmask[lxchar+1] & LEXDIG){// look for floating constant
25341: unget(lxchar);
25342: goto getfp;
25343: }
25344: saved = lxchar;
25345: reti(DOT,0);
25346:
25347: case A_STR:
25348: /* save string constant in buffer */
25349: get_string();
25350: rets(STRING,txtstart);
25351:
25352: case A_CC:
25353: /* character constant */
25354: rets(CCON,chconst());
25355:
25356: case A_BCD:
25357: {
25358: register i;
25359: int j;
25360:
25361: pch('`');
25362:
25363: for (i=0; i<7; ++i) {
25364: pch(get(j));
25365: if (j == '`' ) break;
25366: }
25367: pch(0);
25368: if (6<i)
25369: error('l',"bcd constant exceeds 6 characters" );
25370: rets(CCON,txtstart);
25371: }
25372:
25373: case A_SL: /* / */
25374: switch (get(lxchar)) {
25375: case '*':
25376: lxcom();
25377: break;
25378: case '/':
25379: linecom();
25380: break;
25381: case '=':
25382: reti(ASOP,ASDIV);
25383: default:
25384: saved = lxchar;
25385: reti(DIVOP,DIV);
25386: }
25387:
25388: case A_WS:
25389: continue;
25390:
25391: case A_NL:
25392: ++tloc.line;
25393: // Nline++;
25394: saved = lxtitle();
25395: continue;
25396:
25397: case A_LC:
25398: if (BLMAX <= b_level++) {
25399: error('l',"blocks too deeply nested");
25400: ext(3);
25401: }
25402: retl(LC);
25403:
25404: case A_RC:
25405: if (lcount+b_level-- <= 0) {
25406: error("unexpected '}'");
25407: b_level = 0;
25408: }
25409: retl(RC);
25410:
25411: case A_L:
25412: p_level++;
25413: reti(LP,0);
25414:
25415: case A_R:
25416: if (p_level-- <= 0) {
25417: error("unexpected ')'");
25418: p_level = 0;
25419: }
25420: reti(RP,0);
25421:
25422: case A_ASS:
25423: switch (get(lxchar)) {
25424: case '=':
25425: reti(EQUOP,EQ);
25426: default:
25427: saved = lxchar;
25428: reti(ASSIGN,ASSIGN);
25429: }
25430:
25431: case A_COL:
25432: switch (get(lxchar)) {
25433: case ':':
25434: reti(MEM,0);
25435: case '=':
25436: error("':=' is not a c++ operator");
25437: reti(ASSIGN,ASSIGN);
25438: default:
25439: saved = lxchar;
25440: reti(COLON,COLON);
25441: }
25442: case A_NOT:
25443: switch (get(lxchar)) {
25444: case '=':
25445: reti(EQUOP,NE);
25446: default:
25447: saved = lxchar;
25448: reti(NOT,NOT);
25449: }
25450: case A_GT:
25451: switch(get(lxchar)) {
25452: case '>':
25453: switch (get(lxchar)) {
25454: case '=':
25455: reti(ASOP,ASRS);
25456: break;
25457: default:
25458: saved = lxchar;
25459: reti(SHIFTOP,RS);
25460: }
25461: case '=':
25462: reti(RELOP,GE);
25463: default:
25464: saved = lxchar;
25465: reti(GT,GT);
25466: }
25467: case A_LT:
25468: switch (get(lxchar)) {
25469: case '<':
25470: switch (get(lxchar)) {
25471: case '=':
25472: reti(ASOP,ASLS);
25473: default:
25474: saved = lxchar;
25475: reti(SHIFTOP,LS);
25476: }
25477: case '=':
25478: reti(RELOP,LE);
25479: default:
25480: saved = lxchar;
25481: reti(LT,LT);
25482: }
25483: case A_AND:
25484: switch (get(lxchar)) {
25485: case '&':
25486: reti(ANDAND,ANDAND);
25487: case '=':
25488: reti(ASOP,ASAND);
25489: default:
25490: saved = lxchar;
25491: reti(AND,AND);
25492: }
25493: case A_OR:
25494: switch (get(lxchar)) {
25495: case '|':
25496: reti(OROR,OROR);
25497: case '=':
25498: reti(ASOP,ASOR);
25499: default:
25500: saved = lxchar;
25501: reti(OR,OR);
25502: }
25503: case A_ER:
25504: switch (get(lxchar)) {
25505: case '=':
25506: reti(ASOP,ASER);
25507: default:
25508: saved = lxchar;
25509: reti(ER,ER);
25510: }
25511: case A_PL:
25512: switch (get(lxchar)) {
25513: case '=':
25514: reti(ASOP,ASPLUS);
25515: case '+':
25516: reti(ICOP,INCR);
25517: default:
25518: saved = lxchar;
25519: reti(PLUS,PLUS);
25520: }
25521: case A_MIN:
25522: switch (get(lxchar)) {
25523: case '=':
25524: reti(ASOP,ASMINUS);
25525: case '-':
25526: reti(ICOP,DECR);
25527: case '>':
25528: if (get(lxchar) == '*')
25529: {reti(REFMUL,REF);}
25530: else
25531: saved = lxchar;
25532: reti(REF,REF);
25533: default:
25534: saved = lxchar;
25535: reti(MINUS,MINUS);
25536: }
25537: case A_MUL:
25538: switch (get(lxchar)) {
25539: case '=':
25540: reti(ASOP,ASMUL);
25541: case '/':
25542: error('w',"*/ not as end of comment");
25543: default:
25544: saved = lxchar;
25545: reti(MUL,MUL);
25546: }
25547: case A_MOD:
25548: switch (get(lxchar)) {
25549: case '=':
25550: reti(ASOP,ASMOD);
25551: default:
25552: saved = lxchar;
25553: reti(DIVOP,MOD);
25554: }
25555: default:
25556: {error('i',"lex act==%d getc()->%d",p,lxchar);}
25557:
25558: }
25559:
25560: error('i',"lex, main switch");
25561: }
25562:
25563: }
25564:
25565: int lxtitle()
25566: /*
25567: called after a newline; set linenumber and file name
25568: */
25569: {
25570: register c;
25571:
25572: for(;;)
25573: switch ( get(c) ) {
25574: default: // e.g. not '\n', not '#'
25575: return c;
25576: case '\n':
25577: tloc.line++;
25578: // Nline++;
25579: ll:
25580: break;
25581: case '#': /* # lineno "filename" */
25582: { int cl = tloc.line;
25583: tloc.line = 0;
25584: for(;;)
25585: switch (get(c)) {
25586: case '"':
25587: start_txt();
25588: for(;;)
25589: switch (get(c)) {
25590: case '"':
25591: pch('\0');
25592:
25593: while (get(c) != '\n') ; // skip to eol.. ignore anything more
25594:
25595: if (*txtstart) { // stack file name
25596: char* fn;
25597: if (tcurr_file == 0){
25598: if (( fn = file_name[0])
25599: && (strcmp(txtstart,fn)!=0)){ // 1st include
25600: if (MAXFILE*4<++Nfile) error('i',"fileN buffer overflow");
25601: if (MAXFILE<++tcurr_file) error('i',"fileN stack overflow");
25602: file_stack[tcurr_file] = Nfile;
25603:
25604: char* p1 = new char[txtfree-txtstart];
25605: (void) strcpy(p1,txtstart);
25606: file_name[Nfile] = p1;
25607: // Nstr++;
25608: }
25609: else { //&& line is dummy #line "input.c"
25610: // ignore
25611: }
25612: //&& dead, dead, dead goto push;
25613: }
25614: else if ( (fn=file_name[file_stack[tcurr_file]])
25615: && (strcmp(txtstart,fn)==0) ) {
25616: //new line, same file: ignore
25617: }
25618: else if ( (fn=file_name[file_stack[tcurr_file-1]])
25619: && (strcmp(txtstart,fn)==0) ) {
25620: // previous file: pop
25621: tcurr_file--;
25622: }
25623: else { // new file name: push
25624: //&& push:
25625: if (MAXFILE*4<Nfile++) error('i',"fileN buffer overflow");
25626: if (MAXFILE<tcurr_file++) error('i',"fileN stack overflow");
25627: file_stack[tcurr_file] = Nfile;
25628: char* p = new char[txtfree-txtstart];
25629: (void) strcpy(p,txtstart);
25630: file_name[Nfile] = p;
25631: // Nstr++;
25632: }
25633: }
25634: else { // no name .. back to the original .c file: ""
25635: tcurr_file = 0;
25636: }
25637: del_txt();
25638: tloc.file = file_stack[tcurr_file];
25639: goto ll;
25640: case '\n':
25641: error("unexpected end of line on '# line'");
25642: default:
25643: pch(c);
25644: }
25645: case ' ':
25646: break;
25647:
25648: case '0':
25649: case '1':
25650: case '2':
25651: case '3':
25652: case '4':
25653: case '5':
25654: case '6':
25655: case '7':
25656: case '8':
25657: case '9':
25658: tloc.line = tloc.line*10+c-'0';
25659: break;
25660:
25661: case 'l': // look for "#line ..." and then ignore "line"
25662: if (get(c)=='i' && get(c)=='n' && get(c)=='e') break;
25663: case '\n':
25664: tloc.putline();
25665: goto ll;
25666:
25667: default: // pass #rubbish through
25668: tloc.line = cl;
25669: pch('#');
25670: pch(c);
25671: while (get(c) != '\n') pch(c);
25672: pch('\0');
25673: fprintf(out_file,"\n%s\n",txtstart);
25674: start_txt();
25675: tloc.line++;
25676: // Nline++;
25677: goto ll;
25678: }
25679: }
25680: }
25681: }
25682: 0707071010112044351004440001630000160000010204200466055404600000700000046311main.c /*ident "@(#)ctrans:src/main.c 1.9" */
25683: /***********************************************************************
25684:
25685: C++ source for cfront, the C++ compiler front-end
25686: written in the computer science research center of Bell Labs
25687:
25688: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
25689: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
25690:
25691: main.c:
25692:
25693: Initialize global environment
25694: Read argument line
25695: Start compilation
25696: Clean up and exit
25697:
25698: **************************************************************************/
25699:
25700: #ifdef __cplusplus
25701: #include <stdlib.h>
25702: #endif
25703:
25704: #include <ctype.h>
25705: #include <string.h>
25706: #include <libc.h>
25707: #include <osfcn.h>
25708: #include <fstream.h>
25709: #include "size.h"
25710: #include "cfront.h"
25711: #include "tree_dump.h"
25712: #include "template.h"
25713: #include "hash.h"
25714:
25715: char* prog_name = "<<AT&T C++ Translator <(3.0)(PT)> 08/08/90>>";
25716: char* src_file_name = "";
25717: char* line_format = "\n# %d \"%s\"\n";
25718:
25719: int dump_tree;
25720: int tree_dump_brief = 0;
25721: dcn_arg dump_tree_arg;
25722:
25723: #ifdef unix
25724: #include <signal.h>
25725:
25726: static void core_dump(int = 0)
25727: {
25728: if (error_count)
25729: fprintf(stderr,"sorry, cannot recover from previous error\n");
25730: else
25731: error('i',"bus error (or something nasty like that)");
25732: ext(99);
25733: }
25734: #endif
25735:
25736: Plist isf_list;
25737: Pstmt st_ilist;
25738: Pstmt st_dlist;
25739: Ptable sti_tbl;
25740: Ptable std_tbl;
25741: Plist stat_mem_list;
25742:
25743: int vtbl_opt = -1; // how to deal with vtbls:
25744: // -1 static and defined
25745: // 0 external and supposed to be defined elsewhere
25746: // 1 external and defined
25747: int debug_opt;
25748: int gplus_opt; // -g to cc, overrides print optimization
25749: int ansi_opt;
25750: int strict_opt; // disallow features from the anachronism section
25751: // of the manual
25752: int warning_opt; // produce more warnings if set
25753: bit stmtno = 0;
25754:
25755: extern simpl_init();
25756: extern typ_init();
25757: extern syn_init();
25758: extern lex_init();
25759: extern error_init();
25760:
25761: char *st_name(char*); // generates names of static ctor, dtor callers, ptbl_vec
25762: Pname def_name; // first definition in file
25763: Pname pdef_name; // used with ptbl_vec if function is first definition
25764:
25765: int syn_count = 0; // to set conditional breakpoints to find particular expressions
25766: Hash *dumper_node_hash_table;
25767:
25768: void static
25769: clean_dumper_hash_table() {
25770: if(!dumper_node_hash_table)
25771: return;
25772: else {
25773: HashWalker hi(*dumper_node_hash_table);
25774: while(hi.valid ()) {
25775: struct node& n = *(struct node*) hi.key();
25776: if(n.permanent == 0 || n.permanent == 3) /* flush deleted nodes */
25777: dumper_node_hash_table->del(hi.key());
25778: hi.advance();
25779: }
25780: }
25781: }
25782:
25783: void run()
25784: /*
25785: run the appropriate stages
25786: */
25787: {
25788: Pname n;
25789: templp = new templ_compilation; // canonical instance
25790:
25791:
25792: if(dump_tree) {
25793: dumper_node_hash_table =
25794: dump_tree_arg.nodes_seen_hash = new pointer_hash (10000);
25795: dump_tree_arg.verbose = dt_recursive_1;
25796: }
25797:
25798: while (n=syn()) {
25799: if (n == Pname(1)) continue;
25800: if (n->n_list) PERM(n->tp);
25801:
25802: DB( if(Rdebug>=1) error('d',"run: syn(): '%s'", n->string););
25803: templp->instantiate_ref_templ();
25804:
25805: for (Pname nx, nn=n; nn; nn=nx) {
25806: Pname rr;
25807: ++syn_count;
25808: nx = nn->n_list;
25809: nn->n_list = 0;
25810:
25811: DB( if(Rdebug>=1) error('d',"run: dcl(): %n, base: %k",nn,nn->base););
25812:
25813: if ((rr=nn->dcl(gtbl,EXTERN))==0
25814: || nn->base==0
25815: || error_count) continue;
25816:
25817: DB( if(Rdebug>=1) error('d',"run: simpl(): %n",nn););
25818:
25819: nn->simpl();
25820:
25821: if (error_count) {
25822: if(dump_tree) {
25823: display_cfront_node (dump_tree_arg, nn);
25824: *dump_tree_arg.output_stream << "---------------------------\n\n";
25825: }
25826: continue;
25827: }
25828:
25829: DB( if(Rdebug>=1) error('d',"run:print(): %n (%k) tp %t",nn,nn->base,nn->tp););
25830:
25831: if (nn->base == TNAME)
25832: nn->dcl_print(0);
25833: else {
25834: Ptype t = nn->tp;
25835: llxx:
25836: switch (t->base) {
25837: case TYPE:
25838: t = Pbase(t)->b_name->tp; goto llxx;
25839: case CLASS:
25840: DB( if(Rdebug>=1) fprintf(stderr," -- class\n"););
25841: if (vtbl_opt==1 || gplus_opt) n->dcl_print(0);
25842: break;
25843: case ENUM:
25844: DB( if(Rdebug>=1) fprintf(stderr," -- enum\n"););
25845: Penum(n->tp)->dcl_print(0);
25846: break;
25847: case FCT:
25848: DB( if(Rdebug>=1) error('d'," -- fct%n inline %d body %d",nn,Pfct(t)->f_inline,Pfct(t)->body););
25849: if (Pfct(t)->body==0
25850: || (debug_opt==0 && Pfct(t)->f_inline && ((n->n_table!=gtbl) || strcmp(nn->string,"main")))
25851: || Pfct(t)->f_imeasure && Pfct(t)->f_inline==0) break;
25852: DB( if(Rdebug>=1) error('d',"rr %n inline %d body %d",rr,Pfct(rr->tp)->f_inline,Pfct(rr->tp)->body););
25853: rr->dcl_print(0);
25854: break;
25855:
25856: default:
25857: DB( if(Rdebug>=1) error('d'," -- %n tpbase: %k",nn,nn->tp->base););
25858: // print class def, if appropriate
25859: // can't use tsizeof() since this may
25860: // print an error if class isn't defined
25861: { for(Ptype tx = t;;) {
25862: switch ( tx->base ) {
25863: case VEC:
25864: tx=Pvec(tx)->typ;
25865: continue;
25866: case TYPE: case COBJ:
25867: tx=Pbase(tx)->b_name->tp;
25868: continue;
25869: }
25870: Pclass cl = Pclass(tx);
25871: if ( cl->base == CLASS
25872: && (cl->defined&(DEFINED|SIMPLIFIED))
25873: && cl->c_body==1 )
25874: cl->dcl_print(0);
25875: break;
25876: }
25877: }
25878: nn->dcl_print(0);
25879: }
25880: }
25881:
25882: if(dump_tree) {
25883: display_cfront_node (dump_tree_arg, nn);
25884: *dump_tree_arg.output_stream << "---------------------------\n\n";
25885: }
25886:
25887: if (error_count) continue;
25888:
25889: DB( if(Rdebug>=1) error('d',"run: cleanup"););
25890: switch (nn->tp->base) { // clean up
25891: default:
25892: {
25893: Pexpr i = nn->n_initializer;
25894: DB( if(Rdebug>=1) error('d',"default nn %n i %d",nn,i););
25895: if (i && i!=Pexpr(1)) {
25896: DEL(i);
25897: nn->n_initializer = 0;
25898: if (def_name==0 && rr->n_scope != STATIC) {
25899: def_name = rr;
25900: if (pdef_name == 0) ptbl_init(0);
25901: }
25902: }
25903: break;
25904: }
25905:
25906: case FCT:
25907: {
25908: Pfct f = Pfct(nn->tp);
25909: DB( if(Rdebug>=1) error('d', "function nn: %n local_class: %d %d", nn, local_class, f->local_class ););
25910: if (f->body
25911: && f->f_inline==0
25912: && f->f_imeasure==0) {
25913: if ( local_class = f->local_class ) {
25914: delete_local();
25915: local_class = 0;
25916: }
25917:
25918: if (ansi_opt && f->f_this) {
25919: f->f_this->n_table = 0;
25920: for (Pname n=f->f_this->n_list; n; n=n->n_list)
25921: n->n_table = 0;
25922: }
25923:
25924: DEL(f->body);
25925: if (def_name==0) {
25926: def_name = rr;
25927: if (pdef_name == 0) ptbl_init(0);
25928: }
25929: }
25930: break;
25931: }
25932:
25933: case CLASS:
25934: { Pclass cl = Pclass(nn->tp);
25935: for (Pname px, p=cl->mem_list; p; p=px) {
25936: px = p->n_list;
25937: if (p->tp) {
25938: switch (p->tp->base) {
25939: case FCT:
25940: { Pfct f = (Pfct)p->tp;
25941: if (f->body) {
25942: if (f->f_inline==0
25943: && f->f_imeasure==0) {
25944: if ( local_class = f->local_class ) {
25945: delete_local();
25946: local_class = 0;
25947: }
25948: DEL(f->body);
25949: f->body = 0;
25950: }
25951: }
25952: }
25953: case CLASS:
25954: case ENUM:
25955: break;
25956: case COBJ:
25957: case EOBJ:
25958: DEL(p);
25959: break;
25960: default:
25961: delete p;
25962: }
25963: } else {
25964: delete p;
25965: }
25966: } // for
25967: cl->mem_list = 0;
25968: cl->permanent = 3;
25969: break;
25970: }
25971: }
25972: DEL(nn);
25973: }
25974: lex_clear();
25975: if (dump_tree) clean_dumper_hash_table();
25976: }
25977: templp->end_of_compilation() ;
25978:
25979: switch (no_of_undcl) {
25980: case 1: {error('w',"undeclaredF%n called",undcl);}
25981: case 0: break;
25982: default: {error('w',"%d undeclaredFs called; for example%n",no_of_undcl,undcl);}
25983: }
25984:
25985: switch (no_of_badcall) {
25986: case 1: {error('w',"%n declaredWoutAs calledWAs",badcall);}
25987: case 0: break;
25988: default: {error('w',"%d Fs declaredWoutAs calledWAs; for example%n",no_of_badcall,badcall);}
25989: }
25990:
25991: if (error_count) return;
25992:
25993: int i = 1;
25994: for (Pname m=gtbl->get_mem(i); m; m=gtbl->get_mem(++i)) {
25995: if (m->base==TNAME
25996: || m->n_sto==EXTERN
25997: || m->n_stclass == ENUM) continue;
25998:
25999: Ptype t = m->tp;
26000: if (t == 0) continue;
26001: switch (t->base) {
26002: case CLASS:
26003: case ENUM:
26004: case OVERLOAD: continue;
26005: case COBJ:
26006: //case ANON:
26007: case VEC: break;
26008: case FCT:
26009: if (Pfct(t)->f_inline || Pfct(t)->body==0) continue;
26010: }
26011:
26012: //error('d',&m->where,"%n %d %d %s",m,m->n_addr_taken,m->n_used,m->n_sto==STATIC?"static":"");
26013: //xxx doesn't check anon union members as their use bits are set differently
26014: if (m->n_addr_taken==0
26015: && m->n_used==0
26016: && m->n_sto == STATIC) { // (static or anon?)
26017: for(;;) {
26018: //error('d',&m->where," %t tconst(): %d",t,t->tconst());
26019: if(t->base==TYPE) {
26020: if(t->tconst()) break;
26021: t=Pbase(t)->b_name->tp;
26022: } else if(t->base==VEC) {
26023: t=Pvec(t)->typ;
26024: } else {
26025: if ( t->tconst() == 0 ) {
26026: //error('d',"m%n tp%t t%t",m,m->tp,t);
26027: if ( t->base != COBJ )
26028: error('w',&m->where,"%n defined but not used",m);
26029: else { Pclass cl;
26030: cl = Pclass(Pbase(t)->b_name->tp);
26031: if ( cl->has_ctor()==0 )
26032: if ( cl->csu == ANON )
26033: ; //error('w',&m->where,"anonymous union defined but not used");
26034: else
26035: error('w',&m->where,"%n defined but not used",m);
26036: }
26037: } // if const
26038: break;
26039: }
26040: } // for
26041: } // if static and not used
26042: }
26043:
26044: Pname ctor = 0;
26045: Pname dtor = 0;
26046: --curloc.line;
26047:
26048: if (st_ilist) { // make an "init" function;
26049: // it calls all constructors for static objects
26050: DB( if(Rdebug>=1) error('d',"make sti"); );
26051: Pname n = new name( st_name("__sti__") );
26052: Pfct f = new fct(void_type,0,1);
26053: n->tp = f;
26054: f->body = new block(st_ilist->where,0,st_ilist);
26055: // f->body->s = st_ilist;
26056: f->body->memtbl = sti_tbl;
26057: n->n_sto = EXTERN;
26058: // assignments here are really initializations:
26059: ignore_const++;
26060: f->f_linkage = linkage_C;
26061: f->sign();
26062: (void) n->dcl(gtbl,EXTERN);
26063: ignore_const--;
26064: n->simpl();
26065: n->dcl_print(0);
26066: ctor = n;
26067: }
26068:
26069: if (st_dlist) { // make a "done" function;
26070: // it calls all destructors for static objects
26071: DB( if(Rdebug>=1) error('d',"make std"); );
26072: Pname n = new name( st_name("__std__") );
26073: Pfct f = new fct(void_type,0,1);
26074: n->tp = f;
26075: f->body = new block(st_dlist->where,0,st_dlist);
26076: // f->body->s = st_dlist;
26077: f->body->memtbl = std_tbl;
26078: n->n_sto = EXTERN;
26079: f->f_linkage = linkage_C;
26080: f->sign();
26081: (void) n->dcl(gtbl,EXTERN);
26082: n->simpl();
26083: n->dcl_print(0);
26084: dtor = n;
26085: }
26086:
26087: #ifdef PATCH
26088: /*For fast load: make a static "__link" */
26089: if (ctor || dtor)
26090: {
26091: printf("static struct __linkl { struct __linkl * next;\n");
26092: if ( ansi_opt )
26093: printf("void (*ctor)(); void (*dtor)(); } __link = \n");
26094: else
26095: printf("char (*ctor)(); char (*dtor)(); } __link = \n");
26096: // printf("{ (struct __linkl *)0, %s, %s };\n",
26097: // ctor_name ? ctor_name : "0",
26098: // dtor_name ? dtor_name : "0");
26099: putstring("{ (struct __linkl *)0, ");
26100: if (ctor) ctor->print(); else putch('0');
26101: putch(',');
26102: if (dtor) dtor->print(); else putch('0');
26103: putstring("};\n");
26104: }
26105: #endif
26106:
26107: DB( if(Rdebug>=1) error( 'd', "run: vlist: %d", vlist ); );
26108: do {
26109: for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt);
26110: vlist = 0;
26111:
26112: for (Plist l=isf_list; l; l=l->l) {
26113: Pname n = l->f;
26114: Pfct f = Pfct(n->tp);
26115: DB( if(Rdebug>=1)error('d',"isf %n %t f %d addr %d",n,f,f,n->n_addr_taken); );
26116: if (f->base == OVERLOAD) {
26117: n = Pgen(f)->fct_list->f; // first fct
26118: f = Pfct(n->tp);
26119: }
26120:
26121: if (debug_opt==0 &&
26122: n->n_addr_taken) {
26123: f->f_inline = 0;
26124: if (n->n_dcl_printed<2) {
26125: if (warning_opt)
26126: error('w',"out-of-line copy of %n created",n);
26127: n->dcl_print(0);
26128: }
26129: }
26130: }
26131: } while (vlist);
26132:
26133: if (strict_opt == 0) { // define static members
26134: // patch for SysV VAX -g linkage botch
26135: for (Plist l=stat_mem_list; l; l=l->l) {
26136: Pname n = l->f;
26137: // error('d',"stat mem %n %d %d ",n,n->n_initializer,n->n_evaluated);
26138: if (n->n_initializer==0 && n->n_evaluated==0) {
26139: Ptype t = n->tp;
26140: n->n_sto = 0;
26141: Pname cn = t->is_cl_obj();
26142: if (cn==0) cn = cl_obj_vec;
26143: if (cn) (void) t->tsizeof(); // be sure to print class
26144: if ((cn && Pclass(cn->tp)->has_ctor())
26145: || t->is_ref())
26146: ; // force explicit definition
26147: else
26148: n->dcl_print(0);
26149: }
26150: }
26151: }
26152:
26153: i = 1;
26154: for (Pname nm=ptbl->get_mem(i); nm; nm=ptbl->get_mem(++i)) {
26155: DB( if(Rdebug>=1) error('d',"ptbl anme %s string2 %s key:%k",nm->string==0?"???":nm->string2,nm->string2==0?"???":nm->string2,nm->n_key); );
26156: if ( nm->n_key == 0 ) { // ptbl used in file, generate definition
26157: int str1 = (*src_file_name)?strlen(src_file_name)+2:0; // +2 for __
26158: int str2 = strlen(nm->string2) - str1;
26159: char *ps = new char[ str2 + 1 ];
26160: strncpy( ps, nm->string2, str2 ); // grab vtbl name
26161: ps[str2]='\0';
26162: ps[2] = 'v';
26163: fprintf(out_file,"extern struct __mptr %s[];\n",ps);
26164: // fprintf(out_file,"struct __mptr* %s = %s;\n",nm->string2,ps);
26165: ptbl_add_pair(nm->string2,ps);
26166: delete ps;
26167: }
26168: }
26169:
26170: ptbl_init(1);
26171: curloc.putline();
26172: fprintf(out_file,"\n/* the end */\n");
26173: }
26174:
26175:
26176: #ifdef DBG
26177: int Adebug = 0;
26178: int Ddebug = 0;
26179: int Edebug = 0;
26180: int Ldebug = 0;
26181: int Mdebug = 0;
26182: int Ndebug = 0;
26183: int Pdebug = 0;
26184: int Rdebug = 0;
26185: int Sdebug = 0;
26186: int Tdebug = 0;
26187: //Ydebug == yydebug initialized in y.tab.c
26188: void
26189: process_debug_flags( char* p )
26190: {
26191: // arg to +Dxxx or debugging comments //@!xxx
26192: // format of xxx == sequence of any combination of
26193: // +flags -- increment flags (default)
26194: // -flags -- decrement flags
26195: // 0flags -- unset flags
26196: // where flags are single chars
26197: int incr = 1;
26198: char c;
26199: fprintf(stderr,"\n*** processing debugging flags '%s'\n",p);
26200: while ( c = *p++ ) {
26201: switch ( c ) {
26202: case '+': incr = 1; break;
26203: case '-': incr = -1; break;
26204: case '0': incr = 0; break;
26205: case ' ': break;
26206: // flags...
26207: case 'A': if(incr==0) Adebug=0; else Adebug+=incr; break;
26208: case 'D': if(incr==0) Ddebug=0; else Ddebug+=incr; break;
26209: case 'E': if(incr==0) Edebug=0; else Edebug+=incr; break;
26210: case 'L': if(incr==0) Ldebug=0; else Ldebug+=incr; break;
26211: case 'M': if(incr==0) Mdebug=0; else Mdebug+=incr; break;
26212: case 'N': if(incr==0) Ndebug=0; else Ndebug+=incr; break;
26213: case 'P': if(incr==0) Pdebug=0; else Pdebug+=incr; break;
26214: case 'R': if(incr==0) Rdebug=0; else Rdebug+=incr; break;
26215: case 'S': if(incr==0) Sdebug=0; else Sdebug+=incr; break;
26216: case 'T': if(incr==0) Tdebug=0; else Tdebug+=incr; break;
26217: case 'Y': if(incr==0) Ydebug=0; else Ydebug+=incr; break;
26218: default: error('w',"unknown debugging flag '%c'",c);
26219: }
26220: }
26221: }
26222: #endif /*DBG*/
26223:
26224: int no_of_undcl, no_of_badcall;
26225: Pname undcl, badcall;
26226:
26227: void pt_option(char * ostr)
26228: { // options +O[BTo] for PT
26229: ostr ++; /* skip the O */
26230: switch(*ostr) {
26231: default:
26232: fprintf(stderr, "cfront: argument syntax: invalidZizedTs option (+O[BTo].");
26233: exit(11);
26234: case 'B':
26235: tree_dump_brief = 1;
26236: case 'T':
26237: dump_tree = 1;
26238: if(0 == *(ostr + 1) || strcmp (ostr, "T-") == 0)
26239: dump_tree_arg.output_stream = (ostream*)&cout;
26240: else {
26241: dump_tree_arg.output_stream
26242: = new ofstream (ostr+1, ios::out);
26243: if(dump_tree_arg.output_stream->fail()) {
26244: perror ("cfront");
26245: fprintf (stderr, "Failed to open %s\n", ostr + 1);
26246: exit (11);
26247: }
26248: }
26249: break;
26250: case 'o':
26251: out_file = fopen (ostr+1, "w");
26252: if(out_file == NULL) {
26253: perror ("cfront");
26254: fprintf(stderr, "Failed to open %s\n", ostr+1);
26255: exit(11);
26256: }
26257: break;
26258: }
26259: }
26260:
26261: main(int argc, char* argv[])
26262: /*
26263: read options, initialize, and run
26264: */
26265: {
26266: register char * cp;
26267: char* afile = "";
26268: #ifdef unix
26269:
26270: #ifdef COMPLETE_SIG_PF
26271: signal(SIGILL,core_dump);
26272: signal(SIGIOT,core_dump);
26273: signal(SIGEMT,core_dump);
26274: signal(SIGFPE,core_dump);
26275: signal(SIGBUS,core_dump);
26276: signal(SIGSEGV,core_dump);
26277: #else
26278: typedef void (*ST)(int ...); // trick to circumvent problems with old
26279: ST sick = ST(&signal); // (or C) versions <signal.h>
26280: (*sick)(SIGILL,core_dump);
26281: (*sick)(SIGIOT,core_dump);
26282: (*sick)(SIGEMT,core_dump);
26283: (*sick)(SIGFPE,core_dump);
26284: (*sick)(SIGBUS,core_dump);
26285: (*sick)(SIGSEGV,core_dump);
26286:
26287: #endif
26288: #endif
26289:
26290: // SUM: not needed
26291: // #ifdef apollo
26292: // set_sbrk_size(1000000); // resets free store size
26293: //#else
26294: #ifndef apollo
26295: //(void) malloc(0); // suppress cashing in V8 malloc
26296: #endif
26297:
26298: error_init();
26299:
26300: for (int i=1; i<argc; ++i) {
26301: switch (*(cp=argv[i])) {
26302: case '+':
26303: while (*++cp) {
26304: switch(*cp) {
26305: case 'O':
26306: pt_option(cp);
26307: goto xx;
26308: case 'f':
26309: src_file_name = cp+1;
26310: goto xx;
26311: case 'x': // read cross compilation table
26312: if (read_align(afile = cp+1)) {
26313: fprintf(stderr,"bad size-table (option +x)\n");
26314: exit(11);
26315: }
26316: goto xx;
26317: case 'e':
26318: switch (*++cp) {
26319: case '0':
26320: case '1':
26321: vtbl_opt = *cp-'0';
26322: break;
26323: default:
26324: fprintf(stderr,"bad +e option\n");
26325: exit(11);
26326: }
26327: break;
26328: case 'd':
26329: debug_opt = 1;
26330: break;
26331: case 'g':
26332: gplus_opt = 1;
26333: break;
26334: case 'D':
26335: #ifdef DBG
26336: process_debug_flags(++cp);
26337: #else
26338: error('w',"cfront not compiled for debugging -- +D%s ignored",++cp);
26339: #endif
26340: goto xx;
26341: case 'w':
26342: warning_opt = 1;
26343: break;
26344: case 'a':
26345: switch (*++cp) {
26346: case '0':
26347: case '1':
26348: ansi_opt = *cp-'0';
26349: break;
26350: default:
26351: fprintf(stderr,"bad +a option\n");
26352: exit(11);
26353: }
26354: break;
26355: case 'p':
26356: strict_opt = 1;
26357: break;
26358: case 'L':
26359: line_format = "\n#line %d \"%s\"\n";
26360: break;
26361: default:
26362: fprintf(stderr,"%s: unexpected option: +%c ignored\n",prog_name,*cp);
26363:
26364: }
26365: }
26366: xx:
26367: break;
26368: default:
26369: fprintf(stderr,"%s: bad argument \"%s\"\n",prog_name,cp);
26370: exit(11);
26371: }
26372: }
26373:
26374:
26375: fprintf(out_file,line_format+1,1,src_file_name); // strips leading \n
26376: fprintf(out_file,"\n/* %s */\n",prog_name);
26377: if (*src_file_name) fprintf(out_file,"/* < %s > */\n",src_file_name);
26378:
26379: // if (Nspy) {
26380: // start_time = time(0);
26381: // print_align(afile);
26382: // }
26383: fflush(stderr);
26384: otbl_init();
26385: lex_init();
26386: syn_init();
26387: typ_init();
26388: simpl_init();
26389: scan_started = 1;
26390: curloc.putline();
26391: if ((BI_IN_BYTE==0) && (SZ_INT==0) && (SZ_WPTR==0))
26392: error("no size/alignment values - use +x of provide #ifdef in size.h");
26393: run();
26394: if(dump_tree) {
26395: ostream_printf(*dump_tree_arg.output_stream, "------------ GTBL ------------\n\n");
26396: display_cfront_node (dump_tree_arg, ktbl);
26397: ostream_printf(*dump_tree_arg.output_stream, "------------ KTBL ------------\n\n");
26398: display_cfront_node (dump_tree_arg, ktbl);
26399: }
26400:
26401: // if (Nspy) {
26402: // stop_time = time(0);
26403: // spy(src_file_name);
26404: // }
26405: exit( (0<=error_count && error_count<127) ? error_count : 127);
26406: }
26407:
26408: char* st_name(char* pref)
26409: /*
26410: make name "pref|source_file_name|_" or "pref|source_file_name|_"
26411: where non alphanumeric characters are replaced with '_'
26412: and add def_name at end to ensure uniqueness
26413: */
26414: {
26415: int prefl = strlen(pref);
26416: int strl = prefl + 2; // trailing '_' and 0
26417: if (*src_file_name) strl += strlen(src_file_name);
26418: char* defs;
26419: int defl;
26420: if (def_name) {
26421: defs = def_name->string;
26422: defl = strlen(defs)+1; // '_'
26423: }
26424: else {
26425: defs = 0;
26426: defl = 0;
26427: }
26428: char* name = new char[strl+defl];
26429: strcpy(name,pref);
26430: if (*src_file_name) strcpy(name+prefl,src_file_name);
26431: name[strl-2] = '_';
26432: name[strl-1] = 0;
26433: // char *p = name;
26434: // while ( *++p ) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
26435: for (char* p = name; *p; p++) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
26436: if (defs) {
26437: strcpy(name+strl-1,defs); // after the '_'
26438: name[strl+defl-2] = '_';
26439: name[strl+defl-1] = 0;
26440: }
26441: #ifdef DENSE
26442: void chop(char*);
26443: chop(name);
26444: #endif
26445:
26446: return name;
26447: }
26448: 0707071010112041141004440001630000160000010112640466055427400001100000007532makefile #ident "@(#)ctrans:src/makefile 1.3"
26449: ###############################################################################
26450: # Copyright (c) 1984 AT&T
26451: # All Rights Reserved
26452: #
26453: # THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
26454: #
26455: # The copyright notice above does not evidence any
26456: # actual or intended publication of such source code.
26457: #
26458: ###############################################################################
26459: CC = CC
26460:
26461: #The ANSI_OUT option has been replaced by the +a1 and +a0 compilation options
26462:
26463: #for systems which only recognize identifiers of up to 31 characters
26464: #setting DENSE to -DDENSE causes cfront to generate internal names
26465: #of 31 characters or less
26466: DENSE=
26467:
26468: # The use of RETBUG is nolonger needed with version 2.0 and has been removed.
26469: # RETBUG was used in 1.* Translator versions to circumvent a C compiler bug.
26470:
26471: CCFLAGS=-O
26472:
26473: # top level makefile modifies the following
26474: MPMACRO = PATCH
26475: MPFILE = patch
26476:
26477: OFILES = alloc.o dcl.o dcl2.o dcl3.o dcl4.o del.o \
26478: discrim.o doprint.o error.o expand.o \
26479: expr.o expr2.o expr3.o find.o hash.o lalex.o lex.o main.o \
26480: norm.o norm2.o print.o print2.o print_self.o repr.o simpl.o \
26481: simpl2.o size.o table.o template.o tree_copy.o tree_dump.o \
26482: tree_walk.o typ.o typ2.o y.tab.o
26483:
26484: cfront: $(OFILES)
26485: $(CC) -o cfront $(CCFLAGS) $(OFILES)
26486:
26487: $(OFILES): cfront.h token.h typedef.h
26488:
26489: y.tab.c: gram.y
26490: yacc gram.y
26491:
26492: alloc.o: alloc.c
26493: $(CC) $(CCFLAGS) -c alloc.c
26494:
26495: dcl.o: dcl.c size.h
26496: $(CC) $(CCFLAGS) -c dcl.c
26497:
26498: dcl2.o: dcl2.c size.h
26499: $(CC) $(CCFLAGS) -c dcl2.c
26500:
26501: dcl3.o: dcl3.c size.h
26502: $(CC) $(CCFLAGS) -c dcl3.c
26503:
26504: dcl4.o: dcl4.c size.h
26505: $(CC) $(CCFLAGS) -c dcl4.c
26506:
26507: del.o: del.c
26508: $(CC) $(CCFLAGS) -c del.c
26509:
26510: discrim.o: discrim.c cfront.h
26511: $(CC) $(CCFLAGS) -c discrim.c
26512:
26513: doprint.o: doprint.c
26514: $(CC) $(CCFLAGS) -c doprint.c
26515:
26516: error.o: error.c size.h
26517: $(CC) $(CCFLAGS) -c error.c
26518:
26519: expand.o: expand.c
26520: $(CC) $(CCFLAGS) -c expand.c
26521:
26522: expr.o: expr.c size.h
26523: $(CC) $(CCFLAGS) -c expr.c
26524:
26525: expr2.o: expr2.c size.h
26526: $(CC) $(CCFLAGS) -c expr2.c
26527:
26528: expr3.o: expr3.c size.h
26529: $(CC) $(CCFLAGS) -c expr3.c
26530:
26531: find.o: find.c
26532: $(CC) $(CCFLAGS) -c find.c
26533:
26534: hash.o: hash.c hash.h
26535: $(CC) $(CCFLAGS) -c hash.c
26536:
26537: lalex.o:lalex.c yystype.h tqueue.h
26538: $(CC) $(CCFLAGS) -c lalex.c
26539:
26540: lex.o: lex.c size.h tqueue.h yystype.h
26541: $(CC) $(CCFLAGS) -c lex.c
26542:
26543: # main depends on this makefile to force recompilation
26544: # when going from patch to munch
26545: main.o: main.c makefile
26546: $(CC) -D$(MPMACRO) $(DENSE) $(CCFLAGS) -c main.c
26547:
26548: norm.o: norm.c size.h
26549: $(CC) $(CCFLAGS) -c norm.c
26550:
26551: norm2.o: norm2.c size.h
26552: $(CC) $(CCFLAGS) -c norm2.c
26553:
26554: print.o: print.c
26555: $(CC) $(CCFLAGS) -c print.c
26556:
26557: print2.o: print2.c
26558: $(CC) $(DENSE) $(CCFLAGS) -c print2.c
26559:
26560: print_self.o: print_self.c
26561: $(CC) $(CCFLAGS) -c print_self.c
26562:
26563: repr.o: repr.c
26564: $(CC) $(CCFLAGS) -c repr.c
26565:
26566: simpl.o: simpl.c size.h
26567: $(CC) $(CCFLAGS) -c simpl.c
26568:
26569: simpl2.o: simpl2.c size.h
26570: $(CC) $(CCFLAGS) -c simpl2.c
26571:
26572: size.o: size.c size.h
26573: $(CC) $(CCFLAGS) -c size.c
26574:
26575: table.o: table.c
26576: $(CC) $(CCFLAGS) -c table.c
26577:
26578: template.o: template.c
26579: $(CC) $(CCFLAGS) -c template.c
26580:
26581: tree_copy.o: tree_copy.c
26582: $(CC) $(CCFLAGS) -c tree_copy.c
26583:
26584: tree_dump.o: tree_dump.c cfront.h
26585: $(CC) $(CCFLAGS) -c tree_dump.c
26586:
26587: tree_walk.o: tree_walk.c
26588: $(CC) $(CCFLAGS) -c tree_walk.c
26589:
26590: typ.o: typ.c size.h
26591: $(CC) $(CCFLAGS) -c typ.c
26592:
26593: typ2.o: typ2.c size.h
26594: $(CC) $(CCFLAGS) -c typ2.c
26595:
26596: y.tab.o: y.tab.c size.h
26597: $(CC) -DGRAM $(CCFLAGS) -c y.tab.c
26598:
26599: cpio:
26600: ls alloc.c dcl.c dcl2.c dcl3.c dcl4.c del.c discrim.c doprint.c \
26601: error.c expand.c expr.c expr2.c expr3.c find.c hash.c \
26602: lalex.c lex.c main.c norm.c norm2.c print.c print2.c \
26603: print_self.c repr.c simpl.c simpl2.c size.c table.c \
26604: template.c tree_copy.c tree_dump.c tree_walk.c typ.c typ2.c \
26605: gram.y \
26606: cfront.h token.h size.h tqueue.h typedef.h yystype.h \
26607: hash.h ios_printf.h node_classes.h print_self.h \
26608: template.h token_names.h tree_copy.h tree_dump.h tree_walk.h \
26609: makefile | cpio -oc > cfront.cpio
26610:
26611: 0707071010112046101004440001630000160000010212500466055421000001700000012215node_classes.h /* ident "@(#)ctrans:src/node_classes.h 1.2" */
26612: /*
26613: * node_classes.h
26614: */
26615:
26616: #ifndef _node_classes
26617: #define _node_classes
26618:
26619: enum discriminator_error {
26620: discrim_none_valid = 0,
26621: discrim_bad_index = -1,
26622: discrim_inconsistent_node = -2,
26623: };
26624:
26625: enum node_class {
26626: nc_unused = 0,
26627: nc_eof = 1,
26628: nc_virt = 2,
26629: nc_nlist = 3,
26630: nc_gen = 4,
26631: nc_vec = 5,
26632: nc_ptr = 6,
26633: nc_fct = 7,
26634: nc_table = 8,
26635: nc_basetype = 9,
26636: nc_name = 10,
26637: nc_expr = 11,
26638: nc_stmt = 12,
26639: nc_enumdef = 13,
26640: nc_classdef = 14,
26641: nc_baseclass = 15,
26642: nc_iline = 16,
26643: nc_ia = 17,
26644: };
26645:
26646: /*
26647: searching this is slower than a directly indexed array,
26648: but this is more maintainable. We can speed it up later.
26649: */
26650:
26651: #ifdef DEFINE_TOKEN_CLASS_TABLE
26652: struct token_class {
26653: TOK token;
26654: node_class nclass;
26655: } token_classes[] = {
26656: { EOFTOK, nc_eof },
26657: { ASM, nc_stmt },
26658: { AUTO, nc_basetype },
26659: { BREAK, nc_stmt },
26660: { CASE, nc_stmt },
26661: { CHAR, nc_basetype },
26662: { CLASS, nc_classdef },
26663: { CONTINUE, nc_stmt },
26664: { DEFAULT, nc_stmt },
26665: { DELETE, nc_expr },
26666: { DO, nc_stmt },
26667: { DOUBLE, nc_basetype },
26668: { ELSE, nc_stmt },
26669: { ENUM, nc_enumdef },
26670: { EXTERN, nc_basetype },
26671: { FLOAT, nc_basetype },
26672: { FOR, nc_stmt },
26673: { FORTRAN, nc_unused },
26674: { FRIEND, nc_basetype },
26675: { GOTO, nc_stmt },
26676: { IF, nc_stmt },
26677: { INT, nc_basetype },
26678: { LONG, nc_basetype },
26679: { NEW, nc_expr },
26680: { OPERATOR, nc_fct },
26681: { RETURN, nc_stmt },
26682: { PUBLIC, nc_name },
26683: { CONST, nc_basetype },
26684: { REGISTER, nc_basetype },
26685: { RETURN, nc_stmt },
26686: { SHORT, nc_basetype },
26687: { SIZEOF, nc_expr },
26688: { STATIC, nc_basetype },
26689: { STRUCT, nc_unused },
26690: { SWITCH, nc_stmt },
26691: { THIS, nc_expr },
26692: { TYPEDEF, nc_basetype },
26693: { UNION, nc_unused },
26694: { UNSIGNED, nc_basetype },
26695: { VOID, nc_basetype },
26696: { WHILE, nc_stmt },
26697: { LP, nc_unused },
26698: { RP, nc_unused },
26699: { LB, nc_unused },
26700: { RB, nc_unused },
26701: { REF, nc_expr },
26702: { DOT, nc_expr },
26703: { NOT, nc_expr },
26704: { COMPL, nc_expr },
26705: { INCR, nc_expr },
26706: { DECR, nc_expr },
26707: { MUL, nc_expr },
26708: { DIV, nc_expr },
26709: { AND, nc_expr },
26710: { MOD, nc_expr },
26711: { PLUS, nc_expr },
26712: { MINUS, nc_expr },
26713: { LS, nc_expr },
26714: { RS, nc_expr },
26715: { LT, nc_expr },
26716: { LE, nc_expr },
26717: { GT, nc_expr },
26718: { GE, nc_expr },
26719: { EQ, nc_expr },
26720: { NE, nc_expr },
26721: { ER, nc_expr },
26722: { OR, nc_expr },
26723: { ANDAND, nc_expr },
26724: { OROR, nc_expr },
26725: { QUEST, nc_expr },
26726: { COLON, nc_unused },
26727: { ASSIGN, nc_expr },
26728: { CM, nc_expr },
26729: { SM, nc_stmt },
26730: { SM_PARAM, nc_stmt },
26731: { LC, nc_unused },
26732: { RC, nc_unused },
26733: { INLINE, nc_fct },
26734: { OVERLOAD, nc_gen },
26735: { VIRTUAL, nc_fct }, /* but might be a basecl */
26736: { COERCE, nc_unused },
26737: { PROTECTED, nc_name },
26738: { ID, nc_unused },
26739: { STRING, nc_expr },
26740: { ICON, nc_expr },
26741: { FCON, nc_expr },
26742: { CCON, nc_expr },
26743: { NAME, nc_name }, /* but might be basecl */
26744: { ZERO, nc_expr },
26745: { ASOP, nc_expr },
26746: { RELOP, nc_expr },
26747: { EQUOP, nc_expr },
26748: { DIVOP, nc_expr },
26749: { SHIFTOP, nc_expr },
26750: { ICOP, nc_expr },
26751: { UNOP, nc_expr },
26752: { TYPE, nc_basetype },
26753: { UMINUS, nc_expr },
26754: { FCT, nc_fct },
26755: { CALL, nc_expr },
26756: { VEC, nc_vec },
26757: { DEREF, nc_expr },
26758: { ADDROF, nc_expr },
26759: { CAST, nc_expr },
26760: { FIELD, nc_basetype },
26761: { LABEL, nc_stmt },
26762: { BLOCK, nc_stmt },
26763: { DCL, nc_stmt },
26764: { COBJ, nc_basetype },
26765: { EOBJ, nc_basetype },
26766: { TNAME, nc_name },
26767: { ILIST, nc_expr },
26768: { PTR, nc_ptr },
26769: { ASPLUS, nc_expr },
26770: { ASMINUS, nc_expr },
26771: { ASMUL, nc_expr },
26772: { ASDIV, nc_expr },
26773: { ASMOD, nc_expr },
26774: { ASAND, nc_expr },
26775: { ASOR, nc_expr },
26776: { ASER, nc_expr },
26777: { ASLS, nc_expr },
26778: { ASRS, nc_expr },
26779: { ARG, nc_basetype },
26780: { ZTYPE, nc_basetype },
26781: { ARGT, nc_basetype },
26782: { ELIST, nc_expr },
26783: { ANY, nc_basetype },
26784: { TABLE, nc_table },
26785: { LOC, nc_unused },
26786: { DUMMY, nc_expr },
26787: { G_ADDROF, nc_expr },
26788: { G_CALL, nc_expr },
26789: { G_CM, nc_expr },
26790: { IVAL, nc_expr },
26791: { ELLIPSIS, nc_unused },
26792: { AGGR, nc_unused },
26793: { RPTR, nc_ptr },
26794: { HIDDEN, nc_unused },
26795: { MEM, nc_expr },
26796: { CTOR, nc_unused },
26797: { DTOR, nc_unused },
26798: { CONST_PTR, nc_ptr },
26799: { CONST_RPTR, nc_ptr },
26800: { TEXT, nc_expr },
26801: { PAIR, nc_stmt },
26802: { ANON, nc_unused },
26803: { ICALL, nc_expr },
26804: { ANAME, nc_expr },
26805: { VOLATILE, nc_basetype },
26806: { SIGNED, nc_basetype },
26807: { UPLUS, nc_expr },
26808: { MEMPTR, nc_unused },
26809: { PRIVATE, nc_name },
26810: { PR, nc_unused },
26811: { MDOT, nc_expr },
26812: { TSCOPE, nc_unused },
26813: { DECL_MARKER, nc_unused },
26814: { REFMUL, nc_expr },
26815: { LDOUBLE, nc_basetype },
26816: { LINKAGE, nc_unused },
26817: { LOCAL, nc_basetype },
26818: { GNEW, nc_expr },
26819: { TEMPLATE, nc_unused },
26820: { STAT_INIT, nc_unused },
26821: { CATCH, nc_unused },
26822: { GDELETE, nc_expr },
26823: { XVIRT, nc_virt },
26824: { XNLIST, nc_nlist },
26825: { XILINE, nc_iline },
26826: { XIA, nc_ia },
26827: { VALUE, nc_expr },
26828: { XDELETED_NODE, nc_unused },
26829: };
26830: #endif
26831:
26832: node_class classify_node (Pnode, int&);
26833: node_class classify_node (Pnode);
26834:
26835: #endif
26836: 0707071010112044361004440001630000160000010204500466055405300000700000120447norm.c /*ident "@(#)ctrans:src/norm.c 1.10" */
26837: /************************************************************************
26838:
26839: C++ source for cfront, the C++ compiler front-end
26840: written in the computer science research center of Bell Labs
26841:
26842: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
26843: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
26844:
26845: norm.c:
26846:
26847: "normalization" handles problems which could have been handled
26848: by the syntax analyser; but has not been done. The idea is
26849: to simplify the grammar and the actions accociated with it,
26850: and to get a more robust error handling
26851:
26852: ****************************************************************************/
26853: #ifdef c_plusplus
26854: overload nested_hide;
26855: #endif
26856:
26857: #include "cfront.h"
26858: #include "size.h"
26859: #include "template.h"
26860:
26861: extern Pname do_nested_type(Pname);
26862: extern int is_anon(char*);
26863:
26864: Pname sta_name = 0;
26865:
26866: void syn_init()
26867: {
26868: any_type = new basetype(ANY,0);
26869: PERM(any_type); any_type->defined = DEFINED;
26870: dummy = new expr(DUMMY,0,0);
26871: PERM(dummy);
26872: dummy->tp = any_type;
26873: zero = new expr(ZERO,0,0);
26874: PERM(zero);
26875: sta_name = new name;
26876: PERM(sta_name);
26877: // Gtbl = new table(GTBLSIZE,0,0); //SYM
26878: // Ctbl = Gtbl; //SYM
26879: }
26880:
26881: int stcount;
26882:
26883: char* make_name(TOK c)
26884: {
26885: char* s = new char[8]; // as it happens: fits in two words
26886:
26887: if (10000 <= ++stcount) error('i',"too many generatedNs");
26888:
26889: sprintf(s,"__%c%d",c,stcount);
26890: return s;
26891: }
26892:
26893: Pbase basetype::type_adj(TOK t)
26894: {
26895: DB(if(Ndebug>=1)error('d',"'%k'->type_adj(%k) --%t b_xname%n",base,t,this,b_xname););
26896: if (b_xname) {
26897: if (base)
26898: error("badBT:%n%k",b_xname,t);
26899: else {
26900: base = TYPE;
26901: b_name = b_xname;
26902: }
26903: b_xname = 0;
26904: }
26905:
26906: switch (t) {
26907: case TYPEDEF: b_typedef = 1; break;
26908: case INLINE: b_inline = 1; break;
26909: case VIRTUAL: b_virtual = 1; break;
26910: case CONST: if (b_const) error('w',"two const declarators");
26911: b_const = 1; break;
26912: case UNSIGNED: b_unsigned = 1; break;
26913: case SHORT: b_short = 1; break;
26914: case LONG: if (b_long) error('w',"two long declarators");
26915: if (base == DOUBLE)
26916: base = LDOUBLE;
26917: else
26918: b_long = 1;
26919: break;
26920: case FRIEND:
26921: case OVERLOAD:
26922: case EXTERN:
26923: case STATIC:
26924: case AUTO:
26925: case REGISTER:
26926: if (b_sto)
26927: error("badBT:%k%k",b_sto,t);
26928: else
26929: b_sto = t;
26930: break;
26931: case DOUBLE:
26932: if (b_long) {
26933: t = LDOUBLE;
26934: b_long = 0;
26935: }
26936: // no break
26937: case VOID:
26938: case CHAR:
26939: case INT:
26940: case FLOAT:
26941: if (base)
26942: error("badBT:%k%k",base,t);
26943: else
26944: base = t;
26945: break;
26946: case SIGNED:
26947: case VOLATILE:
26948: error('w',"\"%k\" not implemented (ignored)",t);
26949: break;
26950: default:
26951: error('i',"BT::type_adj(%k)",t);
26952: }
26953: return this;
26954: }
26955:
26956: Pbase basetype::name_adj(Pname n)
26957: {
26958: DB(if(Ndebug>=1)error('d',"'%k'->name_adj(%n) --%t b_xname%n",base,n,this,b_xname));
26959: if (b_xname) {
26960: if (base)
26961: error("badBT:%n%n",b_xname,n);
26962: else {
26963: base = TYPE;
26964: b_name = b_xname;
26965: }
26966: b_xname = 0;
26967: }
26968:
26969: if ( base==0
26970: && n->base == TNAME
26971: && ( n->tp->base!=COBJ || in_arg_list )) {
26972: base = TYPE;
26973: b_name = n;
26974: }
26975: else
26976: b_xname = n;
26977:
26978: return this;
26979: }
26980:
26981: static TOK type_set( Pbase b )
26982: {
26983: TOK t = 0;
26984:
26985: if ( b->b_long ) t = LONG;
26986: else if ( b->b_short ) t = SHORT;
26987: else if ( b->b_unsigned ) t = UNSIGNED;
26988: else if ( b->b_inline ) t = INLINE;
26989: else if ( b->b_virtual ) t = VIRTUAL;
26990: else if ( b->b_sto == OVERLOAD ) t = OVERLOAD;
26991: return t;
26992: }
26993:
26994: int declTag = 1;
26995:
26996: Pbase basetype::base_adj(Pbase b)
26997: {
26998: DB(if(Ndebug>=1)error('d',"'%k'->base_adj(%t) --%t b_xname%n",base,b,this,b_xname));
26999: Pname bn = b->b_name;
27000:
27001: switch (base) {
27002: case COBJ:
27003: case EOBJ:
27004: error("NX after%k%n",base,b_name);
27005: return this;
27006: }
27007:
27008: TOK t;
27009: if (base) {
27010: if (b_name)
27011: error("badBT:%k%n%k%n",base,b_name,b->base,bn);
27012: else
27013: error("badBT:%k%k%n",base,b->base,bn);
27014: }
27015: else if ( t = type_set(this)) {
27016: if (b_name)
27017: error("badBT:%k%n%k%n",t,b_name,b->base,bn);
27018: else {
27019: if ( declTag++ && (t!= INLINE)) error("badBT:%k%k%n",t,b->base,bn);
27020: base=b->base; b_name = bn;
27021: // error('d',"base_adj: t: %k", t );
27022: }
27023: }
27024: else {
27025: base = b->base;
27026: b_name = bn;
27027: b_table = b->b_table;
27028: }
27029:
27030: if ( b->base == COBJ ) {
27031: Pclass cl = Pclass(bn->tp);
27032: if ( cl->in_class &&
27033: bn->tpdef &&
27034: bn->tpdef->lex_level == NESTED )
27035: { // peculiar case: class x { typedef class bn {} _bn; ...
27036: // bn has been half dealt with in do_nested_type ...
27037: Pname n = new name(bn->string);
27038: n->tp = b;
27039: Pname nn = ktbl->insert(n, NESTED); //SYM
27040: nn->tpdef = bn->tpdef;
27041: nn->tpdef->lex_level = nn->lex_level = 0;
27042: bn->tpdef = 0;
27043: }
27044: }
27045:
27046: return this;
27047: }
27048:
27049: Pbase basetype::check(Pname n)
27050: /*
27051: "n" is the first name to be declared using "this"
27052: check the consistency of "this"
27053: and use "b_xname" for "n->string" if possible and needed
27054: */
27055: {
27056: b_inline = 0;
27057: b_virtual = 0;
27058: //error('d',"basetype::check(%n) base %k b_xname %n",n,base,b_xname);
27059:
27060: if (b_xname && (n->tp || n->string)) {
27061: if (base)
27062: error("badBT:%k%n",base,b_xname);
27063: else {
27064: base = TYPE;
27065: b_name = b_xname;
27066: }
27067: b_xname = 0;
27068: }
27069:
27070: if (b_xname) {
27071: if (n->string)
27072: error("twoNs inD:%n%n",b_xname,n);
27073: else {
27074: n->string = b_xname->string;
27075: b_xname->hide();
27076: }
27077: b_xname = 0;
27078: }
27079:
27080: if (ccl==0
27081: && n
27082: && n->n_oper==TNAME
27083: && n->n_qualifier==0
27084: && n->string) { // hide type name
27085: Pname nx = ktbl->look(n->string,0); //SYM
27086: if (nx) nx->hide();
27087: }
27088:
27089: int defa = 0;
27090: switch (base) {
27091: case 0:
27092: defa = 1;
27093: base = INT;
27094: break;
27095: case EOBJ:
27096: case COBJ:
27097: if (b_name->base == TNAME) error('i',"TN%n inCO %p",b_name,this);
27098: }
27099:
27100: if (b_long || b_short) {
27101: TOK sl = (b_short) ? SHORT : LONG;
27102: if (b_long && b_short) error("badBT:long short%k%n",base,n);
27103: if (base != INT)
27104: error("badBT:%k%k%n",sl,base,n);
27105: else
27106: base = sl;
27107: b_short = b_long = 0;
27108: }
27109:
27110: if (b_typedef && b_sto) error("badBT:Tdef%k%n",b_sto,n);
27111: b_typedef = b_sto = 0;
27112:
27113: if (b_linkage) {
27114: if (1 <= bl_level) error("local linkage directive");
27115: }
27116:
27117: if (Pfctvec_type == 0) return this;
27118:
27119: if (b_const) {
27120: if (b_unsigned) {
27121: switch (base) {
27122: default:
27123: error("badBT: unsigned const %k%n",base,n);
27124: b_unsigned = 0;
27125: case LONG:
27126: case SHORT:
27127: case INT:
27128: case CHAR:
27129: return this;
27130: }
27131: }
27132: return this;
27133: }
27134: else if (b_unsigned) {
27135: switch (base) {
27136: case LONG:
27137: delete this;
27138: return ulong_type;
27139: case SHORT:
27140: delete this;
27141: return ushort_type;
27142: case INT:
27143: delete this;
27144: return uint_type;
27145: case CHAR:
27146: delete this;
27147: return uchar_type;
27148: default:
27149: error("badBT: unsigned%k%n",base,n);
27150: b_unsigned = 0;
27151: return this;
27152: }
27153: }
27154: else {
27155: switch (base) {
27156: case LONG:
27157: delete this;
27158: return long_type;
27159: case SHORT:
27160: delete this;
27161: return short_type;
27162: case INT:
27163: if (this==int_type || this==defa_type) return this;
27164: // if (this != int_type)
27165: delete this;
27166: if (defa) return defa_type;
27167: return int_type;
27168: case CHAR:
27169: delete this;
27170: return char_type;
27171: case VOID:
27172: delete this;
27173: return void_type;
27174: case TYPE:
27175: /* use a single base saved in the keyword */
27176: if (b_name->n_qualifier) {
27177: Pbase rv = Pbase(b_name->n_qualifier);
27178: delete this;
27179: return rv;
27180: }
27181: else {
27182: PERM(this);
27183: b_name->n_qualifier = (Pname)this;
27184: return this;
27185: }
27186: default:
27187: return this;
27188: }
27189: }
27190: }
27191:
27192: Pname basetype::aggr()
27193: /*
27194: "type SM" seen e.g. struct s {};
27195: class x;
27196: enum e;
27197: int tname;
27198: friend cname;
27199: friend class x;
27200: int;
27201:
27202: typedef int i; // where i is tname
27203:
27204: convert
27205: union { ... };
27206: into
27207: union name { ... } name ;
27208: */
27209: {
27210: DB(if(Ndebug>=1)error('d',"'%k'->aggr() --%t b_xname%n ccl%t",base,this,b_xname,ccl));
27211: if (b_xname) {
27212: if (base) {
27213: Pname n = new name(b_xname->string);
27214: /*SYM?*/if (ccl && b_xname->tpdef)
27215: /*SYM?*/ n->tpdef = b_xname->tpdef;
27216: b_xname->hide();
27217: b_xname = 0;
27218: return n->normalize(this,0,0);
27219: }
27220: else {
27221: base = TYPE;
27222: b_name = b_xname;
27223: b_xname = 0;
27224: }
27225: }
27226:
27227: switch (base) {
27228: case COBJ:
27229: { Pclass cl = Pclass(b_name->tp);
27230: char* s = cl->string;
27231: /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n inCO",b_name);
27232: if (b_const) error("const%k%n",cl->csu,b_name);
27233:
27234: if (cl->c_body == 2) { /* body seen */
27235: if (s[0]=='_' && s[1]=='_' && s[2]=='C') {
27236: char* ss = new char[8]; // max size of generated name is 7 chars, see make_name()
27237: Pname obj = new name(ss);
27238: strcpy(ss,s);
27239: if (cl->csu == UNION) {
27240: ss[2] = 'O';
27241: cl->csu = ANON;
27242: return obj->normalize(this,0,0);
27243: }
27244: error('w',"unusable%k ignored",cl->csu);
27245: }
27246: if ( b_sto == FRIEND )
27247: error("friend%k%n{...}",cl->csu,b_name);
27248: cl->c_body = 1;
27249: return b_name;
27250: }
27251: else { /* really a typedef for cfront only: class x; */
27252: if (b_sto == FRIEND) goto frr;
27253: if (ansi_opt) printf("struct %s;\n",s);
27254: return 0;
27255: }
27256: }
27257:
27258: case EOBJ:
27259: { Penum en = Penum(b_name->tp);
27260: /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n in enumO",b_name);
27261: if (b_const) error("const enum%n",b_name);
27262: if (en->e_body == 2) {
27263: en->e_body = 1;
27264: return b_name;
27265: }
27266: else {
27267: error("forwardD of enum%n", b_name);
27268: en->e_type = int_type;
27269: }
27270: return 0;
27271: }
27272:
27273: case 0:
27274: { Pname n = new name(make_name('D'));
27275: n->tp = defa_type;
27276: error("NX inDL");
27277: return n;
27278: }
27279: default:
27280: if (b_typedef) error('w',"illegalTdef ignored");
27281:
27282: if (b_sto == FRIEND && b_name ) {
27283: frr:
27284: Pname fr = ktbl->look(b_name->string,0); //SYM
27285: if (fr == 0) error('i',"cannot find friend%n",b_name);
27286: Pname n = new name(b_name->string);
27287: n->n_sto = FRIEND;
27288: // If it is a parameterized type, use the instantiation
27289: // type, not the general type.
27290: if ((fr->tp->base == COBJ) &&
27291: (Pclass(Pbase(fr->tp)->b_name->tp)->class_base ==
27292: template_class))
27293: {
27294: if (base == COBJ)
27295: n->tp = this;
27296: else
27297: if ((base == TYPE) &&
27298: (Pbase(this)->b_name->base == TNAME) &&
27299: (Pbase(this)->b_name->tp->base == COBJ))
27300: n->tp = Pbase(this)->b_name->tp;
27301: else
27302: error('i', "basetype wasn't a COBJ");
27303: }
27304: else n->tp = fr->tp;
27305: return n;
27306: }
27307: else {
27308: Pname n = new name(make_name('D'));
27309: n->tp = defa_type;
27310: error('w',"NX inDL");
27311: return n;
27312: }
27313: }
27314: }
27315:
27316: void local_name() //SYM -- to be removed
27317: { /* need to provide an additional temporary name
27318: * to handle case of
27319: * f() {
27320: * { class x{...}; }
27321: * { class x{...}; }
27322: * }
27323: * generate name after closing } of block
27324: * to distinquish between separate blocks at same lexical level
27325: */
27326: for (Plist l=local_blk; l; l=l->l) {
27327: Pname n = l->f;
27328: if ( n->tp == 0 ) error( 'i', "no tp yet: #0 local_name" );
27329: if ( Pbase(n->tp)->b_name == 0 ) error( 'i', "no tp yet: #1 local_name" );
27330: Pname bn = Pbase(n->tp)->b_name;
27331: if ( bn->tp == 0 ) error( 'i', "no tp yet#2: local_name" );
27332: Pclass cl = Pclass(bn->tp);
27333: cl->lcl = make_name( 'L' );
27334: // error( 'd', "local_name(): %n bn: %n: cl : %s nof: %d", n, bn, cl->string, cc->nof );
27335: }
27336: }
27337:
27338: void local_restore() //SYM -- to be removed
27339: {
27340: for (Plist l=local_tn; l; l=l->l) {
27341: Pname n = l->f;
27342: // error('d',"local_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
27343: n->n_key = (n->lex_level==0) ? 0
27344: : (n->lex_level && n->lex_level<=bl_level) ? LOCAL : HIDDEN;
27345: }
27346: }
27347:
27348: void local_hide( Pname n ) //SYM -- to be removed
27349: {
27350: // error('d',"local_hide(%n )",n);
27351:
27352: if ( n->base != TNAME ) return;
27353: if ( n->n_key == 0 ) {
27354: local_tn = new name_list( n, local_tn );
27355: n->n_key = HIDDEN;
27356: // error( 'd', "local_hide(): %n n_key: %d", n, n->n_key );
27357: }
27358: }
27359:
27360: void
27361: nested_restore() //SYM -- to be removed
27362: {
27363: for (Plist l = nested_type; l; l=l->l)
27364: {
27365: Pname n = l->f;
27366: n->n_key = NESTED;
27367: }
27368:
27369: for (l=nested_tn; l; l=l->l) {
27370: Pname n = l->f;
27371: Ptype tp = n->tp;
27372: // error('d',"nested_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
27373: // error('d'," --- n_key %k", n->n_key );
27374:
27375: if ( tp->in_class )
27376: n->n_key = NESTED;
27377: else
27378: if ( tp->lex_level )
27379: n->n_key = LOCAL;
27380: else
27381: n->n_key = 0;
27382: // error('d'," --- n_key %k", n->n_key );
27383: }
27384: }
27385:
27386: void
27387: nested_hide( Pname n ) //SYM -- to be removed
27388: {
27389: // error('d',"nested_hide(%n )",n);
27390:
27391: if ( n->base != TNAME ) return;
27392: if ( n->n_key == 0 ) {
27393: nested_tn = new name_list( n, nested_tn );
27394: n->n_key = HIDDEN;
27395: // error( 'd', "nested_hide(): %n n_key: %d", n, n->n_key );
27396: }
27397: }
27398:
27399: static void
27400: nested_hide( Plist l ) //SYM -- to be removed
27401: {
27402: // error('d',"nested_hide( list )");
27403:
27404: for (; l; l=l->l) {
27405: Pname nn = l->f;
27406: Pname n = ktbl->look(nn->string,0);
27407: // error('d',"nested_hide %n %t", n, n->tp, n->n_key);
27408: if (n==0) continue;
27409:
27410: if ( n->base != TNAME )
27411: error('i', "nested_hide: %n not a type name (%t)", n, n->tp );
27412: if ( n->n_key == 0 ) {
27413: nested_tn = new name_list( n, nested_tn );
27414: n->n_key = HIDDEN;
27415: // error( 'd', "nested_hide(list): %n n_key: %d", n, n->n_key );
27416: // nn->n_key = 0;
27417: }
27418: }
27419: }
27420:
27421: int defer_check = 0;
27422: Pname statStat = 0;
27423:
27424: void name::hide()
27425: /*
27426: hide "this": that is, "this" should not be a keyword in this scope
27427: */
27428: {
27429: if (base != TNAME) return;
27430: // error('d',"'%n '->hide() -- %t lex_level %d bl_level %d",this,tp,lex_level,::bl_level);
27431: if (n_key == 0) {
27432: if (lex_level == bl_level && in_arg_list == 0) {
27433: if (tp->base != COBJ) {
27434: if ( !in_typedef )
27435: error("%n redefined: typedef and identifier", this);
27436: else if ( in_typedef->base
27437: && tp->base != type_set(Pbase(in_typedef))
27438: && in_typedef->check(tp,0) ) {
27439: if ( defer_check == 0 )
27440: error("%n redefined: previous: %t now: %t", this, tp, in_typedef);
27441: }
27442: }
27443: else {
27444: //error('d',"in_typedef%t %d tp%t %d",in_typedef,in_typedef,tp,tp);
27445: //error('d',"in_typedef%k tp%k",in_typedef->base,tp->base);
27446: if ( in_typedef && in_typedef->base
27447: && in_typedef->check(tp, 0) ) {
27448: if ( defer_check == 0 )
27449: error( "%n redefined: previous: %t now: %t", this, tp, in_typedef);
27450: }
27451: else {
27452: Pname nn = Pbase(tp)->b_name;
27453: Pclass cl = Pclass( nn->tp );
27454: // check for 'typedef class X X;'
27455: // and 'typedef X X;'
27456: if ( in_typedef )
27457: while ( in_typedef->base == TYPE )
27458: in_typedef = Pbase(in_typedef)->b_name->tp;
27459: if ( in_typedef
27460: && in_typedef->base==COBJ
27461: && Pbase(in_typedef)->b_name->tp==cl )
27462: in_typedef = tp;
27463: else if ( cl->has_ctor() )
27464: error( "%n redefined: both aCNWK and %s", this, in_typedef?"a type name":"an identifier" );
27465: }
27466: }
27467:
27468: }
27469: // error( 'd', "%n::hide", this );
27470: modified_tn = new name_list(this,modified_tn);
27471: n_key = HIDDEN;
27472: }
27473: }
27474:
27475: static Pname Ntncheck; // ensure TNAMES hidden within class scopes
27476: static int notReally = 0;
27477:
27478: void set_scope(Pname tn) //SYM -- to be shrunk
27479: /* enter the scope of class tn after seeing "tn::f" */
27480: {
27481: // error( 'd', "set_scope: %n %t %d", tn, tn->tp, tn->tp->base );
27482: // error( 'd', "set_scope: %d", notReally );
27483:
27484: Pbase b = Pbase(tn->tp);
27485: while ( b->base == TYPE ) b=Pbase(b->b_name->tp); // typedef class X T
27486: if (b->base != COBJ) return; // error caught elsewhere
27487:
27488: Pclass cl = Pclass(b->b_name->tp);
27489: char *str = cl->string;
27490:
27491: if ( cl->nest_list && notReally == 0 ) {
27492: nested_type = cl->nest_list;
27493: nested_hide(cl->nest_list);
27494: }
27495:
27496: Pname ntn = Ntncheck;
27497: if( notReally == 0 )
27498: while ( ntn && ntn->tp->base == TYPE ) ntn = Pbase(ntn->tp)->b_name;
27499:
27500: if ( notReally || ntn == 0 || strcmp( str,ntn->string )) {
27501: if ( cl->baselist ) {
27502: Pname nb = new name, nbc = new name;
27503: nb->tp = new basetype(COBJ,0);
27504: Pbase(nb->tp)->b_name = nbc;
27505: for (Pbcl bx, bb=cl->baselist; bb; bb = bb->next) {
27506: bx = bb->next;
27507: if ( bb->bclass != 0 ) {
27508: nbc->tp = bb->bclass;
27509: notReally++; set_scope(nb); notReally--;
27510: }
27511: }
27512: DEL(nbc); /*DEL(nb->tp);*/ DEL(nb);
27513: }
27514:
27515: int i = 1;
27516: Pname n = 0;
27517: Plist ll = 0;
27518: if (b->parametrized_class()) {
27519: for (Pname nn = cl->mem_list; nn; nn = nn->n_list)
27520: switch (nn->base) {
27521: case PUBLIC: case PRIVATE: case PROTECTED:
27522: continue;
27523: default:
27524: if (nn->tp->base == CLASS) continue;
27525: if (nn->tp->base == ENUM) continue;
27526: if ((nn->base == NAME) &&
27527: ((nn->n_oper == TNAME) && (nn->tp->base == FCT)) ||
27528: (nn->n_oper == CTOR) ||
27529: (nn->n_oper == DTOR)) continue ;
27530: n = ktbl->look( nn->string, 0 );
27531: if (n) ll = new name_list( n, ll );
27532: }
27533: } // if b->parametrized_class()
27534: else
27535: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i) ) {
27536: if (nn->base == TNAME || nn->base == PUBLIC) continue;
27537: if (nn->tp->base == CLASS) continue;
27538: if (nn->tp->base == ENUM) continue;
27539: n = ktbl->look( nn->string, 0 );
27540: if (n) ll = new name_list( n, ll );
27541: }
27542:
27543: if ( ll ) cl->tn_list = ll;
27544: if (notReally == 0) Ntncheck = tn;
27545: }
27546:
27547: for (Plist l=cl->tn_list; l; l=l->l) {
27548: Pname n = l->f;
27549: n->n_key = (n->lex_level) ? 0 : HIDDEN;
27550: modified_tn = new name_list(n,modified_tn);
27551: }
27552: }
27553:
27554: void restore() //SYM -- to be removed
27555: {
27556: for (Plist l=modified_tn; l; l=l->l) {
27557: Pname n = l->f;
27558: // error('d',"restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
27559: //fprintf(stderr," -- n_key %d\n",n->n_key);
27560: n->n_key = (n->lex_level==0 || (n->lex_level && n->lex_level<=bl_level)) ? 0 : HIDDEN;
27561: //fprintf(stderr," -- n_key %d\n",n->n_key);
27562: if ( n->lex_level == 0
27563: && (n->tp->base == COBJ || n->tp->base == EOBJ)) {
27564: Pname nn = gtbl->look( n->string, 0 );
27565: if ( nn ) n->n_key = HIDDEN;
27566: }
27567: //fprintf(stderr," -- n_key %d\n",n->n_key);
27568: }
27569: }
27570:
27571: Pbase start_cl(TOK t, Pname c, Pbcl b)
27572: {
27573: int mk_local = 0;
27574: DB(if(Ndebug>=1)error('d',"start_cl(%k,%d,%d)",t,c,b););
27575: if (c == 0) {
27576: c = new name(make_name('C'));
27577: c->lex_level -= in_class_decl + 1;
27578: if ( in_typedef && c->lex_level )
27579: mk_local = 1;
27580: else c->lex_level = 0;
27581: }
27582:
27583: for ( Pclass tc = ccl; tc; tc = tc->in_class ) {
27584: if ( tc->lex_level == c->lex_level // c not local to mem ftn of tc
27585: && strcmp( tc->string, c->string) == 0) {
27586: error( "C %s redefined", c->string );
27587: error('i', "can't recover from previous errors");
27588: }
27589: }
27590:
27591: Pname n = c->tname(t); /* t ignored */
27592:
27593: if (templp->in_progress && (c->lex_level == 0))
27594: // bring the template in scope
27595: templp->introduce_class_templ(n);
27596:
27597: // typedef struct {} x;
27598: if ( mk_local ) {
27599: n->n_key = LOCAL;
27600: extern Plist local_blk, local_class; // place in cfront.h
27601: local_class = new name_list( n, local_class );
27602: local_blk = new name_list( n, local_blk );
27603: modified_tn = modified_tn->l;
27604: }
27605:
27606: n->where = curloc;
27607: Pbase bt = Pbase(n->tp); /* COBJ */
27608: if (bt->base != COBJ) {
27609: error("twoDs of%n:%t andC",n,bt);
27610: error('i', "can't recover from previous errors");
27611: }
27612:
27613: Pclass occl = ccl;
27614: ccl = Pclass(bt->b_name->tp); /* CLASS */
27615: if (ccl->defined) ccl->defined |= IN_ERROR;
27616: ccl->defined |= DEF_SEEN;
27617:
27618: // error('d', "start_cl: %n ccl->in_class: %t lex_level: %d", n, ccl->in_class, n->lex_level );
27619:
27620: if (ccl->in_class = occl) {
27621: occl->tn_list = modified_tn; // save mod-list
27622: modified_tn = 0;
27623: }
27624:
27625: Ntncheck = 0; // zero it out with each new class declaration
27626: ccl->string = n->string;
27627: ccl->csu = t;
27628:
27629: if (b) { // list of base classes
27630: for (Pbcl bx, bb=b, l=0; bb; bb = bx) {
27631: bx = bb->next;
27632: bb->next = 0;
27633:
27634: if ( bb->bclass
27635: && strcmp(ccl->string,bb->bclass->string)==0 )
27636: error(&n->where,"%nderived from itself",n);
27637: else if (l == 0)
27638: l = bb;
27639: else { // append and check for duplicates
27640: for (Pbcl ll = l;;) {
27641: if (bb->bclass && ll->bclass==bb->bclass) {
27642: error("%s has %s asB twice",ccl->string,bb->bclass->string);
27643: break;
27644: }
27645:
27646: if (ll->next)
27647: ll = ll->next;
27648: else {
27649: bb->next = l;
27650: l = bb;
27651: break;
27652: }
27653: }
27654: }
27655: }
27656:
27657: ccl->baselist = l;
27658: notReally++; set_scope(n); notReally--;
27659: }
27660: return bt;
27661: }
27662:
27663: void end_cl()
27664: {
27665: Pclass occl = ccl->in_class;
27666: Plist ol = occl ? occl->tn_list : 0; // saved modified name list
27667: ccl->c_body = 2;
27668:
27669: if (modified_tn) { // export nested class names to outer scope:
27670: Plist local = 0;
27671: for (Plist l=modified_tn, nl=0; l; l=nl) {
27672: nl = l->l;
27673: Pname n = l->f;
27674:
27675: // in a pure implementation, no longer do this
27676: if (ktbl->look(n->string,0)) {
27677: // add it to enclosing class's modified name list
27678: l->l = ol;
27679: ol = l;
27680: }
27681: else { // retain it in this class's modified name list
27682: l->l = local;
27683: local = l;
27684: }
27685: }
27686: if (ccl->tn_list = modified_tn = local) restore();
27687: }
27688: modified_tn = ol; // restore mod-list (possibly modified)
27689: /*
27690: if ( occl ) {
27691: Pname n = ktbl->look(ccl->string,NESTED);
27692: for (;n; n=n->n_tbl_list) {
27693: Ptype tt = Pbase(n->tp)->b_name->tp;
27694: // error('d',"end_cl: ccl: %t occl: %t in_class: %t", ccl, occl, tt->in_class);
27695: if (strcmp(tt->in_class->string, occl->string) == 0) {
27696: n->n_key = 0;
27697: }
27698: }
27699: }
27700: */
27701: ccl = occl;
27702: }
27703:
27704: Pbase end_enum(Pname n, nlist* b)
27705: {
27706: // error( 'd', "end_enum: %n ccl: %t", n , ccl );
27707: if (n == 0) n = new name(make_name('E'));
27708: n = n->tname(ENUM);
27709: Pbase bt = (Pbase)n->tp;
27710: if (bt->base != EOBJ) {
27711: error("twoDs of%n:%t and enum",n,bt);
27712: error('i', "can't recover from previous errors");
27713: }
27714: Penum en = (Penum)bt->b_name->tp;
27715: en->e_body = 2;
27716: en->mem = name_unlist(b);
27717: if (en->defined) {
27718: // shouldn't be necessary anymore with nested types
27719: // if ( in_class_decl )
27720: // error("%n redefined, enum tag not local to class", n);
27721: en->defined |= IN_ERROR;
27722: }
27723: en->defined |= DEF_SEEN;
27724: en->in_class = ccl;
27725: if (ccl && (bl_level==ccl->lex_level + in_class_decl) && is_anon(n->string))
27726: n=do_nested_type(n);
27727: return bt;
27728: }
27729:
27730: extern Ptype return_nstd_local_type(Pname,TOK&);
27731: Pname name::tdef()
27732: /*
27733: typedef "this"
27734: */
27735: {
27736: DB(if(Ndebug>=1) {
27737: error('d',&where,"'%n'->tdef()%t in_typedef %d",this,tp,in_typedef);
27738: error('d',&where," lex_level %d tpdef%t",lex_level,tpdef);
27739: });
27740: int anon_cl = 0;
27741: if (n_qualifier) {
27742: error("QdN in typedef",this);
27743: n_qualifier = 0;
27744: }
27745:
27746: Pname n;
27747: if ( tpdef && tpdef->in_class ) { // nested typedef
27748: // error('d', "*****%s->tdef: %d ccl: %t", string, tpdef, ccl );
27749: n = ktbl->insert(this,NESTED);
27750: n->tpdef = tpdef;
27751: n->tpdef->lex_level = n->lex_level = 0;
27752: nested_type = new name_list( n, nested_type );
27753: }
27754: else {
27755: Pname nn = ktbl->look(string,NESTED);
27756: if ( nn ) {
27757: TOK ntk = 0; // set by return_nstd...
27758: Ptype tt = return_nstd_local_type(nn,ntk);
27759: error("nested%k%t::%s seen beforeGTdef %s (to do this placeG definition first)",ntk, tt->in_class, string, string);
27760: error( 'i', "cannot recover from previous errors" );
27761: }
27762: lex_level = bl_level - in_class_decl;
27763: n = ktbl->insert(this,0);
27764: }
27765:
27766: if (tp == 0) error('i',"Tdef%n tp==0",this);
27767: n->base = base = TNAME;
27768: PERM(n);
27769: PERM(tp);
27770:
27771: if (tp->base == COBJ || tp->base == EOBJ )
27772: { // typedef struct/enum { } s; => struct/enum s {};
27773: Pname b = Pbase(tp)->b_name;
27774: if (b->string[0] == '_' && b->string[1] == '_' )
27775: switch ( tp->base ) {
27776: case COBJ: {
27777: if (b->string[2] == 'C') {
27778: Pclass cl = Pclass(b->tp);
27779: b->string = n->string;
27780: cl->string = n->string;
27781: cl->strlen = strlen(cl->string);
27782: if ( lex_level ) {
27783: anon_cl = 1;
27784: n->n_key = LOCAL;
27785: }
27786: }
27787: break;
27788: }
27789: case EOBJ: {
27790: if (b->string[2] == 'E') {
27791: Penum en = Penum(b->tp);
27792: b->string = n->string;
27793: en->string = n->string;
27794: en->strlen = strlen(en->string);
27795: }
27796: }
27797: }
27798: }
27799:
27800: if ( anon_cl == 0 )
27801: modified_tn = new name_list(n,modified_tn);
27802: DB(if(Ndebug>=1) {
27803: error('d',&where,">>'%n'->tdef()%t returning",this,tp);
27804: error('d',&where," lex_level %d tpdef%t",lex_level,tpdef);
27805: });
27806: return n;
27807: }
27808:
27809: Pname name::tname(TOK csu)
27810: /*
27811: "csu" "this" seen, return typedef'd name for "this"
27812: return (TNAME,x)
27813: x: (COBJ,y)
27814: y: (NAME,z)
27815: z: (CLASS,ae);
27816: */
27817: {
27818: //error('d',"'%n'::tname(%k)",this,csu);
27819: switch (base) {
27820: case TNAME:
27821: return this;
27822: case NAME:
27823: { Pname tn = ktbl->insert(this,0);
27824: Pname on = new name;
27825: tn->base = TNAME;
27826: tn->lex_level = lex_level;
27827: modified_tn = new name_list(tn,modified_tn);
27828: tn->n_list = n_list = 0;
27829: string = tn->string;
27830: *on = *this;
27831: switch (csu) {
27832: case ENUM:
27833: tn->tp = new basetype(EOBJ,on);
27834: on->tp = new enumdef(0);
27835: Penum(on->tp)->string = tn->string;
27836: break;
27837: case CLASS:
27838: case STRUCT:
27839: case UNION:
27840: on->tp = new classdef(csu);
27841: Pclass(on->tp)->string = tn->string;
27842: Pclass(on->tp)->lex_level = lex_level;
27843: tn->tp = new basetype(COBJ,on);
27844: Pbase(tn->tp)->b_table = Pclass(on->tp)->memtbl;
27845: break;
27846: default:
27847: error('i',&where,"illegal csu%k for%n in name::tname()",csu,this);
27848: }
27849: PERM(tn);
27850: PERM(tn->tp);
27851: PERM(on);
27852: PERM(on->tp);
27853: return tn;
27854: }
27855: default:
27856: error('i',"tname(%s %d %k)",string,this,base);
27857: }
27858: }
27859:
27860: int co_hack;
27861: Pname name::normalize(Pbase b, Pblock bl, bit Cast)
27862: /*
27863: if (bl) : a function definition (check that it really is a type
27864:
27865: if (Cast) : no name string
27866:
27867: for each name on the name list
27868: invert the declarator list(s) and attatch basetype
27869: watch out for class object initializers
27870:
27871: convert
27872: struct s { int a; } a;
27873: into
27874: struct s { int a; }; struct s a;
27875: */
27876: {
27877: Pname n;
27878: Pname nn;
27879: TOK stc;
27880: bit tpdf;
27881: bit inli;
27882: bit virt;
27883: char * lnkg;
27884: DB( if(Ndebug>=1) {
27885: error('d',"'%n'::normalize(b%t, bl %d, cast %d)",this,b,bl,Cast);
27886: error('d'," tp%k - lex_level %d - bl_level %d",tp?tp->base:0,lex_level,bl_level);
27887: });
27888: if (b) {
27889: stc = b->b_sto;
27890: tpdf = b->b_typedef;
27891: inli = b->b_inline;
27892: virt = b->b_virtual;
27893: lnkg = b->b_linkage;
27894: }
27895: else {
27896: stc = 0;
27897: tpdf = 0;
27898: inli = 0;
27899: virt = 0;
27900: lnkg = 0;
27901: }
27902:
27903: if (inli && stc==EXTERN) {
27904: error("both extern and inline");
27905: inli = 0;
27906: }
27907:
27908: if ( stc==STATIC && tp &&
27909: tp->base == FCT
27910: && Pfct(tp)->f_const )
27911: error( "%n staticMF cannot be const", this );
27912:
27913: if (stc==FRIEND && tp==0) {
27914: /* friend x;
27915: must be handled during syntax analysis to cope with
27916: class x { friend y; y* p; };
27917: "y" is not local to "x":
27918: class x { friend y; ... }; y* p;
27919: is legal
27920:
27921: examples:
27922:
27923: typedef void SIG_TYP(int);
27924: class x {
27925: friend class y;
27926: friend z;
27927: friend x; // dumb
27928: friend int i; // error
27929: friend SIG_TYP sigFunc; // subtle
27930: friend int f();
27931: friend g(int);
27932: };
27933: */
27934: if (b && (b->base || b->b_name || b->b_xname)) goto ccc;
27935:
27936: if (n_list) {
27937: error("L of friends");
27938: n_list = 0;
27939: }
27940:
27941: if (!Cast) {
27942: Pname nn = gtbl->look( string, 0 );
27943: if ( nn ) {
27944: if (nn->tp->base == FCT)
27945: error("friendF must include signature:%n", this );
27946: else
27947: error("illegal friendD:%n", this );
27948: }
27949: }
27950:
27951: //error( 'd', "%n ll: %d", ccl, ccl->lex_level );
27952: lex_level = ccl->lex_level;
27953: Pname nx = tname(CLASS);
27954: modified_tn = modified_tn->l; /* global */
27955: n_sto = FRIEND;
27956: tp = nx->tp;
27957: return this;
27958: }
27959: ccc:
27960: if (tp // FUDGE: fix the bad grammar
27961: && tp->base==FCT
27962: && (n_oper==TNAME || Pfct(tp)->returns)) {
27963: Pfct f = Pfct(tp);
27964: Pfct f2 = Pfct(f->returns);
27965:
27966: if (f2) {
27967: Ptype pt;
27968: Ptype t = f2;
27969: lxlx:
27970: switch (t->base) {
27971: case PTR: // x(* p)(args) ?
27972: case VEC: // x(* p[10])(args) ?
27973: if (pt = Pptr(t)->typ) {
27974: if (pt->base == TYPE) {
27975: Pptr(t)->typ = 0;
27976: b = Pbase(pt);
27977: // stc = b->b_sto;
27978: // tpdf = b->b_typedef;
27979: // inli = b->b_inline;
27980: // virt = b->b_virtual;
27981: }
27982: else {
27983: t = pt;
27984: goto lxlx;
27985: }
27986: }
27987: goto zse1;
27988: case FCT:
27989: {// Pexpr e = f2->argtype;
27990: Pexpr e = Pfct(f)->argtype;
27991: if (e && e->base==ELIST) { // get the real name; fix its type
27992: if (e->e2 || e->e1->base!=DEREF) goto zse1;
27993: Pexpr ee = e->e1;
27994: Ptype t = 0;
27995: Ptype tpx;
27996: ldld:
27997: switch (ee->base) {
27998: case DEREF:
27999: { Ptype tt = (ee->e2) ? Ptype(new vec(0,ee->e2)) : Ptype (new ptr(PTR,0));
28000: if (t)
28001: Pptr(t)->typ = tt;
28002: else
28003: tpx = tt;
28004: t = tt;
28005: ee = ee->e1;
28006: goto ldld;
28007: }
28008: case NAME:
28009: { Pname rn = Pname(ee);
28010: b = new basetype(TYPE,ktbl->look(string,0));
28011: f->returns = tpx;
28012: n_oper = 0;
28013: string = rn->string;
28014: base = NAME;
28015: }
28016: }
28017: }
28018: }
28019: }
28020: }
28021: }
28022:
28023: zse1:
28024: if (b == 0) {
28025: error("BTX for %s",string);
28026: b = Pbase(defa_type);
28027: }
28028:
28029: if (Cast) string = "";
28030: b = b->check(this);
28031:
28032: switch (b->base) { // separate class definitions
28033: // from object and function type declarations
28034: case COBJ:
28035: nn = b->b_name;
28036: if (Pclass(nn->tp)->c_body==2) { /* first occurrence */
28037: if ( stc == FRIEND ) {
28038: Pclass cl = Pclass(nn->tp);
28039: if ( cl->csu == ANON )
28040: error( &nn->where, "friend anonymous union");
28041: else
28042: error( &nn->where, "%k%n defined in friendD",cl->csu,nn);
28043: }
28044: if (tp && tp->base==FCT && co_hack == 0) {
28045: error(&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this);
28046: nn = this;
28047: break;
28048: }
28049: nn->n_list = this;
28050: Pclass(nn->tp)->c_body = 1; /* other occurences */
28051: }
28052: else
28053: nn = this;
28054: break;
28055: case EOBJ:
28056: nn = b->b_name;
28057: if (Penum(nn->tp)->e_body==2) {
28058: if (tp && tp->base==FCT) {
28059: error(&this->where,"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this);
28060: nn = this;
28061: break;
28062: }
28063: nn->n_list = this;
28064: Penum(nn->tp)->e_body = 1;
28065: }
28066: else {
28067: Penum en = Penum(nn->tp);
28068: if ( en->defined == 0 )
28069: error( "forwardD of enum%n", nn );
28070: en->e_type = int_type;
28071: nn = this;
28072: }
28073: break;
28074: default:
28075: nn = this;
28076: }
28077:
28078: //error('d',&where,"name::normalize: nn%n ll %d nn %d this %d",nn,nn->lex_level,nn,this);
28079: Pname nx;
28080: for (n=this; n; n=nx) {
28081: Ptype t = n->tp;
28082: nx = n->n_list;
28083: n->n_sto = stc;
28084:
28085: if (n->base == TNAME) error('i',"redefinition ofTN%n",n);
28086:
28087: if (t == 0) {
28088: if (bl == 0)
28089: n->tp = t = b;
28090: else {
28091: if ( n->base == NAME && n->n_oper )
28092: error(&n->where,"illegalD of %n",n);
28093: else
28094: error(&n->where,"body of nonF%n",n);
28095: t = new fct(0,0,0);
28096: }
28097: }
28098:
28099: switch (t->base) {
28100: case PTR:
28101: case RPTR:
28102: n->tp = Pptr(t)->normalize(b);
28103: break;
28104: case VEC:
28105: n->tp = Pvec(t)->normalize(b);
28106: break;
28107: case FCT:
28108: n->tp = Pfct(t)->normalize(b);
28109: break;
28110: case FIELD:
28111: if (n->string == 0) n->string = make_name('F');
28112: n->tp = t;
28113: Pbase tb = b;
28114: // error('d', "field t %k tb %k", t->base, tb->base );
28115: flatten:
28116: switch (tb->base) {
28117: case TYPE: /* chase typedefs */
28118: tb = (Pbase)tb->b_name->tp;
28119: goto flatten;
28120: case CHAR:
28121: case SHORT:
28122: case EOBJ:
28123: case INT:
28124: // typedef const unsigned cu_int;
28125: // struct x { x(); cu_int b1: 2; }
28126:
28127: Pbase(t)->b_fieldtype = (b->b_unsigned||tb->b_unsigned) ? uint_type : int_type;
28128: // goto iii;
28129: // case CHAR:
28130: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type;
28131: // goto iii;
28132: // case SHORT:
28133: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type;
28134: // goto iii;
28135: // iii:
28136: Pbase(t)->b_unsigned = b->b_unsigned?b->b_unsigned:tb->b_unsigned;
28137: Pbase(t)->b_const = b->b_const?b->b_const:tb->b_const;
28138: break;
28139: default:
28140: error("non-int field");
28141: n->tp = defa_type;
28142: }
28143: break;
28144: }
28145:
28146: Pfct f = Pfct(n->tp);
28147:
28148: if (f->base != FCT) {
28149: if (bl) {
28150: error("body for nonF%n",n);
28151: n->tp = f = new fct(defa_type,0,0);
28152: continue;
28153: }
28154: if (inli) error("inline nonF%n",n);
28155: if (virt) error("virtual nonF%n",n);
28156:
28157: if (tpdf) {
28158: // error('d', "%n->normalize: ccl: %t", this, ccl );
28159: if (ccl && n->tpdef &&
28160: (n->tpdef->lex_level == NESTED ||
28161: n->tpdef->lex_level == LOCAL))
28162: ; // using this field for nested/local type info
28163: else
28164: if (n->n_initializer) {
28165: error("Ir forTdefN%n",n);
28166: n->n_initializer = 0;
28167: }
28168: n->tdef();
28169: // because do_nested_type can't call tdef()
28170: if ( n->n_key == NESTED )
28171: modified_tn = modified_tn->l;
28172: }
28173: continue;
28174: }
28175:
28176: if ( lnkg ) set_linkage(lnkg);
28177: f->f_linkage = linkage;
28178: if ( lnkg ) set_linkage(0);
28179: // wait and call f->sign() after args are checked
28180:
28181: f->f_inline = inli;
28182: extern int vcounter;
28183: f->f_virtual = virt?(vcounter++,VTOK):0;
28184:
28185: if (tpdf) {
28186: if (f->body = bl) error("Tdef%n { ... }",n);
28187: if (n->n_qualifier) {
28188: // typedef T x::f(args);
28189: // a pointer to member fucntion:
28190: // equivalent to typedef T x::(f)(args);
28191: f->memof = Pclass(Pbase(n->n_qualifier->tp)->b_name->tp);
28192: n->n_qualifier = 0;
28193: }
28194: n->tdef();
28195: // because do_nested_type can't call tdef()
28196: if ( n->n_key == NESTED )
28197: modified_tn = modified_tn->l;
28198: continue;
28199: }
28200:
28201: if (f->body = bl) continue;
28202:
28203: /*
28204: Check function declarations.
28205: Look for class object instantiations
28206: The real ambiguity: ; class x fo();
28207: is interpreted as an extern function
28208: declaration NOT a class object with an
28209: empty initializer
28210: */
28211: { Pname cn = f->returns->is_cl_obj();
28212: Ptype template_formal_type ;
28213: bit clob = (cn || cl_obj_vec);
28214:
28215: if (f->argtype) { /* check argument/initializer list */
28216: Pname nn;
28217:
28218: for (nn=f->argtype; nn; nn=nn->n_list) {
28219: if (nn->base != NAME) {
28220: if (!clob) {
28221: if ((f->returns->base == TYPE) &&
28222: (Pbase(f->returns)->b_name->n_template_arg == template_type_formal))
28223: {
28224: // T x(var); wher T is a template formal
28225: // it could be a class when instantiated
28226: // wait until then to issue error message
28227: template_formal_type = f->returns;
28228: Pname nnn = Pbase(f->returns)->b_name;
28229: nnn->n_template_formal_must_be_class = 1;
28230: goto is_obj;
28231: }
28232: error(&n->where,"ATX for%n",n);
28233: goto zzz;
28234: }
28235: goto is_obj;
28236: }
28237: //if (nn->string) {
28238: // error("AN%n inD of%n",nn,n);
28239: // nn->string = 0;
28240: //}
28241: if (nn->tp) goto ok;
28242: }
28243: if (!clob) {
28244: error("FALX");
28245: goto zzz;
28246: }
28247: is_obj:
28248: /* it was an initializer: expand to constructor */
28249: n->tp = f->returns;
28250: if (f->argtype->base != ELIST) f->f_args = f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0);
28251: if ( n->n_initializer ) {
28252: error(&n->where,"twoIrs for%n",n);
28253: DEL( ((Pexpr)f->argtype) );
28254: f->argtype = 0;
28255: } else
28256: // n->n_initializer = new texpr(VALUE,cn->tp,(Pexpr)f->argtype);
28257: n->n_initializer = new texpr(VALUE, cn ? cn->tp : template_formal_type, (Pexpr)f->argtype);
28258: goto ok;
28259: zzz:
28260: if (f->argtype) {
28261: DEL(Pexpr(f->argtype));
28262: f->argtype = 0;
28263: f->nargs = 0;
28264: f->nargs_known = 1;
28265: }
28266: }
28267: else { /* T a(); => function declaration */
28268: /*
28269: if (clob) {
28270: DEL(n->tp);
28271: n->tp = f->returns;
28272: }
28273: */
28274: }
28275: ok:
28276: ;
28277: }
28278: }
28279: return nn;
28280: }
28281:
28282: Ptype vec::normalize(Ptype vecof)
28283: {
28284: Ptype t = typ;
28285: typ = vecof;
28286:
28287: while(vecof->base == TYPE)
28288: vecof = Pbase(vecof)->b_name->tp;
28289:
28290: switch (vecof->base) {
28291: case RPTR:
28292: error("array ofRs");
28293: break;
28294: case FCT:
28295: error("array ofFs");
28296: break;
28297: default:
28298: break;
28299: }
28300:
28301: if (t == 0) return this;
28302:
28303: switch (t->base) {
28304: case PTR:
28305: case RPTR: return Pptr(t)->normalize(this);
28306: case VEC: return Pvec(t)->normalize(this);
28307: case FCT: return Pfct(t)->normalize(this);
28308: default: error('i',"bad arrayT(%d)",t->base);
28309: }
28310:
28311: }
28312:
28313: Ptype ptr::normalize(Ptype ptrto)
28314: {
28315: // if (this == 0) error('i',"0->ptr.normalize()");
28316: Ptype t = typ;
28317: typ = ptrto;
28318:
28319: int bc = 0;
28320: while (ptrto->base == TYPE) {
28321: bc += Pbase(ptrto)->b_const;
28322: ptrto = Pbase(ptrto)->b_name->tp;
28323: }
28324:
28325: switch (ptrto->base) {
28326: case FCT:
28327: if (memof)
28328: if (Pfct(ptrto)->memof) {
28329: if (memof != Pfct(ptrto)->memof) error("P toMF mismatch: %s and %s",memof->string, Pfct(ptrto)->memof->string);
28330: }
28331: else
28332: Pfct(ptrto)->memof = memof;
28333: else
28334: memof = Pfct(ptrto)->memof;
28335: break;
28336: case RPTR:
28337: switch (base) {
28338: case PTR: error("P toR"); break;
28339: case RPTR: error("R toR"); break;
28340: }
28341: }
28342:
28343: if (t == 0) {
28344: Pbase b = Pbase(ptrto);
28345: if (Pfctvec_type
28346: && rdo==0
28347: && b->b_unsigned==0
28348: && b->b_const==0
28349: && bc == 0
28350: && memof==0
28351: && base==PTR) {
28352: switch (b->base) {
28353: case INT: delete this; return Pint_type;
28354: case CHAR: delete this; return Pchar_type;
28355: case VOID: delete this; return Pvoid_type;
28356: }
28357: }
28358: if (base==RPTR && b->base==VOID) error("void& is not a validT");
28359: return this;
28360: }
28361:
28362: switch (t->base) {
28363: case PTR:
28364: case RPTR: return Pptr(t)->normalize(this);
28365: case VEC: return Pvec(t)->normalize(this);
28366: case FCT: return Pfct(t)->normalize(this);
28367: default: error('i',"badPT(%k)",t->base);
28368: }
28369: }
28370:
28371: Ptype fct::normalize(Ptype ret)
28372: /*
28373: normalize return type
28374: */
28375: {
28376: register Ptype t = returns;
28377: returns = ret;
28378:
28379: if (argtype && argtype->base==NAME && argtype->n_qualifier) {
28380: error("syntax: ANX");
28381: argtype = 0;
28382: nargs = 0;
28383: nargs_known = 0;
28384: }
28385:
28386: while(ret->base == TYPE)
28387: ret = Pbase(ret)->b_name->tp;
28388:
28389: switch(ret->base) {
28390: case VEC:
28391: error("F returning array");
28392: break;
28393: case FCT:
28394: error("F returningF");
28395: returns = ret = t?t:int_type;
28396: break;
28397: default:
28398: break;
28399: }
28400:
28401: if (t == 0) return this;
28402:
28403: switch (t->base) {
28404: case PTR:
28405: case RPTR: return Pptr(t)->normalize(this);
28406: case VEC: return Pvec(t)->normalize(this);
28407: case FCT: return Pfct(t)->normalize(this);
28408: default: error('i',"badFT:%k",t->base);
28409: }
28410: }
28411:
28412: void fct::argdcl(Pname dcl, Pname fn)
28413: /*
28414: sort out the argument types for old syntax:
28415: f(a,b) int a; char b; { ... }
28416: beware of
28417: f(a) struct s { int a; }; struct s a;
28418: */
28419: {
28420: Pname n;
28421: /*fprintf(stderr,"%d argtype %d %d dcl %d %d\n",this, argtype, argtype?argtype->base:0, dcl, dcl?dcl->base:0); fflush(stderr);*/
28422: switch (base) {
28423: case FCT: break;
28424: case ANY: return;
28425: default: error('i',"fct::argdcl(%d)",base);
28426: }
28427:
28428: if (argtype) {
28429: switch (argtype->base) {
28430: case NAME:
28431: if (dcl) error("badF definition syntax");
28432: for (n=argtype; n; n=n->n_list) {
28433: if (n->string == 0) n->string = make_name('A');
28434: }
28435: return;
28436: case ELIST: // expression list: f(a,b,c) int a; ... { ... }
28437: // scan the elist and build a NAME list
28438: {
28439: Pname tail = 0;
28440: n = 0;
28441:
28442: error(strict_opt?0:'w',&fn->where,"old style definition of%n (anachronism)",fn);
28443:
28444: for (Pexpr e=Pexpr(argtype); e; e=e->e2) {
28445: Pexpr id = e->e1;
28446: if (id->base != NAME) {
28447: error("NX inAL");
28448: argtype = 0;
28449: dcl = 0;
28450: break;
28451: }
28452: Pname nn = new name(id->string);
28453: if (n)
28454: tail = tail->n_list = nn;
28455: else
28456: tail = n = nn;
28457: }
28458: f_args = argtype = n;
28459: break;
28460: }
28461: default:
28462: error("ALX(%d)",argtype->base);
28463: argtype = 0;
28464: dcl = 0;
28465: }
28466: }
28467: else if(nargs_known == ELLIPSIS) {
28468: return;
28469: }
28470: else {
28471: nargs_known = 1;
28472: nargs = 0;
28473: if (dcl) error("ADL forFWoutAs");
28474: return;
28475: }
28476:
28477: // nargs_known = 0;
28478:
28479: if (dcl) {
28480: Pname d;
28481: Pname dx;
28482: /* for each argument name see if its type is specified
28483: in the declaration list otherwise give it the default type
28484: */
28485:
28486: for (n=argtype; n; n=n->n_list) {
28487: char* s = n->string;
28488: if (s == 0) {
28489: error("AN missing inF definition");
28490: n->string = s = make_name('A');
28491: }
28492: else if (n->tp) error("twoTs forA %s",n->string);
28493:
28494: for (d=dcl; d; d=d->n_list) {
28495: if (strcmp(s,d->string) == 0) {
28496: if (d->tp->base == VOID) {
28497: error("voidA%n",d);
28498: d->tp = any_type;
28499: }
28500: n->tp = d->tp;
28501: n->n_sto = d->n_sto;
28502: d->tp = 0; // now merged into argtype
28503: goto xx;
28504: }
28505: }
28506: n->tp = defa_type;
28507: xx:;
28508: if (n->tp == 0) error('i',"noT for %s",n->string);
28509: }
28510:
28511: /* now scan the declaration list for "unused declarations"
28512: and delete it
28513: */
28514: for (d=dcl; d; d=dx) {
28515: dx = d->n_list;
28516: if (d->tp) { /* not merged with argtype list */
28517: /*if (d->base == TNAME) ??? */
28518: switch (d->tp->base) {
28519: case CLASS:
28520: case ENUM:
28521: /* WARNING: this will reverse the order of
28522: class and enum declarations
28523: */
28524: d->n_list = argtype;
28525: f_args = argtype = d;
28526: break;
28527: default:
28528: error("%n inADL not inAL",d);
28529: }
28530: }
28531: }
28532: }
28533:
28534: /* add default argument types if necessary */
28535: for (n=argtype; n; n=n->n_list) {
28536: if (n->tp == 0) n->tp = defa_type;
28537: nargs++;
28538: }
28539: }
28540:
28541: Pname cl_obj_vec; /* set if is_cl_obj() found a array of class objects */
28542: Pname eobj; /* set if is_cl_obj() found an enum */
28543:
28544: Pname type::is_cl_obj()
28545: /*
28546: returns this->b_name if this is a class object
28547: returns 0 and sets cl_obj_vec to this->b_name
28548: if this is a array of class objects
28549: returns 0 and sets eobj to this->b_name
28550: if this is an enum object
28551: else returns 0
28552: */
28553: {
28554: bit v = 0;
28555: register Ptype t = this;
28556:
28557: if (t == 0) return 0;
28558: eobj = 0;
28559: cl_obj_vec = 0;
28560: xx:
28561: switch (t->base) {
28562: case TYPE:
28563: t = Pbase(t)->b_name->tp;
28564: goto xx;
28565:
28566: case COBJ:
28567: if (v) {
28568: cl_obj_vec = Pbase(t)->b_name;
28569: return 0;
28570: }
28571: else
28572: return Pbase(t)->b_name;
28573:
28574: case VEC:
28575: t = Pvec(t)->typ;
28576: v=1;
28577: goto xx;
28578:
28579: case EOBJ:
28580: eobj = Pbase(t)->b_name;
28581: default:
28582: return 0;
28583: }
28584: }
28585:
28586: /*
28587: static Pname
28588: lookup(char* s, Pclass cl)
28589: {
28590: Pbcl bc = 0;
28591: Pname n = cl->memtbl->look(s,0);
28592: if ( n ) return n;
28593: Pname n2 = 0;
28594: for (Pbcl b=cl->baselist; b; b=b->next) {
28595: n = b->bclass->lookup(s,cl);
28596: if ( n == 0 ) continue;
28597: if ( n2 ) { // clash?
28598: }
28599: n2 = n;
28600: }
28601: }
28602: */
28603: 0707071010112044371004440001630000160000010205100466055405600001000000011657norm2.c /*ident "@(#)ctrans:src/norm2.c 1.4" */
28604: /************************************************************************
28605:
28606: C++ source for cfront, the C++ compiler front-end
28607: written in the computer science research center of Bell Labs
28608:
28609: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
28610: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
28611:
28612: norm2.c:
28613:
28614: "normalization" handles problems which could have been handled
28615: by the syntax analyser; but has not been done. The idea is
28616: to simplify the grammar and the actions associated with it,
28617: and to get a more robust error handling
28618:
28619: ****************************************************************************/
28620:
28621: #include "cfront.h"
28622: #include "size.h"
28623:
28624: #ifdef DBG
28625: long node_id = 0;
28626: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__);
28627: #else
28628: #define DBCHECK() /**/
28629: #endif
28630:
28631: fct::fct(Ptype t, Pname arg, TOK known)
28632: {
28633: base = FCT;
28634: nargs_known = known;
28635: returns = t;
28636: argtype = arg;
28637: DBID();
28638:
28639: if (arg==0 || arg->base==ELIST) return;
28640: //error('d',"fct::fct %d sig %d",this,f_signature);
28641: register Pname n;
28642: Pname pn = 0;
28643: for (n=arg; n; pn=n,n=n->n_list) {
28644: if( n->n_sto==EXTERN ) error("externA");
28645: if( n->n_sto==STATIC ) error("static used forA%n",arg);
28646:
28647: switch (n->tp->base) {
28648: case VOID:
28649: argtype = 0;
28650: nargs_known = 1;
28651: if(n->n_initializer)
28652: error("voidFA");
28653: else if (n->string)
28654: error("voidFA%n",n);
28655: else if (nargs || n->n_list) {
28656: error("voidFA");
28657: nargs_known = 0;
28658: }
28659: nargs = 0;
28660: break;
28661: case CLASS:
28662: case ENUM:
28663: error("%k defined inAL (will not be in scope at point of call)",n->tp->base);
28664: if (n == argtype)
28665: argtype = n->n_list;
28666: else
28667: pn->n_list = n->n_list;
28668: break;
28669: default:
28670: nargs++;
28671: }
28672: }
28673: }
28674:
28675: expr::expr(TOK ba, Pexpr a, Pexpr b)
28676: {
28677: DBCHECK();
28678:
28679: base = ba;
28680: e1 = a;
28681: e2 = b;
28682: DBID();
28683: }
28684:
28685: stmt::stmt(TOK ba, loc ll, Pstmt a)
28686: {
28687: DBCHECK();
28688:
28689: base = ba;
28690: where = ll;
28691: s=a;
28692: DBID();
28693: }
28694:
28695: classdef::classdef(TOK b)
28696: {
28697: base = CLASS;
28698: csu = b;
28699: memtbl = new table(CTBLSIZE,0,0);
28700: DBID();
28701: }
28702:
28703: classdef::~classdef()
28704: {
28705: delete memtbl;
28706: }
28707:
28708: basetype::basetype(TOK b, Pname n)
28709: {
28710: switch (b) {
28711: case 0: break;
28712: case TYPEDEF: b_typedef = 1; break;
28713: case INLINE: b_inline = 1; break;
28714: case VIRTUAL: b_virtual = 1; break;
28715: case CONST: b_const = 1; break;
28716: case UNSIGNED: b_unsigned = 1; break;
28717: case FRIEND:
28718: case OVERLOAD:
28719: case EXTERN:
28720: case STATIC:
28721: case AUTO:
28722: case REGISTER: b_sto = b; break;
28723: case SHORT: b_short = 1; break;
28724: case LONG: b_long = 1; break;
28725: case ANY:
28726: case ZTYPE:
28727: case VOID:
28728: case CHAR:
28729: case INT:
28730: case FLOAT:
28731: case LDOUBLE:
28732: case DOUBLE: base = b; break;
28733: case TYPE:
28734: case COBJ:
28735: case EOBJ:
28736: case FIELD:
28737: case ASM:
28738: base = b;
28739: b_name = n;
28740: break;
28741: case SIGNED:
28742: case VOLATILE:
28743: error('w',"\"%k\" not implemented (ignored)",b);
28744: break;
28745: default:
28746: error('i',"badBT:%k",b);
28747: }
28748: DBID();
28749: }
28750:
28751: name::name(char* s) : expr(NAME,0,0)
28752: {
28753: // DBCHECK() called in expr::expr()
28754: string = s;
28755: where = curloc;
28756: lex_level = bl_level;
28757: }
28758:
28759: nlist::nlist(Pname n)
28760: {
28761: head = n;
28762: for (Pname nn=n; nn->n_list; nn=nn->n_list);
28763: tail = nn;
28764: }
28765:
28766: void nlist::add_list(Pname n)
28767: {
28768: if (n->tp && (n->tp->defined & IN_ERROR)) return;
28769:
28770: tail->n_list = n;
28771: for (Pname nn=n; nn->n_list; nn=nn->n_list);
28772: tail = nn;
28773: }
28774:
28775: Pname name_unlist(Pnlist l)
28776: {
28777: if (l == 0) return 0;
28778: Pname n = l->head;
28779:
28780: delete l;
28781: return n;
28782: }
28783:
28784: Pstmt stmt_unlist(Pslist l)
28785: {
28786: if (l == 0) return 0;
28787: Pstmt s = l->head;
28788: // NFl++;
28789:
28790: delete l;
28791: return s;
28792: }
28793:
28794: Pexpr expr_unlist(Pelist l)
28795: {
28796: if (l == 0) return 0;
28797: Pexpr e = l->head;
28798: // NFl++;
28799:
28800: delete l;
28801: return e;
28802: }
28803:
28804: void sig_name(Pname n)
28805: {
28806: static char buf[256];
28807: buf[0] = '_';
28808: buf[1] = '_';
28809: buf[2] = 'o';
28810: buf[3] = 'p';
28811: char* p = n->tp->signature(buf+4);
28812: if (255 < p-buf) error('i',"sig_name():N buffer overflow");
28813: char *s = new char [ p - buf + 1 ];
28814: strcpy(s,buf);
28815: n->string = s;
28816: n->tp = 0;
28817: }
28818:
28819: Ptype tok_to_type(TOK b)
28820: {
28821: Ptype t;
28822: switch (b) {
28823: case CHAR: t = char_type; break;
28824: case SHORT: t = short_type; break;
28825: case LONG: t = long_type; break;
28826: case UNSIGNED: t = uint_type; break;
28827: case FLOAT: t = float_type; break;
28828: case DOUBLE: t = double_type; break;
28829: case LDOUBLE: t = ldouble_type; break;
28830: case VOID: t = void_type; break;
28831: default: error("illegalK:%k",b);
28832: case INT: t = int_type;
28833: }
28834: return t;
28835: }
28836:
28837: Pbase defa_type;
28838: Pbase moe_type;
28839: Pexpr dummy;
28840: Pexpr zero;
28841:
28842: Pclass ccl;
28843: Plist modified_tn = 0;
28844:
28845: Plist local_tn = 0;
28846: Plist local_blk = 0;
28847: Plist local_class = 0;
28848:
28849: Plist nested_tn = 0;
28850: Plist nested_type = 0;
28851:
28852: void memptrdcl(Pname bn, Pname tn, Ptype ft, Pname n)
28853: {
28854: Pptr p = new ptr(PTR,0);
28855: p->memof = Pclass(Pbase(bn->tp)->b_name->tp);
28856: Pbase b = new basetype(TYPE,tn);
28857: PERM(p);
28858: Pfct f = Pfct(ft);
28859: Ptype t = n->tp;
28860: if (t) {
28861: p->typ = t;
28862: ltlt:
28863: switch (t->base) {
28864: case PTR:
28865: case RPTR:
28866: case VEC:
28867: if (Pptr(t)->typ == 0) {
28868: Pptr(t)->typ = b;
28869: break;
28870: }
28871: t = Pptr(t)->typ;
28872: goto ltlt;
28873: default:
28874: error('s',"P toMFT too complicated");
28875: }
28876: }
28877: else
28878: p->typ = b;
28879: f->returns = p;
28880: n->tp = f;
28881: }
28882: 0707071010112044401004440001630000160000010205200466055406200001000000061331print.c /*ident "@(#)ctrans:src/print.c 1.3" */
28883: /**************************************************************************
28884:
28885: C++ source for cfront, the C++ compiler front-end
28886: written in the computer science research center of Bell Labs
28887:
28888: Copyright (c) 1984 AT&T, Inc. All rights Reserved
28889: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
28890:
28891: print.c:
28892:
28893: print statements and expressions
28894:
28895: ****************************************************************************/
28896:
28897: #include "cfront.h"
28898:
28899: static int addrof_cm ;
28900: extern void puttok(TOK);
28901:
28902: /*
28903: void cprint(Pexpr e)
28904: {
28905: if (e == 0) return;
28906: //error('d',"%k %n %t",e->base,e->base==NAME?e:0,e->tp);
28907: // if ((e->base==NAME || e->base==ANAME)
28908: // && Pname(e)->n_evaluated==0) {
28909: Ptype t = e->tp;
28910: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
28911: if (t->base == EOBJ) fprintf(out_file,"(int)");
28912: // }
28913:
28914: Eprint(e);
28915: }
28916: */
28917: #define cprint(e) if (e) Eprint(e)
28918: #define eprint(e) if (e) Eprint(e)
28919:
28920: void Eprint(Pexpr e)
28921: {
28922: switch (e->base) {
28923: case REF:
28924: if (Pref(e)->mem && Pref(e)->mem->tp && Pref(e)->mem->tp->base == FCT) {
28925: // suppress ``this'' in ``this->f''
28926: Pref(e)->mem->print();
28927: break;
28928: }
28929: case NAME:
28930: case MDOT:
28931: case ID:
28932: case ZERO:
28933: case ICON:
28934: case CCON:
28935: case FCON:
28936: case STRING:
28937: case IVAL:
28938: case TEXT:
28939: case CM:
28940: case G_CM:
28941: case ELIST:
28942: case COLON:
28943: case ILIST:
28944: case DOT:
28945: case THIS:
28946: case CALL:
28947: case G_CALL:
28948: case ICALL:
28949: case ANAME:
28950: e->print();
28951: case DUMMY:
28952: break;
28953: default:
28954: putch('(');
28955: e->print();
28956: putch(')');
28957: }
28958: }
28959:
28960: void expr::print()
28961: {
28962: if (this == 0) error('i',"0->E::print()");
28963: if (this==e1 || this==e2) error('i',"(%p%k)->E::print(%p %p)",this,base,e1,e2);
28964: // error('d',"(%d %k)->expr::print(%d %d)",this,base,e1,e2);
28965:
28966: switch (base) {
28967: case MDOT:
28968: {
28969: // error('d',"mdot %s i1 %d %t",string2,i1,mem->tp);
28970: int not_allocated = 0;
28971: switch (i1) {
28972: case 0:
28973: putcat('O',string2);
28974: puttok(DOT); // use sub-object directly
28975: mem->print();
28976: break;
28977: case 1:
28978: putcat('P',string2);
28979: puttok(REF); // use through pointer
28980: mem->print();
28981: break;
28982: case 2:
28983: if (mem->tp->is_ptr_or_ref()==0) {
28984: mem->print();
28985: puttok(DOT);
28986: putcat('O',string2);
28987: }
28988: else
28989: {
28990: putch('('); // REF turns pointer into object: add &
28991: putch('&'); // ``this'' is a pointer
28992: putch('(');
28993: eprint(mem);//mem->print();
28994: puttok(REF); // call sub-object directly
28995: putcat('O',string2);
28996: putch(')');
28997: putch(')');
28998: }
28999: break;
29000: case 5:
29001: not_allocated = 1;
29002: // no break;
29003: case 3:
29004: if (mem->tp->is_ptr_or_ref()==0) {
29005: putch('('); // Px is a pointer (T*) turn it back to a T
29006: putch('*'); // *Px
29007: putch('(');
29008: eprint(mem);//mem->print();
29009: puttok(DOT); // call through pointer
29010: putcat('P',string2);
29011: putch(')');
29012: putch(')');
29013: }
29014: else {
29015: // eprint(mem); // <<< mem->print()
29016: if (not_allocated) {
29017: putch('(');
29018: mem->print();
29019: if ( mem->base == NAME )
29020: puttok(REF);
29021: else puttok(DOT);
29022: putcat('O',string4);
29023: putch(')');
29024: }
29025: else eprint(mem);
29026: if (mem->base == NAME && not_allocated)
29027: puttok(DOT);
29028: else puttok(REF); // call through pointer
29029: putcat('P',string2);
29030: }
29031: break;
29032: case 9: // vtbl entry: (p->_vtbl).f, (p->_vtbl).i, (p->_vtbl).d
29033: // or memptr: mp.f, mp.i, mp.d
29034: eprint(mem);
29035: putch('.');
29036: putstring(string2);
29037: } // end switch(i1)
29038: break;
29039: } // end MDOT
29040:
29041: case NAME:
29042: { Pname n = Pname(this);
29043: if (n->n_evaluated
29044: // && n->tp->base!=EOBJ // this output enumerators
29045: && n->n_scope!=ARG) {
29046: Ptype t = tp;
29047: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
29048: if (t->base == EOBJ) t = Penum(Pbase(t)->b_name->tp)->e_type;
29049: if (t->base!=INT || t->is_unsigned()) {
29050: putstring("((");
29051: bit oc = Cast;
29052: Cast = 1;
29053: t->print();
29054: Cast = oc;
29055: fprintf(out_file,")%d)",n->n_val);
29056: }
29057: else
29058: fprintf(out_file,"%d",n->n_val);
29059: }
29060: else
29061: n->print();
29062: break;
29063: }
29064: case ANAME:
29065: if (curr_icall) { // in expansion: look it up
29066: Pname n = Pname(this);
29067: int argno = int(n->n_val);
29068:
29069: for (Pin il=curr_icall; il; il=il->i_next)
29070: if (n->n_table == il->i_table) goto aok;
29071: goto bok;
29072: aok:
29073: if (n = il->i_args[argno].local) {
29074: n->print();
29075: }
29076: else {
29077: Pexpr ee = il->i_args[argno].arg;
29078: Ptype t = il->i_args[argno].tp;
29079: if (ee==0 || ee==this) error('i',"%p->E::print(A %p)",this,ee);
29080: if (ee->tp==0
29081: || (t!=ee->tp
29082: && t->check(ee->tp,0)
29083: && t->is_cl_obj()==0
29084: // && eobj==0)
29085: )
29086: ) {
29087: putstring("((");
29088: bit oc = Cast;
29089: Cast = 1;
29090: t->print();
29091: Cast = oc;
29092: putch(')');
29093: // eprint(ee);
29094: // if (ee->base == CAST) {
29095: // eprint(ee->e1);
29096: // }
29097: // else
29098: eprint(ee);
29099: putch(')');
29100: }
29101: else
29102: eprint(ee);
29103: }
29104: }
29105: else {
29106: bok: /* in body: print it: */
29107: Pname(this)->print();
29108: }
29109: break;
29110:
29111: case ICALL:
29112: { il->i_next = curr_icall;
29113: curr_icall = il;
29114: //error('d',"icall %n",il->fct_name);
29115: if (il == 0) error('i',"E::print: iline missing");
29116: Pexpr a0 = il->i_args[0].arg;
29117: int val = QUEST;
29118: if (il->fct_name->n_oper != CTOR) goto dumb;
29119:
29120: /*
29121: find the value of "this"
29122: if the argument is a "this" NOT assigned to
29123: by the programmer, it was initialized
29124: */
29125: switch (a0->base) {
29126: case ZERO:
29127: val = 0;
29128: break;
29129: case ADDROF:
29130: case G_ADDROF:
29131: val = 1;
29132: break;
29133: case CAST:
29134: if (a0->e1->base == ANAME || a0->e1->base == NAME) {
29135: Pname a = (Pname)a0->e1;
29136: if (a->n_assigned_to == FUDGE111) val = FUDGE111;
29137: }
29138: }
29139: if (val==QUEST) goto dumb;
29140: /*
29141: now find the test: "(this==0) ? _new(sizeof(X)) : 0"
29142:
29143: e1 is a comma expression,
29144: the test is either the first sub-expression
29145: or the first sub-expression after the assignments
29146: initializing temporary variables
29147: */
29148: dumb:
29149: eprint(e1);
29150: if (e2) Pstmt(e2)->print();
29151: curr_icall = il->i_next;
29152: break;
29153: }
29154: case REF:
29155: case DOT:
29156: eprint(e1);
29157: puttok(base);
29158: if (mem == 0) {
29159: fprintf(out_file,"MEM0");
29160: break;
29161: }
29162: if (mem->base == NAME)
29163: Pname(mem)->print();
29164: else
29165: mem->print();
29166: break;
29167:
29168: case MEMPTR:
29169: error("P toMF not called");
29170: break;
29171:
29172: case VALUE:
29173: tp2->print();
29174: puttok(LP);
29175:
29176: // if (e2) {
29177: // putstring(" &");
29178: // e2->print();
29179: // putstring(", ");
29180: // }
29181: if (e1) e1->print();
29182: puttok(RP);
29183: break;
29184:
29185: case SIZEOF:
29186: puttok(SIZEOF);
29187: if (e1 && e1!=dummy) {
29188: eprint(e1);
29189: }
29190: else if (tp2) {
29191: putch('(');
29192: if (tp2->base == CLASS) {
29193: Pclass cl = Pclass(tp2);
29194: putstring((cl->csu == UNION)?"union ":"struct ");
29195: char *str = 0;
29196: // nested local class does not encode name
29197: if ( cl->lex_level && cl->nested_sig == 0 )
29198: str = make_local_name( cl );
29199: putstring(str?str:(cl->nested_sig?cl->nested_sig:cl->string));
29200: delete str;
29201: }
29202: else
29203: tp2->print();
29204: putch(')');
29205: }
29206: break;
29207:
29208: /*
29209: // always turned into function calls:
29210: case NEW:
29211: case GNEW:
29212: // error('d',"print new %d tp2 %t e1 %d e2 %d",base,tp2,e1,e2);
29213: puttok(NEW);
29214: tp2->print();
29215: if (e1) {
29216: putch('(');
29217: e1->print();
29218: putch(')');
29219: }
29220: break;
29221:
29222: case DELETE:
29223: case GDELETE:
29224: //error('d',"print delete");
29225: puttok(DELETE);
29226: e1->print();
29227: break;
29228: */
29229: case CAST:
29230: putch('(');
29231: //error('d',"print cast %t",tp2);
29232: if (tp2->base != VOID && tp2->memptr() == 0 ) {
29233: // when VOID is represented as CHAR not everything
29234: // can be cast to VOID
29235: putch('(');
29236: bit oc = Cast;
29237: Cast = 1;
29238: tp2->print();
29239: Cast = oc;
29240: putch(')');
29241: }
29242: eprint(e1);
29243: putch(')');
29244: break;
29245:
29246: case ICON:
29247: case FCON:
29248: case CCON:
29249: case ID:
29250: if (string) putst(string);
29251: break;
29252:
29253: case STRING:
29254: // avoid printing very long lines
29255: ntok += 4;
29256: fprintf(out_file,"\"%s\"",string);
29257: break;
29258:
29259: case THIS:
29260: case ZERO:
29261: putstring("0 ");
29262: break;
29263:
29264: case IVAL:
29265: fprintf(out_file,"%d",i1);
29266: break;
29267:
29268: case TEXT:
29269: {
29270: int oo = vtbl_opt; // make `simulated static' name
29271: vtbl_opt = -1;
29272: char* s = vtbl_name(string,string2);
29273: vtbl_opt = oo;
29274: s[2] = 'p'; // pointer, not tbl itself
29275: char* t = ptbl_lookup(s);
29276: fprintf(out_file, " %s",t);
29277: delete t;
29278:
29279: char *str = 0;
29280: if ( string ) {
29281: str = new char[ strlen(string) + strlen(string2) + 1 ];
29282: strcpy( str, string );
29283: strcat( str, string2 );
29284: }
29285:
29286: if ( ptbl->look( str?str:string2, 0 ) == 0 &&
29287: ptbl->look( str?str:string2, HIDDEN ) == 0 ) {
29288: Pname nn = ptbl->insert(new name(str?str:string2),0);
29289: nn->string2 = new char[strlen(s)+1];
29290: strcpy(nn->string2,s);
29291: }
29292:
29293: delete str;
29294: delete s;
29295: }
29296: // no break;
29297:
29298: case DUMMY:
29299: break;
29300:
29301: case G_CALL:
29302: case CALL:
29303: { Pname fn = fct_name;
29304: Pname at;
29305: int m_ptr = 0;
29306:
29307: if (fn) {
29308: Pfct f = Pfct(fn->tp);
29309:
29310: if (f->base==OVERLOAD) { // overloaded after call
29311: fct_name = fn = Pgen(f)->fct_list->f;
29312: f = Pfct(fn->tp);
29313: }
29314:
29315: fn->print();
29316: at = f->f_args;
29317: }
29318: else {
29319: Pfct f = Pfct(e1->tp);
29320:
29321: if (f) { // pointer to fct
29322: Pexpr exex = e1;
29323: if ( exex->base == DEREF ) {
29324: exex = exex->e1;
29325: while ( exex->base == CAST )
29326: exex = exex->e1;
29327: if ( exex->base == MDOT )
29328: m_ptr = 1;
29329: }
29330:
29331: if (f->base == OVERLOAD) { // overloaded after call
29332: fct_name = fn = Pgen(f)->fct_list->f;
29333: f = Pfct(fn->tp);
29334: }
29335:
29336: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
29337: if (f->base == PTR) {
29338: putstring("(*");
29339: e1->print();
29340: putch(')');
29341: f = Pfct(Pptr(f)->typ);
29342: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
29343: }
29344: else
29345: eprint(e1);
29346:
29347: // at = (f->f_result) ? f->f_result : f->argtype;
29348: at = f->f_args;
29349: }
29350: else { // virtual: argtype encoded
29351: // f_this already linked to f_result and/or argtype
29352: at = (e1->base==QUEST) ? Pname(e1->e1->tp2) : Pname(e1->tp2);
29353: eprint(e1);
29354: }
29355: }
29356:
29357: puttok(LP);
29358:
29359: if (e2) {
29360: if (at) {
29361: Pexpr e = e2;
29362: while (at) {
29363: Pexpr ex;
29364: Ptype t = at->tp;
29365:
29366: if (t == 0) error('i',"T ofA missing for%n",fn);
29367: if (e == 0) error('i',"%tA missing for%n",t,fn);
29368: if (e->base == ELIST) {
29369: ex = e->e1;
29370: e = e->e2;
29371: }
29372: else
29373: ex = e;
29374:
29375: if (ex == 0) error('i',"A ofT%t missing",t);
29376: if (t!=ex->tp
29377: && ex->tp
29378: && t->check(ex->tp,0)
29379: && t->is_cl_obj()==0
29380: && eobj==0
29381: && m_ptr == 0
29382: && (t->is_ptr()==0 || Mptr==0)) {
29383: putch('(');
29384: bit oc = Cast;
29385: Cast = 1;
29386: t->print();
29387: Cast = oc;
29388: putch(')');
29389: #ifdef sun
29390: if (ex->base == DIV) { // defend against perverse SUN cc bug
29391: putstring("(0+");
29392: eprint(ex);
29393: putch(')');
29394: }
29395: else
29396: #endif
29397: // eprint(ex);
29398: // if (ex->base==CAST) {
29399: // eprint(ex->e1);
29400: // }
29401: // else
29402: eprint(ex);
29403: }
29404: else
29405: ex->print();
29406:
29407: // if m_ptr is set, then don't advance at
29408: // at does not know about generated `this'
29409: if ( m_ptr ) {
29410: m_ptr = 0;
29411: if (at) puttok(CM);
29412: continue;
29413: }
29414:
29415: at = at->n_list;
29416: if (at) puttok(CM);
29417: }
29418: if (e) {
29419: puttok(CM);
29420: e->print();
29421: }
29422: }
29423: else
29424: e2->print();
29425: }
29426: puttok(RP);
29427: break;
29428: }
29429:
29430: case ASSIGN:
29431: if (e1->base==ANAME && Pname(e1)->n_assigned_to==FUDGE111) {
29432: // suppress assignment to "this" that has been optimized away
29433: Pname n = Pname(e1);
29434: int argno = int(n->n_val);
29435: for (Pin il=curr_icall; il; il=il->i_next)
29436: if (il->i_table == n->n_table) goto akk;
29437: goto bkk;
29438: akk:
29439: if (il->i_args[argno].local == 0) {
29440: e2->print();
29441: break;
29442: }
29443: }
29444: //no break
29445: case EQ:
29446: case NE:
29447: case GT:
29448: case GE:
29449: case LE:
29450: case LT:
29451: bkk:
29452: { Ptype t1 = e1->tp;
29453: Ptype t2 = e2->tp;
29454:
29455: if (base!=ASSIGN) {
29456: cprint(e1);
29457: }
29458: else
29459: eprint(e1);
29460: puttok(base);
29461:
29462: if (t1 && t1!=t2 && e2->base!=ZERO) {
29463: // cast, but beware of int!=long etc.
29464: cmp:
29465: switch (t1->base) {
29466: case TYPE:
29467: t1 = Pbase(t1)->b_name->tp;
29468: goto cmp;
29469: default:
29470: // if (e2->base==NAME
29471: // && Pname(e2)->n_evaluated==0
29472: // && e2->tp->base==EOBJ)
29473: // fprintf(out_file,"(int)");
29474: break;
29475: // case EOBJ:
29476: // if (base==ASSIGN) goto cst;
29477: // break;
29478: case PTR:
29479: case RPTR:
29480: case VEC:
29481: if (t2)
29482: while ( t2->base == TYPE )
29483: t2 = Pbase(t2)->b_name->tp;
29484:
29485: if (e2->tp==0
29486: || (Pptr(t1)->typ!=Pptr(t2)->typ && t1->check(t2,0))) {
29487: // cst:
29488: putch('(');
29489: bit oc = Cast;
29490: Cast = 1;
29491: e1->tp->print();
29492: Cast = oc;
29493: putch(')');
29494: }
29495: }
29496: }
29497:
29498: eprint(e2);
29499: break;
29500: }
29501:
29502: case DEREF:
29503: if (e2) {
29504:
29505: eprint(e1);
29506: putch('[');
29507: cprint(e2);
29508: putch(']');
29509: }
29510: else {
29511: putch('(');
29512: putch('*');
29513: eprint(e1);
29514: putch(')');
29515: }
29516: break;
29517:
29518: case ILIST:
29519: puttok(LC);
29520: if (e1) e1->print();
29521: if (e2) { // member pointer initiliazers
29522: puttok(CM);
29523: e2->print();
29524: }
29525: puttok(RC);
29526: break;
29527:
29528: case ELIST:
29529: { Pexpr e = this;
29530: for(;;) {
29531: if (e->base == ELIST) {
29532: e->e1->print();
29533: if (e = e->e2) {
29534: puttok(CM);
29535: }
29536: else
29537: return;
29538: }
29539: else {
29540: e->print();
29541: return;
29542: }
29543: }
29544: }
29545:
29546: case QUEST:
29547: { // look for (&a == 0) etc.
29548: Neval = 0;
29549: binary_val = 1;
29550: long i = cond->eval();
29551: binary_val = 0;
29552: if (Neval == 0)
29553: (i?e1:e2)->print();
29554: else {
29555: eprint(cond);
29556: putch('?');
29557: cprint(e1);
29558: putch(':');
29559: cprint(e2);
29560: }
29561: break;
29562: }
29563:
29564: case CM: // do &(a,b) => (a,&b) for previously checked inlines
29565: case G_CM:
29566: puttok(LP);
29567: switch (e1->base) {
29568: case ZERO:
29569: case IVAL:
29570: case ICON:
29571: case NAME:
29572: case MDOT:
29573: case DOT:
29574: case REF:
29575: case FCON:
29576: // case FVAL:
29577: case STRING:
29578: goto le2; // suppress constant a: &(a,b) => (&b)
29579: default:
29580: { int oo = addrof_cm; // &(a,b) does not affect a
29581: addrof_cm = 0;
29582: eprint(e1);
29583: addrof_cm = oo;
29584: }
29585: puttok(CM);
29586: le2:
29587: if (addrof_cm) {
29588: switch (e2->base) {
29589: case CAST:
29590: if (e2->e2)
29591: switch (e2->e2->base) {
29592: case CM:
29593: case G_CM:
29594: case ICALL: goto ec;
29595: }
29596: case NAME:
29597: case MDOT:
29598: case DOT:
29599: case DEREF:
29600: case REF:
29601: case ANAME:
29602: puttok(ADDROF);
29603: addrof_cm--;
29604: eprint(e2);
29605: addrof_cm++;
29606: break;
29607: case ICALL:
29608: // case CALL:
29609: case CM:
29610: case G_CM:
29611: ec:
29612: eprint(e2);
29613: break;
29614: case G_CALL:
29615: /* & ( e, ctor() ) with temporary optimized away */
29616: if (e2->fct_name
29617: && e2->fct_name->n_oper==CTOR) {
29618: addrof_cm--;
29619: eprint(e2);
29620: addrof_cm++;
29621: break;
29622: }
29623: default:
29624: error('i',"& inlineF call (%k)",e2->base);
29625: }
29626: }
29627: else
29628: // e2->print();
29629: eprint(e2);
29630: puttok(RP);
29631: }
29632: break;
29633:
29634: case UPLUS: // only preserved for ansi_opt==1
29635: case UMINUS:
29636: case NOT:
29637: case COMPL:
29638: // puttok(base);
29639: // eprint(e2);
29640: // break;
29641: goto op2;
29642: case ADDROF:
29643: case G_ADDROF:
29644: switch (e2->base) { // & *e1 or &e1[e2]
29645: case DEREF:
29646: if (e2->e2 == 0) { // &*e == e
29647: e2->e1->print();
29648: return;
29649: }
29650: break;
29651: case ICALL:
29652: addrof_cm++; // assumes inline expanded into ,-expression
29653: eprint(e2);
29654: addrof_cm--;
29655: return;
29656: case ASSIGN: // &(a=b) ??? works on many cc s
29657: eprint(e2); // make sure it breaks!
29658: return;
29659: case NAME: {
29660: Pname n = Pname(e2);
29661: if(n->n_evaluated) {
29662: n->n_evaluated=0;
29663: puttok(ADDROF);
29664: eprint(e2);
29665: n->n_evaluated=1;
29666: return;
29667: }
29668: break;
29669: }
29670: }
29671:
29672: // suppress cc warning on &fct
29673: if (e2->tp==0 || e2->tp->base!=FCT) puttok(ADDROF);
29674:
29675: eprint(e2);
29676: break;
29677:
29678: case PLUS:
29679: case MINUS:
29680: case MUL:
29681: case DIV:
29682: case MOD:
29683: case LS:
29684: case RS:
29685: case AND:
29686: case OR:
29687: case ER:
29688: case ANDAND:
29689: case OROR:
29690: case DECR:
29691: case INCR:
29692: cprint(e1);
29693: op2:
29694: puttok(base);
29695: cprint(e2);
29696: break;
29697: case ASOR:
29698: case ASER:
29699: case ASAND:
29700: case ASPLUS:
29701: case ASMINUS:
29702: case ASMUL:
29703: case ASMOD:
29704: case ASDIV:
29705: case ASLS:
29706: case ASRS:
29707: eprint(e1);
29708: goto op2;
29709:
29710: default:
29711: error('i',"%p->E::print%k",this,base);
29712: // fprintf(out_file," EEE(%d) ",base);
29713: }
29714: }
29715:
29716: Pexpr aval(Pname a)
29717: {
29718: int argno = int(a->n_val);
29719: Pin il;
29720: for (il=curr_icall; il; il=il->i_next)
29721: if (il->i_table == a->n_table) goto aok;
29722: return 0;
29723: aok:
29724: Pexpr aa = il->i_args[argno].arg;
29725: ll:
29726: switch (aa->base) {
29727: case CAST: aa = aa->e1; goto ll;
29728: case ANAME: return aval(Pname(aa));
29729: default: return aa;
29730: }
29731: }
29732:
29733: #define putcond() putch('('); e->print(); putch(')')
29734:
29735: static loc csloc = { 0, 0 }; // loc of last stmt with line!=0
29736:
29737: void stmt::print()
29738: {
29739: //error('d',"S::print %d:%k s %d s_list %d",this,base,s,s_list);
29740: if (where.line == 0) {
29741: if (csloc.line) csloc.putline();
29742: } else {
29743: csloc = where;
29744: if (where.line!=last_line.line)
29745: if (last_ll = where.line)
29746: where.putline();
29747: else
29748: last_line.putline();
29749: }
29750:
29751: if (memtbl && base!=BLOCK) { /* also print declarations of temporaries */
29752: puttok(LC);
29753: Ptable tbl = memtbl;
29754: memtbl = 0;
29755: int i;
29756: int bl = 1;
29757: for (Pname n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i)){
29758: if (n->tp == any_type) continue;
29759: /* avoid double declarartion of temporaries from inlines */
29760: char* s = n->string;
29761: if (s[0]!='_' || s[1]!='_' || s[2]!='X') {
29762: n->dcl_print(0);
29763: bl = 0;
29764: }
29765: Pname cn;
29766: if (bl
29767: && (cn=n->tp->is_cl_obj())
29768: && Pclass(cn->tp)->has_dtor()) bl = 0;
29769: }
29770: if ( last_ll==0 && (last_ll = where.line) )
29771: where.putline();
29772: if (bl) {
29773: Pstmt sl = s_list;
29774: s_list = 0;
29775: print();
29776: memtbl = tbl;
29777: puttok(RC);
29778: if (sl) {
29779: s_list = sl;
29780: sl->print();
29781: }
29782: }
29783: else {
29784: print();
29785: memtbl = tbl;
29786: puttok(RC);
29787: }
29788: return;
29789: }
29790:
29791: switch (base) {
29792: default:
29793: error('i',"S::print(base=%k)",base);
29794:
29795: case ASM:
29796: fprintf(out_file,"asm(\"%s\");\n",(char*)e);
29797: break;
29798:
29799: case DCL:
29800: d->dcl_print(SM);
29801: break;
29802:
29803: case BREAK:
29804: case CONTINUE:
29805: puttok(base);
29806: puttok(SM);
29807: break;
29808:
29809: case DEFAULT:
29810: puttok(base);
29811: //puttok(COLON);
29812: putch(':');
29813: s->print();
29814: break;
29815:
29816: case SM:
29817: if (e) {
29818: e->print();
29819: if (e->base==ICALL && e->e2) break; /* a block: no SM */
29820: }
29821: puttok(SM);
29822: break;
29823:
29824: case WHILE:
29825: puttok(WHILE);
29826: putcond();
29827: if (s->s_list) {
29828: puttok(LC);
29829: s->print();
29830: puttok(RC);
29831: }
29832: else
29833: s->print();
29834: break;
29835:
29836: case DO:
29837: puttok(DO);
29838: s->print();
29839: puttok(WHILE);
29840: putcond();
29841: puttok(SM);
29842: break;
29843:
29844: case SWITCH:
29845: puttok(SWITCH);
29846: putcond();
29847: s->print();
29848: break;
29849:
29850: case RETURN:
29851: {
29852: puttok(RETURN);
29853: if (e) {
29854: //error('d',"print return rt %t etp %t",ret_tp,e->tp);
29855: if (ret_tp && ret_tp!=e->tp) {
29856: Ptype tt = ret_tp;
29857: gook:
29858: switch (tt->base) {
29859: case TYPE:
29860: tt = Pbase(tt)->b_name->tp;
29861: goto gook;
29862: case COBJ:
29863: break; // cannot cast to struct
29864: case RPTR:
29865: case PTR:
29866: if (Pptr(tt)->typ==Pptr(e->tp)->typ) break;
29867: if (Pptr(tt)->memof) break;
29868: default:
29869: if (e->tp==0 || ret_tp->check(e->tp,0)) {
29870: int oc = Cast;
29871: putch('(');
29872: Cast = 1;
29873: ret_tp->print();
29874: Cast = oc;
29875: putch(')');
29876: }
29877: }
29878: }
29879: eprint(e);
29880: }
29881: puttok(SM);
29882: }
29883: while (s_list && s_list->base==SM) s_list = s_list->s_list; // FUDGE!!
29884: break;
29885:
29886: case CASE:
29887: puttok(CASE);
29888: eprint(e);
29889: putch(':');
29890: s->print();
29891: break;
29892:
29893: case GOTO:
29894: puttok(GOTO);
29895: d->print();
29896: puttok(SM);
29897: break;
29898:
29899: case LABEL:
29900: d->print();
29901: putch(':');
29902: s->print();
29903: break;
29904:
29905: case IF:
29906: { int val = QUEST;
29907: if (e->base == ANAME) {
29908: Pname a = Pname(e);
29909: Pexpr arg = aval(a);
29910: //error('d',"arg %d%k %d (%d)",arg,arg?arg->base:0,arg?arg->base:0,arg?arg->e1:0);
29911: if (arg)
29912: switch (arg->base) {
29913: case ZERO: val = 0; break;
29914: case ADDROF:
29915: case G_ADDROF: val = 1; break;
29916: case IVAL: val = arg->i1!=0;
29917: }
29918: }
29919: //error('d',"val %d",val);
29920: switch (val) {
29921: case 1:
29922: s->print();
29923: break;
29924: case 0:
29925: if (else_stmt)
29926: else_stmt->print();
29927: else
29928: puttok(SM); /* null statement */
29929: break;
29930: default:
29931: puttok(IF);
29932: putcond();
29933: if (s->s_list) {
29934: puttok(LC);
29935: s->print();
29936: puttok(RC);
29937: }
29938: else
29939: s->print();
29940: if (else_stmt) {
29941: if (else_stmt->where.line == 0) {
29942: if (csloc.line) csloc.putline();
29943: } else {
29944: csloc = else_stmt->where;
29945: if (else_stmt->where.line!=last_line.line)
29946: if (last_ll = else_stmt->where.line)
29947: else_stmt->where.putline();
29948: else
29949: last_line.putline();
29950: }
29951: puttok(ELSE);
29952: if (else_stmt->s_list) {
29953: puttok(LC);
29954: else_stmt->print();
29955: puttok(RC);
29956: }
29957: else
29958: else_stmt->print();
29959: }
29960: }
29961: break;
29962: }
29963:
29964: case FOR:
29965: {
29966: // int fi = for_init && ((for_init->base!=SM || for_init->memtbl || for_init->s_list);
29967: int fi = 0; // is the initializer statement an expression?
29968: if (for_init) {
29969: fi = 1;
29970: if (for_init->memtbl==0 && for_init->s_list==0)
29971: if (for_init->base==SM)
29972: if (for_init->e->base!=ICALL || for_init->e->e1)
29973: fi = 0;
29974: }
29975: //error('d',"for(; %d%k; %d%k)",e,e->base,e2,e2->base);
29976: if (fi) {
29977: puttok(LC);
29978: for_init->print();
29979: }
29980: putstring("for(");
29981: if (fi==0 && for_init) for_init->e->print();
29982: putch(';'); // to avoid newline: not puttok(SM)
29983: if (e) e->print();
29984: putch(';');
29985: if (e2) e2->print();
29986: puttok(RP);
29987: s->print();
29988: if (fi) puttok(RC);
29989: break;
29990: }
29991:
29992: case PAIR:
29993: if (s&&s2) {
29994: puttok(LC);
29995: s->print();
29996: s2->print();
29997: puttok(RC);
29998: }
29999: else {
30000: if (s) s->print();
30001: if (s2) s2->print();
30002: }
30003: break;
30004:
30005: case BLOCK:
30006: puttok(LC);
30007: //error('d',"block %d d %d memtbl %d own_tbl %d",this,d,memtbl,own_tbl);
30008: if (d) d->dcl_print(SM);
30009: if (memtbl && own_tbl) {
30010: Pname n;
30011: int i;
30012: for (n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
30013: if (n->tp && n->n_union==0 && n->tp!=any_type)
30014: switch (n->n_scope) {
30015: case ARGT:
30016: case ARG:
30017: break;
30018: default:
30019: // error('d', "n: %s %k n_key: %k", n->string, n->base, n->n_key);
30020: if ( n->base == TNAME && n->n_key == NESTED )
30021: continue; // printed from nested class
30022: n->dcl_print(0);
30023: }
30024: }
30025: if (last_ll==0 && s && (last_ll=s->where.line))
30026: s->where.putline();
30027: }
30028: if (s) s->print();
30029: if (where2.line == 0) {
30030: if (csloc.line) csloc.putline();
30031: } else {
30032: csloc = where2;
30033: if (where2.line!=last_line.line)
30034: if (last_ll = where2.line)
30035: where2.putline();
30036: else
30037: last_line.putline();
30038: }
30039: putstring("}\n");
30040: if (last_ll && where.line) last_line.line++;
30041: }
30042:
30043: if (s_list) s_list->print();
30044: }
30045:
30046: /*
30047: void table::dcl_print(TOK s, TOK pub)
30048:
30049: // print the declarations of the entries in the order they were inserted
30050: // ignore labels (tp==0)
30051:
30052: {
30053: register Pname* np;
30054: register int i;
30055:
30056: if (this == 0) return;
30057:
30058: np = entries;
30059: for (i=1; i<free_slot; i++) {
30060: register Pname n = np[i];
30061: switch (s) {
30062: case 0:
30063: n->dcl_print(0);
30064: break;
30065: case EQ:
30066: if (n->tp && n->n_scope == pub) n->dcl_print(0);
30067: break;
30068: case NE:
30069: if (n->tp && n->n_scope != pub) n->dcl_print(0);
30070: break;
30071: }
30072: }
30073: }
30074: */
30075:
30076: struct ptbl_rec {
30077: char* pname;
30078: char* vname;
30079: ptbl_rec* next;
30080: };
30081:
30082: static char* ptbl_name;
30083: static ptbl_rec* ptbl_rec_lookup_head = 0;
30084: static ptbl_rec* ptbl_rec_pair_head = 0;
30085:
30086: void ptbl_init(int flag)
30087: {
30088: if (!flag) {
30089: char *p = st_name( "__ptbl_vec__" );
30090: ptbl_name = new char[strlen(p)+1];
30091: strcpy(ptbl_name, p);
30092: delete p;
30093: fprintf(out_file, "extern struct __mptr* %s[];\n", ptbl_name);
30094: if (last_ll) last_line.line++;
30095: }
30096: else {
30097: ptbl_rec *r, *p = ptbl_rec_lookup_head;
30098: if ( p == 0 ) return; // don't generate an empty object
30099: fprintf(out_file, "struct __mptr* %s[] = {\n", ptbl_name);
30100: if (last_ll) last_line.line++;
30101: int i = 0;
30102: while (p != 0) {
30103: r = ptbl_rec_pair_head;
30104: while (r && strcmp(r->pname, p->pname))
30105: r = r->next;
30106: fprintf(out_file, "%s,\n", r->vname);
30107: if (last_ll) last_line.line++;
30108: p = p->next;
30109: }
30110: // fprintf(out_file, "0\n};\n");
30111: fprintf(out_file, "\n};\n");
30112: if (last_ll) last_line.line += 2;
30113: }
30114: }
30115:
30116: char* ptbl_lookup(char *name)
30117: {
30118: ptbl_rec *r, *s, *p = ptbl_rec_lookup_head;
30119: int i = 0;
30120:
30121: while (p && strcmp(name, p->pname)) {
30122: r = p;
30123: p = p->next;
30124: i++;
30125: }
30126:
30127: if (p == 0) {
30128: s = new ptbl_rec;
30129: s->pname = new char[strlen(name) + 1];
30130: s->vname = 0;
30131: s->next = 0;
30132: strcpy(s->pname, name);
30133: if (ptbl_rec_lookup_head == 0)
30134: ptbl_rec_lookup_head = s;
30135: else r->next = s;
30136: }
30137:
30138: char *pp = new char[ strlen(ptbl_name) + 10 ];
30139: sprintf(pp, "%s[%d]", ptbl_name, i);
30140: return(pp);
30141: }
30142:
30143: void ptbl_add_pair(char* ptbl, char* vtbl)
30144: {
30145: // error('d', "ptbl_add_pair: ptbl: %s, vtbl: %s", ptbl, vtbl );
30146: ptbl_rec *p = new ptbl_rec;
30147:
30148: p->pname = new char[strlen(ptbl) + 1];
30149: strcpy(p->pname, ptbl);
30150: p->vname = new char[strlen(vtbl) + 1];
30151:
30152: strcpy(p->vname, vtbl);
30153: p->next = ptbl_rec_pair_head;
30154:
30155: ptbl_rec_pair_head = p;
30156: }
30157: 0707071010112044411004440001630000160000010205600466055406600001100000140076print2.c /*ident "@(#)ctrans:src/print2.c 1.4" */
30158: /**************************************************************************
30159:
30160: C++ source for cfront, the C++ compiler front-end
30161: written in the computer science research center of Bell Labs
30162:
30163: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
30164: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
30165:
30166: print2.c:
30167:
30168: print names and declarations
30169:
30170: ****************************************************************************/
30171:
30172: #include "cfront.h"
30173: #include "template.h"
30174:
30175: bit Cast;
30176: int last_ll = 1;
30177: Pin curr_icall;
30178: char emode;
30179: int ntok;
30180:
30181: static int MAIN; // fudge to get _main() called by main()
30182:
30183: #define eprint(e) if (e) Eprint(e)
30184:
30185: #ifdef DENSE
30186: void chop(char*);
30187: #endif
30188:
30189: void puttok(TOK t)
30190: /*
30191: print the output representation of "t"
30192: */
30193: {
30194: // if (t<=0 || MAXTOK<t) error("illegal token %d",t);
30195: // char* s = keys[t];
30196: // if (s == 0) error("V representation token %d",t);
30197:
30198: putstring(keys[t]);
30199:
30200: if (12<ntok++) {
30201: ntok = 0;
30202: last_line.putline();
30203: }
30204: else if (t == SM) {
30205: ntok = 0;
30206: putch('\n');
30207: if (last_ll) last_line.line++;
30208: }
30209: else
30210: putch(' ');
30211: }
30212:
30213: #define MX 20
30214: #define NTBUF 10
30215: class dcl_buf {
30216: /*
30217: buffer for assembling declaration (or cast)
30218: left contains CONST_PTR => *CONST
30219: CONST_RPTR => &CONST
30220: PTR => *
30221: RPTR => &
30222: LP => (
30223: right contains RP => )
30224: VEC => [ rnode ]
30225: FCT => ( rnode )
30226: FIELD => : rnode
30227: */
30228: Pbase b;
30229: Pname n;
30230: TOK left[MX], right[MX];
30231: Pnode rnode[MX];
30232: Pclass lnode[MX];
30233: int li, ri;
30234: public:
30235: void init(Pname nn) { b=0; n=nn; li=ri=0; }
30236: void base(Pbase bb) { b = bb; }
30237: void front(TOK t) { left[++li] = t; }
30238: void front(Pclass c) { left[++li] = MEMPTR; lnode[li] = c; }
30239: void back(TOK t, Pnode nod) { right[++ri] = t; rnode[ri] = nod; }
30240: void paran() { front(LP); back(RP,0); }
30241: void put();
30242: } *tbufvec[NTBUF] = {0}, *tbuf = 0;
30243:
30244: int freetbuf = 0;
30245:
30246: void dcl_buf::put()
30247: {
30248: int i;
30249: Pfct ff = 0;
30250:
30251: if (MX<=li || MX<=ri) error('i',"T buffer overflow");
30252: if (b == 0) error('i',"noBT%s",Cast?" in cast":"");
30253:
30254: if (n && n->n_sto && n->n_sto!=REGISTER) puttok(n->n_sto);
30255:
30256: b->dcl_print();
30257:
30258: for( ; li; li--) {
30259: switch (left[li]) {
30260: case LP:
30261: putch('(');
30262: break;
30263: case PTR:
30264: putch('*');
30265: break;
30266: case RPTR:
30267: if (emode)
30268: putch('&');
30269: else
30270: putch('*');
30271: break;
30272: case CONST_PTR:
30273: if (emode)
30274: putstring("*const ");
30275: else
30276: putch('*');
30277: break;
30278: case CONST_RPTR:
30279: if (emode)
30280: putstring("&const ");
30281: else
30282: putch('*');
30283: break;
30284: case MEMPTR:
30285: if (lnode[li]) fprintf(out_file,"%s::",lnode[li]->string);
30286: }
30287: }
30288:
30289: if (n) n->print();
30290:
30291: for(i=1; i<=ri; i++) {
30292: switch (right[i]) {
30293: case RP:
30294: putch(')');
30295: break;
30296: case VEC:
30297: putch('[');
30298: { Pvec v = (Pvec) rnode[i];
30299: Pexpr d = v->dim;
30300: int s = v->size;
30301: if (d) d->print();
30302: if (s) fprintf(out_file,"%d",s);
30303: }
30304: putch(']');
30305: break;
30306: case FCT: // beware of function returning pointer to
30307: // function expressed witout typedef
30308: { Pfct f = Pfct(rnode[i]);
30309: if (f->body) ff = f;
30310: f->dcl_print();
30311: break;
30312: }
30313: case FIELD:
30314: { Pbase f = (Pbase) rnode[i];
30315: Pexpr d = (Pexpr)f->b_name;
30316: int s = f->b_bits;
30317: putch(':');
30318: if (d)
30319: d->print();
30320: else if (s)
30321: fprintf(out_file,"%d",s);
30322: else
30323: puttok(ZERO);
30324: break;
30325: }
30326: }
30327: }
30328: void print_body(Pfct);
30329: if (ff && emode==0) print_body(ff);
30330: }
30331:
30332: static Pexpr mk_zero_init( Ptype tt, Pname obname, Pname currname )
30333: /*
30334: creates 0 initializer for defined objects
30335: side effect: generates right nesting level for {}
30336: */
30337: {
30338: zaq:
30339: switch (tt->base) {
30340: case TYPE:
30341: tt = Pbase(tt)->b_name->tp; goto zaq;
30342: case VEC: // type a[size]; => type a[size] = {0};
30343: {
30344: if ( obname == currname ) {
30345: //xxx initializing vectors blows up the size of some programs
30346: return 0;
30347: } else {
30348: Pexpr i = mk_zero_init(Pvec(tt)->typ,obname,currname);
30349: if ( i == 0 ) return 0;
30350: return new expr( ILIST, i, 0 );
30351: }
30352: }
30353: case COBJ: // "X a;" == "X a = {0};"
30354: {
30355: Pclass cl = Pclass(Pbase(tt)->b_name->tp);
30356: if ( !ansi_opt && (cl->csu == ANON || cl->csu == UNION) ) {
30357: if ( warning_opt ) {
30358: // ridiculous handstands to avoid printing
30359: // compiler generated names in warning
30360: Ptype tn = obname->tp;
30361: for(;;) if(tn->base==VEC) tn=Pvec(tn)->typ; else break;
30362: if ( obname == currname && tt == tn ) {
30363: if ( cl->string[0]=='_' && cl->string[1]=='_' )
30364: error('w',&obname->where,"cannot generate zeroIr for%n ofT union; toI, compile with +a1 or insert non-union object as first member",obname);
30365: else
30366: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t; toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
30367: } else { Pclass cx;
30368: if ( tn->base == COBJ
30369: && (cx=(Pclass)Pbase(tn)->b_name->tp,
30370: cx->string[0]=='_' && cx->string[1]=='_') )
30371: error('w',&obname->where,"cannot generate zeroIr for%n (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname);
30372: else
30373: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
30374: }
30375: } // if warning_opt
30376: return 0;
30377: }
30378: Pbcl l = cl->baselist;
30379: while ( l ) {
30380: if ( l->base == NAME ) cl = l->bclass;
30381: else return new expr(ILIST,zero,0);
30382: l = cl->baselist;
30383: }
30384: int i = 1;
30385: Pname nn = cl->memtbl->get_mem(i);
30386: for ( ; nn; nn = cl->memtbl->get_mem(++i) ) {
30387: Ptype tx = nn->tp;
30388: while ( tx->base == TYPE ) tx = Pbase(tx)->b_name->tp;
30389: if (nn->base==NAME
30390: && nn->n_union==0
30391: && tx->base!=FCT
30392: && tx->base!=OVERLOAD
30393: && tx->base!=CLASS
30394: && tx->base!=ENUM
30395: && nn->n_stclass != STATIC) {
30396: Pexpr i = mk_zero_init(tx,obname,nn);
30397: if ( i == 0 ) return 0;
30398: return new expr(ILIST,i,0);
30399: }
30400: }
30401: return 0;
30402: }
30403: case PTR:
30404: if (tt->memptr()) {
30405: Pexpr i = new expr(ELIST,zero,zero);
30406: return new expr(ILIST,i,zero);
30407: }
30408: // no break
30409: case RPTR:
30410: case CHAR:
30411: case SHORT:
30412: case INT:
30413: case EOBJ:
30414: case LONG:
30415: case FLOAT:
30416: case DOUBLE:
30417: case LDOUBLE: // "int a;" == "int a = 0;"
30418: case FIELD:
30419: case ANY:
30420: return zero;
30421: }
30422: return 0;
30423: }
30424:
30425: void name::dcl_print(TOK list)
30426: /*
30427: Print the declaration for a name (list==0) or a name list (list!=0):
30428: For each name
30429: (1) print storage class
30430: (2) print base type
30431: (3) print the name with its declarators
30432: Avoid (illegal) repetition of basetypes which are class or enum declarations
30433: (A name list may contain names with different base types)
30434: list == SM : terminator SM
30435: list == 0: single declaration with terminator SM
30436: list == CM : separator CM
30437: */
30438: {
30439: if (error_count) return;
30440:
30441: for (Pname n=this; n; n=n->n_list) {
30442: Ptype t = n->tp;
30443: int sm = 0;
30444:
30445: // error('d',"%s->dcl_print() tp %t sto %k",n->string,t,n->n_sto);
30446: if (t == 0) error('i',"N::dcl_print(%n)T missing",n);
30447:
30448: if (n->n_stclass==ENUM) if (list) continue; else return;
30449:
30450: if (n->where.line!=last_line.line || n->where.file!=last_line.file)
30451: //fprintf(stderr,"%s ",n->string?n->string:"<0>"); n->where.put(stderr); fprintf(stderr," last "); last_line.put(stderr); putc('\n',stderr);
30452: if (last_ll = n->where.line)
30453: n->where.putline();
30454: else
30455: last_line.putline();
30456:
30457: int tc = Pbase(t)->b_const;
30458: for (Ptype tt = t; tt->base==TYPE; tt = Pbase(tt)->b_name->tp)
30459: tc |= Pbase(tt)->b_const;
30460:
30461: switch (t->base) {
30462: case CLASS:
30463: //fprintf(stderr,"class %s->dcl_print()\n",n->string);
30464: if (n->base != TNAME) {
30465: Pclass(t)->dcl_print(n);
30466: sm = 1;
30467: }
30468: break;
30469:
30470: case ENUM:
30471: Penum(t)->dcl_print(0);
30472: sm = 1;
30473: break;
30474:
30475: case FCT:
30476: { Pfct f = Pfct(t);
30477:
30478: if (n->base == TNAME) puttok(TYPEDEF);
30479:
30480: // error('d',"fct %n->dcl_print() printed %d body %d defined %d",n,n->n_dcl_printed,f->body,f->defined);
30481: // error('d',"n %d tbl %d tp %t inline %d",n,n->n_table,n->tp,f->f_inline);
30482: if (n->n_dcl_printed==2 // definition already printed
30483: || (n->n_dcl_printed==1 && f->body==0)
30484: // declaration already printed
30485: ) {
30486: // don't print again
30487: sm = 1; // no SM
30488: break;
30489: }
30490:
30491: if (f->f_result == 0) make_res(f);
30492:
30493: if (f->body && n->n_sto==EXTERN) n->n_sto = 0;
30494:
30495: if (f->f_inline && ((n->n_table!=gtbl) || strcmp(n->string,"main"))) {
30496: if (debug_opt) {
30497: //error('d',"f %t defined %d inline %d",f,f->defined,f->f_inline);
30498: if (f->defined&DEFINED
30499: && f->defined&SIMPLIFIED
30500: && f->f_inline!=ITOR)
30501: goto prnt_def;
30502: else if (n->n_dcl_printed==0)
30503: goto prnt_dcl;
30504: else {
30505: sm = 1;
30506: break;
30507: }
30508: }
30509: if (f->f_virtual || n->n_addr_taken) {
30510: prnt_dcl:
30511: //error('d',"prnt_dcl %d %n %k",n,n,n->n_sto);
30512: TOK st = n->n_sto;
30513: Pblock b = f->body;
30514: f->body = 0;
30515: t->dcl_print(n);
30516: n->n_dcl_printed = 1;
30517: n->n_sto = st;
30518: f->body = b;
30519: break;
30520: }
30521: else
30522: sm = 1; // no SM
30523: }
30524: else if ((f->defined&DEFINED)==0
30525: || (f->defined&SIMPLIFIED)==0)
30526: goto prnt_dcl;
30527: else if (n->n_table==gtbl && strcmp(n->string,"main")==0) {
30528: if (f->f_inline) {
30529: if (warning_opt) {
30530: error('w',"main() cannot be inlined");
30531: error('w',"out-of-line copy of main() created");
30532: }
30533: n->n_sto=0;
30534: }
30535: MAIN = 1;
30536: gtbl->look("main",0)->use();
30537: f->f_signature = 0;
30538: t->dcl_print(n);
30539: n->n_dcl_printed = f->body?2:1;
30540: MAIN = 0;
30541: }
30542: else {
30543: prnt_def:
30544: // error('d',"prnt_def %n %k %d %k",n,n->n_oper,n,n->n_sto);
30545: if (n->n_oper==CTOR || n->n_oper==DTOR) {
30546: Pclass cl = Pclass(n->n_table->t_name->tp);
30547: if (cl->c_body == 3) cl->print_all_vtbls(cl);
30548: }
30549:
30550: if ( n->n_sto == STATIC &&
30551: pdef_name == 0 && def_name == 0 ) {
30552: // error('d', "printing ptbl_vec without first definition" );
30553: pdef_name = n;
30554: ptbl_init(0);
30555: }
30556: t->dcl_print(n);
30557: n->n_dcl_printed = f->body?2:1;
30558: }
30559: if (f->body) sm = 1;
30560: break;
30561: }
30562:
30563: case OVERLOAD:
30564: {
30565: for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
30566: Pname nn = gl->f;
30567: nn->dcl_print(0);
30568: sm = 1;
30569: }
30570: break;
30571: }
30572:
30573: case ASM:
30574: fprintf(out_file,"asm(\"%s\")\n",(char*)Pbase(t)->b_name);
30575: break;
30576:
30577: case INT:
30578: case EOBJ:
30579: case CHAR:
30580: case LONG:
30581: case SHORT:
30582: tcx:
30583: // do not allocate space for constants unless necessary
30584: if (tc
30585: && n->n_sto!=EXTERN // extern const one;
30586: // const one = 1;
30587: // allocates storage
30588: && (n->n_scope==EXTERN // FUDGE const one = 1;
30589: // is treated as static
30590: // need loader support
30591: || n->n_scope==STATIC
30592: || n->n_scope==FCT)
30593: ) {
30594: if (n->n_evaluated && n->n_addr_taken==0) {
30595: sm = 1; /* no ; */
30596: break;
30597: }
30598: }
30599: tc = 0;
30600: // no break;
30601:
30602: default:
30603: {
30604: /*
30605: // don't print local instance of const
30606: if ( n->n_dcl_printed == 3 ) {
30607: sm = 1;
30608: break;
30609: }
30610: */
30611: Pexpr i = n->n_initializer;
30612: if (n->base == TNAME && n->n_key == NESTED) i = 0;
30613: if (tc) {
30614: switch (tt->base) {
30615: case CHAR:
30616: case SHORT:
30617: case INT:
30618: case LONG:
30619: case EOBJ:
30620: goto tcx;
30621: }
30622: }
30623:
30624: if (n->base == TNAME) {
30625: /* Always print template formals, even when they have the same
30626: * formal name, since the instantiation name is different. This
30627: * fix should not be required when the copy mechanism is in place. */
30628: if (! n_template_arg)
30629: for (Pname tn=ktbl->look(n->string,HIDDEN); tn; tn=tn->n_tbl_list)
30630: if (tn && tn->lex_level && t==tn->tp) return;
30631: puttok(TYPEDEF);
30632: }
30633:
30634: if (n->n_stclass == REGISTER) {
30635: // (imperfect) check against member functions
30636: // register s a; a.f() illegal
30637: Pname cln = n->tp->is_cl_obj();
30638: if (cln) {
30639: Pclass cl = Pclass(cln->tp);
30640: if (cl->csu!=CLASS
30641: && cl->baselist==0
30642: && cl->has_itor()==0
30643: && cl->virt_count==0) puttok(REGISTER);
30644: }
30645: else
30646: puttok(REGISTER);
30647: }
30648:
30649: if (i) {
30650: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
30651: n->n_initializer = 0;
30652: t->dcl_print(n);
30653: puttok(SM);
30654: n->n_initializer = i;
30655: n->n_sto = 0;
30656: t->dcl_print(n);
30657: n->n_sto = EXTERN;
30658: }
30659: else
30660: t->dcl_print(n);
30661: if(n->n_table) {
30662: Pname nn = n->n_table->look(n->string,0);
30663: if(nn)
30664: nn->n_dcl_printed = 1;
30665: else
30666: n->n_dcl_printed = 1;
30667: }
30668: else
30669: n->n_dcl_printed = 1;
30670: }
30671: else if (n->n_evaluated && Pbase(t)->b_const) {
30672: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
30673: int v = n->n_evaluated;
30674: n->n_evaluated = 0;
30675: t->dcl_print(n);
30676: puttok(SM);
30677: if (n->where.line!=last_line.line || n->where.file!=last_line.file)
30678: if (last_ll = n->where.line)
30679: n->where.putline();
30680: else
30681: last_line.putline();
30682: n->n_evaluated = v;
30683: n->n_sto = 0;
30684: t->dcl_print(n);
30685: n->n_sto = EXTERN;
30686: }
30687: else
30688: t->dcl_print(n);
30689: if(n->n_table) {
30690: Pname nn = n->n_table->look(n->string,0);
30691: if(nn)
30692: nn->n_dcl_printed = 1;
30693: else
30694: n->n_dcl_printed = 1;
30695: }
30696: else
30697: n->n_dcl_printed = 1;
30698: }
30699: else {
30700: //error('d',"%n sto %k val %d stc %k",n,n->n_sto,n->n_val,n_stclass);
30701: if ((n->n_sto==0 || (n->n_val && n->n_evaluated==0))
30702: && n_stclass==STATIC
30703: && n->n_sto!=STATIC
30704: && n->n_table==gtbl) {
30705: if (n->n_val && n->n_evaluated==0) {
30706: // extern x = f();
30707: // generate int x = 0;
30708: // plus dynamic initialization
30709: n->n_sto = 0;
30710: }
30711:
30712: n->n_initializer = i = mk_zero_init(t,n,n);
30713: }
30714: t->dcl_print(n);
30715: if(n->n_table) {
30716: Pname nn = n->n_table->look(n->string,0);
30717: if(nn)
30718: nn->n_dcl_printed = 1;
30719: else
30720: n->n_dcl_printed = 1;
30721: }
30722: else
30723: n->n_dcl_printed = 1;
30724: }
30725:
30726: if (n->n_scope!=ARG) {
30727: if (i) {
30728: puttok(ASSIGN);
30729:
30730: Pexpr i2 = i;
30731: while (i2->base == CAST) i2 = i2->e1;
30732: if (i2->base == ILIST) i = i2;
30733: if (t!=i->tp
30734: && i->base!=ZERO
30735: && i->base!=ILIST /*&& i->tp!=Pchar_type*/) {
30736: Ptype t1 = n->tp;
30737: cmp:
30738: switch (t1->base) {
30739: case TYPE:
30740: t1 = Pbase(t1)->b_name->tp;
30741: goto cmp;
30742: default:
30743: i->print();
30744: break;
30745: // case EOBJ:
30746: // goto cst;
30747: case VEC:
30748: if (Pvec(t1)->typ->base==CHAR) {
30749: i->print();
30750: break;
30751: }
30752: // no break
30753: case PTR:
30754: case RPTR:
30755: if (i->tp==0 || n->tp->check(i->tp,0)) {
30756: // cst:
30757: putch('(');
30758: bit oc = Cast;
30759: Cast = 1;
30760: t->print();
30761: Cast = oc;
30762: putch(')');
30763: }
30764: eprint(i);
30765: }
30766: }
30767: else {
30768: if (i==zero) {
30769: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
30770: // if (t->base == EOBJ) {
30771: // putch('(');
30772: // bit oc = Cast;
30773: // Cast = 1;
30774: // t->print();
30775: // Cast = oc;
30776: // putch(')');
30777: // }
30778: }
30779: eprint(i);
30780:
30781: // i->print();
30782: }
30783: }
30784: else if (n->n_evaluated) {
30785: puttok(ASSIGN);
30786: if (n->tp->base!=INT || n->tp->is_unsigned()) {
30787: putstring("((");
30788: bit oc = Cast;
30789: Cast = 1;
30790: n->tp->print();
30791: Cast = oc;
30792: fprintf(out_file,")%d)",n->n_val);
30793: }
30794: else
30795: fprintf(out_file,"%d",n->n_val);
30796: }
30797: }
30798: }
30799: }
30800:
30801: switch (list) {
30802: case SM:
30803: if (sm==0) puttok(SM);
30804: break;
30805: case 0:
30806: if (sm==0) puttok(SM);
30807: return;
30808: case CM:
30809: if (n->n_list) puttok(CM);
30810: break;
30811: }
30812: }
30813: }
30814:
30815: char *local_sign( Ptype pt )
30816: { // get function signature for local class
30817: char buf[1024];
30818: char* bb = pt->signature(buf);
30819: int ll = bb-buf;
30820: if (1023 < ll) error('i',"local class N buffer overflow");
30821: char *p = new char[ll+1];
30822: strcpy(p,buf);
30823: return p;
30824: }
30825:
30826: void enumdef::dcl_print(Pname cln)
30827: /*
30828: */
30829: {
30830: // note: ***** modify to handle local enums
30831: // error('d', "%t::dcl_print(%n) in_class: %t nested_sig: %s", this, cln, in_class, nested_sig );
30832: char* s = nested_sig?nested_sig:(cln ? cln->string:0);
30833: if ( nested_sig )
30834: fprintf(out_file,"enum __%s { ",nested_sig);
30835: else fprintf(out_file,"enum %s { ",string);
30836:
30837: for (Pname px, p=mem; p; p=px) {
30838: px = p->n_list;
30839: if (s) {
30840: if (p->n_evaluated)
30841: fprintf(out_file,"%s__%s = %d",p->string,s,p->n_val);
30842: else
30843: fprintf(out_file,"%s__%s",p->string,s);
30844: }
30845: else {
30846: if (p->n_evaluated)
30847: fprintf(out_file,"%s = %d",p->string,p->n_val);
30848: else
30849: fprintf(out_file,"%s",p->string);
30850: }
30851: if (px) puttok(CM);
30852: p->n_initializer = 0;
30853: delete p;
30854: }
30855: mem = 0;
30856: puttok(RC);
30857: puttok(SM);
30858: }
30859:
30860: void name::print()
30861: { // print just the name itself
30862: if (this == 0) error('i',"0->N::print()");
30863: if (string == 0) {
30864: if (emode) putch('?');
30865: return;
30866: }
30867:
30868: // error( 'd', "%s->name::print(), base: %k", string, base );
30869: switch (base) {
30870: case TNAME:
30871: if (n_key == NESTED && tpdef &&
30872: tpdef->nested_sig) {
30873: if ( emode == 0 ) {
30874: putstring( " __" );
30875: putst(tpdef->nested_sig);
30876: }
30877: else {
30878: putst(tpdef->in_class->string);
30879: putstring( "::" );
30880: putst(string);
30881: }
30882: return;
30883: }
30884:
30885: if (emode && tp) {
30886: if (n_template_arg_string) {
30887: tp->dcl_print(0); return;
30888: } else
30889: if(tp->base == COBJ) {
30890: Pclass cl = Pclass(Pbase(tp)->b_name->tp);
30891: if(cl && cl->base == CLASS &&
30892: (cl->class_base == instantiated_template_class)) {
30893: Ptclass(cl)->inst->print_pretty_name(); return;
30894: }
30895: }
30896: }
30897:
30898: putst(n_template_arg_string ? n_template_arg_string : string);
30899: return;
30900:
30901: case MDOT:
30902: Pexpr(this)->print();
30903: return;
30904: }
30905:
30906: if (emode) {
30907: Ptable tbl;
30908: char* cs = 0;
30909: bit f = 0;
30910: if (tp) {
30911: switch (tp->base) {
30912: case OVERLOAD:
30913: case FCT:
30914: f = 1;
30915: default:
30916: if (tbl=n_table) {
30917: if (tbl == gtbl) {
30918: if (f == 0) putstring("::");
30919: }
30920: else {
30921: if (tbl->t_name) {
30922: Ptclass pc = Ptclass(tbl->t_name->tp);
30923: cs = tbl->t_name->string;
30924: if ((pc->base == CLASS) &&
30925: (pc->class_base == instantiated_template_class))
30926: pc->inst->print_pretty_name();
30927: else fprintf(out_file,"%s",cs);
30928: fprintf (out_file, "::") ;
30929: }
30930: }
30931: }
30932:
30933: if (n_scope==ARG && strcmp(string,"this")==0) {
30934: // tell which "this" it is
30935: Ptype tt = Pptr(tp)->typ;
30936: Pname cn = Pbase(tt)->b_name;
30937: fprintf(out_file,"%s::",cn->string);
30938: }
30939:
30940: case CLASS:
30941: case ENUM:
30942: // case TYPE:
30943: break;
30944: }
30945: nop:
30946: switch (n_oper) {
30947: case TYPE:
30948: putstring("operator ");
30949: if (tp) Pfct(tp)->returns->dcl_print(0);
30950: break;
30951: case 0:
30952: putstring(string);
30953: break;
30954: case DTOR:
30955: putch('~');
30956: case CTOR:
30957: if (cs) {
30958: if(tbl->t_name) {
30959: Ptclass pc = Ptclass(tbl->t_name->tp);
30960: if ((pc->base == CLASS) &&
30961: (pc->class_base == instantiated_template_class))
30962: pc->inst->print_pretty_name();
30963: else putstring(cs);
30964: }
30965: }
30966: else {
30967: if (string)
30968: fprintf(out_file,"%s()", n_template_arg_string
30969: ? n_template_arg_string : string);
30970: else putstring("constructor");
30971: f = 0;
30972: }
30973: break;
30974: case TNAME:
30975: putstring(string);
30976: break;
30977: default:
30978: putstring("operator ");
30979: putstring(keys[n_oper]);
30980: break;
30981: }
30982: if (f) putstring("()");
30983: }
30984: else {
30985: if (n_oper) goto nop;
30986: if (string)
30987: putstring(n_template_arg_string
30988: ? n_template_arg_string : string);
30989: }
30990: return;
30991: }
30992:
30993: char* sig = 0;
30994: Pclass cl = 0;
30995: Penum en = 0;
30996: int i = n_union;
30997:
30998: if (tp) {
30999: Ptable tbl;
31000:
31001: switch (tp->base) {
31002: default:
31003: if (tbl=n_table) { // global or member
31004: Pname tn;
31005: if (tbl == gtbl) {
31006: // if (i) fprintf(out_file,"__O%d.",i);
31007: if ( i ) {
31008: if (n_anon)
31009: fprintf(out_file,"__O%d.%s.", i, n_anon );
31010: else fprintf(out_file,"__O%d.",i);
31011: }
31012: break;
31013: }
31014:
31015: if (tn=tbl->t_name) {
31016: cl = Pclass(tn->tp);
31017: if (i) {
31018: if (cl->string[0]=='_'
31019: && cl->string[1]=='_'
31020: && cl->string[2]=='C' ) {
31021: if (n_anon)
31022: fprintf(out_file,"__O%d.%s.", i, n_anon );
31023: else fprintf(out_file,"__O%d.",i);
31024: }
31025: else
31026: if ( cl->nested_sig )
31027: fprintf(out_file,"__O%d__%s.",i,cl->nested_sig);
31028: else
31029: if ( cl->lex_level ) {
31030: char *str = make_local_name(cl,1);
31031: fprintf(out_file,"__O%d%s.",i,str);
31032: delete str;
31033: }
31034: else fprintf(out_file,"__O%d__%d%s.",i,cl->strlen,cl->string);
31035: cl = 0;
31036: }
31037: else
31038: if (cl->string[0]=='_'
31039: && cl->string[1]=='_'
31040: && cl->string[2]=='C'
31041: && n_stclass != STATIC )
31042: cl = 0;
31043: break;
31044: }
31045: }
31046:
31047: switch (n_stclass) { // local variable
31048: case STATIC:
31049: case EXTERN:
31050: if (i)
31051: fprintf(out_file,"__O%d.",i);
31052: else if (n_sto==STATIC && tp->base!=FCT) {
31053: if (lex_level == 0)
31054: putstring("__S");
31055: else
31056: fprintf(out_file,"__%d",lex_level);
31057: }
31058: break;
31059: default:
31060: // encode with lexical level UNLESS ``special''
31061: // e.g. __builtin
31062: if (string[0]!='_' || string[1]!='_' || string[2] != 'C' ) {
31063: if (i)
31064: {
31065: if (n_anon)
31066: fprintf(out_file,"__%d__O%d.%s.",lex_level-1,i,n_anon);
31067: else fprintf(out_file,"__%d__O%d.",lex_level-1,i);
31068: }
31069: else
31070: fprintf(out_file,"__%d",lex_level);
31071: }
31072: }
31073: break;
31074: case CLASS:
31075: case ENUM:
31076: if (tp->in_class && tp->nested_sig) en = Penum(tp);
31077: break;
31078: }
31079:
31080: if (tp->base==FCT) {
31081: sig = Pfct(tp)->f_signature;
31082: if (sig && sig[0]==0) sig = 0;
31083: }
31084: }
31085:
31086: if (string) {
31087: #ifdef DENSE
31088: int i = strlen(string);
31089: if (cl) i += cl->strlen+4; // __dd<class name>
31090: if (sig) {
31091: if (cl == 0) i += 2;
31092: i += strlen(sig);
31093: }
31094:
31095: if (31<i) {
31096: char buf[256];
31097: if (cl && sig)
31098: sprintf(buf,"%s__%d%s%s",string,cl->strlen,cl->string,sig);
31099: else if (cl)
31100: sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string);
31101: else if (sig)
31102: sprintf(buf,"%s__%s",string,sig);
31103: else
31104: sprintf(buf,"%s",string);
31105: chop(buf);
31106: fprintf(out_file,"%s ",buf);
31107: return;
31108: }
31109: #endif
31110:
31111: if ( en )
31112: fprintf(out_file,"__%s", en->nested_sig);
31113: else
31114: putstring(n_template_arg_string
31115: ? n_template_arg_string : string);
31116:
31117: if ( cl ) {
31118: if ( cl->nested_sig )
31119: fprintf(out_file,"__%s",cl->nested_sig);
31120: else
31121: if ( cl->lex_level ) {
31122: char *str = make_local_name( cl, 1 );
31123: putstring( str );
31124: delete str;
31125: }
31126: else fprintf(out_file,"__%d%s",cl->strlen,cl->string);
31127: }
31128:
31129: if (sig) {
31130: if (cl == 0) putstring("__");
31131: putstring(sig);
31132: }
31133: putch(' ');
31134: }
31135: }
31136:
31137: #ifdef DENSE
31138: void chop(char* buf)
31139: {
31140: static char alpha[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
31141: static const asz = sizeof(alpha)-1;
31142: int hash = 0;
31143: char* p = &buf[29];
31144:
31145: while (*p) {
31146: hash <<= 1;
31147: if (hash & (1<<12)) {
31148: hash &= ~(1<<12);
31149: hash++;
31150: }
31151: hash ^= *p++;
31152: }
31153:
31154: buf[29] = alpha[(int)(hash%asz)];
31155: buf[30] = alpha[(int)((hash/asz)%asz)];
31156: buf[31] = 0;
31157: }
31158: #endif
31159:
31160: void type::print()
31161: {
31162: switch (base) {
31163: case PTR:
31164: case RPTR:
31165: case VEC:
31166: Pptr(this)->dcl_print(0);
31167: break;
31168: case FCT:
31169: Pfct(this)->dcl_print();
31170: break;
31171: // case VEC:
31172: // Pvec(this)->dcl_print(0);
31173: // break;
31174: case CLASS:
31175: case ENUM:
31176: if (emode)
31177: fprintf(out_file,"%k",base);
31178: else
31179: // error('i',"%p->T::print(%k %s)",this,base,Pclass(this)->string);
31180: fprintf(out_file,"struct %s *",Pclass(this)->string);
31181: break;
31182: case TYPE:
31183: if (Cast||Pbase(this)->b_name->lex_level) {
31184: Pbase(this)->b_name->tp->print();
31185: break;
31186: }
31187: // no break
31188: default:
31189: Pbase(this)->dcl_print();
31190: }
31191: }
31192:
31193: char* type::signature(register char* p)
31194: /*
31195: take a signature suitable for argument types for overloaded
31196: function names
31197: */
31198: {
31199: Ptype t = this;
31200: int pp = 0; // pointer to
31201:
31202: xx:
31203: //error('d',"xx(%d) %d %k",this,t,t->base);
31204:
31205: // first unroll typedefs and handle derived types:
31206:
31207: switch (t->base) {
31208: case TYPE:
31209: if (Pbase(t)->b_const) *p++ = 'C';
31210: t = Pbase(t)->b_name->tp;
31211: goto xx;
31212:
31213: case VEC:
31214: if (pp && Pvec(t)->size) { // A<size>_
31215: *p++ = 'A';
31216: sprintf(p,"%d\0",Pvec(t)->size); // don't trust
31217: // sprintf return value
31218: while (*++p);
31219: *p++ = '_';
31220: }
31221: else
31222: *p++ = 'P';
31223: t = Pvec(t)->typ;
31224: pp = 1;
31225: goto xx;
31226:
31227: case PTR:
31228: if (Pptr(t)->rdo) *p++ = 'C'; // *const
31229: if (Pptr(t)->memof) { // M<size><classname>
31230: Pclass cl = Pptr(t)->memof;
31231: register char* s = cl->string;
31232: int d = cl->strlen;
31233: if (d==0) cl->strlen = d = strlen(s);
31234: *p++ = 'M';
31235: if (d/10) *p++ = '0'+d/10;
31236: *p++ = '0'+ d%10; // assume <100 char
31237: while (*p++ = *s++);
31238: --p; // not the '\0'
31239: }
31240: else
31241: *p++ = 'P';
31242: t = Pptr(t)->typ;
31243: pp = 1;
31244: goto xx;
31245:
31246: case RPTR:
31247: *p++ = 'R';
31248: t = Pptr(t)->typ;
31249: pp = 1;
31250: goto xx;
31251:
31252: case FCT:
31253: { Pfct f = Pfct(t);
31254: Pname n = f->argtype;
31255:
31256: if (f->f_const) *p++ = 'C'; // constant member function
31257: if (f->f_static) *p++ = 'S'; // static member function
31258: // if (f->memof && f->f_this==0) *p++ = 'S'; //SSS static member function
31259: *p++ = 'F';
31260: if (n == 0)
31261: *p++ = 'v'; // VOID, that is f() == f(void)
31262: else
31263: for ( ; n; n=n->n_list) { // print argument encoding
31264: // check if argtype is the same
31265: // as previously seen argtype
31266: int i = 0;
31267: for (Pname nn=f->argtype; n!=nn; nn=nn->n_list) {
31268: i++;
31269: if (nn->tp==n->tp || nn->tp->check(n->tp,0)==0) {
31270: // typeof (n) == typeof(arg i)
31271: int x = 1; // try for a run after n
31272: Pname nnn = n;
31273: while ((nnn=nnn->n_list) && x<9) {
31274: if (nnn->tp==n->tp
31275: || nnn->tp->check(n->tp,0)==0) {
31276: x++;
31277: n = nnn;
31278: }
31279: else
31280: break;
31281: }
31282:
31283: if (x == 1) // Ti
31284: *p++ = 'T';
31285: else { // Nxi
31286: *p++ = 'N';
31287: *p++ = '0'+x;
31288: }
31289:
31290: // assume <100 arguments
31291: if (9<i) *p++ = '0'+i/10;
31292: *p++ = '0'+i%10;
31293: goto zk;
31294: }
31295: }
31296:
31297: // ``normal'' case print argument type signature
31298: // if (n->n_xref) *p++ = 'R';
31299: p = n->tp->signature(p);
31300: zk:;
31301: }
31302:
31303: if (f->nargs_known == ELLIPSIS) *p++ = 'e';
31304:
31305: if (pp) { // '_' result type
31306: *p++ = '_';
31307: p = f->returns->signature(p);
31308: }
31309:
31310: *p = 0;
31311: return p;
31312: }
31313: }
31314:
31315: // base type modifiers:
31316:
31317: if ( Pbase(t)->b_const ) *p++ = 'C';
31318: // if ( Pbase(t)->b_signed ) *p++ = 'S';
31319: if ( Pbase(t)->b_unsigned ) *p++ = 'U';
31320: // if ( Pbase(t)->b_volatile ) *p++ = 'V';
31321:
31322:
31323: // now base types:
31324:
31325: register char *s, *ns = 0;;
31326: int d;
31327: Pclass cl;
31328: //lll:
31329: switch (t->base) {
31330: // case TNAME: t = Pbase(t)->b_name->tp; goto lll;
31331: case ANY: break;
31332: case ZTYPE: break;
31333: case VOID: *p++ = 'v'; break;
31334: case CHAR: *p++ = 'c'; break;
31335: case SHORT: *p++ = 's'; break;
31336: // case EOBJ:
31337: case INT: *p++ = 'i'; break;
31338: case LONG: *p++ = 'l'; break;
31339: case FLOAT: *p++ = 'f'; break;
31340: case DOUBLE: *p++ = 'd'; break;
31341: case LDOUBLE: *p++ = 'r'; break;
31342: case EOBJ:
31343: // *p++ = 'i';
31344: // break;
31345: { Penum en = Penum(Pbase(t)->b_name->tp);
31346: // t = en->e_type;
31347: // goto lll;
31348: ns = en->nested_sig;
31349: s = en->string;
31350: d = en->strlen;
31351: if (d==0) en->strlen = d = strlen(s);
31352: goto pppp;
31353: }
31354:
31355: case COBJ:
31356: { cl = Pclass(Pbase(t)->b_name->tp);
31357: ns = cl->nested_sig;
31358: s = cl->string;
31359: d = cl->strlen;
31360: if (d==0) cl->strlen = d = strlen(s);
31361: pppp:
31362: if ( ns == 0 ) {
31363: if (d/10) *p++ = '0'+d/10;
31364: *p++ = '0'+ d%10; // assume less that 99 characters
31365: }
31366: else s = ns;
31367:
31368: while (*p++ = *s++);
31369: --p;
31370: break;
31371: }
31372: case FIELD:
31373: default:
31374: error('i',"signature of %k",t->base);
31375: }
31376:
31377: *p = 0;
31378: return p;
31379: }
31380:
31381: void basetype::dcl_print()
31382: {
31383: Pname nn;
31384: Pclass cl;
31385:
31386: if (emode) {
31387: if (b_virtual) puttok(VIRTUAL);
31388: if (b_inline) puttok(INLINE);
31389: }
31390: if(ansi_opt || emode)
31391: if (b_const) puttok(CONST);
31392: if (b_unsigned) puttok(UNSIGNED);
31393:
31394: switch (base) {
31395: case ANY:
31396: if (emode)
31397: putstring("any ");
31398: else
31399: putstring("int ");
31400: break;
31401:
31402: case ZTYPE:
31403: if (emode)
31404: putstring("zero ");
31405: else
31406: putstring("int ");
31407: break;
31408:
31409: case VOID:
31410: if (emode==0 && ansi_opt==0) {
31411: // silly trick to bypass BSD C compiler bug
31412: // void* (*)() dosn't work there
31413: // note simpl.c knows that VOID -> CHAR grep for VCVC
31414: puttok(CHAR);
31415: break;
31416: }
31417: case CHAR:
31418: case SHORT:
31419: case INT:
31420: case LONG:
31421: case FLOAT:
31422: case DOUBLE:
31423: case LDOUBLE:
31424: puttok(base);
31425: break;
31426:
31427: case EOBJ:
31428: nn = b_name;
31429: eob:
31430: if (emode == 0)
31431: // puttok(INT);
31432: Penum(nn->tp)->e_type->dcl_print();
31433: else {
31434: puttok(ENUM);
31435: nn->print();
31436: }
31437: break;
31438:
31439: case COBJ:
31440: nn = b_name;
31441: cob:
31442: cl = Pclass(nn->tp);
31443: if (emode && (cl->base == CLASS) &&
31444: (cl->class_base == instantiated_template_class)) {
31445: Ptclass(cl)->inst->print_pretty_name();
31446: break;
31447: } else
31448: if (cl && (cl->csu==UNION || cl->csu==ANON))
31449: puttok(UNION);
31450: else puttok(STRUCT);
31451: {
31452: char* s = 0;
31453: if ( cl && cl->nested_sig )
31454: fprintf(out_file," __%s ",cl->nested_sig);
31455: else {
31456: if ( cl && cl->lex_level )
31457: s = make_local_name( cl );
31458: putst(s?s:nn->string);
31459: delete s;
31460: }
31461: }
31462: break;
31463:
31464: case TYPE:
31465: if (emode == 0) {
31466: switch (b_name->tp->base) {
31467: case COBJ:
31468: nn = Pbase(b_name->tp)->b_name;
31469: goto cob;
31470: case EOBJ:
31471: nn = Pbase(b_name->tp)->b_name;
31472: goto eob;
31473: }
31474: }
31475: b_name->print();
31476: break;
31477:
31478: default:
31479: if (emode) {
31480: if (0<base && base<=MAXTOK && keys[base])
31481: fprintf(out_file," %s",keys[base]);
31482: else
31483: putch('?');
31484: }
31485: else
31486: error('i',"%p->BT::dcl_print(%d)",this,base);
31487: }
31488: }
31489: Pbase memptr_type;
31490:
31491: void type::dcl_print(Pname n)
31492: /*
31493: "this" type is the type of "n". Print the declaration
31494: */
31495: {
31496: //error('d',"%p::dcl_print(%n)",this,n);
31497: Ptype t = this;
31498: Pptr p;
31499: TOK pre = 0;
31500:
31501: if (t == 0) error('i',"0->dcl_print()");
31502: if (n && n->tp!=t) error('i',"not %n'sT (%p)",n,t);
31503:
31504: if (base == OVERLOAD) {
31505: for (Plist gl=Pgen(this)->fct_list; gl; gl=gl->l) {
31506: Pname nn = gl->f;
31507: nn->tp->dcl_print(nn);
31508: if (gl->l) puttok(SM);
31509: }
31510: return;
31511: }
31512:
31513: tbuf = tbufvec[freetbuf];
31514: if (tbuf == 0) {
31515: if (freetbuf == NTBUF-1) error('i',"AT nesting overflow");
31516: tbufvec[freetbuf] = tbuf = new class dcl_buf;
31517: }
31518: freetbuf++;
31519: if ( base==FIELD && Pbase(this)->b_bits == 0 )
31520: tbuf->init(0);// some compilers can't handle mangled names here
31521: else
31522: tbuf->init(n);
31523: if (n && n->n_xref) tbuf->front(PTR);
31524:
31525: while (t) {
31526: TOK k;
31527:
31528: switch (t->base) {
31529: case PTR:
31530: p = Pptr(t);
31531: k = (p->rdo) ? CONST_PTR : PTR;
31532: goto ppp;
31533: case RPTR:
31534: p = Pptr(t);
31535: k = (p->rdo) ? CONST_RPTR : RPTR;
31536: ppp:
31537: if (p->memof) {
31538: if (emode) {
31539: tbuf->front(k);
31540: tbuf->front(p->memof);
31541: }
31542: else {
31543: t = p->typ;
31544: while (t->base==TYPE) t = Pbase(t)->b_name->tp;
31545: if (t->base == FCT) {
31546: tbuf->base(mptr_type);
31547: goto zaq;
31548: }
31549: else
31550: tbuf->front(k);
31551: }
31552: }
31553: else
31554: tbuf->front(k);
31555: pre = PTR;
31556: t = p->typ;
31557: break;
31558: case VEC:
31559: { Pvec v = Pvec(t);
31560: if (Cast && pre != PTR && pre != VEC) { // for Macintosh: ptr to array uses [] notation
31561: tbuf->front(PTR);
31562: pre = PTR;
31563: }
31564: else {
31565: if (pre == PTR) tbuf->paran();
31566: tbuf->back(VEC,v);
31567: pre = VEC;
31568: }
31569: t = v->typ;
31570: break;
31571: }
31572:
31573: case FCT:
31574: { Pfct f = Pfct(t);
31575: if (pre == PTR)
31576: tbuf->paran();
31577: else if (emode && f->memof && n==0)
31578: tbuf->front(f->memof);
31579: tbuf->back(FCT,f);
31580: pre = FCT;
31581: t = (f->s_returns) ? f->s_returns : f->returns;
31582: break;
31583: }
31584: case FIELD:
31585: tbuf->back(FIELD,t);
31586: tbuf->base( Pbase(Pbase(t)->b_fieldtype) );
31587: t = 0;
31588: break;
31589: case 0:
31590: if(!emode)error('i',"noBT(B=0)");
31591: goto dobase;
31592: case TYPE:
31593: if (Cast||Pbase(t)->b_name->lex_level) { // unravel type in case it contains vectors
31594: t = Pbase(t)->b_name->tp;
31595: break;
31596: }
31597: default: // the base has been reached
31598: dobase:
31599: if (emode) {
31600: char* s;
31601: for (Ptype tt = t; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
31602: switch (tt->base) {
31603: case CLASS:
31604: s = Pclass(tt)->string;
31605: if (Ptclass(this)->class_base == instantiated_template_class ||
31606: Ptclass(this)->class_base == uninstantiated_template_class) {
31607: Ptclass(this)->inst->print_pretty_name();
31608: --freetbuf;
31609: return;
31610: }
31611: if (s[0]=='_' &&s[1]=='_' && s[2]=='C') s="class";
31612: goto fret;
31613: case ENUM:
31614: s = "enum";
31615: goto fret;
31616: case OVERLOAD:
31617: s = "overloaded";
31618: fret:
31619: putstring(s);
31620: freetbuf--;
31621: return;
31622: }
31623: }
31624:
31625: tbuf->base( Pbase(t) );
31626: goto zaq;
31627: } // switch
31628: } // while
31629: zaq:
31630: tbuf->put();
31631: freetbuf--;
31632: }
31633:
31634: void fct::dcl_print()
31635: {
31636: Pname nn;
31637: //error('d',"fct::dcl_print()");
31638: if (emode) {
31639: putch('(');
31640: for (nn=argtype; nn;) {
31641: nn->tp->dcl_print(0);
31642: if (nn=nn->n_list) puttok(CM); else break;
31643: }
31644: switch (nargs_known) {
31645: case 0: // putst("?"); break;
31646: case ELLIPSIS: puttok(ELLIPSIS); break;
31647: }
31648: putch(')');
31649: if (f_const) puttok(CONST);
31650: if (f_static) puttok(STATIC); // wrong place for ``static''
31651: return;
31652: }
31653:
31654: Pname at = f_args;
31655: putch('(');
31656:
31657: if (ansi_opt) {
31658: // print typed arguments:
31659: at = (f_this) ? f_this : (f_result) ? f_result : argtype;
31660: // WNG -- note: at = f_args had 0 value with ansi_opt set
31661: // mystery fix added here
31662: if (at == 0) {
31663: if (nargs_known == ELLIPSIS) {
31664: putch(')');
31665: return;
31666: }
31667: puttok(VOID);
31668: }
31669: else if (body && Cast==0)
31670: at->dcl_print(CM); // print argument type and name
31671: else {
31672: for (nn=at; nn;) {
31673: // nn->tp->dcl_print(0); // print argument type
31674: nn->tp->dcl_print(nn); // print argument type
31675: // (there may not be a name)
31676: if (nn=nn->n_list) puttok(CM); else break;
31677: }
31678: }
31679: if (nargs_known == ELLIPSIS) putstring(",...");
31680: putch(')');
31681: }
31682: else {
31683: // print argument names followed by argument type declarations:
31684: if (body && Cast==0) {
31685: for (nn=at; nn;) {
31686: nn->print();
31687: if (nn=nn->n_list) puttok(CM); else break;
31688: }
31689: #ifdef mips
31690: if (nargs_known == ELLIPSIS)
31691: putstring(", va_alist");
31692: #endif
31693: #ifdef sparc
31694: if (nargs_known == ELLIPSIS)
31695: putstring(", __builtin_va_alist");
31696: #endif
31697: putch(')');
31698: }
31699: else
31700: putch(')');
31701: }
31702: }
31703:
31704: void print_body(Pfct f)
31705: {
31706: if (Cast==0) {
31707:
31708: if (ansi_opt==0 && f->f_args) {
31709: f->f_args->dcl_print(SM);
31710: if ( last_ll==0 && (last_ll = f->body->where.line) )
31711: f->body->where.putline();
31712: }
31713:
31714: if (MAIN) {
31715: putstring("{ _main(); "); // call constructors
31716: f->body->print();
31717: puttok(RC);
31718: }
31719: else
31720: f->body->print();
31721: }
31722: }
31723:
31724: Pbcl shared_seen;
31725:
31726: void classdef::print_members()
31727: {
31728: int i;
31729:
31730: Pbcl l = baselist;
31731: // error('d',"%t->print_members()",this);
31732: if (l) {
31733: if (l->base == NAME) {
31734: l->bclass->print_members(); // first base only
31735: // pad to ensure alignment:
31736: int boff = l->bclass->real_size;
31737: int ba = l->bclass->align();
31738: int xtra = boff%ba;
31739: int waste = (xtra) ? ba-xtra : 0; // padding
31740: //error('d',"%s: size % align %d waste %d",string,boff,ba,waste);
31741: if (waste) {
31742: // waste it to protect against structure
31743: // assignments to the base class
31744: char* s = make_name('W');
31745: fprintf(out_file,"char %s[%d];\n",s,waste);
31746: delete s;
31747: }
31748: l = l->next;
31749: }
31750:
31751: for (; l; l=l->next)
31752: /* for second base etc. one must allocate as an object
31753: (rather than a list of members) to ensure proper alignment
31754: for shared base allocate a pointer
31755: size, alignment, & offset handled in cassdef::dcl()
31756: */
31757: if (l->base == NAME) {
31758: Pclass bcl = l->bclass;
31759: char *str = 0;
31760: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
31761: if (bcl->lex_level &&
31762: bcl->nested_sig==0)
31763: str=make_local_name(bcl);
31764: puttok(STRUCT);
31765: putst(str?str:cs);
31766: putcat('O',bcl->string); // leave as unencoded
31767: puttok(SM);
31768: delete str;
31769: }
31770: }
31771:
31772: // Sam: A class or an enum type declared within a class can hide a
31773: // member with the same name, so make sure that it gets printed by
31774: // traversing the n_tbl_list to get at these names.
31775: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) {
31776: do { if (nn->base==NAME
31777: && nn->n_union==0
31778: && nn->tp->base!=FCT
31779: && nn->tp->base!=OVERLOAD
31780: && nn->tp->base!=CLASS
31781: && nn->tp->base!=ENUM
31782: && nn->n_stclass != STATIC) {
31783: // if (nn->tp->base==FIELD && Pbase(nn->tp)->b_bits==0) continue;
31784: Pexpr i = nn->n_initializer;
31785: nn->n_initializer = 0;
31786: nn->dcl_print(0);
31787: nn->n_initializer = i;
31788: }
31789: } while ((nn->base == NAME) &&
31790: ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) &&
31791: (nn = nn->n_tbl_list)) ;
31792: }
31793:
31794: for (l=baselist; l; l=l->next)
31795: if (l->base==VIRTUAL && l->ptr_offset) {
31796: Pclass bcl = l->bclass;
31797: char* str = 0;
31798: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
31799: if (bcl->lex_level &&
31800: bcl->nested_sig==0)
31801: str=make_local_name(bcl);
31802: puttok(STRUCT);
31803: putst(str?str:cs);
31804: putch('*');
31805: putcat('P',bcl->string); // leave unencoded
31806: puttok(SM);
31807: delete str;
31808: }
31809: }
31810:
31811: // void classdef::print_vtbl(Pvirt vtab)
31812: // {
31813: // error('d',"%s->print_vtbl(%s) vtbl_opt %d",string,vtab->string,vtbl_opt);
31814: // error('d',"print_vtbl: lex_level: %d", lex_level );
31815: //
31816: // switch (vtbl_opt) {
31817: // case -1:
31818: // case 1:
31819: // vlist = new vl(this,vtab,vlist);
31820: // }
31821: //
31822: // int oo = vtbl_opt; // make `simulated static' name
31823: // vtbl_opt = -1;
31824: // char* str = lex_level ? make_local_name(this) : 0;
31825: // char* s = vtbl_name(vtab->string,str?str:string);
31826: // vtbl_opt = oo;
31827: // fprintf(out_file,"extern struct __mptr %s[];\n",s);
31828: // s[2] = 'p'; // pointer, not tbl itself
31829: // fprintf(out_file,"extern struct __mptr* %s;\n",s);
31830: //
31831: // delete s;
31832: // delete str;
31833: // }
31834:
31835: vl* vlist;
31836:
31837: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss);
31838:
31839: int p2(Pname nn, Ptype t, Pclass cl, Pvirt vtab, char* s)
31840: {
31841: int init;
31842:
31843: if (t->base == FCT) {
31844: Pfct f = Pfct(t);
31845:
31846: //error('d',"p2 %n init %d inline %d virtual %d",nn,nn->n_initializer,f->f_inline,f->f_virtual);
31847: //error('d',"p2 %s expr %d imeasure %d body %d",s,f->f_expr,f->f_imeasure,f->body);
31848: //error('d',"sto %k",nn->n_sto);
31849: if (nn->n_initializer
31850: || nn->n_sto==STATIC
31851: || f->f_inline
31852: || f->f_imeasure
31853: || f->f_virtual==0) return 0;
31854: init = f->body!=0;
31855: }
31856: else
31857: init = nn->n_initializer!=0;
31858:
31859: int oo = vtbl_opt;
31860: vtbl_opt = 1; // make sure the name is universal
31861: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
31862: char* sstr = (cl->lex_level&&cl->nested_sig==0)? make_local_name(cl) : 0;
31863: char* ss = vtbl_name(vtab->string,sstr?sstr:cs);
31864:
31865: if (init) { // unique definition here
31866: really_really_print(cl,vtab,ss,s);
31867: }
31868: else { // unique definition elsewhere
31869: char *vstr = 0;
31870: if ( vtab && vtab->string ) {
31871: vstr = new char[strlen(vtab->string)+cl->strlen+1];
31872: strcpy( vstr, vtab->string );
31873: strcat( vstr, cl->string );
31874: }
31875: Pname nn;
31876: if (nn=ptbl->look(vstr?vstr:cl->string,0)) { // use of ptbl in file
31877: fprintf(out_file,"extern struct __mptr %s[];\n",ss);
31878: s[2] = 'p';
31879: // fprintf(out_file,"struct __mptr* %s = ",s);
31880: // fprintf(out_file,"%s;\n",ss);
31881: ptbl_add_pair(s, ss);
31882: nn->n_key=HIDDEN;
31883: }
31884: delete vstr;
31885: }
31886: vtbl_opt = oo;
31887:
31888: delete ss;
31889: delete sstr;
31890:
31891: return 1;
31892: }
31893:
31894: void classdef::really_print(Pvirt vtab)
31895: {
31896: // error('d',"really_print %t %d",this,vtbl_opt);
31897: int oo = vtbl_opt; // make `simulated static' name
31898: vtbl_opt = -1;
31899: char *cs = nested_sig?nested_sig:string;
31900: char* str = (lex_level&&nested_sig==0) ? make_local_name(this) : 0;
31901: char* s = vtbl_name(vtab->string,str?str:cs);
31902: // error('d', "really_print: %s, vtab: %s, s: %s", string, vtab->string, s );
31903: vtbl_opt = oo;
31904:
31905: // see if needed
31906: int i;
31907: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
31908: Ptype t = nn->tp;
31909: zse:
31910: if (t)
31911: switch (t->base) {
31912: case TYPE:
31913: t = Pbase(t)->b_name->tp;
31914: goto zse;
31915: /*
31916: case COBJ:
31917: if (nn->n_sto == EXTERN)
31918: { Pclass cl = Pclass(Pbase(t)->b_name->tp);
31919: if (cl->has_ctor()) {
31920: p2(nn,t,this,vtab,s);
31921: return;
31922: }
31923: }
31924: break;
31925: */
31926: case FCT:
31927: if (p2(nn,t,this,vtab,s))
31928: goto xyzzy;
31929: break;
31930:
31931: case OVERLOAD:
31932: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l)
31933: if (p2(gl->f,gl->f->tp,this,vtab,s))
31934: goto xyzzy;
31935: }
31936: }
31937: }
31938:
31939: { // must be initialized var in block to permit goto
31940: char* ss = vtbl_name(vtab->string,str?str:cs);
31941: // error('d', "really_print: %s, vtab: %s, ss: %s", cs, vtab->string, s );
31942:
31943: if (vtbl_opt)
31944: really_really_print(this,vtab,ss,s);
31945: else {
31946: char *vstr = 0;
31947: if ( vtab && vtab->string ) {
31948: vstr = new char[::strlen(vtab->string)+strlen+1];
31949: strcpy( vstr, vtab->string );
31950: strcat( vstr, string );
31951: }
31952: Pname nn;
31953: if (nn=ptbl->look(vstr?vstr:string,0)) { // use of ptbl in file
31954: fprintf(out_file,"extern struct __mptr %s[];\n",ss);
31955: s[2] = 'p';
31956: // fprintf(out_file,"struct __mptr* %s = ",s);
31957: // fprintf(out_file,"%s;\n",ss);
31958: ptbl_add_pair(s, ss);
31959: nn->n_key=HIDDEN;
31960: }
31961: delete vstr;
31962: }
31963: delete ss;
31964: }
31965: xyzzy:
31966: delete s;
31967: delete str;
31968: }
31969:
31970: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss)
31971: {
31972: // error('d',"really %s %s",s, ss);
31973: // make sure function is declared before using
31974: // it in vtbl initializer
31975: Pname nn;
31976: int i;
31977: for (i=0; nn = vtab->virt_init[i].n; i++) {
31978: Pfct f = Pfct(nn->tp);
31979: if (nn->n_initializer) { // pure virtual
31980: static pv;
31981: if (pv == 0) { // VCVC void->char assumed
31982: fprintf(out_file,"char __pure_virtual_called();\n");
31983: pv = 1;
31984: }
31985: continue;
31986: }
31987: if (f->base != FCT) error('i',"vtbl %n",nn);
31988: //extern void expand_dtor(Pclass cl);
31989: // if (f->f_inline == IDTOR) expand_dtor(f->memof);
31990:
31991: if (nn->n_dcl_printed==0 /*|| f->f_inline*/) {
31992: if (f->f_inline && vtbl_opt) puttok(STATIC);
31993: if (f->f_result == 0) make_res(f);
31994: Ptype r = f->s_returns ? f->s_returns : f->returns;
31995: r->print();
31996: nn->print();
31997: putstring("()");
31998: puttok(SM);
31999: nn->n_dcl_printed = 1;
32000: }
32001: }
32002:
32003: // if (vtbl_opt == -1) puttok(STATIC);
32004:
32005:
32006: fprintf(out_file,"struct __mptr %s[] = {0,0,0,\n",s);
32007:
32008: Pname n;
32009: for (i=0; n=vtab->virt_init[i].n; i++) {
32010: if (n->n_initializer)
32011: putstring("0,0,(__vptp)__pure_virtual_called,\n");
32012: else {
32013: fprintf(out_file,"%d,0,(__vptp)",-vtab->virt_init[i].offset);
32014: n->print();
32015: n->n_addr_taken = 1;
32016: putstring(",\n");
32017: }
32018: }
32019: putstring("0,0,0};\n");
32020:
32021: ss[2] = 'p';
32022: // fprintf(out_file,"struct __mptr* %s = ",ss);
32023: s[2] = 'v';
32024: // fprintf(out_file,"%s;\n",s);
32025: ptbl_add_pair(ss,s);
32026:
32027: Pname nm;
32028: char *cstr = 0;
32029: char *vstr = 0;
32030: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
32031: if (cl->lex_level && cl->nested_sig==0) cstr = make_local_name( cl );
32032: if ( vtab && vtab->string ) {
32033: vstr = new char[strlen(vtab->string)+(cstr?strlen(cstr):strlen(cs))+1];
32034: strcpy( vstr, vtab->string );
32035: strcat( vstr, cstr?cstr:cs );
32036: }
32037:
32038: if ( vstr == 0 ) vstr = cstr;
32039: if ( nm = ptbl->look(vstr?vstr:cl->string,0) )
32040: nm->n_key = HIDDEN;
32041: else
32042: if ( ptbl->look(vstr?vstr:cl->string,HIDDEN) == 0 )
32043: ptbl->insert(new name(vstr?vstr:cl->string),HIDDEN);
32044: if (cstr == vstr) delete cstr;
32045: else {
32046: delete cstr;
32047: delete vstr;
32048: }
32049:
32050: //error('d',"really-> %s",s);
32051: }
32052:
32053: #include <ctype.h>
32054: char* vtbl_name(char* s1, char* s2)
32055: {
32056: char* s3 = (vtbl_opt == -1 && *src_file_name) ? src_file_name : 0;
32057: // if vtbl_opt == -1 fake a static (there are no portable
32058: // way of doing a forward declaration of a static in C)
32059: int ll = s1 ? strlen(s1) : 0;
32060: int ll2 = strlen(s2);
32061: int ll3 = s3 ? strlen(s3) : 0;
32062: int sz = (ll+ll2+ll3+20)/32+1; // avoid fragmentation
32063:
32064: sz *= 32;
32065: // error('d',"vtbl_name(%s,%s,%s) %d",s1?s1:"",s2,s3?s3:"",sz);
32066: char* buf = new char[sz];
32067: if (s3) {
32068: if (s1)
32069: sprintf(buf,"__vtbl__%d%s__%d%s__%s",ll,s1,ll2,s2,s3);
32070: else
32071: sprintf(buf,"__vtbl__%d%s__%s",ll2,s2,s3);
32072: }
32073: else if (s1)
32074: sprintf(buf,"__vtbl__%d%s__%d%s",ll,s1,ll2,s2);
32075: else
32076: sprintf(buf,"__vtbl__%d%s",ll2,s2);
32077:
32078: if (vtbl_opt == -1) {
32079: for (char* p = buf+ll2+11; *p; p++)
32080: if (!isalpha(*p) && !isdigit(*p)) *p = '_';
32081: }
32082: #ifdef DENSE
32083: chop(buf);
32084: #endif
32085: return buf;
32086: }
32087:
32088: void classdef::print_all_vtbls(Pclass bcl)
32089: {
32090: //error('d',"%t->print_all_vtbls(%t) vlt %d bl %d",this,bcl,virt_list,baselist);
32091:
32092: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
32093: if (this != blist->vclass) continue;
32094: if (blist->printed) continue;
32095: // if (blist->string==0 && find_vptr(this)==0) { //BSopt
32096: // continue;
32097: // }
32098: // print_vtbl(blist);
32099: vlist = new vl(this,blist,vlist);
32100: blist->printed = 1;
32101: }
32102:
32103: for (Pbcl b = bcl->baselist; b; b = b->next)
32104: print_all_vtbls(b->bclass);
32105:
32106: if (this==bcl) c_body = 0;
32107: }
32108:
32109: extern Pclass current_instantiation;
32110: void classdef::dcl_print(Pname)
32111: {
32112: //error('d',"%t->classdef::dcl_print() -- c_body==%d defined==0%o",this,c_body,defined);
32113: defined |= REF_SEEN;
32114: // ensure template instantiations are printed exactly once.
32115: if (class_base != vanilla_class && current_instantiation != this) return;
32116:
32117: if (c_body==0 || c_body==3 || (defined&DEFINED)==0) return;
32118: c_body = 3;
32119:
32120: int i;
32121: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
32122: if (nn->base==NAME
32123: && nn->n_union==0
32124: && nn->tp->base==CLASS
32125: && Pclass(nn->tp)->c_body==1)
32126: Pclass(nn->tp)->dcl_print(nn);
32127: else if (nn->base == TNAME && Pbase(nn->tp)->base != COBJ)
32128: nn->dcl_print(0);
32129: else if (nn->tp && nn->tp->base == ENUM) {
32130: if(nn->n_union==0) Penum(nn->tp)->dcl_print(nn);
32131: }
32132: }
32133:
32134: TOK lvl = in_class ? NESTED : lex_level ? LOCAL : 0;
32135: Pname n = ktbl->look(string,lvl);
32136: if (n==0) n = ktbl->look(string,HIDDEN);
32137:
32138: if (n) {
32139: if (n->where.line!=last_line.line
32140: || n->where.file!=last_line.file)
32141: if (last_ll = n->where.line)
32142: n->where.putline();
32143: else
32144: last_line.putline();
32145: }
32146:
32147: TOK c = csu==CLASS ? STRUCT : csu;
32148: puttok(c);
32149: // if (string[0]!='_' || string[1]!='_' || string[2]!='C')
32150:
32151: char *str = 0;
32152: if ( lex_level && nested_sig == 0) str = make_local_name( this );
32153: if ( nested_sig ) putstring( " __" );
32154: putst(str?str:(nested_sig?nested_sig:string));
32155:
32156: int sm = 0;
32157: int sz = tsizeof();
32158: int dvirt = 0;
32159:
32160: if ( nested_sig )
32161: fprintf(out_file,"{\t/* sizeof __%s == %d */\n",nested_sig,obj_size);
32162: else
32163: fprintf(out_file,"{\t/* sizeof %s == %d */\n",str?str:string,obj_size);
32164: if ( last_ll ) last_line.line++;
32165: delete str;
32166:
32167: print_members();
32168: for (Pbcl b = baselist; b; b = b->next) { // declare virtual classes
32169: if (b->base != VIRTUAL) continue;
32170: Pclass bcl = b->bclass;
32171: dvirt += bcl->virt_count;
32172: //error('d',"%t in %t %d",b->bclass,this,b->allocated);
32173: if (b->allocated==0) continue;
32174: char* str = 0;
32175: if (bcl->lex_level) str = make_local_name(bcl);
32176: puttok(STRUCT); // struct bcl Obcl;
32177: putst(str?str:bcl->string);
32178: putcat('O',bcl->string); // leave unencoded
32179: puttok(SM);
32180: delete str;
32181: }
32182: putstring("};\n");
32183: if ( last_ll ) last_line.line++;
32184:
32185: for (nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
32186: if (nn->base==NAME && nn->n_union==0) {
32187: Ptype t = nn->tp;
32188: switch (t->base) {
32189: case FCT:
32190: case OVERLOAD:
32191: break;
32192: default:
32193: if (nn->n_stclass == STATIC) {
32194: TOK b = nn->n_sto;
32195: //error('d',"print nn %n tp %t b %k eval %d",nn,nn->tp,b,nn->n_evaluated);
32196: /*
32197: Pname cn;
32198: TOK bb = ((cn=nn->tp->is_cl_obj())
32199: && Pclass(cn->tp)->has_ctor())==0
32200: ?0:b; // force explicit initialization
32201: nn->n_sto = (nn->n_evaluated) ? STATIC : bb;
32202: */
32203: nn->n_sto = (nn->n_evaluated) ? STATIC : b;
32204: nn->dcl_print(0);
32205: nn->n_sto = b;
32206: }
32207: }
32208: }
32209: }
32210: if (vtbl_opt != -1) print_all_vtbls(this); // force declaration
32211: //error('d',"dcl_print -> ");
32212: }
32213:
32214:
32215: char *
32216: make_local_name( Pclass cl, int ln )
32217: {
32218: char *buf;
32219: if ( cl->in_fct == 0 ) error( 'i', "localC %s missingFN", cl->string );
32220: char *fsig = Pfct(cl->in_fct->tp)->f_signature;
32221: if ( fsig == 0 ) fsig = local_sign( cl->in_fct->tp );
32222: char *fs = cl->in_fct->string;
32223: int class_len=cl->strlen+strlen(fsig)+strlen(fs)+strlen(cl->lcl)+4;
32224: int sz = (class_len+20)/32+1; // from vtbl_name()
32225:
32226: if ( Pfct(cl->in_fct->tp)->memof == 0 ) {
32227: sz *= 32;
32228: buf = new char[ sz ];
32229: // error('d', "make_local_name: sz: %d", sz );
32230:
32231: if (ln)
32232: sprintf(buf, "__%d%s__%s__%s%s", class_len, cl->string, fs, fsig, cl->lcl);
32233: else
32234: sprintf(buf, "%s__%s__%s%s", cl->string, fs, fsig, cl->lcl);
32235: }
32236: else
32237: {
32238: char *cs = Pclass(Pfct(cl->in_fct->tp)->memof)->string;
32239: int len = Pclass(Pfct(cl->in_fct->tp)->memof)->strlen;
32240: if ( len < 10 )
32241: ++class_len;
32242: else
32243: if ( len > 99 )
32244: class_len += 3;
32245: else class_len += 2;
32246: class_len += len;
32247: sz = (class_len+20)/32+1;
32248: sz *= 32;
32249: buf = new char[ sz ];
32250: // error('d', "make_local_name: sz: %d", sz );
32251:
32252: if ( ln )
32253: sprintf(buf, "__%d%s__%s__%d%s%s%s",class_len,cl->string,fs,len,cs,fsig,cl->lcl);
32254: else sprintf(buf, "%s__%s__%d%s%s%s",cl->string,fs,len,cs,fsig,cl->lcl);
32255: }
32256:
32257: #ifdef DENSE
32258: chop( buf );
32259: #endif
32260:
32261: return buf;
32262: }
32263:
32264: 0707071010112046021004440001630000160000010210070466055415700001500000001262print_self.c /* ident "@(#)ctrans:src/print_self.c 1.2" */
32265: /* print_self_default.C -- bailout versions of print_self and format_self */
32266: /*
32267: $Source: /usr2/odi/lib.src/RCS/print_self_default.C,v $ $RCSfile: print_self_default.C,v $
32268: $Revision: 1.4 $ $Date: 89/09/19 11:49:58 $
32269: $Author: benson $ $Locker: $
32270: $State: Exp $
32271: */
32272:
32273: #include "print_self.h"
32274:
32275: int ostream_printf (ostream&, const char * ...);
32276:
32277: int _Print_self::print_self (ostream& stream) const
32278: {
32279: return ostream_printf (stream, "<%s at 0x%p>",
32280: this->type_name(), (void *) this);
32281: }
32282:
32283: int _Print_self::format_self (ostream& stream) const
32284: {
32285: return ostream_printf (stream, "<%s at 0x%p>",
32286: this->type_name(), (void *) this);
32287: }
32288: 0707071010112046111004440001630000160000010211170466055421300001500000001261print_self.h /* ident "@(#)ctrans:src/print_self.h 1.2" */
32289: /* print_self.H -- base class for objects that want to support
32290: the 'official' print self for \T in printf. */
32291:
32292: /*
32293: $Header: /usr2/odi/include/RCS/print_self.H,v 1.4 89/09/19 11:49:19 benson Exp $
32294:
32295: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
32296: All rights reserved.
32297:
32298: */
32299:
32300: #ifndef _PRINT_SELF_CLASS
32301: #define _PRINT_SELF_CLASS
32302: #include <iostream.h>
32303:
32304: class _Print_self {
32305: public:
32306: virtual char * type_name () const { return "OBJECT"; }
32307: virtual int print_self (ostream&) const; // returns count of characters printed.
32308: virtual int format_self (ostream&) const; // returns count of characters printed.
32309: };
32310: #endif
32311: 0707071010112044421004440001630000160000010206300466055407100000700000010531repr.c /*ident "@(#)ctrans:src/repr.c 1.4" */
32312: /**************************************************************************
32313:
32314: C++ source for cfront, the C++ compiler front-end
32315: written in the computer science research center of Bell Labs
32316:
32317: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
32318: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
32319:
32320: repr.c:
32321:
32322: *****************************************************************************/
32323:
32324: #include "cfront.h"
32325:
32326: char* oper_name(TOK op)
32327: /*
32328: return the string representation of operator "op"
32329: */
32330: {
32331: switch (op) {
32332: default: error('i',"oper_name(%k)",op);
32333: case GNEW:
32334: case NEW: return "__nw";
32335: case GDELETE:
32336: case DELETE: return "__dl";
32337: case MUL: return "__ml";
32338: case DIV: return "__dv";
32339: case MOD: return "__md";
32340: case UPLUS:
32341: case PLUS: return "__pl";
32342: case MINUS:
32343: case UMINUS: return "__mi";
32344: case LS: return "__ls";
32345: case RS: return "__rs";
32346: case EQ: return "__eq";
32347: case NE: return "__ne";
32348: case LT: return "__lt";
32349: case GT: return "__gt";
32350: case LE: return "__le";
32351: case GE: return "__ge";
32352: case AND:
32353: case ADDROF: return "__ad";
32354: case OR: return "__or";
32355: case ER: return "__er";
32356: case ANDAND: return "__aa";
32357: case OROR: return "__oo";
32358: case NOT: return "__nt";
32359: case COMPL: return "__co";
32360: case INCR: return "__pp";
32361: case DECR: return "__mm";
32362: case CALL: return "__cl";
32363: case DEREF: return "__vc";
32364: case ASSIGN: return "__as";
32365: case REF: return "__rf";
32366: case ASPLUS: return "__apl";
32367: case ASMINUS: return "__ami";
32368: case ASMUL: return "__amu";
32369: case ASDIV: return "__adv";
32370: case ASMOD: return "__amd";
32371: case ASLS: return "__als";
32372: case ASRS: return "__ars";
32373: case ASAND: return "__aad";
32374: case ASOR: return "__aor";
32375: case ASER: return "__aer";
32376: case CTOR: return "__ct";
32377: case DTOR: return "__dt";
32378: // operator T "__op"<signature of T>
32379: // case SIZEOF: return "sizeof";
32380: case CM: return "__cm";
32381: case REFMUL: return "__rm";
32382: // library functions:
32383: // "_vec_delete"
32384: // "_vec_new"
32385: // "_main"
32386: }
32387: }
32388:
32389: #define new_op(ss,v) keys[v]=ss
32390:
32391: void otbl_init()
32392: /*
32393: operator representation table
32394: */
32395: {
32396: new_op("->",REF);
32397: new_op("." ,DOT);
32398: new_op(".* or ->*" ,REFMUL);
32399: new_op("mdot" ,REFMUL);
32400: new_op("!" ,NOT);
32401: new_op("~" ,COMPL);
32402: new_op("++",INCR);
32403: new_op("--",DECR);
32404: new_op("*" ,MUL);
32405: new_op("&" ,AND);
32406: new_op("&" ,ADDROF);
32407: new_op("&" ,G_ADDROF);
32408: new_op("/" ,DIV);
32409: new_op("%" ,MOD);
32410: new_op("+" ,PLUS);
32411: new_op("+" ,UPLUS);
32412: new_op("-" ,MINUS);
32413: new_op("-" ,UMINUS);
32414: new_op("<<",LS);
32415: new_op(">>",RS);
32416: new_op("<" ,LT);
32417: new_op(">" ,GT);
32418: new_op("<=",LE);
32419: new_op(">=",GE);
32420: new_op("==",EQ);
32421: new_op("!=",NE);
32422: new_op("^" ,ER);
32423: new_op("|" ,OR);
32424: new_op("&&",ANDAND);
32425: new_op("||",OROR);
32426: new_op("?:" ,QUEST);
32427: // new_op(":" ,COLON);
32428: new_op("=" ,ASSIGN);
32429: new_op("," ,CM);
32430: new_op("," ,G_CM);
32431:
32432: new_op(";" ,SM);
32433: new_op("{" ,LC);
32434: new_op("}" ,RC);
32435: new_op("(" ,LP);
32436: new_op(")" ,RP);
32437: new_op("[" ,LB);
32438: new_op("]" ,RB);
32439:
32440: new_op("+=",ASPLUS);
32441: new_op("-=",ASMINUS);
32442: new_op("*=",ASMUL);
32443: new_op("/=",ASDIV);
32444: new_op("%=",ASMOD);
32445: new_op("&=",ASAND);
32446: new_op("|=",ASOR);
32447: new_op("^=",ASER);
32448: new_op(">>=",ASRS);
32449: new_op("<<=",ASLS);
32450:
32451: // new_op("sizeof",SIZEOF);
32452: // new_op("new",NEW);
32453: // new_op("delete",DELETE);
32454:
32455: new_op("0" ,ZERO);
32456: new_op("[]" ,DEREF);
32457: new_op("expression list", ELIST);
32458: new_op("initializer list", ILIST);
32459: new_op("static initializer", STAT_INIT);
32460: new_op("()", CALL);
32461: new_op("generated function call",G_CALL);
32462: new_op("inline function call",ICALL);
32463: new_op("cast",CAST);
32464: new_op("inline argument",ANAME);
32465: new_op("text",TEXT);
32466: new_op(".*",MEMPTR);
32467:
32468: new_op("class type", COBJ);
32469: new_op("enum type", EOBJ);
32470: new_op("union", ANON);
32471:
32472: new_op("function",FCT);
32473: new_op("pointer",PTR);
32474: new_op("reference",RPTR);
32475: new_op("array",VEC);
32476: new_op("identifier",ID);
32477: new_op("name",NAME);
32478: new_op("...",ELLIPSIS);
32479: new_op("::",MEM);
32480: new_op("type name",TYPE);
32481: new_op("tname",TNAME);
32482: new_op("{}",BLOCK);
32483: new_op("pair",PAIR);
32484: new_op("declaration",DCL);
32485: new_op("character constant",CCON);
32486: new_op("integer constant",ICON);
32487: new_op("float constant",FCON);
32488: new_op("integer value",IVAL);
32489: new_op("string",STRING);
32490: new_op("label",LABEL);
32491: new_op("'class', 'struct', or 'union'",AGGR);
32492: new_op(" argument",ARG);
32493: new_op(" empty expression",DUMMY);
32494: new_op(" ::new",GNEW);
32495: new_op(" constructor call",VALUE);
32496: new_op(" ::delete",GDELETE);
32497: new_op(ansi_opt?" long double":" double",LDOUBLE);
32498: new_op(" typedef",NESTED); // did not want to introduce new TOKEN
32499: }
32500: 0707071010112044431004440001630000160000010206400466055407500001000000067265simpl.c /*ident "@(#)ctrans:src/simpl.c 1.3" */
32501: /******************************************************************
32502:
32503: C++ source for cfront, the C++ compiler front-end
32504: written in the computer science research center of Bell Labs
32505:
32506: Copyright (c) 1984 AT&T, Inc. All rights Reserved
32507: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
32508:
32509: simpl.c:
32510:
32511: simplify the typechecked function
32512: remove: classes:
32513: class fct-calls
32514: operators
32515: value constructors and destructors
32516: new and delete operators (replace with function calls)
32517: initializers (turn them into statements)
32518: constant expressions (evaluate them)
32519: inline functions (expand the calls)
32520: enums (make const ints)
32521: unreachable code (delete it)
32522: make implicit coersions explicit
32523:
32524: in general you cannot simplify something twice
32525:
32526: *******************************************************************/
32527:
32528: #include "cfront.h"
32529:
32530: Pname new_fct;
32531: Pname del_fct;
32532: Pname vec_new_fct;
32533: Pname vec_del_fct;
32534:
32535: Pstmt del_list;
32536: Pstmt break_del_list;
32537: Pstmt continue_del_list;
32538:
32539: //bit not_inl; // is the current function an inline?
32540: Pname curr_fct; // current function
32541: Pexpr init_list;
32542: Pexpr one;
32543:
32544: Ptype Pfct_type;
32545: Ptype Pvptr_type;
32546: Pbase mptr_type;
32547: Ptype size_t_type;
32548:
32549: Pstmt trim_tail(Pstmt tt);
32550: Pname find_vptr(Pclass);
32551: char *get_classname(char*);
32552: char *drop_classname(char*);
32553: loc no_where; // 0,0
32554:
32555: int imeasure; // a counter trying to measure the complexity of a function
32556: // body to try to avoid expanding ``monster'' inlines.
32557:
32558: static Pclass topclass;
32559:
32560: void simpl_init()
32561: {
32562: char* ns = oper_name(NEW);
32563: char* ds = oper_name(DELETE);
32564:
32565: size_t_type = Pvoid_type->tsizeof()>uint_type->tsizeof()?ulong_type:uint_type;
32566:
32567: Pname nw = new name(ns);
32568: nw->n_oper = NEW;
32569: Pname a = new name;
32570: a->tp = size_t_type;
32571: nw->tp = new fct(Pvoid_type,a,1);
32572: new_fct = nw->dcl(gtbl,EXTERN); // void* operator new(long);
32573: delete nw;
32574: // new_fct->use();
32575:
32576: Pname dl = new name(ds);
32577: dl->n_oper = DELETE;
32578: a = new name;
32579: a->tp = Pvoid_type;
32580: dl->tp = new fct(void_type,a,1);
32581: del_fct = dl->dcl(gtbl,EXTERN);
32582: delete dl;
32583: // del_fct->use();
32584:
32585:
32586: Pname vn = new name("__vec_new");
32587: Pname vd = new name("__vec_delete");
32588:
32589: a = new name;
32590: a->tp = Pvoid_type;
32591: Pname al = a;
32592: a = new name;
32593: a->tp = int_type;
32594: a->n_list = al;
32595: al = a;
32596: a = new name;
32597: a->tp = int_type;
32598: a->n_list = al;
32599: al = a;
32600: a = new name;
32601: a->tp = Pvoid_type;
32602: a->n_list = al;
32603: al = a; /* (Pvoid, int, int, Pvoid) */
32604:
32605: vec_new_fct = gtbl->insert(vn,0);
32606: delete vn;
32607: vec_new_fct->tp = new fct(Pvoid_type,al,1);
32608: Pfct(vec_new_fct->tp)->f_linkage = linkage_C;
32609: vec_new_fct->n_scope = EXTERN;
32610: PERM(vec_new_fct);
32611: PERM(vec_new_fct->tp);
32612: vec_new_fct->use();
32613: vec_new_fct->dcl_print(0);
32614:
32615: a = new name;
32616: a->tp = int_type;
32617: al = a;
32618: a = new name;
32619: a->tp = int_type;
32620: a->n_list = al;
32621: al = a;
32622: a = new name;
32623: a->tp = Pvoid_type;
32624: a->n_list = al;
32625: al = a;
32626: a = new name;
32627: a->tp = int_type;
32628: a->n_list = al;
32629: al = a;
32630: a = new name;
32631: a->tp = int_type;
32632: a->n_list = al;
32633: al = a;
32634: a = new name;
32635: a->tp = Pvoid_type;
32636: a->n_list = al;
32637: al = a; /* (Pvoid, int, int, Pvoid, int, int) */
32638:
32639: vec_del_fct = gtbl->insert(vd,0);
32640: delete vd;
32641: vec_del_fct->tp = new fct(void_type,al,1);
32642: Pfct(vec_del_fct->tp)->f_linkage = linkage_C;
32643: vec_del_fct->n_scope = EXTERN;
32644: PERM(vec_del_fct);
32645: PERM(vec_del_fct->tp);
32646: vec_del_fct->use();
32647: vec_del_fct->dcl_print(0);
32648:
32649: one = new ival(1);
32650: one->tp = int_type;
32651: PERM(one);
32652:
32653: Pfct_type = new fct(int_type,0,1); // int (*)()
32654: Pfct_type = Pfct_type->addrof();
32655: PERM(Pfct_type);
32656:
32657: putstring("typedef int (*__vptp)();\n");
32658: putstring("struct __mptr {short d; short i; __vptp f; };\n");
32659: Pname b = new name("__mptr");
32660: b->tp = new classdef(STRUCT);
32661: b->tp->defined = 1;
32662: Pclass(b->tp)->obj_size = 8;
32663: mptr_type = new basetype(COBJ,b);
32664: PERM(mptr_type);
32665:
32666: Pvptr_type = mptr_type->addrof();
32667: PERM(Pvptr_type);
32668: }
32669:
32670: Ptable scope; /* current scope for simpl() */
32671: Pname expand_fn; /* name of function being expanded or 0 */
32672: Ptable expand_tbl; /* scope for inline function variables */
32673:
32674: Pname classdef::has_oper(TOK op)
32675: {
32676: Pexpr n = find_name(oper_name(op),0);
32677: if (n == 0) return 0;
32678:
32679: while (n->base==REF || n->base==MDOT) {
32680: Pexpr e = Pexpr(n);
32681: n = Pname(n->mem);
32682: delete e;
32683: }
32684: if (n->tp->base==FCT && Pname(n)->n_dcl_printed==0) Pname(n)->dcl_print(0);
32685: return Pname(n);
32686: }
32687:
32688: int is_expr(Pstmt s)
32689: /*
32690: is this statement simple enough to be converted into an expression for
32691: inline expansion?
32692: */
32693: {
32694: int i = 0;
32695: while (s->base == BLOCK) {
32696: if (s->s == 0) return 1;
32697: s = s->s;
32698: }
32699: for (Pstmt ss = s; ss; ss = ss->s_list) {
32700: //error('d',"ss %k",ss->base);
32701: switch (ss->base) {
32702: case BLOCK:
32703: if (Pblock(ss)->memtbl || is_expr(ss->s)==0) return 0;
32704: case SM:
32705: if (ss->e && ss->e->base==ICALL) {
32706: Pname fn = ss->e->il->fct_name;
32707: Pfct f = Pfct(fn->tp);
32708: if (f->f_expr == 0) return 0;
32709: }
32710: break;
32711: case IF:
32712: if (is_expr(ss->s)==0) return 0;
32713: if (ss->else_stmt && is_expr(ss->else_stmt)==0) return 0;
32714: break;
32715: default:
32716: return 0;
32717: }
32718: i++;
32719: }
32720: return i;
32721: }
32722:
32723: int no_of_returns;
32724:
32725: void name::simpl()
32726: {
32727: //error('d',"name::simpl%n %d %k",this,tp->base,tp->base);
32728: if (base == PUBLIC) return;
32729:
32730: if (tp == 0) error('i',"%n->N::simple(tp==0)",this);
32731:
32732: switch (tp->base) {
32733: case 0:
32734: error('i',"%n->N::simpl(tp->B==0)",this);
32735:
32736: case TYPE:
32737: case VEC:
32738: case PTR:
32739: {
32740: Ptype t = tp;
32741: xx:
32742: switch (t->base) {
32743: case TYPE: t = Pbase(t)->b_name->tp; goto xx;
32744: case VEC: t = Pvec(t)->typ; goto xx;
32745: case PTR: t = Pptr(t)->typ; goto xx;
32746: case FCT: break;
32747: }
32748: break;
32749: }
32750:
32751: case OVERLOAD:
32752: { for (Plist gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl();
32753: break;
32754: }
32755:
32756: case FCT:
32757: { Pfct f = Pfct(tp);
32758: Pname n;
32759: Pname th = f->f_this;
32760:
32761: if (th) {
32762: // Make "this" a register if it is used more than twice:
32763: if (th->n_addr_taken) error("&this");
32764: th->n_stclass = (2 < th->n_used) ? REGISTER : AUTO;
32765: if (warning_opt
32766: && th->n_assigned_to
32767: && th->n_assigned_to!=FUDGE111)
32768: error('w',&where,"assignment to this (anachronism)");
32769: }
32770:
32771: if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return;
32772:
32773: for (n=f->f_args; n; n=n->n_list) n->simpl();
32774:
32775: if (f->body) {
32776: Ptable oscope = scope;
32777: Pname ocurr = curr_fct;
32778: int oim = imeasure;
32779: scope = f->body->memtbl;
32780: //error('d',"body");
32781: if (scope == 0) error('i',"%n memtbl missing",this);
32782: curr_fct = this;
32783: f->simpl();
32784: if (f->f_inline==0 || debug_opt)
32785: f->f_imeasure = 0; // not a converted inline
32786: else {
32787:
32788: if (warning_opt && f->f_virtual)
32789: error('w',"virtual function %n cannot be inlined",this);
32790: // first check if the function is too large to
32791: // be worth inlining
32792: if (12<f->f_imeasure) { // cut-over point:
32793: // about 12 assignments
32794: // f->f_imeasure indicates
32795:
32796: if (warning_opt) {
32797: error('w',"%n too large for inlining",this);
32798: }
32799: f->f_inline = 0;// a converted inline
32800: //error('d',"don't inline%n %d %d %d",this,this,f,f->f_imeasure);
32801: scope = oscope;
32802: tp->defined |= SIMPLIFIED;
32803: return;
32804: }
32805: int i = 0;
32806: for (n=f->f_args; n; n=n->n_list) {
32807: n->base = ANAME;
32808: n->n_val = i++;
32809: // ?? if (n->n_table != scope) error('i',"aname scope: %d %n %d %d\n",n,n,n->n_table,scope);
32810: }
32811: expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0;
32812: expand_fn = this;
32813:
32814: if (expand_tbl) {
32815: genlab:
32816: // value returning: generate expr
32817: // the body still holds the memtbl
32818: Pexpr ee = Pexpr(f->body->expand());
32819: Ptype t = 0;
32820: if (f->s_returns) {
32821: if (ee->tp!=f->s_returns) t = f->s_returns;
32822: }
32823: else if (ee->tp!=f->returns)
32824: t = f->returns;
32825: // VCVC assumes VOID is output as CHAR:
32826: if (t && t==void_type)
32827: ee = new expr(CM,ee,new cast(char_type,zero));
32828: f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee);
32829: // print.c assumes expansion into comma expression
32830: }
32831: else {
32832: if (is_expr(f->body)) {
32833: // can generate expr: do
32834: expand_tbl = scope;
32835: goto genlab;
32836: }
32837: // not value return: can generate block
32838: f->f_expr = 0;
32839: f->body = Pblock(f->body->expand());
32840: }
32841: expand_fn = 0;
32842: expand_tbl = 0;
32843: }
32844: scope = oscope;
32845: curr_fct = ocurr;
32846: imeasure = oim;
32847: }
32848: break;
32849: }
32850:
32851: case CLASS:
32852: Pclass(tp)->simpl();
32853: }
32854:
32855: // if (n_initializer) n_initializer->simpl();
32856: if (n_key != NESTED && n_initializer) n_initializer->simpl();
32857: tp->defined |= SIMPLIFIED;
32858: }
32859:
32860: Pexpr call_ctor(Ptable tbl, Pexpr p, Pexpr ctor, Pexpr args, int d, Pexpr vb_args)
32861: {
32862: Pexpr ee = new ref(d,p,ctor);
32863: if (p==0 || tbl==0) ee->tp = ctor->tp;
32864: //error('d',"call_ctor(tbl %d, p %d, %n, args %d)",tbl,p,ctor,args);
32865: if (args && args->base!=ELIST) args = new expr(ELIST,args,0);
32866: ee = new expr(G_CALL,ee,args);
32867: Pname n = Pname(ctor);
32868: while (n->base == MDOT) n = Pname(n->mem);
32869: if (n->tp->base == FCT) ee->fct_name = n;
32870: if (tbl)
32871: ee = ee->typ(tbl);
32872: else if (n->tp->base == FCT)
32873: ee->tp = Pfct(n->tp)->s_returns;
32874: if (ee->tp == any_type) return ee;
32875: args = ee->e2;
32876:
32877: if (vb_args == 0) { // attach zero vbase arguments
32878: Pfct f = Pfct(ee->fct_name->tp); // not n->fct_name
32879: for (Pname nn = f->f_args->n_list; nn && nn!=f->argtype; nn=nn->n_list)
32880: args = new expr(ELIST,zero,args);
32881: }
32882: else { // attach vbase arguments
32883: if (args) {
32884: for (Pexpr d = vb_args; d->e2; d=d->e2);
32885: d->e2 = args;
32886: }
32887: args = vb_args;
32888: }
32889:
32890: ee->e2 = args;
32891: return ee;
32892: }
32893:
32894: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg, int d, Pexpr vb_args)
32895: {
32896: // error('d',"call dtor %k %n %t vb_args %d",d,dtor,dtor->tp,vb_args);
32897: Pexpr r = new ref(d,p,dtor);
32898:
32899: if (arg && vb_args)
32900: arg = new ival(3);
32901: else if (vb_args)
32902: arg = new ival(2);
32903: else if (arg==0)
32904: arg = zero;
32905: if (arg->tp == 0) arg->tp = int_type;
32906:
32907: Pexpr aa = new expr(ELIST,arg,0); // argument controlling deallocation
32908: // 2: destroy vbases
32909: // 1: dealllocate, 0: don't
32910:
32911: Pfct f = Pfct(dtor->tp); // attach virtual base arguments
32912: // for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) {
32913: // Pexpr xx = vb_args ? new cast(nn->tp,one) : zero;
32914: // aa = new expr(ELIST,xx,aa);
32915: // }
32916:
32917:
32918: Pexpr ee = new call(r,aa);
32919: while (dtor->base == MDOT) dtor = dtor->mem;
32920: if (d == REF) // could be virtual
32921: ee->fct_name = Pname(dtor);
32922: else { // virtual suppressed, store fct name
32923: r->n_initializer = dtor;
32924: ee->fct_name = 0;
32925: }
32926: ee->base = G_CALL;
32927: ee->tp = void_type;
32928:
32929: if (f->memof->c_body == 1) f->memof->dcl_print(0);
32930: if (Pname(dtor)->n_dcl_printed==0) Pname(dtor)->dcl_print(0);
32931:
32932: return ee;
32933: }
32934:
32935: //extern int new_used; // pre-define new and delete only if the user didn't
32936:
32937: Pstmt fct::dtor_simpl(Pclass cl, Pexpr th)
32938: {
32939: Pstmt dtail = 0;
32940: //error('d',"simpl_dtor(%t) a %d",cl,f_args);
32941: // if (new_used == 0) new_init();
32942:
32943: Pname fa = new name("__free"); // fake argument for dtor
32944: fa->tp = int_type;
32945: Pname free_arg = fa->dcl(body->memtbl,ARG);
32946: free_arg->where = no_where;
32947: delete fa;
32948: Pname a = f_args;
32949: if (a==0 || a->n_list==0) error('i',"__freeA missing in destructor for %t",cl);
32950: Pname p = 0;
32951: for(;;p=a,a=a->n_list) { // replace nameless fake argument
32952: //error('d',"a %d %t",a,a->tp);
32953: if (a->n_list == 0) {
32954: // a->n_list = free_arg;
32955: DEL(p->n_list);
32956: p->n_list = free_arg;
32957: break;
32958: }
32959: }
32960:
32961: // generate calls to destructors for all members of class cl:
32962: Ptable tbl = cl->memtbl;
32963: int i = 1;
32964: for (Pname m=tbl->get_mem(i); m; m=tbl->get_mem(++i) ) {
32965:
32966: if (m->n_stclass == STATIC || m->base == PUBLIC) continue;
32967:
32968: Ptype t = m->tp;
32969: Pexpr ee = 0;
32970: Pname cn;
32971: Pname dtor;
32972:
32973: if (cn = t->is_cl_obj()) {
32974: Pclass cl = (Pclass)cn->tp;
32975: if (dtor = cl->has_dtor()) { // dtor(this,0,ones);
32976: ee = new ref(REF,th,m);
32977: ee->tp = m->tp;
32978: ee = call_dtor(ee,dtor,0,DOT,one);
32979: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
32980: }
32981: }
32982: else if (cl_obj_vec) {
32983: Pclass cl = Pclass(cl_obj_vec->tp);
32984: if (dtor = cl->has_dtor()) {
32985: Pfct f = Pfct(dtor->tp);
32986: int i = 0;
32987: for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++;
32988: //error('d',"dtor %n i %d",dtor,i);
32989: ee = new ref(REF,th,m);
32990: ee->tp = m->tp;
32991: ee = cdvec(vec_del_fct,ee,cl,dtor,0,new ival(i));
32992: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
32993: }
32994: }
32995:
32996: if (ee) {
32997: Pstmt es = new estmt(SM,curloc,ee,0);
32998: // reverse order of destructors for members
32999: es->s_list = del_list;
33000: del_list = es;
33001: if (dtail == 0) dtail = es;
33002: }
33003: }
33004:
33005:
33006: Pexpr ee = 0;
33007: // look for bases with destructors:
33008: // generate: dtor(base,0);
33009:
33010: Pbcl b = 0; // get dtors in order with virtual bases last
33011: Pbcl t = 0;
33012: for (Pbcl l = cl->baselist; l; l=l->next) {
33013: if (l->base != VIRTUAL) {
33014: Pbcl x = new basecl(l->bclass,0);
33015: if (t == 0)
33016: b = x;
33017: else
33018: t->next = x;
33019: t = x;
33020: x->base = l->base;
33021: x->obj_offset = l->obj_offset;
33022: }
33023: }
33024: for (l = cl->baselist; l; l=l->next) {
33025: if (l->base == VIRTUAL) {
33026: b = new basecl(l->bclass,b);
33027: b->base = l->base;
33028: b->obj_offset = l->obj_offset;
33029: }
33030: }
33031: Pexpr ve = 0;
33032:
33033: for (; b; b=l) {
33034: Pclass bcl = b->bclass;
33035: l = b->next;
33036: Pname dtor = bcl->has_dtor();
33037:
33038: if (dtor) {
33039: Pexpr val = rptr(bcl->this_type,th,b->obj_offset);
33040: val = val->contents();
33041: Pexpr e = call_dtor(val,dtor);
33042: if (b->base == VIRTUAL) {
33043: // if (x) this->x.dtor(); where x is a vbase
33044: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list)
33045: if (strcmp(dd->string,bcl->string)==0) break;
33046:
33047: if (ansi_opt) { // q?void:int would be an error
33048: e = new expr(G_CM,e,zero);
33049: e->tp = zero_type;
33050: }
33051: e = new expr(QUEST,e,zero);
33052: Pexpr two = new ival(2);
33053: two->tp = int_type;
33054: e->cond = new expr (AND,free_arg,two);//dd;
33055: }
33056: ee = ee ? new expr(CM,e,ee) : e;
33057: }
33058: delete b;
33059: }
33060:
33061: Pstmt es = ee ? new estmt(SM,curloc,ee,0) : 0;
33062:
33063: ee = new expr(ELIST,th,0); // free storage
33064: Pname n = new name(oper_name(DELETE));
33065: Pexpr del = find_name(n,cl,scope,CALL,curr_fct);
33066: if (del->tp->base==OVERLOAD || Pfct(del->tp)->nargs==2) {
33067: Pexpr ss = new texpr(SIZEOF,cl,0);
33068: ss->tp = uint_type;
33069: ee->e2 = new expr(ELIST,ss,0);
33070: }
33071: ee = new call(del,ee);
33072: ee->tp = ee->call_fct(scope);
33073:
33074: Pstmt ess = new estmt(SM,curloc,ee,0);
33075: ess = new ifstmt(curloc,new expr(AND,free_arg,one),ess,0);
33076: if (es)
33077: es->s_list = ess;
33078: else
33079: es = ess;
33080:
33081: free_arg->use();
33082: Pname(th)->use();
33083:
33084: if (dtail)
33085: dtail->s_list = es;
33086: else
33087: del_list = es;
33088:
33089: del_list = new ifstmt(curloc,th,del_list,0);
33090: if (del_list) del_list->simpl();
33091: return dtail;
33092: }
33093:
33094:
33095: Pclass find_vbase_ptr(Pclass cl, Pclass vbase)
33096: {
33097: for (Pbcl bb = cl->baselist; bb; bb = bb->next) {
33098: if (bb->base==VIRTUAL) {
33099: if (bb->bclass==vbase && bb->ptr_offset) return cl;
33100: }
33101: else {
33102: Pclass f = find_vbase_ptr(bb->bclass,vbase);
33103: if (f) return f;
33104: }
33105: }
33106: return 0;
33107: }
33108:
33109: Pclass second_base(Pclass cl, Pclass base)
33110: {
33111: //error('d',"second_base(%t,%t)",cl,base);
33112: for (Pbcl b = cl->baselist; b && b->base==NAME; b = b->next) {
33113: if (b->bclass==base) {
33114: if (b==cl->baselist) return 0;
33115: return base;
33116: }
33117: Pclass bb = second_base(b->bclass,base);
33118: if (bb == Pclass(-1)) continue; // not found
33119: if (bb) {
33120: if (b!=cl->baselist) error('s',"C hierarchy too complicated");
33121: return bb; // second base of b->bclass
33122: }
33123: if (b==cl->baselist) return 0;
33124: return b->bclass; // b->bclass is second base
33125: }
33126: return Pclass(-1);
33127: }
33128:
33129: //Pclass topclass;
33130:
33131: Pexpr classdef::get_vptr_exp(char *s)
33132: {
33133: //error('d',"%t::get_vptr_exp(%s)",this,s?s:"0");
33134: if (c_body == 1) dcl_print(0);
33135: if (c_body == 3) print_all_vtbls(this);
33136: if (s == 0) return find_vptr(this);
33137: Pbcl b = get_base(get_classname(s));
33138: Pexpr vp = b->bclass->get_vptr_exp(drop_classname(s));
33139: if (b==baselist && b->base!=VIRTUAL) return vp;
33140: vp = new mdot(b->bclass->string,vp);
33141: if (c_body == 1) b->bclass->dcl_print(0);
33142: if (c_body == 3) b->bclass->print_all_vtbls(b->bclass);
33143: if (b->base == VIRTUAL) {
33144: vp->i1 = 1;
33145: if (b->ptr_offset == 0) { // pointer to base in intermediate base
33146: Pclass bb = find_vbase_ptr(this,b->bclass);
33147: Pclass sb = second_base(topclass,bb);
33148: //error('d',"mdot %t %t : %d %t ",topclass,bb,sb,sb==Pclass(-1)?0:sb);
33149: if (sb && sb!=Pclass(-1)) vp = new mdot(sb->string,vp);
33150: }
33151: }
33152: return vp;
33153: }
33154:
33155: int fct::ctor_simpl(Pclass cl, Pexpr th)
33156: {
33157: Ptable tbl = cl->memtbl;
33158:
33159: int ass_count = 0;
33160: init_list = 0;
33161: //error('d',"ctor_simpl %t: %t",cl,this);
33162: /*
33163: initialization order:
33164: (1) virtual base pointers and virtual bases
33165: (they may be used in non-virtual bases)
33166: (2) non-virtual bases
33167: (3) virtual function pointers
33168: (4) members
33169: */
33170:
33171: // initialize virtual base pointers and virtual base objects
33172: for (Pbcl l = cl->baselist; l; l=l->next) {
33173: Pexpr i = l->init;
33174: if (l->base != VIRTUAL) continue;
33175: l->init = 0;
33176: //error('d',"simpl virtual base %t i %d ",l->bclass,i);
33177:
33178: // assign virtual OP to virtual base AP
33179: Pclass bc = l->bclass;
33180: Pexpr dp = 0;
33181:
33182: // dd = pointer argument for this base;
33183: // non-zero if already initialized
33184: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list)
33185: if (strcmp(dd->string,bc->string)==0) break;
33186:
33187: // initialize virtual base object
33188: //error('d',"bc %t dd %n offset %d init %d",bc,dd,l->obj_offset,l->init);
33189: // => bc_arg = (bc*)((char*)this+offset)
33190: int off = l->obj_offset;
33191: Pexpr val = rptr(bc->this_type,th,off);
33192: dp = new expr(ASSIGN,dd,val);
33193: dd->assign();
33194:
33195: // => bc::bc()
33196: if (i) {
33197: switch (i->base) {
33198: case ASSIGN:
33199: case CM:
33200: break;
33201: case CALL:
33202: case G_CALL:
33203: { Pcall cc = Pcall(i);
33204: Pname bn = cc->fct_name;
33205: ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
33206: cc->simpl();
33207: break;
33208: }
33209: default:
33210: error('i',"badBCIr %k",i->base);
33211: }
33212: dp = new expr(CM,dp,i);
33213: }
33214:
33215: // => (bc_arg==0)?dp:bc_arg
33216: for (Pname a = f_args->n_list; a; a = a->n_list)
33217: if (strcmp(bc->string,a->string)==0) {
33218: dp = new expr(QUEST,dp,a);
33219: dp->cond = new expr(EQ,a,zero);
33220: break;
33221: }
33222:
33223: // Pname dpp = find_vbase_ptr(bc,cl);
33224: for (Pbcl ll=cl->baselist; ll; ll=ll->next) {
33225: if (ll->bclass==bc && ll->ptr_offset) {
33226: // make sure that the delegate_arg is needed
33227: // here and not just in a base
33228:
33229: // this->Pd = (bc_arg==0)?dp:bc_arg
33230: Pexpr dpp = new mdot(bc->string,th);
33231: dpp->i1 = 3;
33232: dp = new expr(ASSIGN,dpp,dp);
33233: //error('d',"dpp %n",dpp);
33234: break;
33235: }
33236: }
33237:
33238: // reverse init order
33239: if (dp) init_list = init_list ? new expr(CM,dp,init_list) : dp;
33240: }
33241:
33242: // generate: this=base::base(args) (non-virtual bases)
33243: {
33244: for (Pbcl l = cl->baselist; l; l=l->next) {
33245: Pexpr i = l->init;
33246: if (i==0 || l->base==VIRTUAL) continue;
33247: //error('d',"simpl base %t i %d ",l->bclass,i);
33248: l->init = 0;
33249:
33250: switch (i->base) {
33251: case ASSIGN:
33252: case CM:
33253: break;
33254: case CALL:
33255: case G_CALL:
33256: { Pcall cc = Pcall(i);
33257: Pname bn = cc->fct_name;
33258: ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
33259: cc->simpl();
33260: // assign to ``this'' only from only base
33261: if (l==cl->baselist && cl->baselist->next==0) i = new expr(ASSIGN,th,cc);
33262: break;
33263: }
33264: default:
33265: error('i',"badBCIr %k",i->base);
33266: }
33267:
33268: init_list = init_list ? new expr(G_CM,init_list,i) : i;
33269: }
33270: }
33271:
33272: // initialize the vptrs that are updated by this class
33273: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
33274: // if (blist->string==0 && find_vptr(cl)==0) { //opt
33275: //error('d',"!!!vptr init %s in %s",blist->string,cl->string);
33276: // continue;
33277: // }
33278: //error('d',"vptr init %s in %s",blist->string,cl->string);
33279: topclass = cl;
33280: Pexpr vp = cl->get_vptr_exp(blist->string);
33281:
33282: char *str = 0;
33283: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
33284: if (cl->lex_level && cl->nested_sig==0) str = make_local_name( cl );
33285: Pexpr vtbl = new text_expr(blist->string,str?str:cs);
33286: //Pexpr vtbl = new text_expr(blist->string,cl->string);
33287: // vtbl = new cast(Pvptr_type,vtbl);
33288:
33289: Pexpr ee = new ref(REF,th,vp);
33290: ee->tp = vp->tp;
33291: ee = new expr(ASSIGN,ee,vtbl);
33292: init_list = init_list ? new expr(CM,init_list,ee) : ee;
33293: }
33294:
33295: // initialize members in declaration order:
33296: int i;
33297: for (Pname m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) {
33298: Ptype t = m->tp;
33299: Pname cn;
33300: Pname ctor;
33301: if (t == 0) continue;
33302:
33303: switch (t->base) {
33304: case FCT:
33305: case OVERLOAD:
33306: case CLASS:
33307: case ENUM:
33308: continue;
33309: }
33310:
33311: switch (m->n_stclass) {
33312: case STATIC:
33313: case ENUM:
33314: continue;
33315: }
33316:
33317: if (m->base == PUBLIC) continue;
33318:
33319: Pexpr ee = m->n_initializer;
33320: if (ee) m->n_initializer = 0; // from fct must not persist until next fct
33321: //error('d',"simpl m %n ee %d",m,ee);
33322: if (ee) {
33323: // init of non-class mem
33324: // set in fct::mem_init()
33325: }
33326: else if (cn=t->is_cl_obj()) { // try for default
33327: Pclass cl = Pclass(cn->tp);
33328: if (ctor = cl->has_ictor()) {
33329: Pexpr r = new ref(REF,th,m);
33330: ee = call_ctor(tbl,r,ctor,0,DOT);
33331: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
33332: }
33333: else if (cl->has_ctor()) {
33334: error("M%n needsIr (no defaultK forC %s)",m,cl->string);
33335: }
33336: }
33337: else if (cl_obj_vec) {
33338: Pclass cl = Pclass(cl_obj_vec->tp);
33339: if (ctor = cl->has_ictor()) { // _new_vec(vec,noe,sz,ctor);
33340: Pexpr mm = new ref(REF,th,m);
33341: mm->tp = m->tp;
33342: ee = cdvec(vec_new_fct,mm,cl,ctor,-1,0);
33343: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
33344: }
33345: else if (cl->has_ctor()) {
33346: error("M%n[] needsIr (no defaultK forC %s)",m,cl->string);
33347: }
33348: }
33349: else if (t->is_ref()) {
33350: error("RM%n needsIr",m);
33351: }
33352: else if (t->tconst() && vec_const==0) {
33353: error("constM%n needsIr",m);
33354: }
33355:
33356: if (ee) {
33357: ee->simpl();
33358: init_list = init_list ? new expr(CM,init_list,ee) : ee;
33359: }
33360: } // for m
33361: //error('d',"ctor->");
33362: return ass_count;
33363: }
33364:
33365: void fct::simpl()
33366: /*
33367: call only for the function definition (body != 0)
33368:
33369: simplify argument initializers, and base class initializer, if any
33370: then simplify the body, if any
33371:
33372: for constructor:call allocator if this==0 and this not assigned to
33373: (auto and static objects call constructor with this!=0,
33374: the new operator generates calls with this==0)
33375: call base & member constructors
33376: for destructor: call deallocator (no effect if this==0)
33377: case base & member destructors
33378:
33379: for arguments and function return values look for class objects
33380: that must be passed by constructor X(X&).
33381:
33382: Allocate temporaries for class object expressions, and see if
33383: class object return values can be passed as pointers.
33384:
33385: call constructor and destructor for local class variables.
33386: */
33387: {
33388: Pexpr th = f_this;
33389: Ptable tbl = body->memtbl;
33390: Pstmt ss = 0;
33391: Pstmt tail;
33392: Pclass cl = th ? Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp) : 0;
33393: Pstmt dtail = 0;
33394:
33395: Pname ocurr_fct = curr_fct;
33396: int oret = no_of_returns;
33397: int oim = imeasure;
33398:
33399: //error('d',"fct::simpl %n %t",curr_fct,this);
33400: // not_inl = f_inline==0;
33401: del_list = 0;
33402: continue_del_list = 0;
33403: break_del_list = 0;
33404: scope = tbl;
33405: if (scope == 0) error('i',"F::simpl()");
33406: int ass_count = 0;
33407: imeasure = 0;
33408: no_of_returns = 0;
33409:
33410: cc->stack();
33411: cc->nof = curr_fct;
33412: cc->ftbl = tbl;
33413:
33414: // modification for local classes defined within inline functions
33415: // error( 'd', "simpl local_class: %d", local_class );
33416: for ( Plist l = local_class; l; l = l->l ) {
33417: Pname n = l->f;
33418: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
33419: if ( cl->in_fct == 0 ) cl->in_fct = cc->nof;
33420: if ( cl->lcl == 0 ) cl->lcl = make_name( 'L' );
33421: if ( cl->c_body == 1 ) cl->dcl_print(0);
33422: }
33423:
33424: Pfct(cc->nof->tp)->local_class = local_class;
33425: local_class = 0;
33426: // error( 'd', "simpl nof: %n %d local_class: %d", cc->nof, cc->nof, Pfct(cc->nof->tp)->local_class );
33427:
33428: switch (curr_fct->n_scope) {
33429: case 0:
33430: case PUBLIC:
33431: cc->not = curr_fct->n_table->t_name;
33432: cc->cot = Pclass(cc->not->tp);
33433: cc->tot = cc->cot->this_type;
33434: }
33435:
33436: switch (curr_fct->n_oper) {
33437: case DTOR:
33438: dtail = dtor_simpl(cl,th);
33439: break;
33440: case CTOR:
33441: ass_count = ctor_simpl(cl,th);
33442: }
33443:
33444: tail = body->simpl();
33445:
33446: if (returns->base!=VOID || f_result) { // return must have been seen
33447: if (no_of_returns) { // could be OK
33448: Pstmt tt = (tail->base==RETURN || tail->base==LABEL) ? tail : trim_tail(tail);
33449:
33450: switch (tt->base) {
33451: case RETURN:
33452: case GOTO:
33453: del_list = 0; // no need for del_list
33454: break;
33455: case SM:
33456: if (tt->e)
33457: switch (tt->e->base) {
33458: case ICALL:
33459: case G_CALL:
33460: goto chicken;
33461: }
33462: default:
33463: if (warning_opt || strcmp(curr_fct->string,"main"))
33464: error('w',"maybe no value returned from%n",curr_fct);
33465: case IF:
33466: case SWITCH:
33467: case DO:
33468: case WHILE:
33469: case FOR:
33470: case LABEL:
33471: chicken: // don't dare write a warning
33472: break;
33473: }
33474: }
33475: else { // must be an error
33476: // but we don't dare complain about main()
33477: // if (strcmp(curr_fct->string,"main"))
33478: // error(Pfct(curr_fct->tp)->returns->is_cl_obj()?0:'w',"no value returned from%n",curr_fct);
33479: // else if (warning_opt)
33480: // error('w',"no value returned from%n",curr_fct);
33481: if (Pfct(curr_fct->tp)->f_inline
33482: && Pfct(curr_fct->tp)->returns!=void_type
33483: && Pfct(curr_fct->tp)->returns->is_cl_obj())
33484: // can cause code generation errors if allowed
33485: error("no value returned from%n",curr_fct);
33486: else if (warning_opt || strcmp(curr_fct->string,"main"))
33487: error('w',"no value returned from%n",curr_fct);
33488: }
33489: if (del_list) goto zaq;
33490: }
33491: else if (del_list) { // return may not have been seen
33492: zaq:
33493: if (tail)
33494: tail->s_list = del_list;
33495: else
33496: body->s = del_list;
33497: tail = dtail;
33498: }
33499:
33500: if (curr_fct->n_oper == DTOR) { // body => if (this == 0) body
33501:
33502: // reset the vptrs that were set by this class
33503: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
33504: //error('d',"vptr init %s in %s",blist->string,cl->string);
33505: topclass = cl;
33506: Pexpr vp = cl->get_vptr_exp(blist->string);
33507:
33508: char *str = 0;
33509: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
33510: if (cl->lex_level && cl->nested_sig==0) str = make_local_name(cl);
33511: Pexpr vtbl = new text_expr(blist->string,str?str:cs);
33512:
33513: Pexpr ee = new ref(REF,th,vp);
33514: ee->tp = vp->tp;
33515: ee = new expr(ASSIGN,ee,vtbl);
33516: Pstmt es = new estmt(SM,curloc,ee,0);
33517: es->s_list = body->s;
33518: body->s = es;
33519: }
33520:
33521: body->s = new ifstmt(body->where,th,body->s,0);
33522: }
33523:
33524: if (curr_fct->n_oper == CTOR) {
33525:
33526: loc temploc=body->where;
33527: Pstmt tempss=body->s;
33528: while (tempss) {
33529: temploc=tempss->where;
33530: tempss=tempss->s_list;
33531: }
33532:
33533: if (Pname(th)->n_assigned_to == 0) {
33534: /* generate:
33535: if (this || (this=_new( sizeof(class cl) ))) {
33536: init_list ;
33537: body;
33538: }
33539: */
33540: Pname(th)->n_assigned_to = ass_count ? ass_count : FUDGE111;
33541: Pexpr sz = new texpr(SIZEOF,cl,0);
33542: (void) cl->tsizeof();
33543: sz->tp = uint_type;
33544: Pexpr ee = new expr(ELIST,sz,0);
33545: Pname n = new name(oper_name(NEW));
33546: Pexpr p = find_name(n,cl,scope,CALL,curr_fct);
33547: //error('d',"in ctor %n call %n",curr_fct,p);
33548: ee = new call(p,ee);
33549: (void) ee->call_fct(cl->memtbl);
33550: ee->simpl();
33551: ee = new expr(ASSIGN,th,ee);
33552: ee = new expr(OROR,th,ee);
33553: /*ifs->simpl();
33554: do not simplify
33555: or "this = " will cause an extra call of base::base
33556: */
33557: if (init_list) {
33558: Pstmt es = new estmt(SM,body->where,init_list,0);
33559: es->s_list = body->s;
33560: body->s = es;
33561: // if (tail == 0) tail = es;
33562: }
33563: else if (body->s == 0)
33564: body->s = new estmt(SM,body->where,0,0);
33565: else if(tail->base==RETURN) {
33566: if(body->s == tail) {
33567: delete body->s;
33568: body->s = new estmt(SM,body->where,0,0);
33569: }
33570: else {
33571: Pstmt pr = body->s;
33572: while(pr->s_list != tail)
33573: pr = pr->s_list;
33574: delete pr->s_list;
33575: pr->s_list = 0;
33576: }
33577: }
33578:
33579: ifstmt* ifs = new ifstmt(body->where,ee,body->s,0);
33580: body->s = ifs;
33581: // if (tail == 0)
33582: tail = ifs;
33583: }
33584: // generate: body; return this;
33585: Pstmt st = new estmt(RETURN,temploc,th,0);
33586: if (tail)
33587: tail->s_list = st;
33588: else
33589: body->s = st;
33590: tail = st;
33591: }
33592: f_imeasure = imeasure;
33593: curr_fct = ocurr_fct;
33594: no_of_returns = oret;
33595: imeasure = oim;
33596: cc->unstack();
33597: }
33598:
33599:
33600: void classdef::simpl()
33601: {
33602: int i;
33603: //error('d',"classdef::simpl %s %d",string,defined&SIMPLIFIED);
33604:
33605: if (defined&SIMPLIFIED) return;
33606:
33607: Pclass oc = in_class;
33608: in_class = this;
33609:
33610: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
33611: Pexpr i = m->n_initializer;
33612: m->n_initializer = 0;
33613: m->simpl();
33614: m->n_initializer = i;
33615: }
33616:
33617: in_class = oc;
33618:
33619: for (Plist fl=friend_list; fl; fl=fl->l) { // simplify friends
33620: Pname p = fl->f;
33621: switch (p->tp->base) {
33622: case FCT:
33623: case OVERLOAD:
33624: p->simpl();
33625: }
33626: }
33627:
33628: defined |= SIMPLIFIED;
33629: }
33630: 0707071010112045111004440001630000160000010207100466055410100001100000140465simpl2.c /*ident "@(#)ctrans:src/simpl2.c 1.5" */
33631: /******************************************************************
33632:
33633: C++ source for cfront, the C++ compiler front-end
33634: written in the computer science research center of Bell Labs
33635:
33636: Copyright (c) 1984 AT&T, Inc. All rights Reserved
33637: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
33638:
33639: simpl2.c:
33640:
33641: simplify the typechecked function
33642: remove: classes:
33643: class fct-calls
33644: operators
33645: value constructors and destructors
33646: new and delete operators (replace with function calls)
33647: initializers (turn them into statements)
33648: constant expressions (evaluate them)
33649: inline functions (expand the calls)
33650: enums (make const ints)
33651: unreachable code (delete it)
33652: make implicit coersions explicit
33653:
33654: in general you cannot simplify something twice
33655:
33656: *******************************************************************/
33657:
33658: #include "cfront.h"
33659: #include "size.h"
33660: #include <ctype.h>
33661:
33662: extern Pname Ntmp;
33663: Pname find_vptr(Pclass);
33664:
33665: extern int no_of_returns;
33666:
33667: extern Pname new_fct;
33668: //extern Pname del_fct;
33669:
33670: extern Pstmt del_list;
33671: extern Pstmt break_del_list;
33672: extern Pstmt continue_del_list;
33673:
33674: extern Pname curr_fct; // current function
33675: extern Pexpr init_list;
33676: extern int imeasure;
33677:
33678: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int tail, Pexpr i, Pexpr vec2)
33679: /*
33680: generate a call to construct or destroy the elements of a vector
33681: */
33682: {
33683: Pexpr sz = new texpr(SIZEOF,cl,0); // sizeof elem
33684: sz->tp = uint_type;
33685: (void) cl->tsizeof();
33686:
33687: Pexpr esz = new texpr(SIZEOF,cl,0); // noe = sizeof(vec)/sizeof(elem)
33688: esz->tp = int_type;
33689:
33690: Pexpr noe;
33691: if (vec2) noe = new texpr(SIZEOF,vec2->tp,0);
33692: else noe = new texpr(SIZEOF,vec->tp,0);
33693:
33694: // Pexpr noe = new texpr(SIZEOF,vec->tp,0);
33695: noe->tp = int_type;
33696: noe = new expr(DIV,noe,esz);
33697: noe->tp = uint_type;
33698: // error('d',"cdvec tail %d i %d",tail,i);
33699: // Pexpr arg = (0<=tail) ? new expr(ELIST,zero,0) : 0; // 0 or 1 for dtors
33700: Pexpr arg = (i) ? new expr(ELIST,i,0) : 0;
33701: arg = (0<=tail) ? new expr(ELIST,zero,arg) : arg; // 0 or 1 for dtors
33702: arg = new expr(ELIST,cd,arg); // constructor or destructor
33703: cd->lval(ADDROF); // cd->take_addr();
33704:
33705: arg = new expr(ELIST,sz,arg);
33706: arg = new expr(ELIST,noe,arg);
33707: arg = new expr(ELIST,vec,arg);
33708:
33709: arg = new call(f,arg);
33710: arg->base = G_CALL;
33711: arg->fct_name = f;
33712:
33713: return arg;
33714: }
33715:
33716: /*
33717: int new_used; // pre-define new and delete only if the user didn't
33718:
33719: void new_init()
33720: {
33721: char* ns = oper_name(NEW);
33722: char* ds = oper_name(DELETE);
33723:
33724: new_used = 1;
33725:
33726: new_fct = gtbl->look(ns,0);
33727: del_fct = gtbl->look(ds,0);
33728:
33729: if (new_fct && !del_fct)
33730: error('w',"%n defined but not operator delete()",new_fct);
33731: if (del_fct && !new_fct)
33732: error('w',"%n defined but not operator new()",del_fct);
33733:
33734: if (Pfct(new_fct->tp)->body==0) new_fct->dcl_print(0);
33735: if (Pfct(del_fct->tp)->body==0) del_fct->dcl_print(0);
33736: }
33737: */
33738: Pstmt trim_tail(Pstmt tt)
33739: /*
33740: strip off statements after RETURN etc.
33741: NOT general: used for stripping off spurious destructor calls
33742: */
33743: {
33744: if (tt == 0) return 0;
33745:
33746: while (tt->s_list) {
33747: Pstmt tpx;
33748: switch (tt->base) {
33749: case PAIR:
33750: tpx = trim_tail(tt->s2);
33751: goto tpxl;
33752: case BLOCK:
33753: tpx = trim_tail(tt->s);
33754: tpxl:
33755: if (tpx == 0) return 0;
33756:
33757: switch (tpx->base) {
33758: case SM:
33759: break;
33760: case CONTINUE:
33761: case BREAK:
33762: case GOTO:
33763: case RETURN:
33764: if (tt->s_list->base != LABEL) tt->s_list = 0;
33765: default:
33766: return tpx;
33767: }
33768: default:
33769: if (tt = tt->s_list) break;
33770: return 0;
33771: case RETURN:
33772: if (tt->s_list->base != LABEL) tt->s_list = 0;
33773: return tt;
33774: }
33775: }
33776:
33777: switch (tt->base) {
33778: case PAIR: return trim_tail(tt->s2);
33779: // case LABEL: return trim_tail(tt->s);
33780: case BLOCK: if (tt->s) return trim_tail(tt->s);
33781: default: return tt;
33782: }
33783: }
33784:
33785: extern Ptype Pfct_type;
33786:
33787: Pexpr mptr_assign(Pexpr n, Pexpr in)
33788: {
33789: Pexpr i1;
33790: Pexpr i2;
33791: Pexpr i3;
33792:
33793: if ( n->base == NAME )
33794: Pname(n)->use();
33795:
33796: if (in->base == NAME) {
33797: i1 = new mdot("d",in);
33798: i1->i1 = 9;
33799: i2 = new mdot("i",in);
33800: i2->i1 = 9;
33801: i3 = new mdot("f",in);
33802: i3->i1 = 9;
33803: }
33804: else {
33805: i1 = in->e1->e1;
33806: i2 = in->e1->e2;
33807: i3 = in->e2;
33808: }
33809: Pexpr nd = new mdot("d",n);
33810: nd->i1 = 9;
33811: Pexpr e1 = new expr(ASSIGN,nd,i1);
33812:
33813: Pexpr ni = new mdot("i",n);
33814: ni->i1 = 9;
33815: Pexpr e2 = new expr(ASSIGN,ni,i2);
33816:
33817: Pexpr nf = new mdot("f",n);
33818: nf->i1 = 9;
33819: // Pexpr ii = in->e2; //new cast(Pfct_type,in->e2);
33820: Pexpr e3 = new expr(ASSIGN,nf,i3);
33821:
33822: Pexpr ee = new expr(CM,e2,e3);
33823: return new expr(CM,e1,ee);
33824: }
33825:
33826: Pstmt block::simpl()
33827: {
33828: int i;
33829: Pname n;
33830: Pstmt ss=0, sst=0;
33831: Pstmt dd=0, ddt=0;
33832: Pstmt stail;
33833: Ptable old_scope = scope;
33834: DB( if(Sdebug>=1)
33835: error('d',"%d->block::simple() own_tbl %d memtbl %d curr_fct%n",this,own_tbl,memtbl,curr_fct);
33836: );
33837: if (own_tbl == 0) {
33838: ss = (s) ? s->simpl() : 0;
33839: return ss;
33840: }
33841:
33842: scope = memtbl;
33843: if (scope->init_stat == 0) scope->init_stat = 1; /* table is simplified. */
33844:
33845: for (n=scope->get_mem(i=1); n; n=scope->get_mem(++i)) {
33846: Pstmt st = 0;
33847: Pname cln;
33848: Pexpr in = n->n_initializer;
33849: // error('d',"local %k %n in %k %t",n->n_sto,n,in?in->base:0,in?in->tp:0);
33850: if (in || n->n_evaluated) {
33851: scope->init_stat = 2; /* initializer in this scope */
33852: if (n->n_sto == EXTERN) {
33853: error(&n->where,"Id local extern%n",n);
33854: continue;
33855: }
33856: }
33857:
33858: switch (n->n_scope) {
33859: case ARG:
33860: case 0:
33861: case PUBLIC:
33862: continue;
33863: }
33864:
33865: if (n->n_stclass == STATIC) { // local static class object
33866: /* initialization of local static objects;
33867: * set up first pass switch
33868: * temp_switch ? 0
33869: * : (stat_obj=init_expr, temp_switch=1);
33870: *
33871: * ARGS: temporary class object in init_expr with dtor
33872: * must call dtor once in std function
33873: */
33874:
33875: if ((in==0 && n->n_scope==ARGS) ||
33876: (in && in->base==STAT_INIT))
33877: {
33878: Pname cn;
33879: Pname x;
33880: Ptype ct;
33881: int vec_seen = 0;
33882:
33883: cn = n->tp->is_cl_obj();
33884: if ( cn == 0 ) { ++vec_seen; cn = cl_obj_vec; }
33885:
33886: if ( cn ) {
33887: ct = new ptr(PTR,vec_seen?Pvec(n->tp)->typ:n->tp);
33888: x = make_tmp('F', ct, gtbl );
33889: x->n_initializer = zero;
33890: }
33891: else
33892: x = make_tmp('F',int_type,scope);
33893:
33894: x->n_sto = n->n_stclass = STATIC;
33895:
33896: if (in) {
33897: if (in->e2)
33898: in->base = ASSIGN;
33899: else in = in->e1;
33900: }
33901:
33902: Pexpr set;
33903: if ( cn ) {
33904: x->dcl_print(0);
33905: Pclass cl = Pclass(cn->tp);
33906: Pname dtor = cl->has_dtor();
33907:
33908: Pexpr cc;
33909: if ( dtor ) {
33910: if ( vec_seen == 0 ) {
33911: Pexpr eee = new expr(DEREF, x, 0 );
33912: Pexpr c = call_dtor(eee,dtor,0,DOT,one);
33913: c->tp = any_type;
33914: cc = new expr( QUEST, c, zero );
33915: cc->cond = x;
33916: }
33917: else cc = cdvec(vec_del_fct,x,cl,dtor,0,zero,n);
33918: cc->tp = any_type; // arghh!
33919:
33920: Pstmt dls = new estmt( SM, n->where, cc, 0 );
33921: if ( st_dlist ) dls->s_list = st_dlist;
33922: st_dlist = dls;
33923: }
33924:
33925: Pexpr xe;
33926: if (cn) {
33927: if ( vec_seen == 0 )
33928: xe = new expr( G_ADDROF, 0, n );
33929: else {
33930: Pexpr ee = new expr( DEREF, n, zero );
33931: xe = new expr( G_ADDROF, 0, ee );
33932: }
33933: }
33934:
33935: set = new expr(ASSIGN,x,xe);
33936: set->tp = ct;
33937: }
33938: else {
33939: set = new expr(ASSIGN,x,one);
33940: set->tp = int_type;
33941: }
33942:
33943: // set pointer to static object and continue
33944: // sorry for goto, but beats rewriting code
33945: if ( n->n_scope == ARGS && in == 0 ) {
33946: set = new expr( QUEST, zero, set );
33947: set->cond = x;
33948: st = new estmt(SM,n->where,set,0);
33949: goto init_stat3;
33950: }
33951:
33952: in = new expr(G_CM,in,set);
33953: in = new expr(STAT_INIT,zero,in);
33954: in->cond = x;
33955: }
33956: else
33957: continue;
33958: }
33959:
33960: if ( in ) {
33961: if ((in->base == ILIST && in->e2 == 0) ||
33962: (in->base == STRING && n->tp->base == VEC))
33963: if (ansi_opt==0) {
33964: error('s',&n->where,"initialization of%n (automatic aggregate)",n);
33965: continue;
33966: }
33967: }
33968:
33969: if (n->tp == 0) continue; /* label */
33970: if (n->n_evaluated) continue;
33971:
33972: /* construction and destruction of temporaries is handled locally */
33973: { char* s = n->string;
33974: register char c3 = s[4];
33975: if (s[0]=='_' && s[1]=='_' && s[2]=='D' && isdigit(c3)) continue;
33976: }
33977:
33978: if ( cln=n->tp->is_cl_obj() ) {
33979: Pclass cl = Pclass(cln->tp);
33980: Pname d = cl->has_dtor();
33981:
33982: if ( n->n_stclass == STATIC // local static class object
33983: && in && in->base==STAT_INIT )
33984: goto stat_init;
33985:
33986: if (d) { // n->cl.dtor(0);
33987: Pexpr dl = call_dtor(n,d,0,DOT,one);
33988: // Pstmt dls = new estmt(SM,n->where,dl,0);
33989: Pstmt dls = new estmt(SM,no_where,dl,0);
33990: if (dd) {
33991: dls->s_list = dd;
33992: dd = dls;
33993: }
33994: else
33995: ddt = dd = dls;
33996: }
33997:
33998: // error('d',"%n: in %d",n,in?in->base:0);
33999: if (in) {
34000: switch (in->base) {
34001: case DEREF: // *constructor?
34002: if (in->e1->base == G_CALL) {
34003: Pname fn = in->e1->fct_name;
34004: if (fn==0 || fn->n_oper!=CTOR) goto ddd;
34005: st = new estmt(SM,n->where,in->e1,0);
34006: n->n_initializer = 0;
34007: break;
34008: }
34009: goto ddd;
34010: case STAT_INIT:
34011: stat_init:
34012: // error('d', "block::simpl: case #1 stat_init : n: %n", n );
34013: in->base = QUEST;
34014: st = new estmt(SM,n->where,in,0);
34015: n->n_initializer = 0;
34016: break;
34017: case G_CM:
34018: st = new estmt(SM,n->where,in->e1,0);
34019: n->n_initializer = 0;
34020: break;
34021: case ASSIGN: // assignment to "n"?
34022: if (in->e1 == n) {
34023: st = new estmt(SM,n->where,in,0);
34024: n->n_initializer = 0;
34025: break;
34026: }
34027: default:
34028: goto ddd;
34029: }
34030: }
34031: }
34032: else if (cl_obj_vec) {
34033: Pclass cl = Pclass(cl_obj_vec->tp);
34034: Pname d = cl->has_dtor();
34035: Pname c = cl->has_ictor();
34036: n->n_initializer = 0;
34037:
34038: if ( n->n_stclass == STATIC // local static class object
34039: && in && in->base==STAT_INIT )
34040: goto stat_init2;
34041:
34042: if (c) { // _vec_new(vec,noe,sz,ctor);
34043: if (in==0 || in->base==ILIST) {
34044: Pexpr a = cdvec(vec_new_fct,n,cl,c,-1,0);
34045: st = new estmt(SM,n->where,a,0);
34046: }
34047: else
34048: st = new estmt(SM,n->where,in,0);
34049: }
34050: // no default ctor but provided all elements with argument
34051: else if ( in ) st = new estmt(SM,n->where,in,0);
34052:
34053:
34054: if (d) { // __vec_delete(vec,noe,sz,dtor,0);
34055: Pfct f = Pfct(d->tp);
34056: int i = 0;
34057: for (Pname nn = f->f_args->n_list;
34058: nn && nn->n_list; nn=nn->n_list) i++;
34059: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
34060: // Pstmt dls = new estmt(SM,n->where,a,0);
34061: Pstmt dls = new estmt(SM,no_where,a,0);
34062: if (dd) {
34063: dls->s_list = dd;
34064: dd = dls;
34065: }
34066: else
34067: ddt = dd = dls;
34068: }
34069: }
34070: else if (in) {
34071: switch (in->base) {
34072: case ILIST:
34073: switch (n->n_scope) {
34074: case FCT:
34075: if (in->e2) { // pointer to member
34076: Pexpr ee = mptr_assign(n,in);
34077: st = new estmt(SM,n->where,ee,0);
34078: n->n_initializer = 0;
34079: break;
34080: }
34081: case ARG:
34082: if (ansi_opt == 0) error('s',"Ir list for localV%n",n);
34083: }
34084: break;
34085: case STAT_INIT:
34086: stat_init2:
34087: // error('d', "block::simpl: case #2 stat_init : n: %n", n );
34088: in->base = QUEST;
34089: st = new estmt(SM,n->where,in,0);
34090: n->n_initializer = 0;
34091: break;
34092: case STRING:
34093: if (n->tp->base==VEC) break; /* BUG char vec only */
34094: default:
34095: ddd:
34096: { Pexpr ee = new expr(ASSIGN,n,in);
34097: st = new estmt(SM,n->where,ee,0);
34098: n->n_initializer = 0;
34099: }
34100: }
34101: }
34102:
34103: init_stat3: if (st) {
34104: if (ss)
34105: sst->s_list = st;
34106: else
34107: ss = st;
34108: sst = st;
34109: }
34110: }
34111:
34112: if (dd) {
34113: Pstmt od = del_list;
34114: Pstmt obd = break_del_list;
34115: Pstmt ocd = continue_del_list;
34116:
34117: dd->simpl();
34118: del_list = (od) ? Pstmt(new pair(curloc,dd,od)) : dd;
34119: break_del_list = (break_del_list&&obd) ? Pstmt(new pair(curloc,dd,obd)) : dd;
34120: continue_del_list = (continue_del_list&&ocd) ? Pstmt(new pair(curloc,dd,ocd)) : dd;
34121:
34122: stail = s ? s->simpl() : 0;
34123:
34124: Pfct f = Pfct(curr_fct->tp);
34125: if (this!=f->body
34126: || f->returns->base==VOID
34127: || (f->returns->base!=VOID && no_of_returns==0 ) // you have been warned!
34128: || strcmp(curr_fct->string,"main")==0 ) {
34129: // not dropping through the bottom of a value returning function
34130: if (stail) {
34131: Pstmt tt = (stail->base==RETURN || stail->base==LABEL) ? stail : trim_tail(stail);
34132: if (tt && tt->base != RETURN) stail->s_list = dd;
34133: }
34134: else
34135: s = dd;
34136: stail = ddt;
34137: }
34138:
34139: del_list = od;
34140: continue_del_list = ocd;
34141: break_del_list = obd;
34142: }
34143: else
34144: stail = s ? s->simpl() : 0;
34145:
34146: if (ss) { /* place constructor calls */
34147: ss->simpl();
34148: sst->s_list = s;
34149: s = ss;
34150: if (stail == 0) stail = sst;
34151: }
34152:
34153: scope = old_scope;
34154:
34155: return stail;
34156: }
34157:
34158: int no_sizeof;
34159:
34160: void expr::simpl()
34161: {
34162: DB(if(Sdebug>=2){
34163: error('d',"%d->expr::simpl() %k",this,this?base:0);
34164: if(Sdebug>=3) display_expr(this);
34165: });
34166: if (this==0 || permanent==2) return; // already expanded
34167: static TOK obase = 0;
34168:
34169: switch (base) {
34170: case MDOT:
34171: obase = base;
34172: mem->simpl();
34173: obase = 0;
34174: // no break
34175:
34176: case ICALL: // already expanded
34177: return;
34178:
34179: case G_ADDROF:
34180: case ADDROF:
34181: // error('d',"simpl & %k",e2->base);
34182:
34183: e2->simpl();
34184: switch (e2->base) {
34185: case DOT:
34186: case REF:
34187: { Pref r = Pref(e2);
34188: Pname m = Pname(r->mem);
34189: while (m->base == MDOT) m = Pname(m->mem);
34190: if (m->n_stclass == STATIC) { // & static member
34191: Pexpr x;
34192: delp:
34193: x = e2;
34194: e2 = m;
34195: r->mem = 0;
34196: DEL(x);
34197: }
34198: else if (m->tp->base == FCT) { // & member fct
34199: Pfct f = Pfct(m->tp);
34200: if (f->f_virtual) { // &p->f ==> p->vtbl[fi].f
34201: int index = f->f_virtual;
34202: Pexpr ie = index ? new ival(index):0;
34203: if (ie) ie->tp = int_type;
34204: Pname cn = m->n_table->t_name;
34205: Pname vp = find_vptr(Pclass(cn->tp));
34206: r->mem = vp;
34207:
34208: if ( obase == MDOT ) {
34209: base = DEREF;
34210: e1 = e2;
34211: e2 = ie;
34212: }
34213: else { // support old style &b.vf
34214: base = MDOT;
34215: mem = new expr(DEREF,e2,ie);
34216: string2 = "f";
34217: i1 = 9;
34218: }
34219: }
34220: else {
34221: goto delp;
34222: }
34223: }
34224: break;
34225: }
34226: }
34227: break;
34228:
34229: case ANDAND:
34230: case OROR:
34231: Ntmp = 0;
34232: // no break
34233:
34234: default:
34235: if (e1) e1->simpl();
34236: if (e2) e2->simpl();
34237: break;
34238:
34239: case CM:
34240: case G_CM:
34241: {
34242: Pname n = 0;
34243: e1->simpl();
34244: e2->simpl();
34245: if (e1->base==ICALL && e1->e1==0) n = e1->il->fct_name;
34246: if (e2->base==ICALL && e2->e1==0) n = e2->il->fct_name;
34247: if (n) error('s',"cannot expand inline void%n called in commaE",n);
34248: // no break
34249: }
34250: case NAME:
34251: case DUMMY:
34252: case ICON:
34253: case FCON:
34254: case CCON:
34255: case IVAL:
34256: // case FVAL:
34257: // case LVAL:
34258: case STRING:
34259: case ZERO:
34260: case ILIST:
34261: // case MDOT:
34262: return;
34263: /*
34264: case SIZEOF:
34265: base = IVAL;
34266: i1 = tp2->tsizeof();
34267: tp2 = 0; // can't DEL(tp2)
34268: break;
34269: */
34270: case SIZEOF:
34271: if (e1) e1->simpl();
34272: return;
34273:
34274: case G_CALL:
34275: case CALL:
34276: Pcall(this)->simpl();
34277: break;
34278:
34279: case NEW:
34280: case GNEW:
34281: simpl_new();
34282: return;
34283:
34284: case DELETE:
34285: case GDELETE:
34286: simpl_delete();
34287: break;
34288:
34289: case QUEST:
34290: cond->simpl();
34291: Ntmp = 0;
34292: e2->simpl();
34293: // no break
34294:
34295: case CAST:
34296: case REF:
34297: e1->simpl();
34298: break;
34299:
34300: case DOT:
34301: e1->simpl();
34302: switch (e1->base) {
34303: case CM:
34304: case G_CM:
34305: { // &( , name). => ( ... , &name)->
34306: Pexpr ex = e1;
34307: cfr:
34308: switch (ex->e2->base) {
34309: case NAME:
34310: base = REF;
34311: ex->e2 = ex->e2->address();
34312: break;
34313: case CM:
34314: case G_CM:
34315: ex = ex->e2;
34316: goto cfr;
34317: }
34318: }
34319: }
34320: break;
34321:
34322: case ASSIGN:
34323: {
34324: Pfct f = 0;
34325: Pexpr th = 0;
34326: if ( curr_fct ) {
34327: f = Pfct(curr_fct->tp);
34328: th = f->f_this;
34329: }
34330:
34331: imeasure++;
34332: if (e1) e1->simpl();
34333: if (e2) {
34334: Pexpr c = e2;
34335: c->simpl();
34336: while (c->base == CAST) c = c->e1;
34337: if (c->base == ILIST) e2 = c;
34338:
34339: if (e2->base == ILIST) { // pointer to member assignment
34340: Pexpr ee = mptr_assign(e1,e2);
34341: Pexpr eee = new expr(CM,ee->e2,e1);
34342: e1 = ee->e1;
34343: e2 = eee;
34344: base = CM;
34345: delete ee;
34346: }
34347: }
34348:
34349: if (th && th==e1 && curr_fct->n_oper==CTOR && init_list) {
34350: // this=e2 => (this=e2,init_list)
34351: Pclass cl = Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp);
34352: if (cl->c_body == 1) cl->dcl_print(0);
34353: imeasure++;
34354: base = CM;
34355: e1 = new expr(ASSIGN,e1,e2);
34356: e2 = init_list;
34357: if (warning_opt) // timid
34358: error('w',"assignment to ``this'' inK: try defining%t::operator new() instead",f->memof);
34359: }
34360: break;
34361: }
34362: }
34363:
34364: switch (base) {
34365: case QUEST:
34366: case ANDAND:
34367: case OROR:
34368: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,base);
34369: // no break;
34370: default:
34371: Ntmp = 0;
34372: }
34373:
34374: if (tp==int_type || tp==defa_type) {
34375: Neval = 0;
34376: no_sizeof = 1; // do not convert sizeof's to ints
34377: long i = eval();
34378: no_sizeof = 0;
34379: if (Neval == 0) {
34380: base = IVAL;
34381: i1 = i;
34382: }
34383: }
34384:
34385: }
34386:
34387: Pexpr vptr_entry(Pexpr pp, Pexpr ie, Pclass cl)
34388: {
34389: Pptr ttemp = pp->tp->is_ptr_or_ref();
34390:
34391: if (ttemp) {
34392: Ptype pt = ttemp->typ; // check if cast pp = (base*)pp
34393: Pclass pc = Pclass(pt->is_cl_obj()->tp); // is needed
34394: if (pc!=cl) pp = new cast(cl,pp);
34395: }
34396: Pname vp = find_vptr(cl);
34397: if (vp == 0) error('i',"can't find vptr");
34398: Pexpr vptr = new ref(REF,pp,vp); // pp->vptr
34399: return new expr(DEREF,vptr,ie); // pp->vptr[i]
34400: }
34401:
34402: Pexpr new_this(Pexpr pp, Pexpr ee)
34403: {
34404: //error('d',"new this");
34405: Pexpr dee = new mdot("d",ee); // pp->vptr[i].d
34406: dee->i1 = 9;
34407: Pexpr nthis = new cast(Pchar_type,pp);
34408: nthis = new expr(PLUS,nthis,dee); // ((char*)pp)+delta
34409: Ptype ct = pp->tp;
34410: if (pp->base==NAME && Pname(pp)->n_xref) ct = pp->tp->addrof();
34411: return new cast(ct,nthis);
34412: }
34413:
34414: Pcall vcall(Pexpr pp, Pexpr ie, Pfct f, Pclass cl, Pexpr args)
34415: /*
34416: generate a call of the virtual function with the index ``ie''
34417: and type "f" in class ``cl'' for the object pointed to by ``pp''
34418:
34419: multiple inheritance virtual call:
34420:
34421: p->f(x) is resolved like this
34422: pp = p; // avoid side effects
34423: pp = p.base_object; // often: pp = p;
34424: // done when the name was resolved
34425: i = index(f);
34426: entry = pp->_vtbl[i-1];
34427: pp = (T*)(((char*)pp)+entry.d)
34428: (*(ftype)entry.f)(pp,x)
34429: */
34430: {
34431: //error('d',"vcall %t",cl);
34432: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl
34433:
34434: imeasure+=6;
34435: Pexpr ee = vptr_entry(pp,ie,cl);
34436:
34437: Pexpr fee = new mdot("f",ee);
34438: fee->i1 = 9;
34439: Ptype pft = f->addrof();
34440: fee = new cast(pft,fee); // (T)pp->vptr[i].f
34441: Pexpr r = new expr(DEREF,fee,0); // *(T)pp->vptr[i].f
34442: // e1->tp must be 0, means "argtype encoded"
34443: r->tp2 = Ptype(f->f_this); // encode argtype
34444:
34445: Pexpr nthis = new_this(pp,ee);
34446:
34447: args = new expr(ELIST,nthis,args);
34448: args->simpl();
34449:
34450: Pcall c = new call(r,args);
34451: c->tp = f->returns;
34452: return c;
34453: }
34454:
34455: void call::simpl()
34456: /*
34457: fix member function calls:
34458: p->f(x) becomes f(p,x)
34459: o.f(x) becomes f(&o,x)
34460: or if f is virtual:
34461: p->f(x) is resolved like this
34462: pp = p;
34463: i = index(f);
34464: entry = pp->_vtbl[i-1];
34465: pp = (T*)(((char*)pp)+entry.i)
34466: (*entry.f)(pp,x)
34467: replace calls to inline functions by the expanded code
34468: */
34469: {
34470: Pname fn = fct_name;
34471: //error('d',"%d call::simpl() fn %n %d e1 %d",this,fn,fn,e1);
34472: Pfct f = fn ? Pfct(fn->tp) : 0;
34473:
34474: if (fn == 0) e1->simpl();
34475:
34476: if (f) {
34477: switch(f->base) {
34478: case ANY:
34479: return;
34480: case OVERLOAD:
34481: fct_name = fn = Pgen(f)->fct_list->f;
34482: f = Pfct(fn->tp);
34483: }
34484: }
34485:
34486: switch (e1->base) {
34487: case MEMPTR: // (p ->* q)(args)
34488: {
34489: Pexpr p = e1->e1;
34490: Pexpr q = e1->e2;
34491: Pclass cl = Pclass(e1->tp2);
34492: Pfct f = Pfct(q->tp->deref());
34493:
34494: if (e2) e2->simpl();
34495:
34496: if (f->f_this == 0) { // might not know about ``this'' yet
34497: if (f->memof == 0) error('i',"memof missing");
34498: Pname tt = new name("this");
34499: tt->n_scope = ARG;
34500: tt->tp = f->memof->this_type;
34501: PERM(tt);
34502: // f->f_this = f->f_args = tt;
34503: tt->n_list = f->argtype;
34504: // f->f_this = tt;
34505: tt->n_list = f->f_result ? f->f_result : f->argtype;
34506: f->f_this = f->f_args = tt;
34507: }
34508: //error('d',"f_this %d",f->f_this);
34509: extern has_virt(Pclass);
34510:
34511: // beware of sideeffects:
34512: nin = 1;
34513: if (q->not_simple()) error('s',"2nd operand of .* too complicated");
34514: nin = 0;
34515:
34516: Pexpr qq = new mdot("f",q); // the function: (*(right type)q.f)
34517: qq->i1 = 9;
34518: qq = new cast(f->addrof(),qq);
34519: Pexpr nc = new expr(DEREF,qq,0);
34520: nc->tp2 = Ptype(f->f_this); // encode argtype
34521:
34522: Pexpr nthis = new_this(p,q); // arguments: (p+q.d,args)
34523: Pexpr args = new expr(ELIST,nthis,e2);
34524: imeasure+=3;
34525:
34526: if (has_virt(cl) == 0) { // no virtuals: simple
34527: if (cl->defined == 0)
34528: error("call throughP toMF before definition ofC %t",cl);
34529: //error('d',"no virt");
34530: // (p ->* q)(args) => (*q.f)(p+q.d,args)
34531: e1 = nc;
34532: e2 = args;
34533: return;
34534: }
34535:
34536: if (find_vptr(cl) == 0) { // must be a call to a second base
34537: // that we cannot handle yet
34538: // it is OK not to to generate
34539: // a virtual call since a
34540: // `sorry' will have been generated
34541: // at the point of initialization
34542: e1 = nc;
34543: e2 = args;
34544: return;
34545:
34546: }
34547: // beware of sideeffects:
34548: nin = 1;
34549: if (p->not_simple()) error('s',"1st operand of .* too complicated");
34550: nin = 0;
34551:
34552: Pexpr c = new mdot("i",q); // condition (q.i<0)
34553: c->i1 = 9;
34554: c = new expr(LT,c,zero);
34555:
34556: Pexpr ie = new mdot("i",q);
34557: ie->i1 = 9;
34558:
34559: base = QUEST;
34560: e1 = new call(nc,args);
34561: e2 = vcall(p,ie,f,cl,e2);
34562: cond = c;
34563: return;
34564: }
34565: case DOT:
34566: // if e1 is an object and not just a reference
34567: // the vtbl need not be used
34568: case REF:
34569: { Pref r = Pref(e1);
34570: Pexpr a1 = r->e1;
34571: int obj = r->n_initializer!=0; // if B::f don't use vcall
34572:
34573: if (obj == 0) { // don't use vcall if we have an object
34574: // (not a pointer or a reference)
34575: if (e1->base==DOT && a1->base!=DEREF) obj = 1;
34576: }
34577:
34578: //error('d',"fct_name %n f %d %d obj %d",fct_name,f,f->f_virtual,obj);
34579: if (f && obj==0 && f->f_virtual) {
34580: Pexpr a11 = 0;
34581:
34582: switch(a1->base) { // see if temporary might be needed
34583: case NAME:
34584: case MDOT:
34585: a11 = a1;
34586: break;
34587: case REF:
34588: case DOT:
34589: if (a1->e1->base==NAME
34590: || ((a1->e1->base==DOT || a1->e1->base==REF) && a1->e1->e1->base==NAME)) a11 = a1;
34591: break;
34592: case ADDROF:
34593: case G_ADDROF:
34594: if (a1->e2->base == NAME
34595: || ((a1->e2->base==DOT || a1->e2->base==REF) && a1->e2->e1->base==NAME)) a11 = a1;
34596: break;
34597: case CAST:
34598: switch (a1->e1->base) {
34599: case NAME:
34600: case MDOT:
34601: a11 = a1;
34602: }
34603: }
34604:
34605: // if( a1->base==REF && fn->n_oper==DTOR ){
34606: // a11 = a1;
34607: // goto zsw;
34608: // }
34609: //
34610: if (e1->base == DOT) {
34611: // zsw:
34612: if (a11) a11 = a11->address();
34613: a1 = a1->address();
34614: }
34615:
34616: if (a11 == 0) { // temporary (maybe) needed
34617: // e->f() => (t=e,t->f(t))
34618: if (a1->base==NAME)
34619: a11 = a1; // &*name has become name
34620: else {
34621: Pname nx = new name(make_name('K'));
34622: nx->tp = a1->tp;
34623: Pname n = nx->dcl(scope,ARG); // no init!
34624: delete nx;
34625: Pname cln = a1->tp->is_cl_obj();
34626: if (cln) {
34627: Pclass cl = Pclass(cln->tp);
34628: if (Ntmp==0 && cl->has_dtor()) Ntmp = cln;
34629: if (cl->has_itor()) n->n_xref = 1;
34630: }
34631: n->n_scope = FCT;
34632: n->assign();
34633: a11 = n;
34634: a1 = new expr(ASSIGN,n,a1);
34635: a1->tp = n->tp;
34636: a1->simpl();
34637: Pcall cc = new call(0,0);
34638: *cc = *this;
34639: base = CM;
34640: e1 = a1;
34641: e2 = cc;
34642: this = cc;
34643: }
34644: }
34645:
34646: int i = f->f_virtual;
34647: Pexpr ie = i?new ival(i):0; // index
34648: Pname cn = fn->n_table->t_name;
34649: if (fn
34650: && fn->n_initializer
34651: && cc->nof
34652: && cc->nof->n_oper==CTOR
34653: && Pfct(cc->nof->tp)->memof->c_abstract
34654: && strcmp(Pfct(cc->nof->tp)->memof->string, cn->string) == 0 ) {
34655: // permit x::x( x& xx ) { xx.pvf(); }
34656: Pexpr ee = e1->e1;
34657: while ( ee && ee->base != NAME ) ee = ee->e1;
34658: if ( ee && strcmp( ee->string, "this" )==0)
34659: error("call of pure virtualF%n inK%n",fn,cc->nof);
34660: }
34661: Pcall vc = vcall(a11,ie,f,Pclass(cn->tp),e2);
34662: *this = *vc;
34663: return;
34664: }
34665:
34666: Ptype tt = r->mem->tp;
34667: llp:
34668: //error('d',"llp %t",tt);
34669: switch (tt->base) {
34670: // default: // pointer to function: (n->ptr_mem)(args); do nothing
34671: case TYPE:
34672: tt = Pbase(tt)->b_name->tp;
34673: goto llp;
34674: case OVERLOAD: // n->fctmem(args);
34675: case FCT:
34676: if (fct_name==0) {
34677: // reconstitute fn destroyed to suppress "virtual"
34678: fct_name = fn = Pname(e1->n_initializer);
34679: f = Pfct(fn->tp);
34680: }
34681:
34682: if (e1->base == DOT) a1 = a1->address();
34683: e2 = new expr(ELIST,a1,e2);
34684: e1 = r->mem;
34685: }
34686: }
34687: }
34688:
34689: if (e2) e2->simpl();
34690: //error('d',"fn %n inl %d imes %d",fn,f->f_inline,f->f_imeasure);
34691: if (fn && f->f_inline && debug_opt==0) {
34692: imeasure += f->f_imeasure;
34693: Pclass cl = f->memof;
34694: if (cl && cl->c_body) cl->dcl_print(0);
34695: Ptable oscope = scope;
34696: Pexpr ee = f->expand(fn,scope,e2);
34697: scope = oscope;
34698: if (ee) *Pexpr(this) = *ee;
34699: }
34700: else if (fn && f->f_inline==0 && f->f_imeasure) {
34701: extern void uninline(Pname fn);
34702: uninline(fn);
34703: imeasure += 3;
34704: }
34705: else if (fn && debug_opt && f->f_inline==ITOR) {
34706: extern void expand_itor(Pclass);
34707: expand_itor(f->memof);
34708: }
34709: else
34710: imeasure += 3;
34711: }
34712:
34713: void uninline(Pname fn)
34714: // inline turned static
34715: {
34716: Pfct f = Pfct(fn->tp);
34717: //error('d',"uninline %n %d %d",fn,f->body,f->f_expr);
34718:
34719: if (warning_opt) {
34720: error('w',"%n too complex for inlining",fn);
34721: error('w',"out-of-line copy of %n created",fn);
34722: }
34723: f->f_imeasure = 0; // now it really is just static
34724:
34725: Pstmt s = f->body->s;
34726: // for (s = f->body->s; s; s=s->s_list)
34727: //error('d',"start %d %k",s->e,s->e->base);
34728: // s = f->body->s;
34729: while (s) {
34730: //error('d',"s %k %d %k",s->base,s->e,s->e->base);
34731: if (s->base == SM) {
34732: // turn comma expression into statement list
34733: Pexpr e = s->e;
34734: if (e)
34735: switch (e->base) {
34736: case CM:
34737: case G_CM:
34738: { Pstmt ss = new estmt(SM,no_where,e->e2,0);
34739: s->e = e->e1;
34740: ss->s_list = s->s_list;
34741: s->s_list = ss;
34742: delete e;
34743: continue;
34744: }
34745: }
34746: }
34747: s = s->s_list;
34748: }
34749: // for (s = f->body->s; s; s=s->s_list)
34750: //error('d',"echo %k %d %k",s->base,s->e,s->e->base);
34751:
34752: fn->dcl_print(0);
34753: }
34754:
34755: /*
34756: void ccheck(Pexpr e)
34757:
34758: Is there a conditional in this expression? (not perfect)
34759:
34760: {
34761: //error('d',"ccheck(e %k)",e,e?e->base,0);
34762: if (e)
34763: switch (e->base) {
34764: case QUEST:
34765: case ANDAND:
34766: case OROR:
34767: error('s',"E too complicated: uses%k and needs temporary ofCW destructor",e->base);
34768: break;
34769: case LT:
34770: case LE:
34771: case GT:
34772: case GE:
34773: case EQ:
34774: case NE:
34775: case ASSIGN:
34776: case ASPLUS:
34777: case ASMINUS:
34778: case G_CM:
34779: case CM:
34780: case PLUS:
34781: case MINUS:
34782: case MUL:
34783: case DIV:
34784: case OR:
34785: case ER:
34786: case AND:
34787: case G_CALL:
34788: case CALL:
34789: case ELIST:
34790: case DEREF:
34791: ccheck(e->e1);
34792: case NOT:
34793: case COMPL:
34794: case CAST:
34795: case ADDROF:
34796: case G_ADDROF:
34797: ccheck(e->e2);
34798: break;
34799: case ICALL: // check inlined arguments
34800: { Pin il = e->il;
34801: for (int i = 0; il->args[i].arg && i<il->i_slots; i++) ccheck(il->args[i].arg);
34802: }
34803: }
34804: }
34805: */
34806:
34807: void temp_in_cond(Pexpr ee, Pstmt ss, Ptable tbl)
34808: /*
34809: insert destructor calls 'ss' into condition 'ee'
34810: ee => (Qnn = ee, dtors, Qnn)
34811: */
34812: {
34813: //error('d',"temp_in_cond");
34814: // ccheck(ee);
34815: while (ee->base==CM || ee->base==G_CM) ee = ee->e2;
34816: Ptype ct = ee->tp;
34817: Pname n = new name(make_name('Q')); // int Qnn;
34818: n->tp = ct;
34819: Pname tmp = n->dcl(tbl,ARG);
34820: delete n;
34821: tmp->n_scope = FCT;
34822:
34823: Pexpr v = new expr(0,0,0);
34824: *v = *ee;
34825: PERM(ct);
34826: v = new cast(ct,v);
34827:
34828: tmp->n_assigned_to = 1;
34829: Pexpr c = new expr(ASSIGN,tmp,v); // Qnn = ee
34830: c->tp = ct;
34831: ee->base = CM;
34832: ee->e1 = c;
34833:
34834: Pexpr ex = 0; // add dtors at end
34835:
34836: for (Pstmt sx = ss; sx; sx = sx->s_list) {
34837: if (ex) {
34838: ex = new expr(CM,ex,sx->e);
34839: ex->tp = sx->e->tp;
34840: }
34841: else
34842: ex = sx->e;
34843: }
34844: ee->e2 = new expr(CM,ex,tmp); // add Qnn at end
34845: ee->e2->tp = ct;
34846: }
34847:
34848: bit not_safe(Pexpr e)
34849: {
34850:
34851: switch (e->base) {
34852: default:
34853: return 1;
34854: /*
34855: case CALL:
34856: case G_CALL:
34857: case DOT:
34858: case REF:
34859: case ANAME:
34860: return 1;
34861: */
34862: case NAME:
34863: // if the name is automatic and has a destructor it is not safe
34864: // to destroy it before returning an expression depending on it
34865: { Pname n = Pname(e);
34866: if (n->n_table!=gtbl && n->n_table->t_name==0) {
34867: Pname cn = n->tp->is_cl_obj();
34868: if (cn && Pclass(cn->tp)->has_dtor()) return 1;
34869: }
34870: }
34871: case IVAL:
34872: case ICON:
34873: case CCON:
34874: case FCON:
34875: case STRING:
34876: return 0;
34877: case NOT:
34878: case COMPL:
34879: case ADDROF:
34880: case G_ADDROF:
34881: return not_safe(e->e2);
34882: case DEREF:
34883: // return not_safe(e->e1) || e->e2?not_safe(e->e2):0;
34884: { int i = not_safe(e->e1);
34885: if (i) return i;
34886: if (e->e2) return not_safe(e->e2);
34887: return 0;
34888: }
34889: case CM:
34890: case PLUS:
34891: case MINUS:
34892: case MUL:
34893: case DIV:
34894: case MOD:
34895: case ASSIGN:
34896: case ASPLUS:
34897: case ASMINUS:
34898: case ASMUL:
34899: case ASDIV:
34900: case OR:
34901: case AND:
34902: case OROR:
34903: case ANDAND:
34904: case LT:
34905: case LE:
34906: case GT:
34907: case GE:
34908: case EQ:
34909: case NE:
34910: return not_safe(e->e1) || not_safe(e->e2);
34911: case QUEST:
34912: return not_safe(e->cond) || not_safe(e->e1) || not_safe(e->e2);
34913: }
34914: }
34915:
34916:
34917: Pexpr curr_expr; /* to protect against an inline being expanded twice
34918: in a simple expression keep track of expressions
34919: being simplified
34920: */
34921: Pstmt stmt::simpl()
34922: /*
34923: return a pointer to the last statement in the list, or 0
34924: */
34925: {
34926: if (this == 0) error('i',"0->S::simpl()");
34927: DB( if(Sdebug>=1){
34928: error('d',"%d->stmt::simpl(): %k",this,base);
34929: if(Sdebug>=2) display_stmt(this);
34930: });
34931: //Pstmt ostmt = Cstmt;
34932: //if ( where.line ) Cstmt = this;
34933:
34934: stmtno++;
34935: curr_expr = e;
34936: //error('d',"stmt::simpl %k s_list %d",base,s_list);
34937:
34938: switch (base) {
34939: default:
34940: error('i',"S::simpl(%k)",base);
34941:
34942: case ASM:
34943: break;
34944:
34945: case BREAK:
34946: if (break_del_list) { // break => { _dtor()s; break; }
34947: Pstmt bs = new stmt(base,where,0);
34948: Pstmt dl = break_del_list->copy();
34949: base = BLOCK;
34950: s = new pair(where,dl,bs);
34951: }
34952: break;
34953:
34954: case CONTINUE:
34955: if (continue_del_list) { // continue => { _dtor()s; continue; }
34956: Pstmt bs = new stmt(base,where,0);
34957: Pstmt dl = continue_del_list->copy();
34958: base = BLOCK;
34959: s = new pair(where,dl,bs);
34960: }
34961: break;
34962:
34963: case DEFAULT:
34964: s->simpl();
34965: break;
34966:
34967: case SM:
34968: if (e) {
34969: if (e->base == DEREF) e = e->e1;
34970: e->simpl();
34971: if (e->base == DEREF) e = e->e1;
34972: }
34973: break;
34974:
34975: case RETURN:
34976: { /* return x;
34977: =>
34978: { dtor()s; return x; }
34979: OR (returning an X where X(X&) is defined) =>
34980: { ctor(_result,x); _dtor()s; return; }
34981: OR (where x needs temporaries)
34982: OR (where x might involve an object to be destroyed) =>
34983: { _result = x; _dtor()s; return _result; }
34984: return; =>
34985: { _dtor()s; return; }
34986: OR (in constructors) =>
34987: { _dtor()s; return _this; }
34988: */
34989: Pstmt sx = this;
34990: Pexpr ex = e;
34991:
34992: no_of_returns++;
34993:
34994: Pstmt dl = (del_list) ? del_list->copy() : 0;
34995: Pfct f = Pfct(curr_fct->tp);
34996:
34997: if (e == 0) e = dummy;
34998: if (e==dummy && curr_fct->n_oper==CTOR) e = f->f_this;
34999:
35000:
35001: // need to generate a temporary for mptr return
35002: Pexpr tt = e;
35003: while ( tt->base == CAST )
35004: tt = tt->e1;
35005: if ( tt->base == ILIST )
35006: e = tt;
35007:
35008: if (e->base == ILIST) {
35009: extern Pbase mptr_type;
35010: extern Ptype Pvptr_type;
35011: Pexpr mptr_assign(Pexpr, Pexpr);
35012: // memptr constant
35013: // return({1,2,f}) ==> memptr t; return((t={1,2,f},&t))
35014:
35015: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
35016: Pname temp = make_tmp('A',mptr_type,ftbl);
35017:
35018: // placed in mptr_assign()
35019: // temp->use(); // necessary for inlines to force declaration
35020:
35021: e = mptr_assign(temp,e);
35022: e = new expr(G_CM,e,temp);
35023: e->tp = mptr_type;
35024: }
35025:
35026: if (f->f_result) { // ctor(_result,x); dtors; return;
35027: if (e->base == G_CM) e = replace_temp(e,f->f_result);
35028: e->simpl();
35029: Pstmt cs = new estmt(SM,where,e,0);
35030: if (dl) cs = new pair(where,cs,dl);
35031: base = PAIR;
35032: s = cs;
35033: s2 = new estmt(RETURN,where,0,0);
35034: //#ifdef RETBUG
35035: // s2->empty = 1; // fudge to bypass C bug (see print.c)
35036: // s2->ret_tp = ret_tp;
35037: //#endif
35038: }
35039: else { // dtors; return e;
35040: e->simpl();
35041: if (dl) {
35042: if (e!=dummy && not_safe(e)) {
35043: // { _result = x; _dtor()s; return _result; }
35044: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
35045:
35046: Pname r = ftbl->look("_result",0);
35047: if (r == 0) {
35048: r = new name("_result");
35049: r->tp = ret_tp;
35050: Pname rn = r->dcl(ftbl,ARG);
35051: rn->n_scope = FCT;
35052: rn->where = no_where;
35053: rn->assign();
35054: delete r;
35055: r = rn;
35056: }
35057: Pexpr as = new expr(ASSIGN,r,e);
35058: as->tp = ret_tp; // wrong if = overloaded, but then X(X&) ought to have been used
35059: Pstmt cs = new estmt(SM,where,as,0);
35060: cs = new pair(where,cs,dl);
35061: base = PAIR;
35062: s = cs;
35063: s2 = new estmt(RETURN,where,r,0);
35064: // s2->ret_tp = ret_tp;
35065: }
35066: else { // { _dtor()s; return x; }
35067: base = PAIR;
35068: s = dl;
35069: s2 = new estmt(RETURN,where,e,0);
35070: }
35071: s2->ret_tp = ret_tp;
35072: }
35073: }
35074:
35075: // if (sx->memtbl) {
35076: // int i;
35077: // for (Pname n=sx->memtbl->get_mem(i=1); n; n=sx->memtbl->get_mem(++i)) {
35078: // Pname cn = n->tp->is_cl_obj();
35079: // if (cn && Pclass(cn->tp)->has_dtor()) {
35080: // ccheck(ex);
35081: // break;
35082: // }
35083: // }
35084: // }
35085: break;
35086: }
35087:
35088: case WHILE:
35089: case DO:
35090: e->simpl();
35091: { Pstmt obl = break_del_list;
35092: Pstmt ocl = continue_del_list;
35093: break_del_list = 0;
35094: continue_del_list = 0;
35095: s->simpl();
35096: break_del_list = obl;
35097: continue_del_list = ocl;
35098: }
35099: break;
35100:
35101: case SWITCH:
35102: e->simpl();
35103: { Pstmt obl = break_del_list;
35104: break_del_list = 0;
35105: s->simpl();
35106: break_del_list = obl;
35107: }
35108: switch (s->base) {
35109: case DEFAULT:
35110: case LABEL:
35111: case CASE:
35112: break;
35113: case BLOCK:
35114: if (s->s)
35115: switch (s->s->base) {
35116: case BREAK: // to cope with #define Case break; case
35117: case CASE:
35118: case LABEL:
35119: case DEFAULT:
35120: break;
35121: default:
35122: goto df;
35123: }
35124: break;
35125: default:
35126: df:
35127: error(&s->where,"S orIdE not reached: (case label missing?)");
35128: }
35129: break;
35130:
35131: case CASE:
35132: e->simpl();
35133: s->simpl();
35134: break;
35135:
35136: case LABEL:
35137: if (del_list) error('s',"label in blockW destructors");
35138: s->simpl();
35139: break;
35140:
35141: case GOTO:
35142: /* If the goto is going to a different (effective) scope,
35143: then it is necessary to activate all relevant destructors
35144: on the way out of nested scopes, and issue errors if there
35145: are any constructors on the way into the target.
35146:
35147: Only bother if the goto and label have different effective
35148: scopes. (If mem table of goto == mem table of label, then
35149: they're in the same scope for all practical purposes.
35150: */
35151: {
35152: Pname n = scope->look( d->string, LABEL );
35153: if (n == 0) error('i',&where,"label%n missing",d);
35154: if(n->n_realscope!=scope && n->n_assigned_to) {
35155:
35156: /* Find the root of the smallest subtree containing
35157: the path of the goto. This algorithm is quadratic
35158: only if the goto is to an inner or unrelated scope.
35159: */
35160:
35161: Ptable r = 0;
35162:
35163: for(Ptable q=n->n_realscope; q!=gtbl; q=q->next) {
35164: for( Ptable p = scope; p != gtbl; p = p->next ) {
35165: if( p==q ) {
35166: r = p; // found root of subtree!
35167: goto xyzzy;
35168: }
35169: }
35170: }
35171:
35172: xyzzy: if( r==0 ) error( 'i',&where,"finding root of subtree" );
35173:
35174: /* At this point, r = root of subtree, n->n_realscope
35175: * = mem table of label, and scope = mem table of goto. */
35176:
35177: /* Climb the tree from the label mem table to the table
35178: * preceding the root of the subtree, looking for
35179: * initializers and ctors. If the mem table "belongs"
35180: * to an unsimplified block(s), the n_initializer field
35181: * indicates presence of initializer, otherwise initializer
35182: * information is recorded in the init_stat field of
35183: * mem table. */
35184:
35185: for( Ptable p=n->n_realscope; p!=r; p=p->next )
35186: if( p->init_stat == 2 ) {
35187: error(&where,"goto%n pastDWIr",d);
35188: goto plugh; /* avoid multiple error msgs */
35189: }
35190: else if( p->init_stat == 0 ) {
35191: int i;
35192: for(Pname nn=p->get_mem(i=1);nn;nn=p->get_mem(++i))
35193: if(nn->n_initializer||nn->n_evaluated){
35194: error(&nn->where,"goto%n pastId%n",d,nn);
35195: goto plugh;
35196: }
35197: }
35198: plugh:
35199:
35200: /* Proceed in a similar manner from the point of the goto,
35201: * generating the code to activate dtors before the goto. */
35202: /* There is a bug in this code. If there are class objects
35203: * of the same name and type in (of course) different mem
35204: * tables on the path to the root of the subtree from the
35205: * goto, then the innermost object's dtor will be activated
35206: * more than once. */
35207:
35208: {
35209: Pstmt dd = 0, ddt = 0;
35210:
35211: for( Ptable p=scope; p!=r; p=p->next ) {
35212: int i;
35213: for(Pname n=p->get_mem(i=1);n;n=p->get_mem(++i)) {
35214: Pname cln;
35215: if (n->tp == 0) continue; /* label */
35216:
35217: if ( cln=n->tp->is_cl_obj() ) {
35218: Pclass cl = (Pclass)cln->tp;
35219: Pname d = cl->has_dtor();
35220:
35221: if (d) { /* n->cl::~cl(0); */
35222: Pexpr dl = call_dtor(n,d,0,DOT,one);
35223: Pstmt dls = new estmt(SM,n->where,dl,0);
35224: if (dd)
35225: ddt->s_list = dls;
35226: else
35227: dd = dls;
35228: ddt = dls;
35229: }
35230:
35231: }
35232: else if (cl_obj_vec) {
35233: Pclass cl = (Pclass)cl_obj_vec->tp;
35234: // Pname c = cl->has_ictor();
35235: Pname d = cl->has_dtor();
35236:
35237: if (d) { // __vec_delete(vec,noe,sz,dtor,0);
35238: Pfct f = Pfct(d->tp);
35239: int i = 0;
35240: for (Pname nn = f->f_args->n_list;
35241: nn && nn->n_list; nn=nn->n_list) i++;
35242: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
35243: Pstmt dls = new estmt(SM,n->where,a,0);
35244: if (dd)
35245: ddt->s_list = dls;
35246: else
35247: dd = dls;
35248: ddt = dls;
35249: }
35250: }
35251: } /* end mem table scan */
35252: } /* end dtor loop */
35253:
35254: /* "activate" the list of dtors obtained. */
35255:
35256: if( dd ) {
35257: dd->simpl();
35258: Pstmt bs = new stmt( base, where, 0 );
35259: *bs = *this;
35260: base = PAIR;
35261: s = dd;
35262: s2 = bs;
35263: }
35264: }
35265: } /* end special case for non-local goto */
35266: }
35267: break;
35268:
35269: case IF:
35270: e->simpl();
35271: s->simpl();
35272: if (else_stmt) else_stmt->simpl();
35273: break;
35274:
35275: case FOR: // "for (s;e;e2) s2; => "s; for(;e,e2) s2"
35276: if (for_init) for_init->simpl();
35277: if (e) {
35278: curr_expr = e;
35279: e->simpl();
35280: }
35281: if (e2) {
35282: curr_expr = e2;
35283: e2->simpl();
35284: if (e2->base==ICALL)
35285: if (e2->e1 == 0) error('s',"cannot expand inline void%n called in forE", e2->il->fct_name);
35286: }
35287: { Pstmt obl = break_del_list;
35288: Pstmt ocl = continue_del_list;
35289: break_del_list = 0;
35290: continue_del_list = 0;
35291: s->simpl();
35292: break_del_list = obl;
35293: continue_del_list = ocl;
35294: }
35295: break;
35296:
35297: case BLOCK:
35298: Pblock(this)->simpl();
35299: break;
35300:
35301: case PAIR:
35302: break;
35303: }
35304:
35305: /*if (s) s->simpl();*/
35306: //error('d',"base %k memtbl %d",base,memtbl);
35307: if (base!=BLOCK && memtbl) {
35308: Pstmt t1 = (s_list) ? s_list->simpl() : 0;
35309: Pstmt tpx = t1 ? t1 : this;
35310:
35311: Pstmt ss = 0;
35312: Pname cln; // used for warnings
35313: int i;
35314: Pname tn = memtbl->get_mem(i=1);
35315: for (; tn; tn=memtbl->get_mem(++i)) {
35316: if (cln = tn->tp->is_cl_obj()) {
35317: Pname d = Pclass(cln->tp)->has_dtor();
35318: if (d) { /* n->cl::~cl(0); */
35319: Pexpr dl = call_dtor(tn,d,0,DOT,one);
35320: Pstmt dls = new estmt(SM,tn->where,dl,0);
35321: dls->s_list = ss;
35322: ss = dls;
35323: }
35324: }
35325: }
35326:
35327: if (ss) {
35328: Pstmt t2 = ss->simpl();
35329:
35330: switch (base) {
35331: case IF:
35332: case WHILE:
35333: case DO:
35334: case SWITCH:
35335: temp_in_cond(e,ss,memtbl);
35336: break;
35337:
35338: case PAIR: // can hide a return
35339: { Pstmt ts = s2;
35340: while (ts->base==PAIR) ts = ts->s2;
35341: if (ts->base == RETURN) { // sordid
35342: this = ts;
35343: goto retu;
35344: }
35345: goto def;
35346: }
35347: case RETURN:
35348: retu:
35349: {
35350: if (e == 0) {
35351: // return; dtors; => dtors; return;
35352: Pstmt rs = new estmt(RETURN,where,0,0);
35353: //rs->empty = empty; // BSD fudge
35354: rs->ret_tp = ret_tp;
35355: base = PAIR;
35356: s = ss;
35357: s2 = rs;
35358: //Cstmt = ostmt;
35359: return t1 ? t1 : rs;
35360: }
35361:
35362: Pname cln = e->tp->is_cl_obj();
35363: if (cln==0
35364: || Pclass(cln->tp)->has_oper(ASSIGN)==0) {
35365: // ... return e; dtors; =>
35366: // ... X r; ... r = e; dtors; return r;
35367: Pname rv = new name("_rresult"); // NOT "_result"
35368: rv->tp = ret_tp /* e->tp */;
35369: if (memtbl == 0) memtbl = new table(4,0,0);
35370: Pname n = rv->dcl(memtbl,ARG);
35371: n->where = no_where;
35372: n->n_scope = FCT;
35373: n->n_assigned_to = 1;
35374: delete rv;
35375: Pstmt rs = new estmt(RETURN,where,n,0);
35376: rs->ret_tp = ret_tp;
35377: base = SM;
35378: e = new expr(ASSIGN,n,e);
35379: e->tp = n->tp;
35380: Pstmt ps = new pair(where,ss,rs);
35381: ps->s_list = s_list;
35382: s_list = ps;
35383: //Cstmt = ostmt;
35384: return t1 ? t1 : rs;
35385: }
35386: }
35387:
35388: case FOR: // don't know which expression the temp comes from
35389: error('s',&where,"E in %kS needs temporary ofC%nW destructor",base,cln);
35390: break;
35391:
35392: case SM: // place dtors after all "converted" DCLs
35393: if (t1) {
35394: // ccheck(e);
35395: for (Pstmt ttt, tt=this;
35396: (ttt=tt->s_list) && ttt->base==SM;
35397: tt = ttt) ;
35398: t2->s_list = ttt;
35399: tt->s_list = ss;
35400: //Cstmt = ostmt;
35401: return t1!=tt ? t1 : t2;
35402: }
35403: default:
35404: def:
35405: // if (e) ccheck(e);
35406: if (t1) { // t1 == tail of statment list
35407: t2->s_list = s_list;
35408: s_list = ss;
35409: //Cstmt = ostmt;
35410: return t1;
35411: }
35412: s_list = ss;
35413: //Cstmt = ostmt;
35414: return t2;
35415: }
35416: }
35417: //Cstmt = ostmt;
35418: return (t1) ? t1 : this;
35419: }
35420:
35421: //Cstmt = ostmt;
35422: return (s_list) ? s_list->simpl() : this;
35423: }
35424:
35425: Pstmt stmt::copy()
35426: // now handles dtors in the expression of an IF stmt
35427: // not general!
35428: {
35429: Pstmt ns = new stmt(0,curloc,0);
35430:
35431: *ns = *this;
35432: if (s) ns->s = s->copy();
35433: if (s_list) ns->s_list = s_list->copy();
35434:
35435: switch (base) {
35436: case PAIR:
35437: ns->s2 = s2->copy();
35438: break;
35439: }
35440:
35441: return ns;
35442: }
35443:
35444: Pname overFound = 0;
35445:
35446: static Pexpr
35447: mk_new_with_args( Pexpr pe, Ptype tt, Pclass cl, Pexpr vec = 0 )
35448: { // allocate using operator new(sizeof(cl),args1)
35449: Pexpr p;
35450: Pexpr args = pe->e2;
35451:
35452: // Pexpr ce = new texpr(SIZEOF,tt,0);
35453: Pexpr ce;
35454: if (vec)
35455: ce = vec;
35456: else ce = new texpr(SIZEOF,tt,0);
35457:
35458: (void) tt->tsizeof();
35459: ce->tp = size_t_type;
35460: args = new expr(ELIST,ce,args);
35461: char* s = oper_name(NEW);
35462: Pname n = new name(s);
35463: if (pe->base == GNEW) // ::new
35464: p = gtbl->look(s,0);
35465: else
35466: p = find_name(n,cl,scope,CALL,curr_fct);
35467: p = new call(p,args);
35468: overFound=0; // set in call_fct
35469: (void) p->call_fct(cl->memtbl);
35470: if (overFound && overFound->n_scope != EXTERN)
35471: check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
35472: overFound=0;
35473: return p;
35474: }
35475:
35476: void expr::simpl_new()
35477: /*
35478: change NEW or GNEW node to CALL node
35479: */
35480: {
35481: Pname cln;
35482: Pname ctor;
35483: int sz = 1;
35484: // int esz;
35485: Pexpr var_expr = 0;
35486: Pexpr const_expr = 0;
35487: Ptype tt = tp2;
35488: Pexpr arg;
35489: Pexpr szof;
35490: Pname nf;
35491: Pexpr init = e1;
35492:
35493: if (init && init->base) init = 0; // only non-ctor init
35494: // error('d',"simpl_new %k e1 %k e2 %k init %k",base, e1?e1->base:0,e2?e2->base:0,init?init->base:0);
35495:
35496: if ((cln=tt->is_cl_obj()) && init == 0) {
35497: Pclass cl = Pclass(cln->tp);
35498: Pexpr p;
35499: ctor=cl->has_ctor();
35500: // error('d',"cl %t ctor %n",cl, ctor);
35501: if (e2 // placement
35502: || ctor==0 // no constructor
35503: || ctor->n_table!=cl->memtbl // inherited constructor???
35504: || (base==GNEW && cl->has_oper(NEW)) )
35505: p = mk_new_with_args( this, tt, cl ); // new(sizeof(cl),args1)
35506: else {
35507: p = zero; // 0->ctor(args)
35508: // check visibility anyway...
35509: (void)mk_new_with_args(this,tt,cl);
35510: }
35511:
35512: if (ctor) {
35513: Pexpr c = e1; // ctor call generated in expr::typ
35514: Ptype ttt = tp;
35515: c->e1->e1 = p; // p->ctor
35516: c->simpl();
35517: *this = *c;
35518: tp = ttt;
35519: delete c;
35520: }
35521: else { // (tp)new(args)
35522: base = CAST;
35523: tp2 = tp;
35524: e1 = p;
35525: e2 = 0;
35526: simpl();
35527: }
35528: return;
35529: } else if ( cln ) {
35530: Pclass cl = Pclass(cln->tp);
35531: // check visibility anyway...
35532: (void)mk_new_with_args(this,tt,cl);
35533: }
35534:
35535: Pclass covn = 0;
35536: if (cl_obj_vec) {
35537: covn = Pclass(cl_obj_vec->tp);
35538: ctor = covn->has_ictor();
35539: if (ctor == 0) {
35540: if (covn->has_ctor()) error("new %s[], no defaultK",covn->string);
35541: cl_obj_vec = 0;
35542: }
35543: }
35544:
35545: xxx:
35546: //error('d',"xxx %t",tt);
35547: switch (tt->base) {
35548: case TYPE:
35549: tt = Pbase(tt)->b_name->tp;
35550: goto xxx;
35551:
35552: default:
35553: (void) tt->tsizeof();
35554: szof = new texpr(SIZEOF,tt,0);
35555: szof->tp = uint_type;
35556: break;
35557:
35558: case VEC:
35559: { Pvec v = Pvec(tt);
35560: //error('d',"v %d %d",v->size,v->dim);
35561: if (v->size)
35562: sz *= v->size;
35563: else if (v->dim)
35564: var_expr = v->dim;
35565: else
35566: sz = 0;
35567: tt = v->typ;
35568: goto xxx;
35569: }
35570: }
35571:
35572: if (cl_obj_vec) { // _vec_new(0,no_of_elements,element_size,ctor)
35573: const_expr = new ival(sz);
35574: Pexpr noe = (var_expr) ? (sz!=1) ? new expr(MUL,const_expr,var_expr) : var_expr : const_expr;
35575: const_expr = szof;
35576: const_expr->tp = uint_type;
35577: base = CALL;
35578: arg = new expr(ELIST,ctor,0);
35579: /*ctor->take_addr();*/
35580: ctor->lval(ADDROF);
35581: Pexpr sub=0;
35582: if (e2 && e2->e1 &&
35583: e2->e1->tp &&
35584: e2->e1->tp->base != PTR )
35585: { // new(size_t, args)
35586: Pexpr vec_sz = new expr(MUL, noe, const_expr);
35587: sub = mk_new_with_args( this, tt, covn, vec_sz );
35588: }
35589: arg = new expr(ELIST,const_expr,arg);
35590: arg = new expr(ELIST,noe,arg);
35591: // arg = new expr(ELIST,e2?e2:zero,arg); // may be preallocated
35592: arg = new expr(ELIST,e2?(sub?sub:e2):zero,arg); // may be preallocated
35593: base = CAST;
35594: tp2 = tp;
35595: e1 = new expr(G_CALL,vec_new_fct,arg);
35596: e1->fct_name = vec_new_fct;
35597: e1->tp = Pfct(vec_new_fct->tp)->returns;
35598: simpl();
35599: return;
35600: }
35601:
35602: /* call _new(element_size*no_of_elements) */
35603: //error('d',"sz %d var %d",sz,var_expr);
35604: if (sz == 1)
35605: arg = (var_expr) ? new expr(MUL,szof,var_expr) : szof;
35606: else {
35607: const_expr = new ival(sz);
35608: const_expr->tp = uint_type;
35609: const_expr = new expr(MUL,const_expr,szof);
35610: const_expr->tp = uint_type;
35611: arg = (var_expr) ? new expr(MUL,const_expr,var_expr) : const_expr;
35612: }
35613:
35614: arg->tp = uint_type;
35615: base = CAST;
35616: tp2 = tp;
35617: arg = new expr(ELIST,arg,e2);
35618: nf = gtbl->look(oper_name(NEW),0); // always global,
35619: // all class object handled above
35620: e1 = new expr(G_CALL,nf,arg);
35621: (void) e1->call_fct(gtbl);
35622: simpl();
35623:
35624: if (init) { // alloc(sz) => (p=alloc(sz),*p=init,p);
35625: Pexpr p = init->e1;
35626: Pexpr ee = new expr(0,0,0);
35627: *ee = *this;
35628: ee = new expr(ASSIGN,p,ee); // ee: p = alloc(sz);
35629: init->base = ASSIGN;
35630: init->e1 = p->contents(); // init: *p = init_val
35631: ee = new expr(CM,ee,init);
35632: ee->simpl();
35633: base = CM;
35634: e1 = ee;
35635: e2 = p;
35636: }
35637: }
35638:
35639: void expr::simpl_delete()
35640: /*
35641: delete p => _delete(p);
35642: or cl::~cl(p,1);
35643: delete[s]p => _delete(p);
35644: or vec_del_fct(p,vec_sz,elem_sz,~cl,1);
35645: */
35646: {
35647: for (Ptype tt = e1->tp; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
35648: tt = Pptr(tt)->typ;
35649: //error('d',"simpl_delete() %t",e1->tp);
35650: Pname cln = tt->is_cl_obj();
35651: Pname n;
35652: Pclass cl;
35653:
35654: if (cln) {
35655: cl = Pclass(cln->tp);
35656: if ((cl->defined&DEFINED) == 0) error('w',"delete%t (%t not defined)",cl,cl);
35657: }
35658: else
35659: cl = 0;
35660:
35661: if (cl && (n=cl->has_dtor())) { // ~cl() might be virtual
35662: //xxx check for private/protected op delete
35663: {
35664: Pexpr ee = new expr(ELIST,e1,0);
35665: char* s = oper_name(DELETE);
35666: Pname n;
35667: //error('d',"%s( %k )",s,e1->base);
35668: if (base!=GDELETE) {
35669: n = new name(s);
35670: n = (Pname)find_name(n,cl,scope,CALL,curr_fct);
35671: //error('d',"found%n %t",n,n->tp);
35672: if (n->tp->base==OVERLOAD
35673: || Pfct(n->tp)->nargs==2) {
35674: Pexpr ss = new texpr(SIZEOF,cl,0);
35675: ss->tp = size_t_type;
35676: ee->e2 = new expr(ELIST,ss,0);
35677: }
35678: }
35679: else
35680: n = gtbl->look(s,0);
35681: //error('d',"found%n %t",n,n->tp);
35682: ee = new call(n,ee);
35683: ee->base = G_CALL;
35684: //error('d',"delete..."); display_expr(ee);
35685: // following commented out to avoid typ::checking problems
35686: //overFound=0; // set in call_fct
35687: //(void) ee->call_fct(cl->memtbl);
35688: //if (overFound && overFound->n_scope != EXTERN)
35689: //check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
35690: //overFound=0;
35691: }
35692:
35693: //if ( base!=GDELETE ) (void) cl->has_oper(DELETE);
35694:
35695: if(base==GDELETE && e2==0 || Pfct(n->tp)->f_virtual) { // may need temp
35696: nin=1;
35697: int needtemp = e1->not_simple();
35698: nin=0;
35699: if(needtemp) {
35700: // convert: delete [e2] e1
35701: // to: (T=e1), delete [e2] T
35702: // where T is a new temporary.
35703: Pname tnx = new name(make_name('K'));
35704: tnx->tp = e1->tp;
35705: Pname tn = tnx->dcl(scope,FCT);
35706: delete tnx;
35707: tn->assign();
35708: e1 = new expr(ASSIGN,tn,e1);
35709: e2 = new expr(base,tn,e2);
35710: base=CM;
35711:
35712: simpl();
35713: return;
35714: }
35715: }
35716: Pexpr r = e1;
35717:
35718: // handle delete p, where p has a private destructor
35719: if (n->n_scope != PUBLIC) check_visibility(n,0,cl,cc->ftbl,cc->nof);
35720: //error('d',"e2 %d %k",e2,base);
35721: if (e2 == 0) { // e1->cl::~cl(1)
35722: Pexpr ee = call_dtor(r,n,base==GDELETE?0:one,REF,one);
35723: if (Pfct(n->tp)->f_virtual) {
35724: if (ansi_opt) { // q?void:int would be an error
35725: ee = new expr(G_CM,ee,zero);
35726: ee->tp = zero_type;
35727: }
35728: ee = new expr(QUEST,ee,zero);
35729: ee->tp = ee->e1->tp;
35730: ee->cond = r;
35731: }
35732: if (base == GDELETE) {
35733: char* s = oper_name(DELETE);
35734: Pexpr p = gtbl->look(s,0);
35735: e2 = new call(p,new expr(ELIST,e1,0));
35736: base = CM;
35737: e1 = ee;
35738: }
35739: else {
35740: *this = *ee;
35741: delete ee;
35742: }
35743: simpl();
35744: return;
35745: }
35746: else { // del_cl_vec(e1,e2,elem_size,~cl,1);
35747: Pexpr sz = new texpr(SIZEOF,tt,0);
35748: (void)tt->tsizeof();
35749: Pfct f = Pfct(n->tp);
35750: int i = 0;
35751: Pname nn = f->f_args->n_list;
35752: for (; nn && nn->n_list; nn=nn->n_list) i++;
35753: //error('d',"n %n i %d",n,i);
35754: Pexpr arg = new ival(i);
35755: sz->tp = uint_type;
35756: // Pexpr arg = one;
35757: arg = new expr(ELIST,one,arg);
35758: if (Pfct(n->tp)->f_virtual) {
35759: Pexpr a = new ref(REF,e1,n);
35760: a = a->address();
35761: a = new mdot( "f", a );
35762: a->i1 = 9;
35763: arg = new expr(ELIST,a,arg);
35764: }
35765: else {
35766: arg = new expr(ELIST,n,arg);
35767: n->lval(ADDROF); // n->take_addr();
35768: }
35769:
35770: arg = new expr(ELIST,sz,arg);
35771: if (e2->base==DUMMY) {
35772: e2 = new ival(-1); // handle `delete[]p'
35773: }
35774:
35775: arg = new expr(ELIST,e2,arg);
35776: arg = new expr(ELIST,e1,arg);
35777: Pexpr ee = new expr(G_CALL,vec_del_fct,arg);
35778: ee->fct_name = vec_del_fct;
35779: ee->tp = tp;
35780: // if (ansi_opt) { // q?void:int would be an error
35781: // ee = new expr(G_CM,ee,zero);
35782: // ee->tp = zero_type;
35783: // }
35784: // ee = new expr(QUEST,ee,zero);
35785: // ee->tp = tp;
35786: // ee->cond = r;
35787: *this = *ee;
35788: simpl();
35789: return;
35790: }
35791: }
35792: else if (cl_obj_vec) {
35793: error("delete array of arrays");
35794: }
35795: else { // _delete(e1)
35796: Pexpr ee = new expr(ELIST,e1,0);
35797: char* s = oper_name(DELETE);
35798: if (cl && base!=GDELETE) {
35799: Pname n = new name(s);
35800: e1 = find_name(n,cl,scope,CALL,curr_fct);
35801: if (e1->tp->base==OVERLOAD || Pfct(e1->tp)->nargs==2) {
35802: Pexpr ss = new texpr(SIZEOF,cl,0);
35803: ss->tp = size_t_type;
35804: ee->e2 = new expr(ELIST,ss,0);
35805: }
35806: }
35807: else
35808: e1 = gtbl->look(s,0);
35809: base = G_CALL;
35810: e2 = ee;
35811: overFound=0; // set in call_fct
35812: (void) call_fct(scope);
35813: if (overFound && overFound->n_scope != EXTERN)
35814: check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
35815: overFound=0;
35816: }
35817:
35818: Pcall(this)->simpl();
35819: }
35820: 0707071010112045371004440001630000160000010207600466055410400000700000013461size.c /*ident "@(#)ctrans:src/size.c 1.3" */
35821: /*********************************************************************
35822:
35823: C++ source for cfront, the C++ compiler front-end
35824: written in the computer science research center of Bell Labs
35825:
35826: Copyright (c) 1984 AT&T, Inc. All rigths Reserved
35827: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
35828:
35829: size.c:
35830:
35831: initialize alignment and sizeof "constants"
35832:
35833: **********************************************************************/
35834:
35835: #include "cfront.h"
35836: #include "size.h"
35837:
35838: int BI_IN_WORD = DBI_IN_WORD;
35839: int BI_IN_BYTE = DBI_IN_BYTE;
35840: int SZ_CHAR = DSZ_CHAR;
35841: int AL_CHAR = DAL_CHAR;
35842: int SZ_SHORT = DSZ_SHORT;
35843: int AL_SHORT = DAL_SHORT;
35844: int SZ_INT = DSZ_INT;
35845: int AL_INT = DAL_INT;
35846: int SZ_LONG = DSZ_LONG;
35847: int AL_LONG = DAL_LONG;
35848: int SZ_FLOAT = DSZ_FLOAT;
35849: int AL_FLOAT = DAL_FLOAT;
35850: int SZ_DOUBLE = DSZ_DOUBLE;
35851: int AL_DOUBLE = DAL_DOUBLE;
35852: int SZ_LDOUBLE = DSZ_LDOUBLE;
35853: int AL_LDOUBLE = DAL_LDOUBLE;
35854: int SZ_STRUCT = DSZ_STRUCT;
35855: int AL_STRUCT = DAL_STRUCT;
35856: //int SZ_FRAME = DSZ_FRAME;
35857: //int AL_FRAME = DAL_FRAME;
35858: int SZ_WORD = DSZ_WORD;
35859: int SZ_WPTR = DSZ_WPTR;
35860: int AL_WPTR = DAL_WPTR;
35861: int SZ_BPTR = DSZ_BPTR;
35862: int AL_BPTR = DAL_BPTR;
35863: //int SZ_TOP = DSZ_TOP;
35864: //int SZ_BOTTOM = DSZ_BOTTOM;
35865: char* LARGEST_INT = DLARGEST_INT;
35866: int F_SENSITIVE = DF_SENSITIVE;
35867: int F_OPTIMIZED = DF_OPTIMIZED;
35868:
35869: int arg1 = 0;
35870:
35871: int get_line(FILE* fp)
35872: {
35873: char s[32];
35874: char s2[32];
35875:
35876: if (fscanf(fp,"%s %s",s2,s) == EOF) return 0;
35877:
35878: if (strcmp("DLARGEST_INT",s) == 0) {
35879: if (fscanf(fp," %s",s2)==EOF) return 0;
35880: //// get rid of quotes
35881: for(int i=0;i<=strlen(s2)+1;i++)
35882: if (s2[i]== '"') {
35883: for (int j=i;j<=strlen(s2)+1;j++)
35884: s2[j]=s2[j+1];
35885: }
35886: }
35887: else
35888: if (fscanf(fp,"%d ",&arg1) == EOF) return 0;
35889:
35890: if (strcmp("DSZ_CHAR",s) == 0) {
35891: SZ_CHAR = arg1;
35892: return 1;
35893: }
35894:
35895: if (strcmp("DAL_CHAR",s) == 0) {
35896: AL_CHAR = arg1;
35897: return 1;
35898: }
35899:
35900: if (strcmp("DSZ_SHORT",s) == 0) {
35901: SZ_SHORT = arg1;
35902: return 1;
35903: }
35904:
35905: if (strcmp("DAL_SHORT",s) == 0) {
35906: AL_SHORT = arg1;
35907: return 1;
35908: }
35909:
35910: if (strcmp("DSZ_INT",s) == 0) {
35911: SZ_INT = arg1;
35912: return 1;
35913: }
35914:
35915: if (strcmp("DAL_INT",s) == 0) {
35916: AL_INT=arg1;
35917: return 1;
35918: }
35919:
35920: if (strcmp("DLARGEST_INT",s) == 0) {
35921: LARGEST_INT = new char[strlen(s2)+1];
35922: strcpy(LARGEST_INT,s2);
35923: return 1;
35924: }
35925:
35926: if (strcmp("DSZ_LONG",s) == 0) {
35927: SZ_LONG = arg1;
35928: return 1;
35929: }
35930:
35931: if (strcmp("DAL_LONG",s) == 0) {
35932: AL_LONG = arg1;
35933: return 1;
35934: }
35935:
35936: if (strcmp("DSZ_FLOAT",s) == 0) {
35937: SZ_FLOAT = arg1;
35938: return 1;
35939: }
35940:
35941: if (strcmp("DAL_FLOAT",s) == 0) {
35942: AL_FLOAT = arg1;
35943: return 1;
35944: }
35945:
35946: if (strcmp("DSZ_DOUBLE",s) == 0) {
35947: SZ_DOUBLE = arg1;
35948: return 1;
35949: }
35950:
35951: if (strcmp("DAL_DOUBLE",s) == 0) {
35952: AL_DOUBLE = arg1;
35953: return 1;
35954: }
35955:
35956: if (strcmp("DSZ_LDOUBLE",s) == 0) {
35957: SZ_LDOUBLE = arg1;
35958: return 1;
35959: }
35960:
35961: if (strcmp("DAL_LDOUBLE",s) == 0) {
35962: AL_LDOUBLE = arg1;
35963: return 1;
35964: }
35965:
35966: if (strcmp("DBI_IN_BYTE",s) == 0) {
35967: BI_IN_BYTE = arg1;
35968: return 1;
35969: }
35970:
35971: if (strcmp("DBI_IN_WORD",s) == 0) {
35972: BI_IN_WORD= arg1;
35973: return 1;
35974: }
35975:
35976: if (strcmp("DSZ_STRUCT",s) == 0) {
35977: SZ_STRUCT = arg1;
35978: return 1;
35979: }
35980:
35981: if (strcmp("DAL_STRUCT",s) == 0) {
35982: AL_STRUCT = arg1;
35983: return 1;
35984: }
35985:
35986: if (strcmp("DF_SENSITIVE",s) == 0) {
35987: F_SENSITIVE = arg1;
35988: return 1;
35989: }
35990:
35991: if (strcmp("DF_OPTIMIZED",s) == 0) {
35992: F_OPTIMIZED = arg1;
35993: return 1;
35994: }
35995:
35996: if (strcmp("frame",s) == 0) {
35997: // SZ_FRAME = arg1;
35998: // AL_FRAME = arg2;
35999: return 1;
36000: }
36001:
36002: if (strcmp("DSZ_WORD",s) == 0) {
36003: SZ_WORD = arg1;
36004: return 1;
36005: }
36006:
36007: if (strcmp("DSZ_WPTR",s) == 0) {
36008: SZ_WPTR = arg1;
36009: return 1;
36010: }
36011:
36012: if (strcmp("DAL_WPTR",s) == 0) {
36013: AL_WPTR = arg1;
36014: return 1;
36015: }
36016:
36017: if (strcmp("DSZ_BPTR",s) == 0) {
36018: SZ_BPTR = arg1;
36019: return 1;
36020: }
36021:
36022: if (strcmp("DAL_BPTR",s) == 0) {
36023: AL_BPTR = arg1;
36024: return 1;
36025: }
36026:
36027: if (strcmp("top",s) == 0) {
36028: // SZ_TOP = arg1;
36029: // SZ_BOTTOM = arg2;
36030: return 1;
36031: }
36032: return 0;
36033: }
36034:
36035: int read_align(char* f)
36036: {
36037: char* p = f;
36038: if (*p == 0) {
36039: fprintf(stderr,"size/align file missing\n");
36040: ext(1);
36041: }
36042: FILE* fp = fopen(f,"r");
36043: if (fp == 0) return 1;
36044: while (get_line(fp)) ;
36045: return 0;
36046: }
36047: /*
36048: print_align(char* s)
36049: {
36050: fprintf(stderr,"%s sizes and alignments\n\n",s);
36051:
36052: fprintf(stderr," size align largest\n");
36053: fprintf(stderr,"char %d %d\n",SZ_CHAR,AL_CHAR);
36054: fprintf(stderr,"short %d %d\n",SZ_SHORT,AL_SHORT);
36055: fprintf(stderr,"int %d %d %s\n",SZ_INT,AL_INT,LARGEST_INT);
36056: fprintf(stderr,"long %d %d\n",SZ_LONG,AL_LONG);
36057: fprintf(stderr,"float %d %d\n",SZ_FLOAT,AL_FLOAT);
36058: fprintf(stderr,"double %d %d\n",SZ_DOUBLE,AL_DOUBLE);
36059: fprintf(stderr,"ldouble %d %d\n",SZ_LDOUBLE,AL_LDOUBLE);
36060: fprintf(stderr,"bptr %d %d\n",SZ_BPTR,AL_BPTR);
36061: fprintf(stderr,"wptr %d %d\n",SZ_WPTR,AL_WPTR);
36062: fprintf(stderr,"struct %d %d\n",SZ_STRUCT,AL_STRUCT);
36063: fprintf(stderr,"struct2 %d %d\n",F_SENSITIVE,F_OPTIMIZED);
36064: // fprintf(stderr,"frame %d %d\n",SZ_FRAME,AL_FRAME);
36065:
36066: fprintf(stderr,"%d bits in a byte, %d bits in a word, %d bytes in a word\n",
36067: BI_IN_BYTE, BI_IN_WORD, SZ_WORD);
36068: return 1;
36069: }
36070: */
36071:
36072: int c_strlen(const char* s)
36073: /*
36074: return sizeof(s) with escapes processed
36075: sizeof("") == 1 the terminating 0
36076: sizeof("a") == 2
36077: sizeof("\0x") == 3 0 x 0
36078: sizeof("\012") == 2 '\012'
36079: sizeof("\01") '\001'
36080: sizeof("\x") == 2 \ ignored
36081:
36082: */
36083: {
36084: int i = 1;
36085: for (const char* p = s; *p; i++,p++) {
36086: if (*p == '\\') { // '\?
36087: switch (*++p) {
36088: case '0':
36089: switch (p[1]) { // '\01' or '\012'
36090: case '0': case '1': case '2': case '3':
36091: case '4': case '5': case '6': case '7':
36092: break;
36093: default:
36094: continue; // '\0'
36095: }
36096: /* no break */
36097: case '1': case '2': case '3':
36098: case '4': case '5': case '6': case '7': // '\123'
36099: switch (*++p) {
36100: case '0': case '1': case '2': case '3':
36101: case '4': case '5': case '6': case '7':
36102: switch (*++p) {
36103: case '0': case '1': case '2': case '3':
36104: case '4': case '5': case '6': case '7':
36105: break;
36106: default:
36107: --p;
36108: }
36109: break;
36110: default:
36111: --p;
36112: break;
36113: }
36114: break;
36115: case '\n': // \newline doesn't count
36116: i--;
36117: break;
36118: }
36119: }
36120: }
36121: return i;
36122: }
36123: 0707071010112045661004440001630000160000010207700466055411000000700000020157size.h /*ident "@(#)ctrans:src/size.h 1.2" */
36124: /*************************************************************************
36125:
36126: C++ source for cfront, the C++ compiler front-end
36127: written in the computer science research center of Bell Labs
36128:
36129: Copyright (c) 1984 AT&T, Inc. All rigths Reserved
36130: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
36131:
36132: size.h:
36133: sizes and alignments used to calculate sizeofs
36134:
36135: table and butffer sizes
36136:
36137: ***************************************************************************/
36138: #ifndef GRAM
36139: extern BI_IN_WORD;
36140: extern BI_IN_BYTE;
36141: /* byte sizes */
36142: extern SZ_CHAR;
36143: extern AL_CHAR;
36144:
36145: extern SZ_SHORT;
36146: extern AL_SHORT;
36147:
36148: extern SZ_INT;
36149: extern AL_INT;
36150:
36151: extern SZ_LONG;
36152: extern AL_LONG;
36153:
36154: extern SZ_FLOAT;
36155: extern AL_FLOAT;
36156:
36157: extern SZ_DOUBLE;
36158: extern AL_DOUBLE;
36159:
36160: extern SZ_LDOUBLE;
36161: extern AL_LDOUBLE;
36162:
36163: extern SZ_STRUCT; /* minimum struct size */
36164: extern AL_STRUCT;
36165:
36166: //extern SZ_FRAME;
36167: //extern AL_FRAME;
36168:
36169: extern SZ_WORD;
36170:
36171: extern SZ_WPTR;
36172: extern AL_WPTR;
36173:
36174: extern SZ_BPTR;
36175: extern AL_BPTR;
36176:
36177: //extern SZ_TOP;
36178: //extern SZ_BOTTOM;
36179:
36180: extern char* LARGEST_INT;
36181: extern int F_SENSITIVE; // is field alignment sensitive to the type of the field?
36182: extern int F_OPTIMIZED; // can the compiler fit a small int field into a char?
36183: #endif
36184: // default sizes:
36185: // Note: #if doesn't work on all systems
36186: #ifdef u3b
36187: #define Abbb
36188: #endif
36189: #ifdef u3b2
36190: #define Abbb
36191: #endif
36192: #ifdef u3b5
36193: #define Abbb
36194: #endif
36195: #ifdef u3b15
36196: #define Abbb
36197: #endif
36198: #ifdef pyr
36199: #define Abbb
36200: #endif
36201:
36202:
36203: #ifdef alliant
36204: #define Am68
36205: #endif
36206: #ifdef apollo
36207: #define Am68
36208: #endif
36209: #if defined(sun2) || defined(mc68010)
36210: #define Am68
36211: #endif
36212: #if defined(sun3) || defined(mc68020)
36213: #define Am68
36214: #endif
36215: #if defined(mc68k) || defined(hp9000s200) || defined(hp9000s300)
36216: #define Am68
36217: #endif
36218:
36219: #ifdef iAPX286
36220: #ifdef LARGE
36221: #define Ai286l
36222: #endif
36223: #endif
36224:
36225: #ifdef Abbb
36226: /* AT&T 3Bs */
36227: #define DBI_IN_WORD 32
36228: #define DBI_IN_BYTE 8
36229: #define DSZ_CHAR 1
36230: #define DAL_CHAR 1
36231: #define DSZ_SHORT 2
36232: #define DAL_SHORT 2
36233: #define DSZ_INT 4
36234: #define DAL_INT 4
36235: #define DSZ_LONG 4
36236: #define DAL_LONG 4
36237: #define DSZ_FLOAT 4
36238: #define DAL_FLOAT 4
36239: #define DSZ_DOUBLE 8
36240: #define DAL_DOUBLE 4
36241: #define DSZ_LDOUBLE 8
36242: #define DAL_LDOUBLE 4
36243: #define DSZ_STRUCT 4
36244: #define DAL_STRUCT 4
36245: //#define DSZ_FRAME 4
36246: //#define DAL_FRAME 4
36247: #define DSZ_WORD 4
36248: #define DSZ_WPTR 4
36249: #define DAL_WPTR 4
36250: #define DSZ_BPTR 4
36251: #define DAL_BPTR 4
36252: //#define DSZ_TOP 0
36253: //#define DSZ_BOTTOM 0
36254: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36255: #define DF_SENSITIVE 0
36256: #define DF_OPTIMIZED 1
36257: #else
36258: #ifdef Am68
36259: /* most M68K boxes */
36260: #if defined(hp9000s200) || defined(hp9000s300)
36261: #define DBI_IN_WORD 32
36262: #else
36263: #define DBI_IN_WORD 16
36264: #endif
36265: #define DBI_IN_BYTE 8
36266: #define DSZ_CHAR 1
36267: #define DAL_CHAR 1
36268: #define DSZ_SHORT 2
36269: #define DAL_SHORT 2
36270: #define DSZ_INT 4
36271: #define DAL_INT 2
36272: #define DSZ_LONG 4
36273: #define DAL_LONG 2
36274: #define DSZ_FLOAT 4
36275: #define DAL_FLOAT 2
36276: #define DSZ_DOUBLE 8
36277: #define DAL_DOUBLE 2
36278: #define DSZ_LDOUBLE 8
36279: #define DAL_LDOUBLE 2
36280: #define DSZ_STRUCT 2
36281: #define DAL_STRUCT 2
36282: //#define DSZ_FRAME 4
36283: //#define DAL_FRAME 4
36284: #define DSZ_WORD 2
36285: #define DSZ_WPTR 4
36286: #define DAL_WPTR 2
36287: #define DSZ_BPTR 4
36288: #define DAL_BPTR 2
36289: //#define DSZ_TOP 0
36290: //#define DSZ_BOTTOM 0
36291: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36292: #define DF_SENSITIVE 0
36293: #define DF_OPTIMIZED 1
36294: #else
36295: #ifdef Ai286l
36296: /* Intel 80286 large model */
36297: #define DBI_IN_WORD 16
36298: #define DBI_IN_BYTE 8
36299: #define DSZ_CHAR 1
36300: #define DAL_CHAR 1
36301: #define DSZ_SHORT 2
36302: #define DAL_SHORT 2
36303: #define DSZ_INT 2
36304: #define DAL_INT 2
36305: #define DSZ_LONG 4
36306: #define DAL_LONG 2
36307: #define DSZ_FLOAT 4
36308: #define DAL_FLOAT 2
36309: #define DSZ_DOUBLE 8
36310: #define DAL_DOUBLE 2
36311: #define DSZ_LDOUBLE 8
36312: #define DAL_LDOUBLE 2
36313: #define DSZ_STRUCT 2
36314: #define DAL_STRUCT 2
36315: //#define DSZ_FRAME 4
36316: //#define DAL_FRAME 4
36317: #define DSZ_WORD 2
36318: #define DSZ_WPTR 4
36319: #define DAL_WPTR 2
36320: #define DSZ_BPTR 4
36321: #define DAL_BPTR 2
36322: //#define DSZ_TOP 0
36323: //#define DSZ_BOTTOM 0
36324: #define DLARGEST_INT "32767" /* 2**15 - 1 */
36325: #define DF_SENSITIVE 0
36326: #define DF_OPTIMIZED 1
36327: #else
36328: #if defined(uts) || defined(hp9000s800) || defined(sun4) || defined(sparc)
36329: /* Amdahl running UTS, HP RISC */
36330: #define DBI_IN_WORD 32
36331: #define DBI_IN_BYTE 8
36332: #define DSZ_CHAR 1
36333: #define DAL_CHAR 1
36334: #define DSZ_SHORT 2
36335: #define DAL_SHORT 2
36336: #define DSZ_INT 4
36337: #define DAL_INT 4
36338: #define DSZ_LONG 4
36339: #define DAL_LONG 4
36340: #define DSZ_FLOAT 4
36341: #define DAL_FLOAT 4
36342: #define DSZ_DOUBLE 8
36343: #define DAL_DOUBLE 8
36344: #define DSZ_LDOUBLE 8
36345: #define DAL_LDOUBLE 8
36346: #define DSZ_STRUCT 1
36347: #define DAL_STRUCT 1
36348: #define DSZ_WORD 4
36349: #define DSZ_WPTR 4
36350: #define DAL_WPTR 4
36351: #define DSZ_BPTR 4
36352: #define DAL_BPTR 4
36353: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36354: #if defined(uts)
36355: #define DF_SENSITIVE 1
36356: #else
36357: #define DF_SENSITIVE 0
36358: #endif
36359: #define DF_OPTIMIZED 1
36360: #else
36361: #ifdef hpux
36362: /* hp */
36363: #define DBI_IN_WORD 32
36364: #define DBI_IN_BYTE 8
36365: #define DSZ_CHAR 1
36366: #define DAL_CHAR 1
36367: #define DSZ_SHORT 2
36368: #define DAL_SHORT 2
36369: #define DSZ_INT 4
36370: #define DAL_INT 4
36371: #define DSZ_LONG 4
36372: #define DAL_LONG 4
36373: #define DSZ_FLOAT 4
36374: #define DAL_FLOAT 4
36375: #define DSZ_DOUBLE 8
36376: #define DAL_DOUBLE 8
36377: #define DSZ_LDOUBLE 8
36378: #define DAL_LDOUBLE 8
36379: #define DSZ_STRUCT 1
36380: #define DAL_STRUCT 1
36381: #define DSZ_WORD 4
36382: #define DSZ_WPTR 4
36383: #define DAL_WPTR 4
36384: #define DSZ_BPTR 4
36385: #define DAL_BPTR 4
36386: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36387: #define DF_SENSITIVE 1
36388: #define DF_OPTIMIZED 1
36389: #else
36390: #if defined(vax) || defined(ibm032) || defined(i386)
36391: /* VAX, IBM 32, Intel 386 */
36392: #define DBI_IN_WORD 32
36393: #define DBI_IN_BYTE 8
36394: #define DSZ_CHAR 1
36395: #define DAL_CHAR 1
36396: #define DSZ_SHORT 2
36397: #define DAL_SHORT 2
36398: #define DSZ_INT 4
36399: #define DAL_INT 4
36400: #define DSZ_LONG 4
36401: #define DAL_LONG 4
36402: #define DSZ_FLOAT 4
36403: #define DAL_FLOAT 4
36404: #define DSZ_DOUBLE 8
36405: #define DAL_DOUBLE 4
36406: #define DSZ_LDOUBLE 8
36407: #define DAL_LDOUBLE 4
36408: #define DSZ_STRUCT 1
36409: #define DAL_STRUCT 1
36410: //#define DSZ_FRAME 4
36411: //#define DAL_FRAME 4
36412: #define DSZ_WORD 4
36413: #define DSZ_WPTR 4
36414: #define DAL_WPTR 4
36415: #define DSZ_BPTR 4
36416: #define DAL_BPTR 4
36417: //#define DSZ_TOP 0
36418: //#define DSZ_BOTTOM 0
36419: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36420: #define DF_SENSITIVE 0
36421: #define DF_OPTIMIZED 1
36422: #else
36423: #ifdef mc300
36424: #define DBI_IN_WORD 32
36425: #define DBI_IN_BYTE 8
36426: #define DSZ_CHAR 1
36427: #define DAL_CHAR 1
36428: #define DSZ_SHORT 2
36429: #define DAL_SHORT 2
36430: #define DSZ_INT 4
36431: #define DAL_INT 4
36432: #define DSZ_LONG 4
36433: #define DAL_LONG 4
36434: #define DSZ_FLOAT 4
36435: #define DAL_FLOAT 4
36436: #define DSZ_DOUBLE 8
36437: #define DAL_DOUBLE 4
36438: #define DSZ_LDOUBLE 8
36439: #define DAL_LDOUBLE 4
36440: #define DSZ_STRUCT 2
36441: #define DAL_STRUCT 2
36442: //#define DSZ_FRAME 4
36443: //#define DAL_FRAME 4
36444: #define DSZ_WORD 4
36445: #define DSZ_WPTR 4
36446: #define DAL_WPTR 4
36447: #define DSZ_BPTR 4
36448: #define DAL_BPTR 4
36449: //#define DSZ_TOP 0
36450: //#define DSZ_BOTTOM 0
36451: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */
36452: #define DF_SENSITIVE 0
36453: #define DF_OPTIMIZED 1
36454: #else
36455: #ifdef mips
36456: #define DBI_IN_BYTE 8
36457: #define DBI_IN_WORD 32
36458: #define DSZ_WORD 4
36459: #define DSZ_CHAR 1
36460: #define DAL_CHAR 1
36461: #define DSZ_SHORT 2
36462: #define DAL_SHORT 2
36463: #define DSZ_INT 4
36464: #define DAL_INT 4
36465: #define DLARGEST_INT "2147483647"
36466: #define DSZ_LONG 4
36467: #define DAL_LONG 4
36468: #define DSZ_FLOAT 4
36469: #define DAL_FLOAT 4
36470: #define DSZ_DOUBLE 8
36471: #define DAL_DOUBLE 8
36472: #define DSZ_LDOUBLE 8
36473: #define DAL_LDOUBLE 8
36474: #define DSZ_BPTR 4
36475: #define DAL_BPTR 4
36476: #define DSZ_WPTR 4
36477: #define DAL_WPTR 4
36478: #define DSZ_STRUCT 1
36479: #define DAL_STRUCT 1
36480: #define DF_SENSITIVE 0
36481: #define DF_OPTIMIZED 1
36482: #else
36483: /* defaults: 0 => error */
36484: #define DBI_IN_WORD 0
36485: #define DBI_IN_BYTE 0
36486: #define DSZ_CHAR 1
36487: #define DAL_CHAR 1
36488: #define DSZ_SHORT 0
36489: #define DAL_SHORT 0
36490: #define DSZ_INT 0
36491: #define DAL_INT 0
36492: #define DSZ_LONG 0
36493: #define DAL_LONG 0
36494: #define DSZ_FLOAT 0
36495: #define DAL_FLOAT 0
36496: #define DSZ_DOUBLE 0
36497: #define DAL_DOUBLE 0
36498: #define DSZ_LDOUBLE 0
36499: #define DAL_LDOUBLE 0
36500: #define DSZ_STRUCT 0
36501: #define DAL_STRUCT 0
36502: #define DSZ_WORD 0
36503: #define DSZ_WPTR 0
36504: #define DAL_WPTR 0
36505: #define DSZ_BPTR 0
36506: #define DAL_BPTR 0
36507: #define DLARGEST_INT "0"
36508: #define DF_SENSITIVE 0
36509: #define DF_OPTIMIZED 0
36510: #endif
36511: #endif
36512: #endif
36513: #endif
36514: #endif
36515: #endif
36516: #endif
36517: #endif
36518:
36519: #define KTBLSIZE 123 /* initial keyword table size */
36520: #define GTBLSIZE 257 /* initial global name table size */
36521: #define CTBLSIZE 12 /* initial class table size */
36522: #define TBLSIZE 20 /* initial block table size */
36523: #define BLMAX 50 /* max block nesting */
36524: #define MAXFILE 127 /* max include file nesting */
36525: #define MAXERR 13 /* maximum number of errors before terminating */
36526:
36527: #ifndef GRAM
36528: const CHUNK = 8*1024;
36529: void* chunk(int);
36530: #endif
36531: 0707071010112045671004440001630000160000010210000466055411300001000000015476table.c /*ident "@(#)ctrans:src/table.c 1.3" */
36532: /**************************************************************************
36533:
36534: C++ source for cfront, the C++ compiler front-end
36535: written in the computer science research center of Bell Labs
36536:
36537: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
36538: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
36539:
36540: table.c:
36541:
36542: *****************************************************************************/
36543:
36544: #include "cfront.h"
36545: #include "size.h"
36546:
36547: #ifdef DBG
36548: extern long node_id;
36549: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__);
36550: #else
36551: #define DBCHECK() /**/
36552: #endif
36553:
36554: table::table(short sz, Ptable nx, Pname n)
36555: /*
36556: create a symbol table with "size" entries
36557: the scope of table is enclosed in the scope of "nx"
36558:
36559: both the vector of class name pointers and the hash table
36560: are initialized containing all zeroes
36561:
36562: to simplify hashed lookup entries[0] is never used
36563: so the size of "entries" must be "size+1" to hold "size" entries
36564: */
36565: {
36566: DBCHECK();
36567: base = TABLE;
36568: t_name = n;
36569: size = sz = (sz<=0) ? 2 : sz+1;
36570: //fprintf(stderr,"table::table %d %s %d (%d %d)\n", this, (n)?n->string:"?", sz,(sz*3)/2);
36571: entries = new Pname[sz];
36572: hashsize = sz = (sz*3)/2;
36573: hashtbl = new short[sz];
36574: next = nx;
36575: free_slot = 1;
36576: DBID();
36577: }
36578:
36579: table::~table()
36580: {
36581: delete entries;
36582: delete hashtbl;
36583: }
36584:
36585: Pname table::look(char* s, TOK k)
36586: /*
36587: look for "s" in table, ignore entries which are not of "k" type
36588: look and insert MUST be the same lookup algorithm
36589: */
36590: {
36591: Ptable t;
36592: register char * p;
36593: register char * q;
36594: register int i;
36595: Pname n;
36596: int rr;
36597:
36598: // if (s == 0) error('i',"%d->look(0)",this);
36599: // if (this == 0) error('i',"0->look(%s)",s);
36600: // if (base != TABLE) error('i',"(%d,%d)->look(%s)",this,base,s);
36601:
36602: /* use simple hashing with linear search for overflow */
36603:
36604: p = s;
36605: i = 0;
36606: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
36607: rr = (0<=i) ? i : -i;
36608:
36609: for (t=this; t; t=t->next) {
36610: /* in this and all enclosing scopes look for name "s" */
36611: Pname* np = t->entries;
36612: int mx = t->hashsize;
36613: short* hash = t->hashtbl;
36614: int firsti = i = rr%mx;
36615:
36616: do {
36617: if (hash[i] == 0) goto not_found;
36618: n = np[hash[i]];
36619: if (n == 0) error('i',"hashed lookup");
36620: p = n->string; /* strcmp(n->n_string,s) */
36621: q = s;
36622: while (*p && *q)
36623: if (*p++ != *q++) goto nxt;
36624: if (*p == *q) goto found;
36625: nxt:
36626: if (mx <= ++i) i = 0; /* wrap around */
36627: } while (i != firsti);
36628:
36629: found:
36630: for (; n; n=n->n_tbl_list){ /* for all name "s"s look for a key match */
36631: if (n->n_key == k) return n;
36632: }
36633:
36634: not_found:;
36635: }
36636:
36637: return 0; /* not found && no enclosing scope */
36638: }
36639:
36640: bit Nold; /* non-zero if last insert() failed */
36641:
36642: Pname table::insert(Pname nx, TOK k)
36643: /*
36644: the lookup algorithm MUST be the same as look
36645: if nx is found return the older entry otherwise a copy of nx;
36646: Nold = (nx found) ? 1 : 0;
36647: */
36648: {
36649: register char * p;
36650: register int i;
36651: Pname n;
36652: Pname* np = entries;
36653: Pname* link;
36654: int firsti;
36655: int mx = hashsize;
36656: short* hash = hashtbl;
36657: char* s = nx->string;
36658:
36659: if (s==0) error('i',"%p->insert(0,%k)",this,k);
36660: nx->n_key = k;
36661: if (nx->n_tbl_list || nx->n_table) error('i',"%n in two tables",nx);
36662: /* use simple hashing with linear search for overflow */
36663:
36664: p = s;
36665: i = 0;
36666: while (*p) i += (i + *p++);
36667: if (i<0) i = -i;
36668: firsti = i = i%mx;
36669:
36670: do { /* look for name "s" */
36671: if (hash[i] == 0) {
36672: hash[i] = free_slot;
36673: goto add_np;
36674: }
36675: n = np[hash[i]];
36676: if (n == 0) error('i',"hashed lookup");
36677: if (strcmp(n->string,s) == 0) goto found;
36678: /*
36679: p = n->string;
36680: q = s;
36681: while (*p && *q) if (*p++ != *q++) goto nxt;
36682: if (*p == *q) goto found;
36683: nxt:
36684: */
36685: if (mx <= ++i) i = 0; /* wrap around */
36686: } while (i != firsti);
36687:
36688: error("N table full");
36689:
36690: found:
36691:
36692:
36693: for(;;) {
36694: if ( k!=NESTED && n->n_key==k) { Nold = 1; return n; }
36695:
36696: if (n->n_tbl_list)
36697: n = n->n_tbl_list;
36698: else {
36699: link = &(n->n_tbl_list);
36700: goto re_allocate;
36701: }
36702: }
36703:
36704: add_np:
36705: if (size <= free_slot) {
36706: grow(2*size);
36707: return insert(nx,k);
36708: }
36709:
36710: link = &(np[free_slot++]);
36711:
36712: re_allocate:
36713: {
36714: Pname nw = new name;
36715: *nw = *nx;
36716: char* ps = new char[strlen(s)+1]; // copy string to safer store
36717: strcpy(ps,s);
36718: // Nstr++;
36719: nw->string = ps;
36720: nw->n_table = this;
36721: *link = nw;
36722: Nold = 0;
36723: // Nname++;
36724: return nw;
36725: }
36726: }
36727:
36728: void table::grow(int g)
36729: {
36730: short* hash;
36731: register int j;
36732: int mx;
36733: register Pname* np;
36734: Pname n;
36735:
36736: if (g <= free_slot) error('i',"table.grow(%d,%d)",g,free_slot);
36737: if (g <= size) return;
36738: //error('d',"grow %d %s %d->%d", this, (t_name)?t_name->string:"?", size, g+1);
36739: size = mx = g+1;
36740:
36741: np = new Pname[mx];
36742: for (j=0; j<free_slot; j++) np[j] = entries[j];
36743: delete entries;
36744: entries = np;
36745:
36746: delete hashtbl;
36747: hashsize = mx = (g*3)/2;
36748: hash = hashtbl = new short[mx];
36749:
36750: for (j=1; j<free_slot; j++) { /* rehash(np[j]); */
36751: char * s = np[j]->string;
36752: register char * p;
36753: char * q;
36754: register int i;
36755: int firsti;
36756:
36757: p = s;
36758: i = 0;
36759: while (*p) i += (i + *p++);
36760: if (i<0) i = -i;
36761: firsti = i = i%mx;
36762:
36763: do { /* look for name "s" */
36764: if (hash[i] == 0) {
36765: hash[i] = j;
36766: goto add_np;
36767: }
36768: n = np[hash[i]];
36769: if (n == 0) error('i',"hashed lookup");
36770: p = n->string; /* strcmp(n->n_string,s) */
36771: q = s;
36772: while (*p && *q) if (*p++ != *q++) goto nxt;
36773: if (*p == *q) goto found;
36774: nxt:
36775: if (mx <= ++i) i = 0; /* wrap around */
36776: } while (i != firsti);
36777:
36778: error('i',"rehash??");
36779:
36780: found:
36781: error('i',"rehash failed");
36782:
36783: add_np:;
36784: }
36785: }
36786:
36787: Pname table::get_mem(int i)
36788: /*
36789: return a pointer to the i'th entry, or 0 if it does not exist
36790: */
36791: {
36792: return (i<=0 || free_slot<=i) ? 0 : entries[i];
36793: }
36794:
36795: void table_delete(char* s, TOK k, int ll )
36796: /*
36797: deletes local class entry from keyword table
36798: adjusts pointers if multiple entries
36799: uses same lookup as table::look and table::insert
36800: */
36801: {
36802: Ptable t = ktbl;
36803: register char * p;
36804: register char * q;
36805: register int i;
36806: Pname n;
36807: int rr;
36808:
36809: p = s;
36810: i = 0;
36811: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
36812: rr = (0<=i) ? i : -i;
36813:
36814: // error ('d', "table_delete: %s ll: %d", s, ll );
36815:
36816: Pname* np = t->entries;
36817: int mx = t->hashsize;
36818: short* hash = t->hashtbl;
36819: int firsti = i = rr%mx;
36820:
36821: do {
36822: if (hash[i] == 0) error('i',"table delete: not found: %s", s );
36823: n = np[hash[i]];
36824: if (n == 0) error('i',"table delete: hashed lookup");
36825: p = n->string; /* strcmp(n->n_string,s) */
36826: q = s;
36827: // error( 'd', "table_delete: %s", p );
36828: while (*p && *q)
36829: if (*p++ != *q++) goto nxt;
36830: if (*p == *q) goto found;
36831: nxt:
36832: if (mx <= ++i) i = 0; /* wrap around */
36833: } while (i != firsti);
36834:
36835: found:
36836: for (Pname prev = n; n; prev = n, n=n->n_tbl_list){
36837: // error( 'd', "table_delete: found: %s %k lex: %d", n->string, n->n_key, n->lex_level );
36838: if (n->n_key == k && n->lex_level == ll ) {
36839: // error( 'd', "table_delete: prev: %d n: %d n->tbl_list: %d", prev, n, n->n_tbl_list);
36840: if ( prev == n && n->n_tbl_list == 0 )
36841: hash[i] = 0;
36842: else
36843: prev->n_tbl_list = n->n_tbl_list;
36844: return;
36845: }
36846: }
36847: }
36848: 0707071010112046031004440001630000160000010211300466055416400001300000206556template.c /* ident "@(#)ctrans:src/template.c 1.3" */
36849: /*******************************************************************
36850: * template.c
36851: *
36852: * This file contains most of the implementation for a subset of
36853: * parametrized types as defined by the 1989 Stroustrup JOOP paper.
36854: * The subset chosen here was the subset relevant to the
36855: * implementation of aggregates in ObjectStore.
36856: *
36857: * The following is a list of features supported by the
36858: * implementation. The list of features parallels the
36859: * description of templates in the JOOP paper.
36860: *
36861: * a) Class templates supported.
36862: *
36863: * b) Member function templates supported.
36864: * Type-specific member functions as described at the
36865: * end of the "Outline of an implementation" section
36866: * are also supported.
36867: *
36868: * Non-member function templates are not supported.
36869: *
36870: * c) Template arguments may be of type "type" or
36871: * simple integral, real, double and pointer types
36872: * that are compile-time constants.
36873: *
36874: * Default arguments are not suported.
36875: *
36876: *
36877: * Restrictions:
36878: *
36879: * a) template definitions may not be nested.
36880: *
36881: * b) enums, or class definitions may not be
36882: * nested within a template class definition.
36883: *
36884: * This file also supports an internal template facility
36885: * to facilitate the implementation of ObjectStore data
36886: * model features. The internal template facility is
36887: * only used by compiler implementors, and is not user visible.
36888: *
36889: ************************************************************/
36890:
36891:
36892: /***********************************************************
36893: *
36894: * TBD
36895: *
36896: * 1) Error recovery, a never ending task, could stand improvement.
36897: *
36898: * 2) The template copying process could probably be speeded up
36899: * substantially, by only placing "graph-like" nodes in the hash
36900: * table. The current implementation plays it safe, and places
36901: * all nodes in the hash table.
36902: *
36903: * 3) Clean up $name processing, it needs to be remodularized
36904: * so that class templates and tree templates share the code.
36905: *
36906: * 4) Permit parametrized name default names within member
36907: * functions.
36908: *
36909: ****************************************************************/
36910:
36911: #include "tree_copy.h"
36912: #include "cfront.h"
36913: #include <string.h>
36914: #include "tree_dump.h"
36915: #include "template.h"
36916: #include <stdlib.h>
36917: #include <ctype.h>
36918: #include "hash.h"
36919:
36920: extern int bound ; // is not mentioned in the header file
36921:
36922: const int max_string_size = 1024 ;
36923:
36924: const int default_copy_hash_size = 1000 ;
36925:
36926: // Save and restore global state around a template instantiation
36927: void state::save() {
36928:
36929: Cdcl = ::Cdcl ;
36930: Cstmt = ::Cstmt ;
36931: curloc = ::curloc ;
36932:
36933: curr_file = ::curr_file ;
36934: curr_expr = ::curr_expr ;
36935: curr_icall = ::curr_icall ;
36936: curr_loop = ::curr_loop;
36937: curr_block = ::curr_block;
36938: curr_switch = ::curr_switch;
36939:
36940: bound = ::bound ;
36941: inline_restr = ::inline_restr ;
36942: last_line = ::last_line ;
36943:
36944: no_of_badcall = ::no_of_badcall;
36945: no_of_undcl = ::no_of_undcl ;
36946:
36947: badcall = ::badcall ;
36948: undcl = ::undcl ;
36949: } ;
36950:
36951:
36952: void state::restore() {
36953: ::Cdcl = Cdcl ;
36954: ::Cstmt = Cstmt ;
36955: ::curloc = curloc ;
36956:
36957: ::curr_file = curr_file ;
36958: ::curr_expr = curr_expr ;
36959: ::curr_icall = curr_icall ;
36960: ::curr_loop = curr_loop;
36961: ::curr_block = curr_block;
36962: ::curr_switch = curr_switch;
36963:
36964: ::bound = bound ;
36965: ::inline_restr = inline_restr ;
36966: ::last_line = last_line ;
36967:
36968: ::no_of_badcall = no_of_badcall;
36969: ::no_of_undcl = no_of_undcl ;
36970:
36971: ::badcall = badcall ;
36972: ::undcl = undcl ;
36973: } ;
36974:
36975:
36976: void state::init() {
36977: ::bound = 0 ;
36978: ::inline_restr = 0 ;
36979: ::no_of_badcall = ::no_of_undcl = 0 ;
36980: ::undcl = ::badcall = NULL ;
36981: // lastline needs to be initialized probaly via a call to putline
36982:
36983: }
36984:
36985:
36986: bit basetype::parametrized_class()
36987: { return ((base == COBJ) &&
36988: Ptclass(Pbase(this)->b_name->tp)->class_base == uninstantiated_template_class) ;
36989: }
36990:
36991: class_type_enum get_class_base (Pbase b) {
36992: if (b->base != COBJ) error('i', "badA top ::get_class_type") ;
36993: return Ptclass(Pbase(b)->b_name->tp)->class_base ;
36994: }
36995:
36996: Ptclass get_template_class (Pbase b) {
36997: class_type_enum t = get_class_base(b) ;
36998:
36999: if (! ((t == instantiated_template_class) ||
37000: (t == uninstantiated_template_class)))
37001: error ('i', "C is not aYC") ;
37002:
37003: return Ptclass(Pbase(b)->b_name->tp) ;
37004: }
37005:
37006:
37007: Ptempl_inst get_templ_inst(Pbase b) {
37008:
37009: return (get_template_class(b))->inst ;
37010: }
37011:
37012:
37013: bit classdef::parametrized_class()
37014: { return (class_base == uninstantiated_template_class) ;
37015: }
37016:
37017: // Predicate to determine whether two classes are indeed the same. cfront
37018: // normally relies on pointer identity, however this test is insufficient when
37019: // parametrized class instantiationa are involved, since there are potentially
37020: // many instances of a COBJ and CLASS for a given instantiation.
37021: bit classdef::same_class(Pclass pc)
37022: {
37023: if (this == pc) return true ;
37024:
37025: // An intermediate test to compensate for the fact that instantiations do
37026: // not cause a copy of the syntax tree to be generated. This kludge should
37027: // not be necessary once the template implementation is complete, and tree
37028: // copying is implemented.
37029: // Later, Sam: tree copying is now implemented, i need to remove the
37030: // following two statements and rerun the test suite.
37031:
37032: if ((this->class_base == template_class) &&
37033: (pc->class_base == instantiated_template_class) &&
37034: (Ptclass(pc)->inst->def_basetype()->b_name->tp == this))
37035: return true ;
37036: // The inverse symmetric test
37037: if ((pc->class_base == template_class) &&
37038: (this->class_base == instantiated_template_class) &&
37039: (Ptclass(this)->inst->def_basetype()->b_name->tp == pc))
37040: return true ;
37041:
37042: // Check whether the templates were determined to be identical after
37043: // instantiation.
37044: if ((pc->class_base == instantiated_template_class) &&
37045: (this->class_base == instantiated_template_class) &&
37046: (Ptclass(this)->inst->same(Ptclass(pc)->inst)))
37047: return true ;
37048: return false ;
37049: }
37050:
37051: // determine whether two instantiations are identical; the test asumes that
37052: // the templates have been instantiated.
37053: bool templ_inst::same(Ptempl_inst t)
37054: {
37055: return ((forward && (forward == t->forward)) ||
37056: (forward == t) || (t->forward == this)) ? true : false ;
37057: }
37058:
37059:
37060: /* Template parsing support */
37061:
37062: // The canonical template compilation instance.
37063:
37064: templ_compilation *templp ;
37065:
37066: templ_compilation::templ_compilation()
37067: { templates = new table(128, NULL, NULL) ;
37068: any_type = new basetype(ANY, NULL);
37069: PERM(any_type) ;
37070: }
37071:
37072:
37073: // determine whether the string corresponds to a tree formal parameter
37074: Pname templ_compilation::tree_parameter(char *s) {
37075: for (Plist formal = params ; formal ; formal = formal->l)
37076: if (strcmp(formal->f->string, s) == 0) {
37077: formal->f->n_used++ ;
37078: return formal->f ;
37079: }
37080: return 0 ;
37081: }
37082:
37083:
37084: // Determine whether the name refers to the canonical template class during
37085: // syntax analysis.
37086: Ptempl templ_compilation::is_template(Pname p) {
37087: if (p->tp && (p->tp->base == COBJ) &&
37088: (get_class_base(Pbase(p->tp)) == template_class))
37089: { Pname n = templates->look(p->string, 0) ;
37090: return (n ? Ptempl(n->tp) : 0) ;
37091: }
37092: return 0 ;
37093: }
37094:
37095:
37096: // determine whether the string names a template
37097: Ptempl templ_compilation::is_template(char *s) {
37098: Pname n = templates->look(s,0) ;
37099: return (n ? Ptempl(n->tp) : 0) ;
37100: }
37101:
37102:
37103: // Set up the environment for parsing a template. This involves setting up a
37104: // new nesting level into which the "type type" parameters of the template can
37105: // be entered, so that the lexer can find them as TNAMES. The scope is
37106: // deallocated by end().
37107: void templ_compilation::start()
37108: { templp->in_progress = true ;
37109: // Reinitialize the state.
37110: params = param_end = NULL ; owner = NULL ;
37111: modified_tn = 0 ; // Initialize it here, since ::collect adds new types
37112: }
37113:
37114:
37115:
37116: // Collect each parameter as it is parsed, and add it to the list of parms.
37117: // Validate each parameter to make sure that it is one of the acceptable
37118: // types.
37119: void templ_compilation::collect(TOK parm_type, Pname n)
37120: {
37121: switch (parm_type) {
37122: case CLASS:
37123: // A "type type" parameter, give it the "ANY" type normally used as a
37124: // wildcard match internally by the compiler in cases of error.
37125: n->tp = new basetype(ANY, 0);
37126: n = n->tdef() ; // Set it up to be a typedef.
37127: n->lex_level = bl_level + 1 ; // Inner scope, so restore() can hack it
37128: n->n_template_arg = template_type_formal ;
37129: PERM(n) ; PERM(n->tp) ;
37130: break ;
37131: case STATEMENT:
37132: case EXPRESSION:
37133: // the argument is a post-syntax expression tree
37134: n->n_template_arg =
37135: ((parm_type == EXPRESSION) ?
37136: template_expr_tree_formal : template_stmt_tree_formal) ;
37137: // canonical any_type is ok here
37138: n->tp = any_type ;
37139: PERM(n) ;
37140: break ;
37141: default:
37142: error("theZT for%n must be CLASS, not %k", n,parm_type);
37143: }
37144: append_parameter(n) ;
37145: }
37146:
37147: // append the "non-type" parameter to the end of the list
37148: void templ_compilation::append_parameter(Pname n)
37149: {
37150: if (params){
37151: param_end->l = new name_list(n, NULL) ;
37152: param_end = param_end->l ;
37153: }else params = param_end = new name_list(n, NULL) ;
37154: PERM(n) ; PERM(n->tp) ;
37155: }
37156:
37157:
37158: // collect non "type type" parameters. The tp field of the name
37159: // indicates the type of the formal parameter.
37160: void templ_compilation::collect(Pname n)
37161: {
37162: // The grammar alone should be sufficient to protect against undesirable
37163: // types. Any additional checks go here.
37164: n->n_template_arg = template_expr_formal ;
37165: append_parameter(n) ;
37166: }
37167:
37168:
37169:
37170: // validate the type for a non-type formal, and make it a const.
37171: static void check_non_type_formal(Pname n) {
37172:
37173: switch (n->tp->base) {
37174: case ZTYPE:
37175: case CHAR:
37176: case SHORT:
37177: case INT:
37178: case LONG:
37179: case FLOAT:
37180: case DOUBLE:
37181: case FIELD:
37182: case EOBJ:
37183: case COBJ:
37184: case TYPE:
37185: case ANY:
37186: { // a basetype node
37187: TOK bad_base = 0 ;
37188:
37189: if (Pbase(n->tp)->b_volatile)
37190: bad_base = VOLATILE ;
37191: if (Pbase(n->tp)->b_typedef)
37192: bad_base = TYPEDEF ;
37193: if (Pbase(n->tp)->b_inline)
37194: bad_base = INLINE ;
37195: if (Pbase(n->tp)->b_virtual)
37196: bad_base = VIRTUAL ;
37197: if (bad_base)
37198: error ("bad %k declarator forY formal %n", bad_base,n);
37199:
37200: Pbase b = new basetype(0, 0) ;
37201: *b= *Pbase(n->tp) ;
37202: b->b_const = 1 ;
37203: n->tp = b ;
37204: break ;
37205: }
37206: case PTR:
37207: { Pptr b = new ptr(0,0) ;
37208: *b = *Pptr(n->tp) ;
37209:
37210: b->rdo = 1;
37211: n->tp = b ;
37212: break ;
37213: }
37214: case RPTR:
37215: case VEC:
37216: break; // constant by definition
37217: default:
37218: error ("badZT %t for formalZ %n", n->tp, n);
37219: }
37220: return ;
37221: }
37222:
37223:
37224:
37225: // The template parameters if any, have been parsed. Member function templates
37226: // may choose to default their template arguments to the class arguments, if
37227: // so, make the defaulting happen.
37228: void templ_compilation::enter_parameters()
37229: {
37230: for (Plist list = params ; list ; list = list->l) {
37231: Pname n = list->f ;
37232: switch(n->n_template_arg) {
37233: case template_type_formal:
37234: // Set them up for restoration
37235: modified_tn = new name_list(n,modified_tn);
37236: // Bring the names out of hiding
37237: n->n_key = 0 ;
37238: break ;
37239: case template_expr_formal:
37240: check_non_type_formal(n) ;
37241: n->tp->dcl(gtbl) ;
37242: break ;
37243: case template_expr_tree_formal:
37244: case template_stmt_tree_formal:
37245: // simply note it, the guts of the processing takes place when the
37246: // copy of the syntax tree is generated.
37247: break ;
37248: default:
37249: error ('i', "badY formal" ) ;
37250: }
37251: }
37252: // Save away the list of modified_tn, since the body processing will clobber
37253: // it.
37254: param_tn = modified_tn ;
37255: modified_tn = 0 ;
37256: }
37257:
37258:
37259:
37260: // Resolve the forward declaration of a template to its true definition. The
37261: // template and class type data structures must be reused, since there may be
37262: // outstanding references to them.
37263: void templ::resolve_forward_decl(Plist params, Pclass c) {
37264: check_formals(params) ;
37265: formals = params ;
37266: defined = true ;
37267: definition_number = ++ definition_tick ;
37268: members = c->mem_list ;
37269: }
37270:
37271: void templ::instantiate_forward_decl() {
37272: for (Ptempl_inst i = insts ; i ; i = i->next)
37273: if (Ptclass(Pbase(i->tname->tp)->b_name->tp)->class_base ==
37274: instantiated_template_class &&
37275: ! i->forward)
37276: { // reinstantiate it
37277: i->instantiate(true) ;
37278: }
37279: }
37280:
37281:
37282:
37283: // verify thet the qualifier used to declare the member function matches the
37284: // template arguments in name, ie.
37285: // template <class P, class Q, ..> c<P,Q,..>::member_function() {}
37286: // match it's Ps and Qs.
37287: bool templ_inst::check_qualifier(Plist formals)
37288: {
37289: Pexpr actual = actuals ;
37290: for (Plist formal = formals ; formal && actual ; formal = formal->l,
37291: actual = actual->e2)
37292:
37293: switch (formal->f->n_template_arg) {
37294:
37295: case template_type_formal:
37296: { Pbase b = Pbase(actual->e1->tp) ;
37297:
37298: if (! ((b->base == TYPE) &&
37299: (b->b_name->base == TNAME) &&
37300: (strcmp (Pname(b->b_name)->string, formal->f->string) == 0)))
37301: return false ;
37302: break ;
37303: }
37304:
37305: case template_expr_formal:
37306: if (! ((actual->e1->base == NAME) &&
37307: (strcmp(Pname(actual->e1)->string, formal->f->string) == 0)))
37308: return false ;
37309: break ;
37310:
37311: case template_expr_tree_formal:
37312: case template_stmt_tree_formal:
37313: default:
37314: error ('i',"badY formal") ;
37315: }
37316:
37317: return true ;
37318: }
37319:
37320:
37321: // make the class template visible when compiling the template class
37322: // defintion, so that it can be refernced while compiling the class body.
37323: void templ_compilation::introduce_class_templ(Pname namep)
37324: {
37325: owner = is_template(namep) ;
37326: // create a template definition if one did not already exist, due to a
37327: // forward declaration
37328: if (!owner){
37329: owner = new templ(params, namep) ;
37330: Pname lookup_name = templp->templates->insert(new name(namep->string), 0);
37331: lookup_name->tp = Ptype(owner) ; // lie, to permit use of the table
37332: }
37333: }
37334:
37335:
37336: // The body of the template has been parsed. Finish the definition of the
37337: // template class.
37338: void templ_compilation::end(Pname p)
37339: {
37340: bool forward_definition = false ;
37341: // Restore the name environment to the state before the template parameters
37342: // were processed.
37343: modified_tn = param_tn ;
37344: restore() ;
37345: modified_tn = 0 ;
37346:
37347: if (curr_tree_template) {
37348: // create an expression template
37349: new tree_template(curr_tree_template,
37350: p->string, params, p->n_initializer, templ_refs) ;
37351: }else {
37352: if (!p->tp) {
37353: error ("aC, orMF definition wasX") ;
37354: return ;
37355: }
37356: switch(p->tp->base){
37357:
37358: case CLASS:
37359: // Create the template type to represent the parsed template, and enter it
37360: // into the global table. This is achieved simply by modifying the TNAME
37361: // that was entered into ktbl to represent the class definition.
37362: Pname namep = ktbl->look(p->string, 0) ;
37363:
37364: // check for nested definitions, they aren't supported currently. 2.1 is
37365: // a good time to start supporting them, since they are nested for real.
37366: for (Pname nn = Pclass(p->tp)->mem_list ; nn ; nn = nn->n_list)
37367: switch (nn->base) {
37368: case NAME:
37369: switch(nn->tp->base) {
37370: case CLASS:
37371: error("CD %s not permitted within a ZizedC", nn->string) ;
37372: break ;
37373: case ENUM:
37374: error("enumD %s not permitted within a ZizedC", nn->string) ;
37375: break ;
37376: }
37377: break ;
37378:
37379: case TNAME:
37380: error("typedef %s not permitted within a ZizedC", nn->string) ;
37381: break ;
37382: }
37383:
37384: owner = is_template(namep);
37385: if (owner) {
37386: Pclass c = Pclass(owner->basetype()->b_name->tp) ;
37387: // ignore it, if it is a forward declaration following a real
37388: // definition
37389: if (owner->defined && (Pclass(p->tp)->mem_list != owner->members))
37390: error("YC %s multiply defined", p->string) ;
37391:
37392: forward_definition=bool((c->defined & DEF_SEEN) && (!owner->defined));
37393: if (forward_definition) owner->resolve_forward_decl(params, c) ;
37394: }else
37395: // a forward declaration
37396: introduce_class_templ(namep) ;
37397:
37398: if (templ_refs) owner->templ_refs = templ_refs ;
37399: break ;
37400:
37401: case FCT:
37402: { Pname qual = p->n_qualifier ;
37403: // the function must belong to a declared template class
37404: if (! qual) {
37405: error('s', "onlyYMFs may beZized currently") ;
37406: return ;
37407: }
37408: if (qual->tp && (qual->tp->base == COBJ))
37409: switch (get_class_base(Pbase(qual->tp))) {
37410: case uninstantiated_template_class:
37411: owner = Ptclass(Pbase(qual->tp)->b_name->tp)->inst->def ;
37412: // verify that the formals specified, match the template formals
37413: // in name, note that the length was already matched when the
37414: // instantiation was generated.
37415: if (!get_template_class
37416: (Pbase(qual->tp))->inst->check_qualifier(params))
37417: error ("QrZs must match theY formals") ;
37418: break ;
37419: case template_class:
37420: // the template reference was without any of the formals
37421: owner = is_template(qual) ;
37422: if (! owner->has_tree_expr_formals())
37423: error('w',"Qr %n for %n must specifyYZs", qual, p) ;
37424: break ;
37425: default:
37426: error ("Qr %n for %n wasn't aYC", qual, p) ;
37427: return ;
37428: }
37429: Pfunt ft= owner->collect_function_member(p) ;
37430: if (! Pfct(p->tp)->body)
37431: error ("theYFM %n must have a body", p) ;
37432: ft->templ_refs = templ_refs ;
37433: ft->formals = params ;
37434: owner->check_formals(params) ;
37435: break ;
37436: }
37437: default: error ("C, or MF definitionX.") ;
37438: }
37439: }
37440: // Note the template references from this definition
37441:
37442: clear_ref_templ() ;
37443: param_end = params = 0; // Indicates the end of template processing.
37444: curr_tree_template = 0 ;
37445:
37446: if (forward_definition) owner->instantiate_forward_decl() ;
37447: owner = 0 ;
37448: }
37449:
37450:
37451:
37452:
37453: // Clear the list of templates referenced during the syntax analysis of a top
37454: // level definition. Note that since this list is produced during syntax
37455: // analysis, it does not recognize instantiations that may actualy turn out to
37456: // be identical at instantiation after the substitution of actual parameters.
37457: // Thus, the list may be longer than it would be after actual argument
37458: // substitution.
37459: void templ_compilation::clear_ref_templ() {
37460: for (Pcons p = templ_refs ; p ; p = p->cdr)
37461: Ptempl_inst(p->car)->refp = false ;
37462: templ_refs = 0 ; last_cons = 0 ;
37463: }
37464:
37465:
37466: // Instantiate templates that were referenced by a non-template definition,
37467: // after syntax analysis has been completed on it.
37468: void templ_compilation::instantiate_ref_templ() {
37469: for (Pcons p = templ_refs ; p ; p = p->cdr)
37470: Ptempl_inst(p->car)->instantiate() ;
37471: clear_ref_templ() ;
37472: }
37473:
37474:
37475:
37476:
37477: // Compile all template member body instantiations. Set in motion the
37478: // compilation of the graph of instantiation bodies. Note that compilation of
37479: // a body may in turn initiate the instantiation of templates that had not
37480: // previously been instantiated.
37481: void templ_compilation::end_of_compilation() {
37482: bool change = false ;
37483: do {
37484: change = false ;
37485: for (Ptempl p = list ; p ; p = p->next)
37486: change = ( change | p->instantiate_bodies() ? true : false);
37487: } while (change) ;
37488: }
37489:
37490:
37491: // A predicate to validate that a tname without template parameters is legit
37492: // in the scope, ie. that it does not need actual template arguments.
37493: // Currently, a tname without parameters is ok within the class definition,
37494: // but parameters are required within the member definition. They should not
37495: // be required within the member function either to be consonance with their
37496: // use in the class definition.
37497: Pname templ_compilation::check_tname(Pname p) {
37498: Ptempl t = is_template(p) ;
37499:
37500: if (p->n_template_arg) p->n_used++ ;
37501: if (!t) return p ;
37502: if (in_progress && ((owner && (owner->namep == p)) ||
37503: (!owner && t->basetype()->b_name->tp == ccl)))
37504: return p ;
37505: error ("%n needs Y instantiationAs.", p) ;
37506: return p ;
37507: }
37508:
37509:
37510: // This function determine when the parameters specified to a template are
37511: // redundant, and really refer to the current template class. Thus,
37512: //
37513: // template c<class p1, class p2> c<p1,p2>::foo { ... } ;
37514: // has the redundant template specification c<p1, p2> and can simply be a
37515: // reference to a "c" instead,
37516: bool templ_compilation::current_template(Pname p, Pexpr actuals) {
37517: if (in_progress &&
37518: ((owner && (owner->namep == p)) ||
37519: (!owner && ((p->tp->base == COBJ) &&
37520: (Pbase(p->tp)->b_name->tp == ccl)))))
37521: { // Check whether the formal and actual types are identical
37522: Pexpr actual = actuals;
37523: for (Plist formal = params ; formal && actual ; formal = formal->l,
37524: actual = actual->e2)
37525: if ((formal->f->tp == actual->e1->tp) ||
37526: ((actual->e1->tp && (actual->e1->tp->base == TYPE)) &&
37527: (Pbase(actual->e1->tp)->b_name->tp == formal->f->tp)))
37528: continue ;
37529: else break ;
37530: if (!formal && !actual) return true ;
37531: }
37532: return false ;
37533: }
37534:
37535:
37536:
37537: // Add a new member function to the list of functions for the template class.
37538: Pfunt templ::collect_function_member(Pname fname) {
37539: PERM(fname) ; PERM(fname->tp) ; PERM(Pfct(fname->tp)->body) ;
37540: return new function_template (*this, templp->params, fname) ;
37541: }
37542:
37543:
37544: // Check the formals specified for a member function or a forward definition
37545: // of a class, against the formals for the class.
37546: void basic_template::check_formals(Plist f2) {
37547:
37548: for (Plist f1 = formals; f1 && f2 ; f1 = f1->l, f2 = f2->l)
37549: if (f1->f->base != f2->f->base)
37550: switch (f1->f->n_template_arg) {
37551: case template_type_formal:
37552: error ("Y formalZ mismatch,\
37553: %n must be a type formal parameter.", f2->f) ;
37554: break ;
37555: case template_expr_formal:
37556: error ("formalZ mismatch, %n must be aZ ofT %t",
37557: f2->f, f2->f->tp) ;
37558: break ;
37559: case template_expr_tree_formal:
37560: case template_stmt_tree_formal:
37561: error ("formalZ mismatch, %n must be anE formalZ",
37562: f2->f) ;
37563: break ;
37564: default:
37565: error ("formalZ mismatch betweenC formal: %n andM formal: %n", f1->f, f2->f) ;
37566: }else if (f1->f->n_template_arg == template_expr_formal) {
37567: // the types should be identical
37568: if (f1->f->tp->check(f2->f->tp, 0) == 1)
37569: error ("type mismatch betweenM formal %n, andC formal %n", f2->f, f1->f) ;
37570: }
37571: if (f1)
37572: error ("insufficient formalZs,CZ parameter %n onwards are missing", f1->f) ;
37573: if (f2)
37574: error ("excess formalZs,Z %n onwards not defined forC", f2->f) ;
37575:
37576: }
37577:
37578: // predicate to determine whether the template has expression tree formals
37579: bool templ::has_tree_expr_formals() {
37580:
37581: for (Plist formal= formals; formal ; formal = formal->l)
37582: if (formal->f->n_template_arg == template_expr_tree_formal)
37583: return true ;
37584:
37585: return false ;
37586: }
37587:
37588:
37589: // Check that those formals that require class actual arguments, due to their
37590: // use in member function bodies get them.
37591: bool basic_template::check_constraints(Pexpr actual)
37592:
37593: {
37594: bool ret = true ;
37595:
37596: for (Plist formal = formals ; formal && actual ; formal = formal->l,
37597: actual = actual->e2)
37598: if ((formal->f->n_template_arg == template_type_formal) &&
37599: formal->f->n_template_formal_must_be_class) {
37600:
37601: Pname n = Pname(actual->e1) ;
37602:
37603: if (n && n->tp && n->tp->is_cl_obj())
37604: continue ;
37605: error("expected aCT actual, not %t, for the \"TT\" formal %s",
37606: n->tp, formal->f->string);
37607: ret = false ;
37608: }
37609: return ret ;
37610: }
37611:
37612:
37613: // Check actual template arguments, against the formals.
37614: bool templ::check_actual_args(Pexpr actual)
37615: {
37616: for (Plist formal = formals ; formal && actual ; formal = formal->l,
37617: actual = actual->e2)
37618: switch (formal->f->n_template_arg) {
37619: case template_type_formal:
37620: {
37621: // A "type type" parameter, any actual type that was accepted by the
37622: // parse is acceptable here, just make sure that it is indeed a type.
37623: // If it was parsed as a type, the grammar should have created a name
37624: // node, and attached the type to it, having marked the name as a
37625: // template_actual_arg_dummy.
37626:
37627: Pname n = Pname(actual->e1) ;
37628:
37629: if (!((n->base == NAME) &&
37630: (n->n_template_arg == template_actual_arg_dummy))) {
37631: error ("Y %s A mismatch, the Y formal:%n\
37632: required aT actualZ.", namep->string, formal->f) ;
37633: // recover from the error with a safe expression
37634: n = new name("") ;
37635: n->tp = any_type ;
37636: actual->e1 = n ;
37637: }
37638: if ((formal->f->n_template_formal_must_be_class) &&
37639: !(n->tp && n->tp->is_cl_obj()))
37640: error("expected aCT actual, not %t, for the \"TT\" formal %s",
37641: n->tp, formal->f->string) ;
37642: break ;
37643: }
37644: case template_expr_formal:
37645: // checking can only be done at instantiation, so postpone it
37646: break ;
37647: case template_expr_tree_formal:
37648: case template_stmt_tree_formal:
37649: // anything is acceptable, it is a case of "implementor beware". Any
37650: // illegalities will only be detected when dcl processing takes place.
37651: break ;
37652: default:
37653: error ('i',"badY formal") ;
37654: }
37655: // If we provide for optionals, this is where the processing should get done.
37656: if (formal)
37657: error ("too fewAs supplied forY %s", namep->string) ;
37658: if (actual && actual->e1) {
37659: error ("too manyAs supplied forY %s", namep->string) ;
37660: }
37661: return bool(~(formal || actual)) ;
37662: }
37663:
37664:
37665:
37666:
37667: // Append to the list of references.
37668: void templ_compilation::append_ref(Ptempl_inst ref)
37669: { cons *p = new cons(ref,0) ;
37670: if (last_cons)
37671: last_cons->cdr = p ;
37672: else templ_refs = p ;
37673: last_cons = p ;
37674: } ;
37675:
37676:
37677: // Note the reference by a definition to the template, so that the template
37678: // can be instantiated before the definition is processed.
37679: Ptempl_inst templ_inst::note_ref()
37680: { if ((! refp)) {
37681: refp = true ;
37682: templp->append_ref(this) ;
37683: }
37684: return this ;
37685: }
37686:
37687:
37688:
37689: // Get an instantiation for the template with the given set of actuals. If one
37690: // exists, return it, otherwise create a new one.
37691: Ptempl_inst templ::get_inst(Pexpr actuals, Ptempl_inst exclude)
37692: { Ptempl_inst inst = get_match(actuals, exclude, false) ;
37693:
37694: return (inst ? inst : new templ_inst(actuals, this))->note_ref() ;
37695: }
37696:
37697:
37698: // Find an instantiation that has the same set of actuals, exclude the
37699: // instantaition passed in from the set of candidates
37700: Ptempl_inst templ::get_match(Pexpr actuals,
37701: Ptempl_inst exclude, // don't match this one
37702: // Only instantiated templates match
37703: bool match_instantiated_only)
37704: {
37705: for (Ptempl_inst p = insts ; p ; p = p->next)
37706: if ((p != exclude) &&
37707: (p->actuals_match(actuals)) &&
37708: (match_instantiated_only ?
37709: (Pclass(Pbase(p->tname->tp)->b_name->tp)->class_base ==
37710: instantiated_template_class)
37711: : true))
37712: return (p->forward ? p->forward : p) ;
37713: return NULL ;
37714: }
37715:
37716:
37717: // provides the basetype created for a given set of actuals.
37718: Pbase templ::inst_basetype(Pexpr actuals)
37719: {
37720: return (check_actual_args(actuals) ?
37721: Pbase(get_inst(actuals)->tname->tp) : basep) ;
37722: }
37723:
37724:
37725: // Validate that the name denotes a parametrized type, and prodouce a TNAME
37726: // for the instantiation.
37727: Pname parametrized_typename (Pname p, Pexpr actuals)
37728: {
37729: Ptempl t = templp->is_template(p) ;
37730: // A template instantiation with redundant actuals identical to the formals
37731: // of the current template
37732: if (templp->current_template(p, actuals)) return p ;
37733: if (t) {
37734: Pname tname = t->typename(actuals) ;
37735: return (tname ? tname : p) ;
37736: }
37737: error ("%n hasTAs but is not aZizedC", p) ;
37738: return p ;
37739: }
37740:
37741:
37742: Pbase parametrized_basetype (Pname p, Pexpr actuals)
37743: { Ptempl t = templp->is_template(p) ;
37744: // A template instantiation with redundant actuals identical to the formals
37745: // of the current template
37746: if (templp->current_template(p, actuals)) return Pbase(p->tp) ;
37747: if (t) return t->inst_basetype(actuals) ;
37748: error ("%n is not aZizedC", p) ;
37749: return new basetype(TYPE, p);
37750: }
37751:
37752:
37753: // Similar primitive for obtaining the typename associated with an
37754: // instantiation.
37755: Pname templ::typename(Pexpr actuals)
37756: {
37757: return (check_actual_args(actuals) ? get_inst(actuals)->tname : 0) ;
37758: }
37759:
37760: // predicate to get past all the type nodes
37761: static Ptype real_type (Ptype t)
37762: {
37763: while (t->base == TYPE) t = Pbase(t)->b_name->tp ;
37764: return t ;
37765: }
37766:
37767: static int expr_match(Pexpr a1, Pexpr a2) ;
37768:
37769: // Check whether the actuals provided match the actuals for this instantiation.
37770: // The actuals match the formals, iff they are the same type or parametrized
37771: // type.
37772: bool templ_inst::actuals_match(Pexpr check_actuals)
37773: { Pexpr ae1, ae2 ; // the cons cells
37774: Plist formal = def->formals ;
37775:
37776: // The lists should be the same length, since check_actuals will have taken
37777: // appropriate action.
37778: for (ae1=actuals, ae2=check_actuals ; formal && ae1 && ae2 ;
37779: ae1=ae1->e2, ae2=ae2->e2, formal = formal->l)
37780:
37781: switch (formal->f->n_template_arg) {
37782:
37783: case template_type_formal:
37784: { Ptype t1 = ae1->e1->tp, t2 = ae2->e1->tp ;
37785: if (t1->check(t2,255) == 1)
37786: return false ;
37787: break ;
37788: }
37789: case template_expr_formal:
37790: if (! expr_match(ae1->e1, ae2->e1)) return false ;
37791: break ;
37792:
37793: case template_expr_tree_formal:
37794: case template_stmt_tree_formal:
37795: // these are internal instantiations and consequently never match
37796: return false ;
37797:
37798: default:
37799: error ('i', "bad template formal") ;
37800: }
37801: return true ;
37802: }
37803:
37804:
37805: extern char emode ;
37806:
37807:
37808: // This set of overloaded fuctions are used to accumulate name strings
37809: void stradd(char *&target, char *source) {
37810: while (*target++ = *source++) ;
37811: target-- ;
37812: }
37813:
37814: void stradd(char *&p, long i) {
37815: if (!emode) {
37816: *p++ = 'L' ;
37817: }
37818: char s[16] ;
37819:
37820: sprintf(s,"%ld", i) ;
37821: stradd(p,s) ;
37822: }
37823:
37824: void stradd(char *&p, Pname n) {
37825: if (!emode){
37826: char s[256] ;
37827:
37828: sprintf(s,"%d", strlen(n->string)) ;
37829: stradd(p,s) ;
37830: }
37831: stradd(p, n->string) ;
37832: }
37833:
37834:
37835:
37836: // produce a unique string suitable for use within a name; if in emode ie.
37837: // printing in the context of an error, print a pretty name instead.
37838: char * mangled_expr(char *p, Pexpr e, bool mangle_for_address = false)
37839: {
37840: static int mangle_address = 0 ;
37841: if (e == 0) return p;
37842:
37843: switch (e->base) {
37844: case ADDROF:
37845: case G_ADDROF:
37846: // unary using e2
37847: // rely on the
37848: mangle_address++ ;
37849: p = mangled_expr(p, e->e2) ;
37850: mangle_address -- ;
37851: break ;
37852:
37853: case NAME:
37854: if (mangle_address || mangle_for_address)
37855: stradd(p, Pname(e)) ;
37856: else if (Pname(e)->n_evaluated)
37857: stradd(p, Pname(e)->n_val) ;
37858: else if (Pname(e)->n_initializer)
37859: p = mangled_expr(p, Pname(e)->n_initializer, mangle_for_address) ;
37860: else error ('i', "couldn't mangle %n", e) ;
37861: break ;
37862:
37863: case IVAL:
37864: stradd(p, ((ival *)e)->i1) ;
37865: break ;
37866:
37867: case CAST:
37868: { // an IVAL hiding below the cast ?
37869: if (e->e1->base == IVAL)
37870: stradd(p, ((ival *)e->e1)->i1) ;
37871: else error ('i', "unexpected cast") ;
37872: break ;
37873: }
37874: case ICON:
37875: case CCON:
37876: case FCON:
37877: *p++ = 'L' ;
37878: strcpy(p, e->string) ;
37879: // Sam: there needs to be a better encoding scheme, but it can wait.
37880: if (!emode)
37881: while (*p)
37882: if (! (isalnum(*p)))
37883: switch(*p) {
37884: case '+':
37885: *p++ = 'p' ;
37886: break ;
37887:
37888: case '-':
37889: *p++ = 'm' ;
37890: break ;
37891:
37892: case '.':
37893: *p++ = 'D' ;
37894: break ;
37895:
37896: case 'e':
37897: *p++ = 'E' ;
37898: break ;
37899:
37900: default:
37901: error ('i', "bad character in constant") ;
37902: break ;
37903: } else p++ ;
37904: break ;
37905:
37906: case ZERO:
37907: *p++ = '0' ;
37908: break ;
37909:
37910: default:
37911: error ('i', "can't mangle %k", e->base) ;
37912: }
37913: return p ;
37914: }
37915:
37916: // this function is invoked once at the top level
37917: char *mangled_expr(char *p, Pname n) {
37918: if (n->n_evaluated) {
37919: stradd(p, n->n_val) ;
37920: return p ;
37921: }
37922: return mangled_expr(p, n->n_initializer,
37923: (real_type(n->tp)->base == PTR ? true : false)) ;
37924: }
37925:
37926: // Generate a template instantiation name suitable for printing when it is
37927: // presented to the user.
37928: void templ_inst::print_pretty_name()
37929: {
37930: extern char emode ;
37931:
37932: fprintf(out_file, " %s<", (def->namep ? def->namep->string : "?")) ;
37933: Plist formal = inst_formals ;
37934: emode ++ ; // so that dcl_print generates c++ rather than c names
37935:
37936: for (Pexpr ae1=actuals; formal && ae1 ; ae1=ae1->e2, formal = formal->l) {
37937: switch (formal->f->n_template_arg) {
37938: case template_type_formal:
37939: ae1->e1->tp->dcl_print(0) ;
37940: break ;
37941: case template_expr_formal:
37942: { char buff[256] ;
37943:
37944: mangled_expr(buff, ae1->e1) ;
37945: fprintf(out_file, "%s", buff) ;
37946: break ;
37947: }
37948: case template_expr_tree_formal:
37949: case template_stmt_tree_formal:
37950: // doesn't participate in the name generation
37951: break ;
37952: default:
37953: error ('i', "unexpected formal") ;
37954: }
37955:
37956: // this comma is unfortunately misplaced, since it follows a space printed
37957: // out by dcl_print
37958: if (formal->l) fprintf(out_file, ", ") ;
37959: }
37960: fprintf(out_file, ">") ;
37961: emode -- ;
37962: }
37963:
37964:
37965:
37966: // there are different representations for ICON based upon whether it has been
37967: // evaluated.
37968: int check_for_const(Pexpr a1, Pexpr a2) {
37969: Neval = 0 ;
37970: if ((a1->base == NAME) &&
37971: ((a2->base == ICON) || (a2->base == IVAL) || (a2->base == ZERO)))
37972: { Pname n = Pname(a1) ;
37973: return (n->n_evaluated && (n->n_val == a2->eval())) ;
37974: }else if (((a1->base == ICON) || (a1->base == IVAL) || (a1->base == ZERO))
37975: && (a2->base == NAME))
37976: { Pname n = Pname(a2) ;
37977: return (n->n_evaluated && (n->n_val == a1->eval())) ;
37978: }
37979: return false ;
37980: }
37981:
37982:
37983: // get past the template parameter names to get the the real expression
37984: static Pexpr real_expression(Pexpr e)
37985: {
37986: while (e && (e->base == NAME) &&
37987: (Pname(e)->n_template_arg == template_expr_formal) &&
37988: (! Pname(e)->n_evaluated) && Pname(e)->n_initializer)
37989: e = Pname(e)->n_initializer ;
37990: return e ;
37991: }
37992:
37993:
37994: // determine whether two expressions supplied as actual arguments to
37995: // a "template_expr_formal" formal argument match.
37996: static int expr_match(Pexpr a1, Pexpr a2)
37997: {
37998: static int addr_of = 0 ;
37999:
38000: a1 = (addr_of ? a1 : real_expression(a1)) ;
38001: a2 = (addr_of ? a2 : real_expression(a2)) ;
38002:
38003: if (a1 == a2) return true;
38004:
38005: //
38006: if (a1->base != a2->base) return check_for_const(a1, a2) ;
38007:
38008: switch (a1->base) {
38009: case QUEST:
38010: // a ternary operator
38011: return ( expr_match(a1->cond, a2->cond) &&
38012: expr_match(a1->e1, a2->e1) &&
38013: expr_match(a1->e2, a2->e2)) ;
38014:
38015: case PLUS: case MINUS: case MUL: case DIV: case MOD:
38016: case ER: case OR: case ANDAND: case OROR:
38017: case LS: case RS:
38018: case EQ: case NE: case LT: case LE: case GT: case GE:
38019: // binary operator
38020: return (expr_match(a1->e1, a2->e1) &&
38021: expr_match(a1->e2, a2->e2)) ;
38022: case UMINUS: case UPLUS:
38023: case NOT: case COMPL:
38024: return (expr_match(a1->e2, a2->e2)) ;
38025: case ADDROF:
38026: {
38027: // unary using e2
38028: addr_of ++ ;
38029: int result = (expr_match(a1->e2, a2->e2)) ;
38030: addr_of -- ;
38031: return result ;
38032: }
38033: case CAST:
38034: return (expr_match(a1->e1, a2->e1)) ;
38035: case NAME:
38036: if (! addr_of) {
38037: Pname n1 = Pname(a1), n2 = Pname(a2) ;
38038:
38039: if ((n1->n_evaluated) && n2->n_evaluated && (n1->n_val == n2->n_val))
38040: return true ;
38041: if (n1->n_initializer && (! n2->n_initializer))
38042: return check_for_const(n2, n1->n_initializer) ;
38043: if (n2->n_initializer && (! n1->n_initializer))
38044: return check_for_const(n1, n2->n_initializer) ;
38045: if (n1->n_initializer && n2->n_initializer)
38046: return expr_match(n1->n_initializer, n2->n_initializer) ;
38047: }
38048: return false ;
38049: case DOT:
38050: return (expr_match(a1->e1, a2->e1)) ;
38051: case REF:
38052: return (expr_match(a1->e1, a2->e1)) ;
38053: case IVAL:
38054: return (ival *)a1->i1 == (ival *)a2->i1 ;
38055: case ICON:
38056: case CCON:
38057: case FCON:
38058: case STRING:
38059: return (strcmp (a1->string, a2->string) == 0) ;
38060: case ZERO:
38061: return true ;
38062: case SIZEOF:
38063: { long l1 = a1->eval(), l2 = a2->eval() ;
38064: return (l1 == l2) ;
38065: }
38066: }
38067: return false ;
38068: }
38069:
38070:
38071: static char * non_type_argument_signature(Pexpr e, char *p) {
38072: p = e->tp->signature(p) ;
38073: return mangled_expr(p, e) ;
38074: }
38075:
38076:
38077:
38078: // generate array suffix information for an array signature. cfront does not
38079: // normally generate this as part of the type signature, since it only deals
38080: // with argument signatures, and arrays can't be arguments.
38081: static void add_array_type_suffix(char *&s, Ptype t) {
38082: t = real_type(t) ;
38083: if (t->base == VEC) {
38084: Pvec v = Pvec(t);
38085: int dim;
38086: char a[32] ;
38087: Neval = 0 ;
38088: if(v->dim == 0)
38089: dim = v->size / v->typ->tsizeof();
38090: else dim = (int)v->dim->eval();
38091: sprintf(a, "A%d", dim) ;
38092: stradd(s,a) ;
38093: add_array_type_suffix(s, Pvec(t)->typ);
38094: }
38095: }
38096:
38097:
38098:
38099: // Generate a mangled template instantiation name. The syntax of as template
38100: // mangled class name is of the form:
38101: // original_name__<argument type signatures>__unique_id
38102: // Each non-type argument is replaced by a unique id.
38103: char *templ_inst::mangled_name(char *ip)
38104: { static tree_formal_id = 0 ;
38105:
38106: char *start = ip ;
38107: ip = start ;
38108: strcpy(ip, (def->namep ? def->namep->string : "?")) ;
38109: ip= start + strlen(start) ;
38110: stradd(ip, "__pt__") ;
38111:
38112: {
38113: char a [max_string_size], *p = a ;
38114:
38115: Plist formal = inst_formals ;
38116:
38117: for (Pexpr ae1=actuals ; ae1 ; ae1=ae1->e2, formal = formal->l)
38118: switch (formal->f->n_template_arg) {
38119: case template_expr_formal:
38120: *p++ = 'X' ;
38121: // the formal must have been bound
38122: p = non_type_argument_signature(formal->f, p) ;
38123: break ;
38124:
38125: case template_type_formal:
38126: p = ae1->e1->tp->signature(p) ;
38127: add_array_type_suffix(p,ae1->e1->tp) ;
38128: break ;
38129:
38130: case template_expr_tree_formal:
38131: case template_stmt_tree_formal:
38132: *p++ = 'Y' ;
38133: stradd(p, tree_formal_id++) ;
38134: break ;
38135:
38136: default:
38137: error ("bad template formal:%d", formal->f->base) ;
38138: break ;
38139: }
38140:
38141: *p = 0 ;
38142: sprintf(ip, "%d_", strlen(a)+1) ;
38143: ip = start + strlen(start) ;
38144: strcpy(ip,a) ;
38145: }
38146:
38147: return start ;
38148: }
38149:
38150:
38151:
38152: // The C compiler barfs when it is passed on through C++ as an automatic
38153: // variable
38154: const char leader[]= "\t" ;
38155:
38156: // Explain the location of an instantiation in greater detail, since it may be
38157: // far removed from it's textual definition.
38158: void templ_inst::print_error_loc() {
38159: if (! head) return ; // No active instantiations
38160:
38161: extern void print_loc() ;
38162: state current_state ;
38163: char buffer[max_string_size] ;
38164:
38165: for (int i = 0 ; i < max_string_size; i++) buffer[i] = 0 ;
38166:
38167: current_state.save() ;
38168: fprintf (out_file, "%sanomaly detected during the instantiation of",
38169: leader) ;
38170: print_pretty_name() ;
38171: fprintf(out_file, "\n") ;
38172: if (!head->next_active) {
38173: // A more compact message for a single level of instantiation
38174: context.restore() ;
38175: fprintf (out_file, leader) ;
38176: print_loc() ;
38177: fprintf (out_file, "was the site of the instantiation\n") ;
38178: }else {
38179: // The instantiation chain is longer than one
38180: fprintf (out_file, "%sthe instantiation path was:\n", leader) ;
38181: for (Ptempl_inst p = head ; p ; p = p->next_active) {
38182: p->context.restore() ;
38183: print_loc() ;
38184: fprintf (out_file, " template:") ;
38185: p->print_pretty_name() ;
38186: fprintf(out_file, "\n") ;
38187: }
38188: }
38189: current_state.restore() ;
38190: }
38191:
38192:
38193:
38194: // Generate a class name for the instantiated class. It is constructed in a
38195: // manner similar to the names used in the construction of overloaded functions
38196: char *templ_inst::instantiation_string() {
38197: char inst_name[max_string_size] ;
38198: for (int i = 0 ; i < max_string_size; i++) inst_name[i] = 0 ;
38199: mangled_name(inst_name) ;
38200: return strdup(inst_name) ;
38201: }
38202:
38203:
38204:
38205: // Change the names for the class, constructors, and destructors to reflect
38206: // the new class instantiation name.
38207: void classdef::modify_inst_names(char *s)
38208: {
38209: char *old = string ;
38210: string = s ; // Change the class name
38211: // Change the constructor names
38212: for (Pname p=mem_list; p; p=p->n_list)
38213: if (p->tp && (p->tp->base==FCT) && (!strcmp(old, p->string)))
38214: p->string = s ;
38215: }
38216:
38217: // Get past the fake template argument name typename types
38218: Ptype non_template_arg_type(Pbase t) {
38219: if ((t->base == TYPE) &&
38220: (t->b_name->n_template_arg == template_type_formal))
38221: return non_template_arg_type(Pbase(t->b_name->tp)) ;
38222: else return t ;
38223: }
38224:
38225: // follow the chain until we hit a non
38226: void non_template_arg_non_type(Pname n) {
38227: Pexpr i = n->n_initializer;
38228: while (i &&
38229: (i->base == NAME) &&
38230: (Pname(i)->n_template_arg == template_expr_formal))
38231: {
38232: if (Pname(i)->n_initializer) {
38233: n->n_initializer = Pname(i)->n_initializer ;
38234: i = n->n_initializer ;
38235: continue ;
38236: }
38237: if (Pname(i)->n_evaluated) {
38238: n->n_evaluated = 1 ;
38239: n->n_val = Pname(i)->n_val ;
38240: return ;
38241: }
38242: }
38243: return ;
38244: }
38245:
38246:
38247:
38248: // Now that the actuals are truly resolved, ie. semantics is complete, and the
38249: // template is about to be instantiated.
38250: void forward_template_arg_types(Plist formal, Pexpr actuals)
38251: {
38252: for (Pexpr actual = actuals ; formal && actual ;
38253: formal = formal->l, actual = actual->e2)
38254: switch(formal->f->n_template_arg){
38255: case template_type_formal:
38256: actual->e1->tp = non_template_arg_type(Pbase(actual->e1->tp)) ;
38257: break ;
38258: case template_expr_formal:
38259: break ;
38260: case template_expr_tree_formal:
38261: case template_stmt_tree_formal:
38262: break ;
38263: default:
38264: error ('i', "bad template formal") ;
38265: }
38266: }
38267:
38268: // determine whether the expression supplied as an actual argument to
38269: // atemplate formal of type "template_expr_formal" is suitable. We are nore
38270: // restrictive than we need to be, simply so that the debugger can have an
38271: // easier time. All expressions must be of the form constant integer
38272: // expression, a float or double literal, or the address of a variable, or an
38273: // array, or function
38274: static int suitable_const_expr(Pname n)
38275: {
38276: if (n->n_evaluated) return 1 ;
38277:
38278: if (!n->n_initializer) return 0 ;
38279:
38280: switch (n->n_initializer->base) {
38281:
38282: case CAST:
38283: { // if it is a cast of an integer value, it's fine.
38284: if (n->n_initializer->e1->base == IVAL)
38285: return 1 ;
38286: else return 0 ;
38287: }
38288:
38289: case FCON:
38290: case ZERO:
38291: return 1 ;
38292:
38293: case ADDROF:
38294: case G_ADDROF:
38295: {
38296: Pname an = Pname(n->n_initializer->e2) ;
38297: if (an->base != NAME) return 0 ;
38298: if (an->n_stclass == STATIC) return 1 ;
38299: return 0 ;
38300: }
38301: case NAME:
38302: {
38303: Pname an = Pname(n->n_initializer) ;
38304: if ((an->n_stclass == STATIC) &&
38305: (an->tp->base == VEC))
38306: // assumes that decl processing won, so that the formal could only
38307: // have been apointer
38308: return 1 ;
38309: return 0 ;
38310: }
38311: default:
38312: return 0 ;
38313: }
38314: }
38315:
38316:
38317:
38318: static bool is_stmt_node(Pnode p) {
38319: if (!p) return false ;
38320: switch(p->base) {
38321: case BREAK: case CONTINUE: case DEFAULT:
38322: case SM: case WHILE: case DO: case SWITCH: case RETURN: case CASE:
38323: case FOR:
38324: case IF:
38325: case BLOCK:
38326: case PAIR: // ?
38327: return true ;
38328: }
38329: return false ;
38330: }
38331:
38332:
38333:
38334: static void bind_tree_expr_formal(Pname f, Pexpr actual)
38335: {
38336: if (actual->e1->base == TNAME)
38337: error ('i', "a TNAME is not a valid argument for the formal %n",
38338: f) ;
38339: if (is_stmt_node(actual->e1)) {
38340: error ("an expression node was expected for the expression formal parameter %n", f) ;
38341: actual->e1 = zero ;
38342: }
38343: // bind the formal to the expression, it will be accessed from here by
38344: // the hook function during the copy
38345: f->n_initializer = actual->e1 ;
38346: }
38347:
38348:
38349:
38350: // Bind the formals to the types passed in as the actuals, for the
38351: // instantiation, bind the non-type names to their expressions.
38352: void templ_inst::bind_formals()
38353: { Pexpr actual ;
38354: Plist formal ;
38355:
38356: for (formal = inst_formals, actual = actuals ;
38357: formal && actual ; formal = formal->l, actual = actual->e2)
38358: switch (formal->f->n_template_arg) {
38359: case template_type_formal:
38360: {
38361: formal->f->tp = non_template_arg_type(Pbase(actual->e1->tp)) ;
38362: PERM(formal->f->tp) ;
38363: break ;
38364: }
38365:
38366: case template_expr_formal:
38367: {
38368: actual->e1 = actual->e1->typ(gtbl);
38369: if (formal->f->tp->check(actual->e1->tp,ASSIGN) == 1)
38370: error("template argument mismatch, expected %t for formal %n, not %t",
38371: formal->f->tp, formal->f, actual->e1->tp) ;
38372: // hide the global name around decl processing of the formal name
38373: Pname g = gtbl->look (formal->f->string, 0) ;
38374: if (g) g->n_key = HIDDEN ;
38375: // bind the non type arguments to their expressions
38376: // parameters that are bound at syntax analysis, these parameters are
38377: // bound during dcl processing, so ensure that they can be found.
38378: formal->f->n_initializer = actual->e1 ;
38379: formal->f->simpl() ;
38380: formal->f = formal->f->dcl(gtbl, STATIC) ;
38381: formal->f->n_key = HIDDEN ;
38382:
38383: PERM(formal->f) ;
38384: non_template_arg_non_type(formal->f) ;
38385: if (!suitable_const_expr(formal->f))
38386: error("template argument for formal:%s, is not a suitable constant.",
38387: formal->f->string) ;
38388: if (g) g->n_key = 0 ;
38389: break ;
38390: }
38391:
38392: case template_expr_tree_formal:
38393: {
38394: bind_tree_expr_formal(formal->f, actual) ;
38395: break ;
38396: }
38397: case template_stmt_tree_formal:
38398: {
38399: error("a statement tree may not be specified for a class template") ;
38400: break ;
38401: }
38402:
38403: default:
38404: error ('i', "bad template formal") ;
38405: }
38406:
38407: // now that the formals are bound, compute the instantiation string
38408: char *inst_name = instantiation_string() ;
38409: tname->string = instantiation_string() ;
38410:
38411: for (formal = inst_formals; formal ; formal = formal->l)
38412: if (formal->f->n_template_arg_string)
38413: error('i', "attempt to bind a template parameter multiple times") ;
38414: else
38415: formal->f->n_template_arg_string =
38416: strcat(strcpy(calloc(strlen(formal->f->string)+strlen(inst_name)+1,1),
38417: formal->f->string), inst_name) ;
38418: }
38419:
38420:
38421: // Expose the non-type parameter names so that they are visible during decl
38422: // processing. Conflicting global names are hidden, so that they are not
38423: // found.
38424: void templ_inst::expose_parameter_names() {
38425:
38426: if (hidden_globals)
38427: error ('i', "an expose without a hide of global names") ;
38428:
38429: for (Plist formal = inst_formals ; formal ; formal = formal->l)
38430: if (formal->f->n_template_arg == template_expr_formal) {
38431: // Hide any visible globals
38432: Pname gname = gtbl->look(formal->f->string, 0) ;
38433: if (gname) {
38434: // an existing global name, hide it
38435: gname->n_key = HIDDEN ;
38436: // note them for future restoration
38437: hidden_globals = new name_list(gname,hidden_globals);
38438: }
38439: formal->f->n_key = 0 ; // bring it out of hiding
38440: if (formal->f != gtbl->look(formal->f->string,0))
38441: error('i', "parameter could not be located in the global table") ;
38442: }
38443: }
38444:
38445:
38446: // Hide the non-type parameter names after an instantiation, and restore any
38447: // globals that may have been hidden during the process.
38448: void templ_inst::hide_parameter_names() {
38449:
38450: for (Plist formal = inst_formals ; formal ; formal = formal->l)
38451: if (formal->f->n_template_arg == template_expr_formal) {
38452: formal->f->n_key = HIDDEN ;
38453: }
38454: for (; hidden_globals; hidden_globals= hidden_globals->l)
38455: hidden_globals->f->n_key= 0 ;
38456: hidden_globals = 0 ;
38457: }
38458:
38459:
38460:
38461: // Primitives for saving and restoring the compilation state around a template
38462: // instantiation. It also maintains the stack of template instantiations.
38463: void templ_inst::save_state(Pname p) {
38464: if (next_active) error ('i', "circular instantiation of a template") ;
38465: context.save() ;
38466: if (templ_inst::head)
38467: templ_inst::head->hide_parameter_names() ;
38468: next_active = templ_inst::head ; templ_inst::head = this ;
38469: context.init() ;
38470: Cdcl = p ; Cstmt = NULL ;
38471: curr_file = (Cdcl) ? Cdcl->where.file : 0;
38472: expose_parameter_names() ;
38473: }
38474:
38475:
38476: void templ_inst::restore_state() {
38477: context.restore() ;
38478: hide_parameter_names() ;
38479: templ_inst::head = next_active ; next_active = NULL ;
38480: if (templ_inst::head)
38481: templ_inst::head->expose_parameter_names() ;
38482: }
38483:
38484:
38485: // Copy over the class definition subtree starting from COBJ down to the
38486: // CLASSDEF node. This minimal subtree has to exist during syntax analysis,
38487: // and already contains pointers into it.
38488: void templ_inst::kludge_copy(Pbase pbc)
38489: {
38490: // copy just the COBJ ->b_name NAME ->tp CLASS path for now, note that the
38491: // preceding path of the tree is pre-allocated, since syntax analysis needs
38492: // to generate pointers to these objects.
38493: Pbase pb = Pbase(tname->tp) ;
38494: Pname save_b_name = pb->b_name ;
38495: Ptype save_tp = pb->b_name->tp ;
38496:
38497: if ((pb->base != COBJ) || (pbc->base != COBJ))
38498: error ('i', "cobj nodes were expected here") ;
38499:
38500: *pb = *pbc ;
38501: pb->b_name = save_b_name ;
38502: *pb->b_name = *pbc->b_name ;
38503: pb->b_name->tp = save_tp ;
38504: *Pclass(pb->b_name->tp) = *Pclass(pbc->b_name->tp) ;
38505: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ;
38506:
38507: }
38508:
38509:
38510: // these statics probably belong in templ_inst and shouldn't be dangling
38511: // around
38512:
38513: static Pbase cobj_node ;
38514: static Pname cname_node ;
38515: static Pclass class_node ;
38516:
38517: static void syntax_tree_copy_hook(void *,
38518: Pnode &,
38519: node_class,
38520: tree_node_action &action,
38521: int& never_see_again)
38522: {
38523: never_see_again = 1;
38524: action = tna_continue;
38525: return;
38526: }
38527:
38528:
38529: // create a copy of the expression tree
38530: static Pnode copy_syntax_tree(Pnode n, int no_types = 0) {
38531: pointer_hash cht(default_copy_hash_size) ;
38532:
38533: tree_copy_info info ;
38534:
38535: if(no_types) info.node_hook = syntax_tree_copy_hook;
38536:
38537: copy_tree (n, info, &cht);
38538:
38539: return n ;
38540: }
38541:
38542:
38543:
38544: // hook to perform the copying of the pre-allocated class subtree
38545: bool templ_inst::copy_hook(Pnode &node)
38546: {
38547: switch (node->base) {
38548: case COBJ:
38549: if (node == cobj_node) return false ;
38550:
38551: if (node == def->namep->tp) {
38552: *cobj_node = *Pbase(node) ;
38553: node = cobj_node ;
38554: }
38555: break ;
38556: case NAME:
38557: if (node == cname_node) return false ;
38558: if (node == sta_name) return false ;
38559:
38560: if (node == Pbase(def->namep->tp)->b_name) {
38561: *cname_node= *Pname(node) ;
38562: node = cname_node ;
38563: }else { // check for tree expression formals
38564: char *s = Pname(node)->string ;
38565: Pname f = 0 ;
38566: if (s && (*s == '$') && (f = get_parameter(s+1)))
38567: {
38568: if(Pname(node)->n_list)
38569: error ('i', "n_list set in tree template formal.");
38570: node = copy_syntax_tree(Pname(f)->n_initializer) ;
38571: return false ;
38572: }
38573: }
38574: break ;
38575: case CLASS:
38576: if (node == class_node) return false ;
38577:
38578: if (node == Pbase(def->namep->tp)->b_name->tp) {
38579: *class_node = *Pclass(node) ;
38580: node = class_node ;
38581: }
38582: break ;
38583: }
38584: return true ;
38585: }
38586:
38587:
38588: /*
38589:
38590: This hook function used during a class copy.
38591:
38592: */
38593: static void copy_hook(void /* Ptempl_inst */ *p, Pnode &node,
38594: node_class, tree_node_action &action,
38595: int& never_see_again)
38596: {
38597: action = (Ptempl_inst(p)->copy_hook(node) ? tna_continue : tna_stop ) ;
38598: never_see_again = (action != tna_stop);
38599: return ;
38600: }
38601:
38602:
38603:
38604: void establish_class_subtree_correspondence(pointer_hash &h, Pname key_tname,
38605: Pname value_tname)
38606: {
38607: h[int(key_tname)] = int(value_tname) ;
38608: h[int(key_tname->tp)] = int(value_tname->tp) ;
38609: h[int(Pbase(key_tname->tp)->b_name)] =
38610: int(Pbase(value_tname->tp)->b_name) ;
38611: h[int(Pbase(key_tname->tp)->b_name->tp)] =
38612: int(Pbase(value_tname->tp)->b_name->tp) ;
38613: }
38614:
38615:
38616:
38617:
38618: Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs)
38619: {
38620: cons dummy(0,0), *last = &dummy ;
38621:
38622: for (Pcons pc = old_templ_refs ; pc ; pc = pc->cdr) {
38623:
38624: Ptempl_inst t = Ptempl_inst(pc->car) ;
38625: // +**** this doesn't work without class instances of new and delete
38626: // +**** dtor places this onto free_list: ugh
38627: // +**** want to restore this once new/delete isntances are restored
38628: // expr dummy(ELIST, 0, 0) ;
38629: // elist list(&dummy) ;
38630: Pexpr dummy = new expr(ELIST, 0, 0);
38631: elist list(dummy);
38632:
38633: // copy the trees corresponding to the actuals
38634: for (Pexpr actual = t->actuals ; actual ; actual = actual->e2) {
38635: Pnode root = actual->e1 ;
38636: copy_tree (root, info, &h);
38637: // make sure that references to enclosing formals are resolved
38638: root = Pexpr(root)->typ(gtbl);
38639: list.add(new expr(ELIST, Pexpr(root), 0)) ;
38640: }
38641: Pexpr new_actuals = list.head->e2 ;
38642:
38643: // get one if it exists, create one otherwise.
38644: Ptempl_inst treal = t->def->get_inst(new_actuals, t) ;
38645: Pname new_tname = treal->tname ;
38646:
38647: last = last->cdr = new cons(treal,0);
38648:
38649: establish_class_subtree_correspondence(h, t->tname, new_tname) ;
38650: }
38651:
38652: return dummy.cdr ;
38653: }
38654:
38655:
38656:
38657:
38658: /*
38659: Remap the template references from within the body of the template. This
38660: action is similar to the normal tree copy operation; it would normally have
38661: been done during the syntax phase, that produced the tree, but since there
38662: isn't one, for the instantiated body, it must be done here.
38663:
38664: */
38665: Pcons templ_inst::ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs)
38666: {
38667: expose_parameter_names() ;
38668: Pcons new_refs = make_ref_copy(h,info,old_templ_refs) ;
38669: hide_parameter_names() ;
38670: return new_refs ;
38671: }
38672:
38673: static bool is_forward_instantiation(Pbase b_base, Pbase f_base)
38674: {
38675: return bool(b_base->b_name->tp->defined && f_base->b_name->tp->defined) ;
38676: }
38677:
38678:
38679: /*****************************************************************************
38680: * *
38681: * If the template instantiation is found to be unique after the decl *
38682: * processing of the actuals, create a copy of the post syntax graph for the *
38683: * class. The edges of the graph are determined by "type nodes" that have *
38684: * already been defined, and TNAME nodes that are in the global keyword *
38685: * table. Special care is also taken to avoid copying nodes whose identity *
38686: * must be maintained, since cfront uses them for fast type checks, these *
38687: * nodes always have the "defined" flag turned on and so are never copied. *
38688: * *
38689: * Copying of the pre-allocated class sub-tree for the template: COBJ *
38690: * ->b_name NAME ->tp CLASS *
38691: * *
38692: * is handled by the class_copy hook above, that is invoked during the course *
38693: * of the copy. *
38694: * *
38695: * *
38696: * Template references from within the class need special handling, since *
38697: * each instantiation of the class, results in a potentially new template *
38698: * instantiation. *
38699: * *
38700: *****************************************************************************/
38701: Ptempl_inst templ_inst::class_copy(Pcons &templ_refs, bool recopy)
38702: {
38703: bool forward = false ; // a forward class is instantiated twice
38704:
38705: // associate the formals with their types, and their expressions
38706: if (recopy) {
38707: // remove the class def node from the table, so that it's attributes are
38708: // copied.
38709: corr->del(int(Pbase(def->namep->tp)->b_name->tp)) ;
38710: corr->del(int(Pbase(def->namep->tp)->b_name)) ;
38711: corr->del(int(def->namep->tp)) ;
38712:
38713: corr->del(int(tname->tp)) ;
38714: corr->del(int(Pbase(tname->tp)->b_name)) ;
38715: corr->del(int(Pbase(tname->tp)->b_name->tp)) ;
38716: }else corr = new pointer_hash(default_copy_hash_size) ;
38717:
38718: { // copy the formals & install them in the correspondence table
38719: name_list dummy_formal(0,0) ;
38720: Plist last = &dummy_formal ;
38721:
38722: for (Plist formal = def->formals ; formal ; formal = formal->l) {
38723: Pname copy_name = new name("") ;
38724: *copy_name = *formal->f ;
38725: copy_name->n_tbl_list = 0 ;
38726: last = last->l = new name_list(copy_name, 0) ;
38727: (*corr)[int(formal->f)] = (int)copy_name ;
38728: }
38729: inst_formals = dummy_formal.l ;
38730: }
38731:
38732: bind_formals() ;
38733: if ( ! recopy && ktbl->look(tname->string, 0)) {
38734: // formal binding may result in detecting identical instantiations
38735: Ptempl_inst ti = def->get_match(actuals, this, true) ;
38736: if (ti) return ti ;
38737: error('i', "Generated template instantiation name %swas not unique",
38738: tname->string) ;
38739: }
38740:
38741: {
38742: tree_copy_info info ;
38743: info.node_hook = ::copy_hook ;
38744: info.hook_info = this ;
38745:
38746: (*corr)[int(def->namep)] = int(tname) ; // make the tnames correspond
38747:
38748: templ_refs = ref_copy(*corr, info, templ_refs) ;
38749: Pnode root = def->basep ; // start the copy at the cobj node
38750:
38751: // deal with these nodes differently during the copy, ie. the nodes
38752: // themselves are not copied, but their attributes are.
38753: cobj_node = (Pbase)tname->tp ;
38754: cname_node = Pbase( tname->tp)->b_name ;
38755: class_node = Pclass(Pbase( tname->tp)->b_name->tp) ;
38756:
38757: copy_tree (root, info, corr);
38758:
38759: { // dump the tree if the flag is set
38760: extern int dump_tree ;
38761: extern dcn_arg dump_tree_arg;
38762:
38763: if (dump_tree) display_cfront_node (dump_tree_arg, root);
38764: }
38765: }
38766: // Perform name modifications for the class, so that it is an
38767: // instantiation-specific name.
38768: cname_node->string = tname->string ;
38769: if (!recopy)
38770: namep = ktbl->insert(tname, 0) ;
38771: else class_node->defined &= ~(DEFINED|SIMPLIFIED) ;
38772: namep->tp = cobj_node;
38773:
38774: class_node->modify_inst_names(cname_node->string) ;
38775: return 0 ;
38776: }
38777:
38778:
38779: /*
38780: This hook function is responsible for the replacement of references to
38781: expression when copying function bodies
38782: */
38783: static void function_copy_hook(void *current_templ_inst,
38784: Pnode &node,
38785: node_class,
38786: tree_node_action &action,
38787: int& never_see_again)
38788: {
38789: never_see_again = 1;
38790:
38791: switch (node->base) {
38792: case SM_PARAM:
38793: error ('i', "statement parameters not permitted for member functions") ;
38794: break ;
38795:
38796: case NAME:
38797: {
38798: if(node == sta_name) {
38799: action = tna_stop;
38800: return;
38801: }
38802: char *s = Pname(node)->string ;
38803: Pname f = 0 ;
38804: if (s && (*s == '$') &&
38805: (f = Ptempl_inst(current_templ_inst)->get_parameter(s+1))) {
38806: if(Pname(node)->n_list)
38807: error ('i', "n_list set in tree template formal.");
38808: node = copy_syntax_tree(Pname(f)->n_initializer) ;
38809: action = tna_stop ;
38810: never_see_again = 0;
38811: }else action = tna_continue ;
38812: return ;
38813: }
38814: default:
38815: action = tna_continue ;
38816: return ;
38817: }
38818: }
38819:
38820:
38821:
38822: /*
38823:
38824: Create a copy of a function member, as part of the instantiation of a function
38825: body. The correspondence table is first initialized with the contents of the
38826: correspondence table used to instantiate the class. Copying is initiated
38827: in this context.
38828:
38829: */
38830:
38831: Pname templ_inst::function_copy(Pfunt fnt, Pcons &templ_refs)
38832: {
38833: pointer_hash fcorr(*corr) ; // initialize it with the old hash table
38834:
38835: {
38836: tree_copy_info info ;
38837: Pnode root = fnt->fn ;
38838:
38839: // establish a correspondence between the formals used for the class
38840: // template, andthe formals used for the function template, all references
38841: // to the function template formals will be replaced by references to the
38842: // instantiated class template formals after the copy has been completed.
38843:
38844: for (Plist fformal = fnt->formals, cformal = inst_formals ;
38845: fformal ; fformal = fformal->l, cformal = cformal->l)
38846: {
38847: fcorr[int(fformal->f)] = int(cformal->f) ;
38848: if (fcorr[int(fformal->f)] != int(cformal->f))
38849: error ('i', "hash table bug") ;
38850: }
38851:
38852: info.node_hook = ::function_copy_hook ;
38853: info.hook_info = this ;
38854:
38855: templ_refs = ref_copy(fcorr, info, templ_refs) ;
38856: if (fcorr[int(def->namep)] != int(tname))
38857: error ('i', "template to instantiation typename correspondence is missing") ;
38858:
38859: copy_tree (root, info, &fcorr);
38860:
38861: { // dump the tree if the flag is set
38862: extern int dump_tree ;
38863: extern dcn_arg dump_tree_arg;
38864:
38865: if (dump_tree)
38866: display_cfront_node (dump_tree_arg, root);
38867: }
38868: return Pname(root) ;
38869: }
38870: }
38871:
38872:
38873: /*****************************************************************************
38874: * *
38875: * A matching template was found at instantiation time, which was not *
38876: * detected at syntax analysis time. This can happen, when an instantiation *
38877: * has as its arguments not real types but template arguments, so that *
38878: * matches cannot be detected until the templates are bound. Note that it is *
38879: * also possible to match a template that is in the process of being *
38880: * instantiated further up the instantiation call chain. In such cases, the *
38881: * kludge_copy operation will copy over an incomplete class subtree, which *
38882: * will be recopied with the completed one after the instantiation is *
38883: * completed, in templ_inst::instantiate. *
38884: * *
38885: *****************************************************************************/
38886: void templ_inst::instantiate_match(Ptempl_inst match)
38887: { Pbase pb = Pbase(match->tname->tp) ;
38888: kludge_copy(pb) ;
38889: forward = match ; // Note the fact that this template was matched
38890: }
38891:
38892:
38893: Pclass current_instantiation = 0 ;
38894:
38895: // Do the class declaration instantiation.
38896: void templ_inst::instantiate(bool reinstantiate)
38897: {
38898: Pcons templ_refs = def->templ_refs ;
38899: if (! reinstantiate) {
38900: switch (Ptclass(Pbase(tname->tp)->b_name->tp)->class_base) {
38901: case instantiated_template_class:
38902: return ;
38903: case uninstantiated_template_class:
38904: break ;
38905: case vanilla_class:
38906: case template_class: // the canonical template class
38907: default:
38908: error ('i', "attempt to instantiate a non-template class") ;
38909: }
38910: status = class_instantiated ;
38911: // Check whether, the template has already been instantiated, if so use it.
38912: forward_template_arg_types(def->formals, actuals) ;
38913: Ptempl_inst match = def->get_match(actuals, this, true) ;
38914:
38915: if (match || (match = class_copy(templ_refs, false))){
38916: instantiate_match(match) ;
38917: return ;
38918: }
38919: }else class_copy(templ_refs, true) ;
38920:
38921: Pbase pb = Pbase(tname->tp) ;
38922:
38923: // Save the state around decl processing
38924: { save_state(def->namep) ;
38925:
38926: if (def->open_instantiations++ > 1) {
38927: error ("an infinite instantiation sequence was initiated") ;
38928: def->open_instantiations-- ;
38929: return ;
38930: }
38931: // Mark the class as instantiated so that there are no circular
38932: // instantiations.
38933: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ;
38934:
38935: // if it is a forward reference, rely on the usual compilation to
38936: // provide an error message, if indeed it is an error, and not a
38937: // benign forward reference such as: friend class foo<X,Y>
38938:
38939: if (def->basep->b_name->tp->defined) {
38940:
38941: // Put out the typedefs for the template parameters do this before the
38942: // call to name::dcl below, since dcl processing will emit c declarations
38943: // that make use of the type
38944: for (Plist formal = inst_formals; formal ; formal = formal->l)
38945: switch(formal->f->n_template_arg) {
38946: case template_expr_tree_formal:
38947: case template_stmt_tree_formal:
38948: break ;
38949: default:
38950: formal->f->dcl_print(0) ;
38951: }
38952: // Instantiate the parametrized types referenced by this template
38953: for (Pcons pc = templ_refs ; pc ; pc = pc->cdr)
38954: Ptempl_inst(pc->car)->instantiate() ;
38955:
38956: if (!((pb->b_name->dcl(gtbl, EXTERN) == 0 ) || error_count)) {
38957: pb->b_name->simpl() ;
38958:
38959: if (pb->b_name->tp->base != CLASS)
38960: error('i', "a classdef was expected in templ_inst::instantiate") ;
38961:
38962: current_instantiation = Pclass(pb->b_name->tp) ;
38963: pb->b_name->dcl_print(0) ;
38964: if (! (pb->b_name->tp->defined & DEFINED))
38965: error ('i', "dcl class is not yet defined") ;
38966: current_instantiation = 0 ;
38967: }
38968: }
38969:
38970: // bash every template instantiation class that has been forwarded to
38971: // it, with the decl processed version.
38972: for (Ptempl_inst clone = def->insts ; clone ; clone = clone->next)
38973: if (clone != this) {
38974: if (clone->forward == this)
38975: clone->kludge_copy(Pbase(tname->tp)) ;
38976: else {
38977: // resolve references to forward declarations
38978: if (this == def->get_match(clone->actuals, clone, true)) {
38979: clone->kludge_copy(Pbase(tname->tp)) ;
38980: clone->forward = this ;
38981: }
38982: }
38983: }
38984: Pclass result = Pclass(pb->b_name->tp);
38985:
38986: // dcl_print the member functions, so that they can be referenced
38987: int i = 0 ;
38988: for (Pname fn= Pclass(pb->b_name->tp)->memtbl->get_mem(i=1); fn;
38989: fn=Pclass(pb->b_name->tp)->memtbl->get_mem(++i))
38990: if ((fn->base == NAME) && (fn->tp->base == FCT))
38991: fn->dcl_print(0) ;
38992:
38993: restore_state() ;
38994: def->open_instantiations-- ;
38995: }
38996: }
38997:
38998: /* Template Constructors */
38999:
39000:
39001: templ::templ(Plist parms, Pname p) {
39002: namep = p ;
39003: formals = parms ;
39004:
39005: if (!formals) error ("a parametrized type must have parameters !") ;
39006:
39007: basep = Pbase(namep->tp) ;
39008:
39009: Pclass(basep->b_name->tp)->class_base = template_class ;
39010: defined = ((basep->b_name->tp->defined & DEF_SEEN) ? true : false) ;
39011: if (defined)
39012: members = Pclass(basep->b_name->tp)->mem_list ;
39013:
39014: PERM(namep) ; PERM(namep->tp) ;
39015: // Chain on to the list of templates for the compilation.
39016: next = templp->list ;
39017: templp->list = this ;
39018: }
39019:
39020:
39021: templ_inst::templ_inst (Pexpr act, Ptempl owner)
39022: {
39023: // Set up the basetype for the class, so that nodes that need to point to it
39024: // during syntax processing can do so. Theese objects are merely
39025: // place-holders during syntax analysis, and are actually filled in during
39026: // the copy phase of instantiation.
39027: Pclass c ;
39028:
39029: def = owner ;
39030: tname = new name(def->namep->string) ;
39031: tname->base = TNAME ;
39032: tname->tp = new basetype(COBJ, new name(def->namep->string)) ;
39033: Pbase(tname->tp)->b_name->tp = c = new templ_classdef(this) ;
39034: PERM(tname) ; PERM(tname->tp) ; PERM(Pbase(tname->tp)->b_name) ;
39035: PERM(Pbase(tname->tp)->b_name->tp) ;
39036:
39037: // initialize the member list so that set_scope can do the right thing
39038: c->mem_list = Pclass(def->basetype()->b_name->tp)->mem_list ;
39039:
39040: actuals = act ;
39041: next = owner->insts ;
39042: owner->insts = this ;
39043: }
39044:
39045:
39046: templ_classdef::templ_classdef(Ptempl_inst i): classdef(CLASS) {
39047: inst = i ;
39048: class_base = uninstantiated_template_class ;
39049: string = unparametrized_tname()->string ;
39050: }
39051:
39052:
39053: // Create a new function template.
39054: function_template::function_template (templ &owner, Plist params, Pname n)
39055: {
39056: definition_number = ++definition_tick ;
39057:
39058: if (owner.fns_end)
39059: owner.fns_end->next = this ;
39060: else owner.fns = this ;
39061: owner.fns_end = this ;
39062: formals = params ;
39063: fn = n ;
39064: PERM(n) ; PERM(n->tp) ;
39065: }
39066:
39067:
39068: // create the tree template
39069: tree_template::tree_template(TOK tree_kind, char *s, Plist params, Pnode tree,
39070: Pcons references)
39071: {
39072: string = s ;
39073: formals = params;
39074: e = tree ;
39075: if (!e)
39076: error('w', "the internal template %s does not have an associated body", s);
39077: templ_refs = references ;
39078: kind = tree_kind ;
39079:
39080: // add the expression template too the list of known templates
39081: if (get(s)) {
39082: error ("duplicate definition of the internal template %s", s) ;
39083: return ;
39084: }
39085: // link it in
39086: next = templ_compilation::tree_templates ;
39087: templ_compilation::tree_templates = this ;
39088:
39089: // check that formals weren't misspelt
39090: for (Plist formal = formals ; formal ; formal = formal->l)
39091: if (! formal->f->n_used)
39092: error('w', "the formal parameter %n was not referenced within the template body",formal->f) ;
39093: }
39094:
39095:
39096: // lookup an internal expression template
39097: Ptreet tree_template::get(char *s) {
39098: for (Ptreet o = templ_compilation::tree_templates ; o ; o = o->next)
39099: if (strcmp(o->string, s) == 0) return o ;
39100: return 0 ;
39101: }
39102:
39103:
39104: Pname tree_template::get_parameter(char *s) {
39105: for (Plist formal = formals ; formal ; formal = formal->l) {
39106: if (strcmp(formal->f->string, s)== 0)
39107: return formal->f ;
39108: }
39109: return 0 ;
39110: }
39111:
39112:
39113:
39114: // Sam: some remodularization seems to be in order here, so that this method
39115: // can be shared
39116: Pname templ_inst::get_parameter(char *s) {
39117: for (Plist formal = inst_formals ; formal ; formal = formal->l) {
39118: if (strcmp(formal->f->string, s)== 0)
39119: return formal->f ;
39120: }
39121: return 0 ;
39122: }
39123:
39124: Pexpr tree_template::expand(Pexpr)
39125: {
39126: error('i', "no support for tree templates") ;
39127: return 0 ;
39128: }
39129:
39130:
39131: // Instantiate each function member body. It assumes that the class
39132: // declaration has been instantiated. The return value indicates whether an
39133: // instantiation of bodies actually took place. This function is only invoked
39134: // at the end of a file compilation, after all source text has been processed.
39135: bool templ::instantiate_bodies(){
39136: bool change = false ;
39137: // Perform the instantiation of the member function bodies.
39138: if (!fns) return change ;
39139:
39140: for (Ptempl_inst inst = insts ; inst ; inst = inst->next)
39141: if (!inst->forward && (inst->status == class_instantiated)) {
39142: // Set up the environment for the declaration, and subsequent compilation
39143: // of the function bodies.
39144: inst->status = body_instantiated ; change = true ;
39145:
39146: { Pclass ic = inst->get_class() ; int i ;
39147: // note all the overriding definitions explicitly provided by the user
39148: for (Pname fn= ic->memtbl->get_mem(i=1); fn; fn=ic->memtbl->get_mem(++i))
39149: if ((fn->base == NAME) && (fn->tp->base == FCT) && Pfct(fn->tp)->body)
39150: fn->n_redefined = 1 ;
39151: }
39152:
39153: for (Pfunt fnt = fns; fnt ; fnt = fnt->next) {
39154: Pcons templ_ref_copy = fnt->templ_refs ;
39155: Pname fn = inst->function_copy(fnt, templ_ref_copy) ;
39156:
39157: // Change the qualifier to be the name of the instantiated, rather than
39158: // the parametrized class name
39159: fn->n_qualifier = inst->namep ;
39160: if (fn->n_oper != TYPE ) // cond contains type information
39161: fn->n_table = 0;
39162: fn->n_tbl_list = 0 ;
39163:
39164: // Note that the formals were bound to the actuals when the class decl
39165: // was instantiated, so the binding is not redone.
39166:
39167: // Modify constructor and destructor names.
39168: if (!strcmp(fn->string, namep->string))
39169: fn->string = inst->namep->string ;
39170: { inst->save_state(fn) ;
39171: // Instantiate the parametrized types referenced by this template
39172: for (Pcons pc = templ_ref_copy ; pc ; pc = pc->cdr)
39173: Ptempl_inst(pc->car)->instantiate() ;
39174:
39175: // ensure that "type type" formals constrained to be class definitions are
39176: if (!fnt->check_constraints(inst->actuals))continue ;
39177:
39178: if ( ((fn = fn->dcl(gtbl, EXTERN)) == 0) || error_count) {
39179: inst->restore_state() ;
39180: continue ;
39181: }
39182: fn->simpl() ;
39183: fn->dcl_print(0) ;
39184: inst->restore_state() ;
39185: }
39186: }
39187: }
39188: return change ;
39189: }
39190: 0707071010112046121004440001630000160000010212600466055421700001300000040045template.h /* ident "@(#)ctrans:src/template.h 1.2" */
39191: /* -*- Mode:C++ -*- */
39192: /*
39193: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v $ $RCSfile: template.h,v $
39194: $Revision: 1.4 $ $Date: 90/04/02 11:31:35 $
39195: $Author: sam $ $Locker: $
39196: $State: Exp $
39197: */
39198: /*
39199: $Header: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v 1.4 90/04/02 11:31:35 sam Exp $
39200:
39201: Copyright 1989 by Object Design, Inc., Burlington, Mass.
39202: All rights reserved.
39203:
39204: */
39205:
39206:
39207: /*****************************************************************************
39208: * *
39209: * This file contains types pertinent to the implementation of the *
39210: * parametrized type facility. *
39211: * *
39212: *****************************************************************************/
39213:
39214: enum bool { true = 1, false = 0 } ;
39215:
39216: typedef class templ *Ptempl ;
39217:
39218: typedef class templ_inst *Ptempl_inst ;
39219:
39220: typedef class function_template *Pfunt ;
39221:
39222: typedef class templ_classdef *Ptclass ;
39223:
39224: typedef class tree_template *Ptreet ;
39225:
39226:
39227: // A Lisp style cons cell to help build lists. The parametrized type facility,
39228: // should obviate the need for this type-unsafe nonsense.
39229: class cons {
39230: public:
39231: void *car ;
39232: cons *cdr ;
39233: cons (void *pcar, cons *pcdr) { car = pcar ; cdr = pcdr ; } ;
39234: } ;
39235:
39236: typedef cons *Pcons ;
39237:
39238:
39239:
39240: /*****************************************************************************
39241: * *
39242: * The class template_compilation holds the state, and the associated methods *
39243: * used during template compilation. There is exactly one instance of the *
39244: * type, it is mainly a device used to enforce modularity. In reality, it *
39245: * would never need to be instantiated since all it's members are static. *
39246: * However, since the type::mem for of reference is not supported as *
39247: * yet(cfront 1.2), we need an instantiation to get to the members via *
39248: * pointer syntax instead. *
39249: * *
39250: * A templ_compilation holds the state relevant to the syntax analysis of a *
39251: * class or member function template definition. *
39252: * *
39253: *****************************************************************************/
39254:
39255: class templ_compilation {
39256: static Plist param_end, // make append easier
39257: param_tn ; // The type names introduced by the parameters
39258:
39259: public:
39260: static Ptempl list ; // The list of templates for the compilation
39261: static Plist params ; // The list of parameters to the template
39262: static Ptempl owner ; // The template when compiling a member
39263: // function.
39264: static table *templates ; // The templates defined during this compilation
39265:
39266: static Ptreet tree_templates; // The list of tree templates
39267:
39268: static bool in_progress; // a template compilation is in progress
39269: // instantiation parameter parsing in progress. Used in the lexer to ensure
39270: // that name string are consed in the heap, rather than being retained as
39271: // pointers into the lex buffer.
39272: static int parameters_in_progress ;
39273:
39274: // the list of templates referenced by the top level definition being compiled.
39275: static Pcons templ_refs ;
39276: static Pcons last_cons ;
39277: static Ptype any_type ; // canonical "ANY" type for formal parms
39278:
39279: // true, if currently compiling an expression tree template
39280: static TOK curr_tree_template ;
39281:
39282: void append_ref(Ptempl_inst ref) ;
39283: void start() ;
39284:
39285: void collect(TOK parm_type, Pname namep) ;
39286: void collect(Pname namep) ;
39287:
39288: void enter_parameters() ;
39289: void introduce_class_templ(Pname cnamep) ;
39290: void end(Pname class_name) ;
39291: Pname forward_declaration(Pname class_name) ;
39292: void instantiate_ref_templ() ;
39293: void clear_ref_templ() ;
39294:
39295: Pname check_tname(Pname p) ;
39296: bool current_template(Pname p, Pexpr actuals) ;
39297: Ptempl is_template(Pname p) ;
39298: Ptempl is_template(char *s);
39299: void end_of_compilation() ; // Done with compilation, instantiate bodies
39300: templ_compilation() ;
39301:
39302: static Pname tree_parameter(char *s) ; // return true if the name is a tree parameter
39303:
39304: private:
39305: void append_parameter(Pname p) ;
39306:
39307: } ;
39308:
39309:
39310:
39311: // The canonical template_compilation instance. templ_compilation exists as a
39312: // class simply to provide a code and data packaging mechanism. There is
39313: // exactly one generated instance of it.
39314:
39315: extern templ_compilation *templp ;
39316:
39317: // should actually be static member functions of templ_compilation
39318: Pname parametrized_typename (Pname p, Pexpr actuals) ;
39319: Pbase parametrized_basetype (Pname p, Pexpr actuals) ;
39320:
39321:
39322:
39323:
39324: // the basis for class and member function templates
39325: class basic_template {
39326: friend templ_compilation ;
39327: protected:
39328: Plist formals ; // The formal arguments to the template
39329: Pcons templ_refs ; // The templates referenced by this template
39330:
39331: // check class constraints placed on formals while processing member
39332: // function bodies.
39333: bool check_constraints(Pexpr actuals) ;
39334:
39335: // ensure that use of formals is consistent across, class, member and
39336: // forward declarations
39337: void check_formals(Plist formals) ;
39338:
39339: public:
39340: // used to order template class definitions for instantiations. Not being
39341: // used as yet.
39342: int definition_number ;
39343:
39344: // used to generate the definition numbers, used by the above member.
39345: static int definition_tick ;
39346:
39347: Plist get_formals() {return formals ;}
39348: } ;
39349:
39350:
39351:
39352: // the template for a class
39353: class templ : public basic_template {
39354: Pbase basep ; // COBJ basetype for the template
39355: Ptempl_inst insts ; // instantiations of the template
39356: Pfunt fns ; // member function declarations
39357: Pfunt fns_end ; // last fun in the above list
39358:
39359: // Use these state variables to set up the correct state for error
39360: // processing. They are used by the "error" routines for statement numbers.
39361: Pname Cdcl ;
39362: Pstmt Cstmt ;
39363:
39364: friend templ_inst ;
39365: friend function_template ;
39366:
39367: // used to detect loops during instantiation; a count greater than two is
39368: // indicative of a non-terminating instantiation sequence
39369: int open_instantiations ;
39370:
39371: Ptempl_inst get_match(Pexpr actuals,
39372: Ptempl_inst exclude,
39373: bool match_instantiated_only) ;
39374: bool check_actual_args (Pexpr actuals) ;
39375:
39376: public:
39377: Ptempl next ; // connects all the class templates in the comp
39378: Pname namep ; // the TNAME for the template class
39379: bool defined ; // the actual definition, not just a forward
39380: // declaration has been seen.
39381:
39382: Pname members ; // note the members to catch redefinition errors
39383:
39384: Ptempl_inst get_inst(Pexpr actuals, Ptempl_inst exclude = 0) ;
39385: templ(Plist parms, Pname p) ;
39386: void resolve_forward_decl(Plist parms, Pclass c) ;
39387: void instantiate_forward_decl() ;
39388:
39389: // The uninstantiated base type
39390: Pbase basetype() {return basep; }
39391: // The basetype for a specific instantiation
39392: Pbase inst_basetype(Pexpr actuals) ;
39393:
39394: Pname typename(Pexpr actuals) ;
39395:
39396: Pfunt collect_function_member(Pname fname) ;
39397: bool has_tree_expr_formals() ;
39398: bool instantiate_bodies() ;
39399: } ;
39400:
39401:
39402:
39403: // Member function templates
39404: class function_template : public basic_template {
39405: Pname fn ; // The name of the member function
39406: Pfunt next ; // connects the list of member functions
39407:
39408: friend templ ;
39409: friend templ_inst ;
39410:
39411: public:
39412: function_template (templ & owner, Plist params, Pname n) ;
39413: } ;
39414:
39415:
39416:
39417: // compiler internal expression templates, used to implement Objectstore constructs
39418: class tree_template : public basic_template {
39419: TOK kind ; // STATEMENT or EXPRESSION
39420: Pnode e ; // the post-syntax tree representing the
39421: // expression or statement constituting the
39422: // template.
39423: Ptreet next ; // the next expression template
39424: static int count ; // the number of instantiations
39425:
39426: public:
39427: char *string ; // the name used for template lookup
39428: tree_template(TOK tree_kind, char *s, Plist params, Pnode tree,
39429: Pcons references) ;
39430: static Ptreet get(char *s) ;
39431: Pname get_parameter(char *s) ;
39432: static void test() ;
39433: Pexpr expand(Pexpr actuals) ;
39434: } ;
39435:
39436:
39437:
39438:
39439: // Global state variables that must be saved around an instantiation. The
39440: // saving of state was required in the implementstion that interspersed decl
39441: // processing and instantiation, rather than the current strategy, which only
39442: // forces instantiations at the top level outside of any dcl-processing
39443: // context. It is retained in case we ever go back to the "interspersed" style
39444: // of instantiation.
39445: class state {
39446:
39447: public:
39448: Pname Cdcl ; // the global variables used by the error routines
39449: Pstmt Cstmt ;
39450: Pname dcl_list ; // Holds the list of typedef names that are hidden
39451: Loc curloc ;
39452:
39453: int curr_file ;
39454: Pexpr curr_expr ;
39455: Pin curr_icall ;
39456: Pstmt curr_loop;
39457: Pblock curr_block;
39458: Pstmt curr_switch;
39459:
39460: int bound ;
39461: int inline_restr ;
39462: Loc last_line ;
39463:
39464: int no_of_badcall;
39465: int no_of_undcl ;
39466:
39467: Pname badcall ;
39468: Pname undcl ;
39469:
39470: state() {} ; // prevent used before set warnings.
39471: void save() ;
39472:
39473: void init() ;
39474: void restore() ;
39475: } ;
39476:
39477:
39478: class pointer_hash ;
39479: class tree_copy_info ;
39480:
39481:
39482: // A template starts out being uninstantiated, and is class_instantiated when
39483: // there is a refrence to it with actual arguments. It is body_instantiated at
39484: // the end of compilation, when all its function members are instantiated.
39485: enum inst_status { uninstantiated, class_instantiated, body_instantiated };
39486:
39487: // templ_inst captures the arguments used in the instantiation of a template.
39488: // These instantiations are rooted in the templ object.
39489: class templ_inst {
39490:
39491: friend class template_instantiation ;
39492:
39493: Pname tname ; // The instantiation name, it is the TNAME that
39494: // leads up to an actual instantiation of the class
39495: Pname namep ; // The version of TNAME in the ktbl
39496: Pexpr actuals ; // instantiation arguments, chained using ELIST
39497: // as an expression "cons" node, e1 is the car
39498: // and e2 the cdr. The car points to a name node.
39499: Ptempl_inst next ; // The linked list of instantiations for this
39500: // template.
39501: Ptempl_inst next_active ; // The list of currently active instantiations.
39502: state context ; // the context of this instantiation
39503: Ptempl_inst forward ; // This instantiation is the same as the one
39504: // pointed to.
39505:
39506: // Contains the list of global names that are hidden during an
39507: // instantiation.
39508: Plist hidden_globals ;
39509:
39510: // The class correspondence table. This table is initialized
39511: // when the class definition is instantiated. Subsequently, it is used to
39512: // initial member correspondence tables before the copy process is
39513: // initiated.
39514: pointer_hash *corr ;
39515:
39516: // the instantiation's copy of the formals
39517: Plist inst_formals ;
39518:
39519: inst_status status ;
39520:
39521: friend class templ ;
39522: friend class templ_classdef ;
39523: friend class tree_template ;
39524: friend Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info,
39525: Pcons old_templ_refs);
39526:
39527: templ_inst (Pexpr act, Ptempl owner) ;
39528: bool actuals_match(Pexpr check_actuals) ;
39529: void instantiate_match(Ptempl_inst match) ;
39530: void kludge_copy(Pbase source_base) ;
39531: // create a copy of the class type subtree preparatory to the ensuing
39532: // instantiation. Return a non-zero value, only if there was no need to
39533: // create a copy, ie. an identical instantiation already existed.
39534: Ptempl_inst class_copy(Pcons &templ_refs, bool recopy) ;
39535: Pcons ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ;
39536:
39537: // save and restore state around the template instantiation
39538: void save_state(Pname p) ;
39539: void restore_state() ;
39540:
39541: // Used to collect references to this template by a definition
39542: Ptempl_inst note_ref() ;
39543: char *instantiation_string() ;
39544:
39545: void expose_parameter_names() ;
39546: void hide_parameter_names() ;
39547:
39548: public:
39549: Ptempl def ; // The template definition, for which this is an
39550: // instantiation.
39551: bool refp ; // A flag used to note template references during
39552: // a C++ definition
39553: void print_error_loc() ; // Wants to be a static function
39554: // Bind the formals before an instantiation
39555: void bind_formals() ;
39556:
39557: Ptempl_inst canonical_instantiation() {
39558: return ( forward ? forward : this ) ;
39559: }
39560:
39561: // get the class associated with this instantiation
39562: Pclass get_class() { return Pclass(Pbase(tname->tp)->b_name->tp) ;}
39563:
39564: void instantiate(bool reinstantiate = false) ;
39565: static Ptempl_inst head ; // Head of the list of active instantiations.
39566: void print_pretty_name() ;
39567: char *mangled_name(char *buffer) ;
39568: // The uninstantiated basetype
39569: Pbase def_basetype() { return def->basep ; } ;
39570: // A general way of determining whether two template instantiations are
39571: // the same
39572: bool same(Ptempl_inst t) ;
39573: bool copy_hook(Pnode&) ;
39574: // return a copy of the function tree starting with it's name
39575: Pname function_copy(Pfunt fnt, Pcons &templ_refs) ;
39576:
39577: // special check for instantiations used in qualifiers for template function
39578: // member declarations.
39579: bool check_qualifier(Plist formals) ;
39580: Pname get_parameter(char *s) ;
39581: } ;
39582:
39583:
39584:
39585: // Experimental debugging toggle
39586: extern int zdebug ;
39587:
39588:
39589: // The class node used for template classes.
39590: // Rep invariant:
39591: // class_base == uninstantiated_template_class ||
39592: // class_base == instantiated_template_class
39593:
39594: class templ_classdef : public classdef {
39595: public:
39596: Ptempl_inst inst ; // a pointer to the instantiation; the
39597: // instantiation also points back to it via
39598: // the tname ->cobj->name->class path
39599: templ_classdef(Ptempl_inst i) ;
39600: Pname unparametrized_tname() { return inst->def->namep ; }
39601: void instantiate() { inst->instantiate() ; }
39602:
39603: } ;
39604:
39605:
39606: // Safe accessor functions for navigating through COBJ base classes
39607:
39608: extern class_type_enum get_class_base (Pbase b) ;
39609:
39610: extern Ptclass get_template_class (Pbase b) ;
39611:
39612: extern Ptempl_inst get_templ_inst(Pbase b) ;
39613:
39614:
39615: /*
39616: $Log: template.h,v $
39617: * Revision 1.4 90/04/02 11:31:35 sam
39618: * Made comments current.
39619: *
39620: * Revision 1.3 90/03/30 18:50:55 sam
39621: * 1) Added the introduce_class_templ member function to the templ_compilation
39622: * class.
39623: * 2) Rationalized the definition of class templ. Made basic_template be it's
39624: * base class, instead of type. The latter was the base type, simply so that
39625: * it could be stored in a table associating strings with types. Don't have
39626: * to resolve to such kludgery in the PT world.
39627: * 3) Added the member open_instantiations to detect non-terminating
39628: * instantiations
39629: *
39630: * Revision 1.2 90/03/27 10:16:27 sam
39631: * > Merged in revision 1.13 from the main line of development
39632: *
39633: * Revision 1.1 89/11/20 08:50:58 benson
39634: * Initial revision
39635: *
39636: * Revision 1.11 89/10/16 15:25:00 sam
39637: * use pointer_hash rather than Hash as the type of the correspondence table.
39638: *
39639: * Revision 1.10 89/09/26 16:44:34 sam
39640: * fix the forward declaration of template classes
39641: *
39642: * Revision 1.9 89/09/18 16:37:37 sam
39643: * provide for error recovery upon argument mismatch in a template instantiation
39644: *
39645: *
39646: * Revision 1.8 89/09/15 09:31:50 benson
39647: * move tree_template.string into the public section.
39648: *
39649: * Revision 1.7 89/08/30 13:02:12 sam
39650: * added support for dealing with __expressions in class formal templates
39651: *
39652: * Revision 1.6 89/08/28 09:42:05 sam
39653: * Support for nested references in internal templates. These nested
39654: * references are instantiated whenever an expansion takes place.
39655: *
39656: * Revision 1.5 89/08/23 10:26:00 sam
39657: * support for BS style formal syntax. refer to 1.5 templates.c for more
39658: * detailed comments.
39659: *
39660: * Revision 1.4 89/08/11 14:57:09 sam
39661: * implementation of multiple instantiation templates.
39662: *
39663: * Revision 1.3 89/07/27 11:33:40 sam
39664: * the comments in template.c 1.3 describe the modifications.
39665: *
39666: * Revision 1.2 89/07/07 14:34:11 sam
39667: * Added the templ_classdef::unparametrized_type_name() function member, as part
39668: * of the base init fix.
39669: *
39670: * Revision 1.1 89/06/29 09:21:32 benson
39671: * Initial revision
39672: *
39673: * Revision 1.1 89/06/22 16:29:29 sam
39674: * Initial revision
39675: *
39676:
39677:
39678: end_log
39679: */
39680:
39681:
39682:
39683: /*
39684: $Log $
39685:
39686:
39687: end_log
39688: */
39689: 0707071010112045701004440001630000160000010210100466055411600001000000012452token.h /*ident "@(#)ctrans:src/token.h 1.4" */
39690: /**************************************************************************
39691:
39692: C++ source for cfront, the C++ compiler front-end
39693: written in the computer science research center of Bell Labs
39694:
39695: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
39696: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
39697:
39698: token.h:
39699:
39700: *****************************************************************************/
39701: /*
39702: #ifndef PRESAFE
39703: extern "C" {
39704: #endif
39705:
39706: extern void free(char*); // alloc.h
39707: extern char* malloc(unsigned);
39708: extern char* calloc(unsigned, unsigned);
39709:
39710: extern strncmp(const char*, const char*, const); // string.h
39711: extern strcmp(const char*, const char*);
39712: extern int strlen(const char*);
39713: extern char* strcpy(char*, const char*);
39714:
39715: #ifdef apollo
39716: extern void set_sbrk_size(int);
39717: #endif
39718:
39719: #ifndef PRESAFE
39720: }
39721: #endif
39722: */
39723:
39724: #include <malloc.h>
39725: #include <string.h>
39726: #include <stdio.h>
39727:
39728: extern void lex_clear();
39729: extern void otbl_init();
39730:
39731: //#define yylex() lalex()
39732:
39733: #define putstring(s) fputs(s,out_file)
39734: #define putst(s) (fputs(s,out_file),putc(' ',out_file))
39735: #define putch(c) putc(c,out_file)
39736: #define putcat(c,s) (putc(c,out_file),fputs(s,out_file))
39737:
39738: /* token numbers for C parser */
39739:
39740: #define MAXTOK 255
39741: extern char* keys[MAXTOK+1];
39742:
39743: #define EOFTOK 0 /* EOF */
39744: /* keywords in alphabetical order */
39745: #define ASM 1
39746: #define AUTO 2
39747: #define BREAK 3
39748: #define CASE 4
39749: #define CHAR 5
39750: #define CLASS 6
39751: #define CONTINUE 7
39752: #define DEFAULT 8
39753: #define DELETE 9
39754: #define DO 10
39755: #define DOUBLE 11
39756: #define ELSE 12
39757: #define ENUM 13
39758: #define EXTERN 14
39759: #define FLOAT 15
39760: #define FOR 16
39761: #define FORTRAN 17
39762: #define FRIEND 18
39763: #define GOTO 19
39764: #define IF 20
39765: #define INT 21
39766: #define LONG 22
39767: #define NEW 23
39768: #define OPERATOR 24
39769: #define PUBLIC 25
39770: #define CONST 26
39771: #define REGISTER 27
39772: #define RETURN 28
39773: #define SHORT 29
39774: #define SIZEOF 30
39775: #define STATIC 31
39776: #define STRUCT 32
39777: #define SWITCH 33
39778: #define THIS 34
39779: #define TYPEDEF 35
39780: #define UNION 36
39781: #define UNSIGNED 37
39782: #define VOID 38
39783: #define WHILE 39
39784:
39785: /* operators in priority order (sort of) */
39786: #define LP 40
39787: #define RP 41
39788: #define LB 42
39789: #define RB 43
39790: #define REF 44
39791: #define DOT 45
39792: #define NOT 46
39793: #define COMPL 47
39794: #define INCR 48
39795: #define DECR 49
39796: #define MUL 50
39797: #define DIV 51
39798: #define AND 52
39799: #define MOD 53
39800: #define PLUS 54
39801: #define MINUS 55
39802: #define LS 56
39803: #define RS 57
39804: #define LT 58
39805: #define LE 59
39806: #define GT 60
39807: #define GE 61
39808: #define EQ 62
39809: #define NE 63
39810: #define ER 64
39811: #define OR 65
39812: #define ANDAND 66
39813: #define OROR 67
39814: #define QUEST 68
39815: #define COLON 69
39816: #define ASSIGN 70
39817: #define CM 71
39818: #define SM 72
39819: #define LC 73
39820: #define RC 74
39821:
39822: #define INLINE 75
39823: #define OVERLOAD 76
39824: #define VIRTUAL 77
39825: #define COERCE 78
39826: #define PROTECTED 79
39827:
39828: /* constants etc. */
39829: #define ID 80
39830: #define STRING 81
39831: #define ICON 82
39832: #define FCON 83
39833: #define CCON 84
39834: #define NAME 85
39835: #define ZERO 86
39836:
39837: /* groups of tokens */
39838: #define ASOP 90 /* op= */
39839: #define RELOP 91 /* LE GE LT GT */
39840: #define EQUOP 92 /* EQ NE */
39841: #define DIVOP 93 /* DIV MOD */
39842: #define SHIFTOP 94 /* LS RS */
39843: #define ICOP 95 /* INCR DECR */
39844: #define UNOP 96 /* NOT COMPL */
39845: #define TYPE 97
39846: /* TYPE = INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO
39847: LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */
39848:
39849: /* new tokens generated by syn() */
39850: #define UMINUS 107
39851: #define FCT 108
39852: #define CALL 109
39853: #define VEC 110
39854: #define DEREF 111
39855: #define ADDROF 112
39856: #define CAST 113
39857: //#define ENDCAST 122
39858: #define FIELD 114
39859: #define LABEL 115
39860: #define BLOCK 116
39861: //#define QUA 117
39862: #define DCL 118 /* local declaration statement */
39863: #define COBJ 119
39864: #define EOBJ 121
39865: #define TNAME 123
39866: #define ILIST 124
39867: #define PTR 125
39868:
39869: #define ASPLUS 126
39870: #define ASMINUS 127
39871: #define ASMUL 128
39872: #define ASDIV 129
39873: #define ASMOD 130
39874: #define ASAND 131
39875: #define ASOR 132
39876: #define ASER 133
39877: #define ASLS 134
39878: #define ASRS 135
39879:
39880: #define ARG 136
39881: #define ARGS 137
39882: #define ZTYPE 138
39883: #define ARGT 139
39884: #define ELIST 140
39885: #define ANY 141
39886: #define TABLE 142
39887: #define LOC 143
39888: #define DUMMY 144
39889: #define G_ADDROF 145
39890: #define G_CALL 146
39891: #define G_CM 147
39892: #define IVAL 150
39893: //#define FVAL 151
39894: //#define LVAL 152
39895: #define ELLIPSIS 155
39896: #define AGGR 156
39897: #define VALUE 157 /* constructor call */
39898: #define RPTR 158 /* reference */
39899: #define HIDDEN 159
39900: #define MEM 160
39901: #define CTOR 161
39902: #define DTOR 162
39903: #define CONST_PTR 163
39904: #define CONST_RPTR 164
39905: #define TEXT 165
39906: #define PAIR 166
39907: #define ANON 167
39908: #define ICALL 168
39909: #define ANAME 169
39910: #define VOLATILE 170
39911: #define SIGNED 171
39912: #define UPLUS 172
39913: #define MEMPTR 173
39914: #define PRIVATE 174
39915: #define PR 175 /* PUBLIC PRIVATE or PROTECTED */
39916: #define MDOT 177
39917: #define TSCOPE 178
39918: #define DECL_MARKER 179
39919: #define REFMUL 180
39920: #define LDOUBLE 181
39921: #define LINKAGE 182
39922: #define LOCAL 183
39923: #define GNEW 184
39924: #define TEMPLATE 185
39925: #define STAT_INIT 186
39926: #define CATCH 187
39927: #define GDELETE 188
39928: //#define CONVERT 189
39929: #define NESTED 190
39930: #define TRY 191
39931:
39932: // class parameterized types constants
39933: #define XVIRT 200 /* class virt */
39934: #define XNLIST 201 /* struct name_list */
39935: #define XILINE 202
39936: #define XIA 203
39937: #define STATEMENT 205
39938: #define EXPRESSION 206
39939: #define SM_PARAM 207
39940: #define TEMPLATE_TEST 208
39941: #define PTNAME 209
39942: #define NEW_INIT_KLUDGE 210
39943: #define XDELETED_NODE 211
39944: #define DUMMY_LAST_NODE 212
39945:
39946: //#define SYN 1
39947: //#define TYP 2
39948: //#define SIMPL 3
39949: //#define ERROR 4
39950:
39951: //#define ICTOR 88
39952: //#define IDTOR 89
39953: 0707071010112046131004440001630000160000010212340466055422200001600000006724token_names.h /* ident "@(#)ctrans:src/token_names.h 1.2" */
39954: struct _token_name { char * string; int val; } token_names [] = {
39955: { "EOFTOK", 0 },
39956: { "ASM", 1 },
39957: { "AUTO", 2 },
39958: { "BREAK", 3 },
39959: { "CASE", 4 },
39960: { "CHAR", 5 },
39961: { "CLASS", 6 },
39962: { "CONTINUE", 7 },
39963: { "DEFAULT", 8 },
39964: { "DELETE", 9 },
39965: { "DO", 10 },
39966: { "DOUBLE", 11 },
39967: { "ELSE", 12 },
39968: { "ENUM", 13 },
39969: { "EXTERN", 14 },
39970: { "FLOAT", 15 },
39971: { "FOR", 16 },
39972: { "FORTRAN", 17 },
39973: { "FRIEND", 18 },
39974: { "GOTO", 19 },
39975: { "IF", 20 },
39976: { "INT", 21 },
39977: { "LONG", 22 },
39978: { "NEW", 23 },
39979: { "OPERATOR", 24 },
39980: { "RETURN", 28 },
39981: { "PUBLIC", 25 },
39982: { "CONST", 26 },
39983: { "REGISTER", 27 },
39984: { "RETURN", 28 },
39985: { "SHORT", 29 },
39986: { "SIZEOF", 30 },
39987: { "STATIC", 31 },
39988: { "STRUCT", 32 },
39989: { "SWITCH", 33 },
39990: { "THIS", 34 },
39991: { "TYPEDEF", 35 },
39992: { "UNION", 36 },
39993: { "UNSIGNED", 37 },
39994: { "VOID", 38 },
39995: { "WHILE", 39 },
39996: { "LP", 40 },
39997: { "RP", 41 },
39998: { "LB", 42 },
39999: { "RB", 43 },
40000: { "REF", 44 },
40001: { "DOT", 45 },
40002: { "NOT", 46 },
40003: { "COMPL", 47 },
40004: { "INCR", 48 },
40005: { "DECR", 49 },
40006: { "MUL", 50 },
40007: { "DIV", 51 },
40008: { "AND", 52 },
40009: { "MOD", 53 },
40010: { "PLUS", 54 },
40011: { "MINUS", 55 },
40012: { "LS", 56 },
40013: { "RS", 57 },
40014: { "LT", 58 },
40015: { "LE", 59 },
40016: { "GT", 60 },
40017: { "GE", 61 },
40018: { "EQ", 62 },
40019: { "NE", 63 },
40020: { "ER", 64 },
40021: { "OR", 65 },
40022: { "ANDAND", 66 },
40023: { "OROR", 67 },
40024: { "QUEST", 68 },
40025: { "COLON", 69 },
40026: { "ASSIGN", 70 },
40027: { "CM", 71 },
40028: { "SM", 72 },
40029: { "LC", 73 },
40030: { "RC", 74 },
40031: { "INLINE", 75 },
40032: { "OVERLOAD", 76 },
40033: { "VIRTUAL", 77 },
40034: { "COERCE", 78 },
40035: { "PROTECTED", 79 },
40036: { "ID", 80 },
40037: { "STRING", 81 },
40038: { "ICON", 82 },
40039: { "FCON", 83 },
40040: { "CCON", 84 },
40041: { "NAME", 85 },
40042: { "ZERO", 86 },
40043: { "ICTOR", 88 },
40044: { "IDTOR", 89 },
40045: { "ASOP", 90 },
40046: { "RELOP", 91 },
40047: { "EQUOP", 92 },
40048: { "DIVOP", 93 },
40049: { "SHIFTOP", 94 },
40050: { "ICOP", 95 },
40051: { "UNOP", 96 },
40052: { "TYPE", 97 },
40053: { "UMINUS", 107 },
40054: { "FCT", 108 },
40055: { "CALL", 109 },
40056: { "VEC", 110 },
40057: { "DEREF", 111 },
40058: { "ADDROF", 112 },
40059: { "CAST", 113 },
40060: { "FIELD", 114 },
40061: { "LABEL", 115 },
40062: { "BLOCK", 116 },
40063: { "QUA", 117 },
40064: { "DCL", 118 },
40065: { "COBJ", 119 },
40066: { "EOBJ", 121 },
40067: { "TNAME", 123 },
40068: { "ILIST", 124 },
40069: { "PTR", 125 },
40070: { "ASPLUS", 126 },
40071: { "ASMINUS", 127 },
40072: { "ASMUL", 128 },
40073: { "ASDIV", 129 },
40074: { "ASMOD", 130 },
40075: { "ASAND", 131 },
40076: { "ASOR", 132 },
40077: { "ASER", 133 },
40078: { "ASLS", 134 },
40079: { "ASRS", 135 },
40080: { "ARG", 136 },
40081: { "KNOWN", 137 },
40082: { "ZTYPE", 138 },
40083: { "ARGT", 139 },
40084: { "ELIST", 140 },
40085: { "ANY", 141 },
40086: { "TABLE", 142 },
40087: { "LOC", 143 },
40088: { "DUMMY", 144 },
40089: { "G_ADDROF", 145 },
40090: { "G_CALL", 146 },
40091: { "G_CM", 147 },
40092: { "IVAL", 150 },
40093: { "FVAL", 151 },
40094: { "LVAL", 152 },
40095: { "ELLIPSIS", 155 },
40096: { "AGGR", 156 },
40097: { "VALUE", 157 },
40098: { "RPTR", 158 },
40099: { "HIDDEN", 159 },
40100: { "MEM", 160 },
40101: { "CTOR", 161 },
40102: { "DTOR", 162 },
40103: { "CONST_PTR", 163 },
40104: { "CONST_RPTR", 164 },
40105: { "TEXT", 165 },
40106: { "PAIR", 166 },
40107: { "ANON", 167 },
40108: { "ICALL", 168 },
40109: { "ANAME", 169 },
40110: { "VOLATILE", 170 },
40111: { "SIGNED", 171 },
40112: { "UPLUS", 172 },
40113: { "MEMPTR", 173 },
40114: { "PRIVATE", 174 },
40115: { "PR", 175 },
40116: { "MDOT", 177 },
40117: { "TSCOPE", 178 },
40118: { "DECL_MARKER", 179 },
40119: { "REFMUL", 180 },
40120: { "LDOUBLE", 181 },
40121: { "LINKAGE", 182 },
40122: { "LOCAL", 183 },
40123: { "GNEW", 184 },
40124: { "TEMPLATE", 185 },
40125: { "STAT_INIT", 186 },
40126: { "CATCH", 187 },
40127: { "GDELETE", 188 },
40128: { "CONVERT", 189 },
40129: { "XVIRT", 200 },
40130: { "XNLIST", 201 },
40131: { "XILINE", 202 },
40132: { "XIA", 203 },
40133: { "STATEMENT", 205 },
40134: { "EXPRESSION", 206 },
40135: { "SM_PARAM", 207 },
40136: { "TEMPLATE_TEST", 208 },
40137: { "PTNAME", 209 },
40138: { "NEW_INIT_KLUDGE", 210 },
40139: { "XDELETED_NODE", 211 },
40140: { "DUMMY_LAST_TOKEN", 212 },
40141: };
40142: 0707071010112045711004440001630000160000010156650466055412200001100000002515tqueue.h /*ident "@(#)ctrans:src/tqueue.h 1.3" */
40143: /**************************************************************************
40144:
40145: C++ source for cfront, the C++ compiler front-end
40146: written in the computer science research center of Bell Labs
40147:
40148: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
40149: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
40150:
40151: tqueue.h:
40152:
40153: *****************************************************************************/
40154:
40155: #ifndef EOF
40156: #include <stdio.h>
40157: #endif
40158:
40159: struct toknode {
40160: TOK tok; /* token for parser */
40161: bit used; /* token has been processed by lalex() */
40162: YYSTYPE retval; /* $arg */
40163: loc place;
40164: toknode* next;
40165: toknode* last;
40166: static toknode* free_toks;
40167: void* operator new(size_t);
40168: void operator delete(void*,size_t);
40169: toknode(TOK,YYSTYPE,loc);
40170: };
40171: extern toknode* front;
40172: extern toknode* rear;
40173:
40174: extern void addtok(TOK,YYSTYPE,loc); /* add tok to rear of Q */
40175: extern TOK deltok(int); /* take tok from front of Q */
40176: extern TOK tlex();
40177:
40178: // interface to parser
40179: extern TOK lalex();
40180: extern int yychar;
40181: extern YYSTYPE yylval;
40182: extern TOK la_look();
40183: extern void la_backup( TOK, YYSTYPE );
40184: extern int la_cast();
40185: extern void check_decl();
40186: extern void check_cast();
40187: extern TOK lalex();
40188:
40189: // save / restore implicit inline functions
40190: extern toknode* save_text();
40191: extern void restore_text();
40192: 0707071010112046041004440001630000160000010211700466055416700001400000014274tree_copy.c /* ident "@(#)ctrans:src/tree_copy.c 1.3" */
40193: /*
40194: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_copy.c,v $ $RCSfile: tree_copy.c,v $
40195: $Revision: 1.1 $ $Date: 89/11/20 08:51:04 $
40196: $Author: benson $ $Locker: $
40197: $State: Exp $
40198: */
40199:
40200: /* utilities to copy pieces of cfront trees.
40201: what we have here is a somewhat parameterizable
40202: action procedure for the tree walker.
40203:
40204: We may make more versions of this for template expansion
40205: and saving things in files, or we may just make it possible
40206: for this to swing more ways.
40207: */
40208:
40209: #include "cfront.h"
40210: #include "tree_walk.h"
40211: #include "tree_copy.h"
40212: #include <memory.h>
40213:
40214: /* determine whether "n" is a an already defined type */
40215: static unsigned int type_is_defined(Pnode n) {
40216: return (Ptype(n)->defined & DEFINED) ;
40217: }
40218:
40219: void
40220: copy_walker (Pnode& node, node_class cl, void * info,
40221: tree_node_action& action, int, Pnode, tree_walk_tree&,
40222: int& register_in_hash)
40223: {
40224: union {
40225: Pnode node;
40226: Pvirt vr;
40227: Plist list;
40228: Pgen g;
40229: Pvec vc;
40230: Pfct f;
40231: Ptable t;
40232: Pbase bt;
40233: Pexpr x;
40234: Pstmt s;
40235: Penum e;
40236: Pclass c;
40237: Pbcl bcl;
40238: Pin iline;
40239: ia * ia;
40240: Pname n;
40241: Pptr p;
40242: } n;
40243: Pnode original_node = node;
40244:
40245: tree_copy_info * tci = (tree_copy_info *)info;
40246: action = tna_continue;
40247:
40248: /* first, give an application-specific hook a shot at the node. */
40249:
40250: tci->check_node(node, cl, action, register_in_hash);
40251: if(action != tna_continue) return;
40252:
40253: if(node != original_node) { /* a replacement */
40254: n.node = node;
40255: } else /* ok, nothing funny, we just go ahead and copy */
40256: switch (cl) {
40257: default:
40258: break;
40259: case nc_eof:
40260: n.node = Pnode(tci->malloc(sizeof (node)));
40261: *n.node = *node;
40262: goto Replace;
40263:
40264: case nc_virt:
40265: n.vr = Pvirt(tci->malloc(sizeof(virt)));
40266: *n.vr = *Pvirt(node);
40267: goto Replace;
40268:
40269: case nc_nlist:
40270: n.list = Plist(tci->malloc(sizeof(name_list)));
40271: *n.list = *Plist(node);
40272: goto Replace;
40273:
40274: case nc_gen:
40275: n.g = Pgen(tci->malloc(sizeof(gen)));
40276: *n.g = *Pgen(node);
40277: goto Replace;
40278:
40279: case nc_vec:
40280: n.vc = Pvec(tci->malloc(sizeof(vec)));
40281: *n.vc = *Pvec(node);
40282: goto Replace;
40283:
40284: case nc_ptr:
40285: n.p = Pptr(tci->malloc(sizeof(ptr)));
40286: *n.p = *Pptr(node);
40287: goto Replace;
40288:
40289: case nc_fct:
40290: n.f = Pfct(tci->malloc(sizeof(fct)));
40291: *n.f = *Pfct(node);
40292: if(n.f->f_signature) {
40293: n.f->f_signature =
40294: (char *)tci->malloc(strlen(Pfct(node)->f_signature)+1);
40295: strcpy(n.f->f_signature, Pfct(node)->f_signature);
40296: };
40297: goto Replace;
40298:
40299: case nc_table:
40300: n.t = Ptable(tci->malloc(sizeof(table)));
40301: *n.t = *Ptable(node);
40302: n.t->entries = (Pname *)tci->malloc(sizeof(Pname) * n.t->size);
40303: memcpy((char *)n.t->entries, (char *)Ptable(node)->entries, n.t->size * sizeof(Pname));
40304: n.t->hashtbl = (short *)tci->malloc(sizeof(short) * n.t->hashsize);
40305: memcpy((char *)n.t->hashtbl, (char *)Ptable(node)->hashtbl, n.t->hashsize * sizeof (short));
40306: goto Replace;
40307:
40308: case nc_basetype:
40309: // Don't copy types that have already been dealt with
40310: if (type_is_defined(node)) {
40311: action = tna_stop ;
40312: return ;
40313: }
40314: n.bt = Pbase(tci->malloc(sizeof(basetype)));
40315: *n.bt = *Pbase(node);
40316: if(n.bt->discriminator(0) == 2 && n.bt->b_linkage) {
40317: n.bt->b_linkage = tci->malloc(strlen(n.bt->b_linkage) + 1);
40318: strcpy(n.bt->b_linkage, Pbase(node)->b_linkage);
40319: }
40320: goto Replace;
40321:
40322: case nc_expr:
40323: // cfront needs identity maintaied for these nodes
40324: if ((node == dummy) || (node == zero)) {
40325: action = tna_stop ;
40326: return ;
40327: }
40328: n.x = Pexpr(tci->malloc(sizeof(expr)));
40329: *n.x = *Pexpr(node);
40330: if(n.x->discriminator(1) == 3 && n.x->string) {
40331: n.x->string = tci->malloc(strlen(n.x->string) + 1);
40332: strcpy(n.x->string, Pexpr(node)->string);
40333: }
40334: if(n.x->discriminator(2) == 3 && n.x->string2) {
40335: n.x->string2 = tci->malloc(strlen(n.x->string2) + 1);
40336: strcpy(n.x->string2, Pexpr(node)->string2);
40337: }
40338: goto Replace;
40339:
40340: case nc_stmt:
40341: n.s = Pstmt(tci->malloc(sizeof(stmt)));
40342: *n.s = *Pstmt(node);
40343: goto Replace;
40344:
40345: case nc_enumdef:
40346: if (type_is_defined(node)) {
40347: action = tna_stop ;
40348: return ;
40349: }
40350: n.e = Penum(tci->malloc(sizeof(enumdef)));
40351: *n.e = *Penum(node);
40352: if(n.e->string) {
40353: n.e->string = tci->malloc(n.e->strlen+1);
40354: strcpy(n.e->string, Penum(node)->string);
40355: }
40356: goto Replace;
40357:
40358: case nc_classdef:
40359: // Don't copy types that have already been dealt with
40360: if (type_is_defined(node)) {
40361: action = tna_stop ;
40362: return ;
40363: }
40364: n.c = Pclass(tci->malloc(sizeof(classdef)));
40365: *n.c = *Pclass(node);
40366: if(n.c->string) {
40367: n.c->string = tci->malloc(strlen(n.c->string)+1);
40368: strcpy(n.c->string, Pclass(node)->string);
40369: }
40370: goto Replace;
40371:
40372: case nc_baseclass:
40373: n.bcl = Pbcl(tci->malloc(sizeof(struct basecl)));
40374: *n.bcl = *Pbcl(node);
40375: goto Replace;
40376:
40377: case nc_iline:
40378: n.iline = Pin(tci->malloc(sizeof(iline)));
40379: *n.iline = *Pin(node);
40380: goto Replace;
40381:
40382: case nc_ia:
40383: n.ia = (ia *)tci->malloc(sizeof(ia));
40384: *n.ia = *(ia *)node;
40385: goto Replace;
40386:
40387: case nc_name:
40388: /* check for globalosity */
40389: if(Pname(node)->string && (node == (node->base == TNAME ? ktbl : gtbl)->look(Pname(node)->string, 0))) {
40390: action = tna_stop;
40391: return;
40392: }
40393: n.n = Pname(tci->malloc(sizeof(name)));
40394: *n.n = *Pname(node);
40395: /* First, hack exprosity */
40396: if(n.x->discriminator(1) == 3 && n.n->string) {
40397: n.n->string = tci->malloc(strlen(n.n->string) + 1);
40398: strcpy(n.n->string, Pexpr(node)->string);
40399: }
40400: if(n.x->discriminator(2) == 3 && n.n->string2) {
40401: n.n->string2 = tci->malloc(strlen(n.n->string2) + 1);
40402: strcpy(n.n->string2, Pexpr(node)->string2);
40403: /* ok, name stuff */
40404: }
40405: if(n.n->n_anon) {
40406: n.n->n_anon = tci->malloc(strlen(n.n->n_anon)+1);
40407: strcpy(n.n->n_anon, Pname(node)->n_anon);
40408: }
40409: if(n.n->n_template_arg_string) {
40410: n.n->n_template_arg_string =
40411: tci->malloc(strlen(n.n->n_template_arg_string)+1);
40412: strcpy(n.n->n_template_arg_string, Pname(node)->n_template_arg_string);
40413: }
40414: }
40415: Replace:
40416: node = n.node;
40417: action = tna_continue;
40418: return;
40419: }
40420:
40421: static int call_error (int i, const char * s)
40422: {
40423: return error (i, s);
40424: }
40425:
40426: void
40427: copy_tree (Pnode& node, tree_copy_info& tci, Hash * cht)
40428: {
40429: tree_walk_control twc;
40430:
40431: twc.call_i_error = 1;
40432: twc.i_error = call_error; /* ... in type of error confuses compiler */
40433: twc.action_proc = copy_walker;
40434: twc.nodes_seen_hash = cht;
40435: twc.callback_info = (void *)&tci;
40436:
40437: walk_tree (twc, node);
40438: }
40439:
40440: 0707071010112046141004440001630000160000010210160466055422600001400000003011tree_copy.h /* ident "@(#)ctrans:src/tree_copy.h 1.2" */
40441: /* -*- Mode: C -*- begin include file tree_copy.H
40442: argument class for copying trees. */
40443:
40444: #include "hash.h"
40445: #include "tree_walk.h"
40446:
40447: /* The copier procedure expects one of these as its
40448: info pointer */
40449:
40450: class tree_copy_info {
40451: public:
40452: /* If non-zero, this procedure is called at each node.
40453: it returns an action. It cannot currently return
40454: a node of a different class and also return an
40455: action other than tna_stop, since the walker won't
40456: notice that the rug has been removed from beneath its feet.
40457: The procedure must set the last argument to indicate whether
40458: or not to register the node in the hash table and use the
40459: replacement every future time it is encountered.
40460: */
40461:
40462: void (* node_hook) (void * info, Pnode&, node_class, tree_node_action&,
40463: int&);
40464:
40465: /* if this is nonzero it is used to allocate space for
40466: the copies. We don't run constructors since we always
40467: bit copy over the new copy. */
40468: char * (* malloc_hook) (void * info, size_t);
40469: void * hook_info;
40470: tree_copy_info ()
40471: {
40472: hook_info = 0;
40473: node_hook = 0;
40474: malloc_hook = 0;
40475: };
40476: char * malloc (size_t s) {
40477: return malloc_hook ? malloc_hook(hook_info, s) : ::malloc (s);
40478: };
40479: void check_node (Pnode& n,
40480: node_class cl,
40481: tree_node_action& action,
40482: int& never_see_again) {
40483: if(node_hook)
40484: node_hook(hook_info, n, cl, action, never_see_again);
40485: };
40486: };
40487:
40488: void copy_tree (Pnode& n, tree_copy_info& tci, Hash * cht = 0);
40489:
40490: /* End tree_copy.H */
40491:
40492: 0707071010112046161004440001630000160000010213300466055423500001400000061200tree_dump.c /* ident "@(#)ctrans:src/tree_dump.c 1.2" */
40493: /* -*- Mode:C++ -*- */
40494: /* tree_dump.C -- utilities for displaying the cfront tree. */
40495: /* BIM 890530 */
40496: /* rewritten 890712 to use the tree-walking facilities */
40497:
40498: /*
40499: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_dump.c,v $ $RCSfile: tree_dump.c,v $
40500: $Revision: 1.1 $ $Date: 89/11/20 08:50:22 $
40501: $Author: benson $ $Locker: $
40502: $State: Exp $
40503:
40504:
40505: */
40506:
40507: #include "tree_dump.h"
40508: #include <stdio.h>
40509: #include <malloc.h>
40510: #include "template.h"
40511: #include "token_names.h"
40512:
40513: const int Indent_Increment = 4;
40514: static char badnamebuf[100];
40515:
40516: char *
40517: token_name(TOK t)
40518: {
40519: char * bnb = badnamebuf;
40520:
40521: if((int) t == -1) return "-1";
40522: if(t > DUMMY_LAST_NODE) {
40523: bad:
40524: printf_to_string(bnb, sizeof(badnamebuf),
40525: "<unknown token %d>", (int) t);
40526: return bnb;
40527: }
40528: int x;
40529: for (x = 0; x < DUMMY_LAST_NODE; x++) {
40530: if(token_names[x].val == t) return token_names[x].string;
40531: }
40532: goto bad;
40533: }
40534:
40535: class displayer{
40536: public:
40537: dcn_arg * arg;
40538: Pnode node;
40539: Pnode node_address;
40540: displayer (dcn_arg& d) { arg = &d; indent = 0; print_null_values = 0; };
40541: void do_node (Pnode& node, node_class cl, tree_node_action& action, int depth, Pnode);
40542: private:
40543: enum ppc {print_ptr_copy = 0, print_ptr_copied = 1};
40544: int indent;
40545: int err;
40546: int print_null_values;
40547: void printf (const char *, ...);
40548: void catprintf (const char *, ...);
40549: void print_ptr (const char *, Pnode);
40550: void print_ptr (Pnode, ppc = print_ptr_copy);
40551: void minimal ();
40552: void a_basetype ();
40553: void a_basecl() ;
40554: void a_type() ;
40555: void a_node() ;
40556: void a_name ();
40557: void a_expr (int from_name = 0);
40558: void a_fct ();
40559: void a_stmt ();
40560: void a_enumdef ();
40561: void a_table();
40562: void a_classdef ();
40563: void a_gen ();
40564: void a_vec ();
40565: void a_ptr ();
40566: void a_virt ();
40567: void a_nlist ();
40568: void a_iline ();
40569: void a_elist ();
40570: void a_ia ();
40571: void a_by_name ();
40572: void print_loc(loc&);
40573: void * display_address () { return node_address; }
40574: void fetch (void * addr, unsigned long length, void *& taddr);
40575: void fetch_string (void * addr, unsigned long length, void *& taddr);
40576: void free_fetched(void *);
40577: void flag (int, const char *);
40578: void print_string (const char *, void *);
40579: void print_string_brief (void *);
40580: void null_field (const char *);
40581: void nz_printf(const char *format, const int i) ;
40582: void nz_printf(const char *format, const char *p) ;
40583: void nz_printf(const char *format, const long l) ;
40584: void ind();
40585: };
40586:
40587: const char many_spaces[] = " ";
40588:
40589: inline void
40590: displayer::ind()
40591: {
40592: arg->output_stream->write(many_spaces, indent);
40593: }
40594:
40595: /* call me for full lines */
40596:
40597: void
40598: displayer::printf (const char * format, ...)
40599: {
40600: va_list args;
40601: va_start(args, format);
40602:
40603: ind();
40604: vostream_printf (format, args, *arg->output_stream);
40605: arg->output_stream->write("\n", 1);
40606: va_end (args);
40607: }
40608:
40609: void
40610: displayer::catprintf (const char * format, ...)
40611: {
40612: va_list args;
40613: va_start(args, format);
40614:
40615: vostream_printf (format, args, *arg->output_stream);
40616: va_end (args);
40617: }
40618:
40619: void
40620: displayer::minimal ()
40621: {
40622: print_ptr(node, print_ptr_copied);
40623: }
40624:
40625: void
40626: displayer::print_ptr(const char * label, Pnode node)
40627: {
40628: if(node || print_null_values) {
40629: ind();
40630: catprintf("%s:\t", label);
40631: print_ptr(node);
40632: catprintf("\n");
40633: }
40634: }
40635:
40636:
40637: void
40638: displayer::print_ptr(Pnode node, ppc copy_ptr)
40639: {
40640: void * string = 0;
40641: void * ncopy;
40642: void * na = (void *)node;
40643:
40644: if(node) {
40645:
40646: if(copy_ptr == print_ptr_copy) {
40647: fetch(na, sizeof(node), ncopy);
40648: node = Pnode(ncopy);
40649: } else ncopy = node;
40650:
40651: switch(node->base) {
40652: case CLASS:
40653: free_fetched(ncopy);
40654: fetch(na, sizeof(classdef),ncopy);
40655: node = Pnode(ncopy);
40656: string = Pclass(node)->string;
40657: break;
40658: case ENUM:
40659: free_fetched(ncopy);
40660: fetch(na, sizeof(enumdef),ncopy);
40661: node = Pnode(ncopy);
40662: string = Penum(node)->string;
40663: break;
40664: case NAME:
40665: case TNAME:
40666: case PUBLIC:
40667: case PROTECTED:
40668: if(!node->baseclass) {
40669: free_fetched(ncopy);
40670: fetch(na, sizeof(name),ncopy);
40671: node = Pnode(ncopy);
40672: string = Pname(node)->string;
40673: }
40674: break;
40675: }
40676: if(string) {
40677: catprintf("<%s |0x%p ", token_name(node->base), na);
40678: print_string_brief(string);
40679: catprintf(">");
40680: }
40681: else catprintf("<%s |0x%p>", token_name(node->base), na);
40682: free_fetched (ncopy);
40683: }
40684: else catprintf("Null");
40685: }
40686:
40687: void
40688: displayer::do_node (Pnode& n, node_class cl, tree_node_action& action,
40689: int depth, Pnode na)
40690: {
40691: int forced_min = 0;
40692: int printed_min = 0;
40693: int prune = 0;
40694:
40695: switch(cl) {
40696: case nc_table:
40697: if(depth > 0 && !arg->walk_tables)prune = 1;
40698: case nc_fct:
40699: case nc_classdef:
40700: case nc_enumdef:
40701: if(arg->stop_at_top && depth > 1) prune = 1;
40702: break;
40703: }
40704:
40705: if((arg->max_depth > 0) && (depth >= arg->max_depth))
40706: prune = 1;
40707:
40708: if(prune || arg->max_depth == 0)
40709: action = tna_stop;
40710: else action = tna_continue;
40711:
40712: node = n;
40713: node_address = na;
40714:
40715: if(arg->verbose == dt_brief || prune) {
40716: printed_min = 1;
40717: minimal();
40718: }
40719: else {
40720: switch(cl)
40721: {
40722: default:
40723: case nc_unused:
40724: ostream_printf(*arg->error_stream, "Unknown node %d\n", node->base);
40725: forced_min = 1;
40726:
40727: case nc_eof:
40728: minimal();
40729: printed_min = 1;
40730: break;
40731:
40732: case nc_virt:
40733: a_virt ();
40734: break;
40735:
40736: case nc_nlist:
40737: a_nlist();
40738: break;
40739:
40740: case nc_gen:
40741: a_gen();
40742: break;
40743:
40744: case nc_vec:
40745: a_vec();
40746: break;
40747:
40748: case nc_ptr:
40749: a_ptr();
40750: break;
40751:
40752: case nc_fct:
40753: a_fct();
40754: break;
40755:
40756: case nc_table:
40757: a_table();
40758: break;
40759:
40760: case nc_basetype:
40761: a_basetype();
40762: break;
40763:
40764: case nc_name:
40765: a_name();
40766: break;
40767:
40768: case nc_expr:
40769: a_expr();
40770: break;
40771:
40772: case nc_stmt:
40773: a_stmt();
40774: break;
40775:
40776: case nc_enumdef:
40777: a_enumdef();
40778: break;
40779:
40780: case nc_classdef:
40781: a_classdef();
40782: break;
40783:
40784: case nc_baseclass:
40785: a_basecl ();
40786: break;
40787:
40788: case nc_iline:
40789: a_iline();
40790: break;
40791:
40792: case nc_ia:
40793: a_ia();
40794: break;
40795:
40796: }
40797: if(printed_min) catprintf(">");
40798: }
40799: }
40800:
40801:
40802: void
40803: displayer::flag(int f, const char * n)
40804: {
40805: if(f)catprintf("%s", n);
40806: }
40807:
40808: void
40809: displayer::free_fetched (void * addr)
40810: {
40811: if (arg->fetcher != null_tfp) /* not in the same address space. */
40812: free ((char *)addr);
40813: }
40814:
40815:
40816: void
40817: displayer::fetch (void * addr, unsigned long length, void *& taddr)
40818: {
40819: if (arg->fetcher == null_tfp) { /* in the same address space. */
40820: taddr = addr;
40821: err = 0;
40822: } else {
40823: taddr = (void *)malloc ((unsigned int)length);
40824: err = arg->fetcher (arg->fetcher_info,
40825: addr,
40826: length,
40827: 0,
40828: taddr);
40829: }
40830: }
40831:
40832: void
40833: displayer::fetch_string (void * addr, unsigned long length, void *& taddr)
40834: {
40835: if (arg->fetcher == null_tfp) { /* in the same address space. */
40836: taddr = addr;
40837: err = 0;
40838: } else {
40839: taddr = (void *)malloc ((unsigned int)length);
40840: err = arg->fetcher (arg->fetcher_info,
40841: addr,
40842: length,
40843: 1,
40844: taddr);
40845: }
40846: }
40847:
40848: /* Print the field, only if it has a non_zero value, or requested to print */
40849: /* always */
40850: void
40851: displayer::nz_printf(const char *format, const int i)
40852: {
40853: if (i || print_null_values) {
40854: printf(format, i) ;
40855: }
40856: }
40857:
40858: void
40859: displayer::nz_printf(const char *format, const char *p)
40860: {
40861: if (p || print_null_values) {
40862: printf(format, (p ? p : "0")) ;
40863: }
40864: }
40865:
40866:
40867: void
40868: displayer::nz_printf(const char *format, const long i)
40869: {
40870: if (i || print_null_values) {
40871: printf(format, i) ;
40872: }
40873: }
40874:
40875: void
40876: displayer::a_node()
40877: {
40878: struct node &n = *node ;
40879:
40880: nz_printf("$node", n.permanent);
40881: // nz_printf("n_key:\t%d", (int)n.n_key) ;
40882: nz_printf("permanent:\t%d", n.permanent) ;
40883: nz_printf("baseclass:\t%d", n.baseclass) ;
40884: }
40885:
40886:
40887:
40888: void
40889: displayer::a_type()
40890: {
40891: struct type& t = *Ptype(node);
40892: int show_up = t.defined /* || t.inline_temp_index != 0 */;
40893:
40894: if(show_up) {
40895: printf("$type") ;
40896: nz_printf("defined:\t%d", t.defined) ;
40897: // nz_printf("inline_temp_index:\t%d", t.inline_temp_index);
40898: indent += Indent_Increment;
40899: }
40900: a_node();
40901: if(show_up) indent -= Indent_Increment;
40902: }
40903:
40904:
40905:
40906:
40907:
40908: void
40909: displayer::null_field(const char * name)
40910: {
40911: nz_printf( "%s:\t0", name);
40912: }
40913:
40914:
40915: void
40916: displayer::a_basecl()
40917: {
40918: struct basecl& bc = *Pbcl(node);
40919:
40920: printf("$basecl %s |0x%p",
40921: token_name(node->base),
40922: node_address);
40923:
40924: nz_printf ("ppp:\t%s", token_name(bc.ppp)) ;
40925: nz_printf ("allocated:\t%d", bc.allocated) ;
40926: nz_printf ("promoted:\t%d", bc.promoted) ;
40927: print_ptr("bclass", bc.bclass);
40928: nz_printf ("ptr_offset:\t%d", bc.ptr_offset) ;
40929: nz_printf ("obj_offset:\t%d", bc.obj_offset) ;
40930: indent += Indent_Increment;
40931: a_node(); /* do the supertype. */
40932: indent -= Indent_Increment;
40933: }
40934:
40935:
40936:
40937:
40938: void
40939: displayer::a_basetype ()
40940: {
40941: struct basetype& bt = *Pbase(node);
40942:
40943: printf("$basetype %s |0x%p",
40944: token_name(node->base),
40945: node_address);
40946:
40947: ind();
40948: catprintf("Flags:\t");
40949: flag(bt.b_unsigned, "unsigned ");
40950: flag(bt.b_signed, "signed ");
40951: flag(bt.b_volatile, "volatile ");
40952: flag(bt.b_const, "const ");
40953: flag(bt.b_typedef, "typedef ");
40954: flag(bt.b_virtual, "virtual ");
40955: flag(bt.b_short, "short ");
40956: flag(bt.b_long, "long ");
40957: catprintf("\n");
40958: nz_printf( "b_bits:\t%d", bt.b_bits);
40959: nz_printf( "b_offset:\t%d", bt.b_offset);
40960: nz_printf( "b_sto:\t%s", bt.b_sto ? token_name(bt.b_sto) : 0);
40961: switch(bt.discriminator(0)) {
40962: case 1:
40963: print_ptr("b_fieldtype", bt.b_fieldtype);
40964: break;
40965: case 2:
40966: nz_printf( "b_linkage:\t%s", bt.b_linkage ? "C" : "0(C++)");
40967: }
40968:
40969: print_ptr("b_name", bt.b_name);
40970: print_ptr("b_table", bt.b_table);
40971: // print_ptr("b_field", bt.b_field);
40972: print_ptr("b_xname", bt.b_xname);
40973:
40974: indent += Indent_Increment;
40975: a_type(); /* do the supertype. */
40976: indent -= Indent_Increment;
40977:
40978: }
40979:
40980: void
40981: displayer::print_loc(loc& loc)
40982: {
40983: catprintf("file %d line %d", (int)loc.file, (int)loc.line);
40984: }
40985:
40986:
40987: void
40988: displayer::print_string_brief(void * addr)
40989: {
40990: void * tmp;
40991:
40992: fetch_string (addr, 1000, tmp);
40993: *arg->output_stream << (char *)tmp;
40994: free_fetched (tmp);
40995: }
40996:
40997: void
40998: displayer::print_string(const char * label, void * addr)
40999: {
41000: ind();
41001: catprintf("%s:\t", label);
41002: print_string_brief(addr);
41003: *arg->output_stream << "\n";
41004: }
41005:
41006: void
41007: displayer::a_expr(int from_name)
41008: {
41009: struct expr& e = *Pexpr(node);
41010:
41011: if(from_name) printf("$expr");
41012: else printf("$expr %s |0x%p",
41013: token_name(node->base),
41014: node_address);
41015:
41016: print_ptr("tp", e.tp);
41017:
41018: switch(e.discriminator(1)) {
41019: case 0: break;
41020: case 1:
41021: print_ptr("e1", e.e1);
41022: break;
41023: case 2:
41024: printf("i1:\t%ld", e.i1);
41025: break;
41026: case 3:
41027: print_string("string", (void *)e.string);
41028: }
41029:
41030: switch(e.discriminator(2)) {
41031: case 0: break;
41032: case 1:
41033: print_ptr("e2", e.e2);
41034: break;
41035: case 2:
41036: printf("i2:\t%ld", e.i2);
41037: break;
41038: case 3:
41039: print_string("string2", (void *)e.string2);
41040: break;
41041: case 4:
41042: print_ptr("n_initializer", e.n_initializer);
41043: }
41044:
41045: switch(e.discriminator(3)) {
41046: case 0:
41047: break;
41048: case 1: print_ptr ("tp2", e.tp2); break;
41049: case 2: print_ptr ("fct_name", e.fct_name); break;
41050: case 3: print_ptr ("cond", e.cond); break;
41051: case 4: print_ptr ("mem", e.mem); break;
41052: case 5: print_ptr ("as_type", e.as_type); break;
41053: case 6: print_ptr ("n_table", e.n_table); break;
41054: case 7: print_ptr ("il", e.il); break;
41055: case 8: print_ptr ("query_this", e.query_this); break;
41056: }
41057:
41058: indent += Indent_Increment;
41059: a_node();
41060: indent -= Indent_Increment;
41061:
41062: }
41063:
41064: void
41065: displayer::a_name()
41066: {
41067: struct name& n = *Pname(node);
41068:
41069:
41070: ind();
41071: catprintf("$name %s |0x%p ",
41072: token_name(node->base),
41073: node_address);
41074: print_string_brief((void *)n.string);
41075: *arg->output_stream << "\n";
41076:
41077: nz_printf("n_key:\t%d", (int)n.n_key) ;
41078: nz_printf( "n_oper:\t\t%s", n.n_oper ?
41079: token_name(n.n_oper) : 0);
41080: nz_printf( "n_sto:\t\t%s", n.n_sto ?
41081: token_name(n.n_sto) : 0);
41082: nz_printf( "n_stclass:\t%s", n.n_stclass ?
41083: token_name(n.n_stclass) : 0);
41084: nz_printf( "n_scope:\t%s", n.n_scope ?
41085: token_name(n.n_scope) : 0);
41086: nz_printf( "n_union:\t%d", n.n_union);
41087: nz_printf( "n_evaluated:\t%d", n.n_evaluated);
41088: nz_printf( "n_xref:\t\t%d", n.n_xref);
41089: nz_printf( "lex_level:\t%d", n.lex_level);
41090: nz_printf( "n_protect:\t%s", n.n_protect ?
41091: token_name(n.n_protect) : 0);
41092: if (n.n_dcl_printed || print_null_values) {
41093: ind();
41094: catprintf("n_dcl_printed:\t%d", n.n_dcl_printed);
41095:
41096: switch(n.n_dcl_printed)
41097: {
41098: case 0:
41099: catprintf("(not)\n");
41100: break;
41101: case 1:
41102: printf("(declaration)\n");
41103: break;
41104: case 2:
41105: printf("(definition)\n");
41106: break;
41107: }
41108:
41109: }
41110: if(n.n_template_arg) {
41111: ind();
41112: catprintf( "n_template_arg:\t");
41113: switch(n.n_template_arg)
41114: {
41115: case template_type_formal:
41116: catprintf("template_type_formal\n");
41117: break;
41118: case template_expr_formal:
41119: catprintf("template_expr_formal\n");
41120: break;
41121: case template_stmt_tree_formal:
41122: catprintf("template_stmt_formal\n");
41123: break;
41124: case template_expr_tree_formal:
41125: catprintf("template_expr_tree_formal\n");
41126: break;
41127: case template_actual_arg_dummy:
41128: catprintf("template_actual_arg_dummy\n");
41129: break;
41130: } ;
41131: }
41132: nz_printf( "n_addr_taken:\t%d", n.n_addr_taken);
41133: nz_printf( "n_used:\t\t%d", n.n_used);
41134: nz_printf( "n_assigned_to:\t%d", n.n_assigned_to);
41135: ind();
41136: catprintf("loc:\t\t");
41137: print_loc(n.where);
41138: catprintf("\n");
41139: nz_printf( "n_offset:\t%d", n.n_offset);
41140: // if(n.output_string) { print_string("output_string", (void *)n.output_string); }
41141: nz_printf( "n_val:\t\t%ld", n.n_val);
41142:
41143: print_ptr("n_list", n.n_list);
41144: print_ptr("n_tbl_list", n.n_tbl_list);
41145: if(n.n_gen_fct_name)
41146: print_string("n_gen_fct_name", n.n_gen_fct_name);
41147: if(n.n_template_arg_string) {
41148: print_string("n_template_arg_string",
41149: n.n_template_arg_string);
41150: }
41151: switch(n.discriminator(0)) {
41152: case 2: print_ptr("n_realscope", n.n_realscope); break;
41153: case 1: print_ptr("n_qualifier", n.n_qualifier); break;
41154: }
41155: nz_printf("n_val:\t%ld", n.n_val);
41156:
41157: indent += Indent_Increment;
41158: a_expr(1); /* do the supertype. */
41159: indent -= Indent_Increment;
41160: }
41161:
41162: void
41163: displayer::a_fct()
41164: {
41165: struct fct& f = *Pfct(node);
41166:
41167: printf("$fct %s |0x%p",
41168: token_name(node->base),
41169: node_address);
41170:
41171:
41172: printf("nargs:\t\t%d", f.nargs);
41173: printf("nargs_known:\t%d%s", f.nargs_known,
41174: f.nargs_known == 0 ? " UNKNOWN" :
41175: (f.nargs_known == 1 ? " KNOWN" :
41176: (f.nargs_known == ELLIPSIS ? "ELLIPSIS" : "" )));
41177: nz_printf( "f_vdef:\t\t%d", f.f_vdef);
41178: printf("f_inline:\t%d%s", f.f_inline,
41179: f.f_inline == 0 ? "" :
41180: f.f_inline == 1 ? " inline" :
41181: f.f_inline == 2 ? " inline in expansion" : "");
41182: nz_printf( "f_const:\t\t%d", f.f_const);
41183: nz_printf( "f_static:\t\t%d", f.f_static);
41184: nz_printf( "f_virtual:\t%d", f.f_virtual);
41185: nz_printf( "f_imeasure:\t%d", f.f_imeasure);
41186: print_string("f_signature", (void *)f.f_signature);
41187:
41188: print_ptr("returns", f.returns);
41189: print_ptr("argtype", f.argtype);
41190: print_ptr("s_returns", f.s_returns);
41191: print_ptr("f_this", f.f_this);
41192: print_ptr("memof", f.memof);
41193: print_ptr("body", f.body);
41194: print_ptr("f_init", f.f_init);
41195: print_ptr("f_expr", f.f_expr);
41196: print_ptr("last_expanded", f.last_expanded);
41197: print_ptr("f_result", f.f_result);
41198: print_ptr("f_args", f.f_args);
41199: print_ptr("local_classes", f.local_class);
41200:
41201: indent += Indent_Increment;
41202: a_type(); /* do the supertype. */
41203: indent -= Indent_Increment;
41204: }
41205:
41206: void
41207: displayer::a_stmt ()
41208: {
41209: struct stmt& s = *Pstmt(node);
41210:
41211: ind();
41212: catprintf("$stmt %s |0x%p ",
41213: token_name(node->base),
41214: node_address);
41215: print_loc(s.where);
41216: *arg->output_stream << "\n";
41217:
41218: ind();
41219: *arg->output_stream << "where:\t";
41220: print_loc(s.where);
41221: *arg->output_stream << "\n";
41222:
41223: print_ptr("s", s.s);
41224: print_ptr("s_list", s.s_list);
41225: print_ptr("memtbl", s.memtbl);
41226: switch(s.discriminator(0)) {
41227: case 1: print_ptr("d", s.d); break;
41228: case 2: print_ptr("e2", s.e2); break;
41229: case 3: print_ptr("has_default", s.has_default); break;
41230: case 4: nz_printf("case_value:\t0x%x", s.case_value);
41231: case 5: print_ptr("ret_tp", s.ret_tp); break;
41232: }
41233: switch(s.discriminator(1)) {
41234: case 1: print_ptr("e", s.e); break;
41235: case 2: nz_printf("own_tbl:\t%d", s.own_tbl); break;
41236: case 3: print_ptr("s2", s.s2); break;
41237: }
41238:
41239: switch(s.discriminator(2)) {
41240: case 1: print_ptr("for_init", s.for_init); break;
41241: case 2: print_ptr("else_stmt",s.for_init); break;
41242: case 3: print_ptr("case_list", s.case_list); break;
41243: }
41244: }
41245:
41246: void
41247: displayer::a_enumdef ()
41248: {
41249: struct enumdef& e = *Penum(node);
41250:
41251: printf("$enumdef %s |0x%p",
41252: token_name(node->base),
41253: node_address);
41254:
41255: nz_printf( "e_body:\t\t%d", e.e_body);
41256: nz_printf( "no_of_enumerators: %d",
41257: e.no_of_enumerators);
41258: nz_printf( "strlen:\t%d", e.strlen);
41259: print_string ("string", (void *)e.string);
41260:
41261: print_ptr("mem", e.mem);
41262: print_ptr("e_type", e.e_type);
41263: indent += Indent_Increment;
41264: a_type(); /* do the supertype. */
41265: indent -= Indent_Increment;
41266: }
41267:
41268: void
41269: displayer::a_classdef ()
41270: {
41271: struct classdef& c = *Pclass(node);
41272:
41273: ind();
41274: catprintf("$classdef %s |0x%p ",
41275: token_name(node->base),
41276: node_address);
41277: print_string_brief(c.string);
41278: *arg->output_stream << "\n";
41279: ind();
41280: catprintf("class_base:\t");
41281: switch(c.class_base)
41282: {
41283: case vanilla_class:
41284: *arg->output_stream << "vanilla_class\n";
41285: break;
41286: case template_class:
41287: *arg->output_stream << "template_class\n";
41288: Template_Class:
41289: nz_printf("inst:\t\t%p", (int)Ptclass(&c)->inst);
41290: break;
41291: case instantiated_template_class:
41292: *arg->output_stream << "instantiated_template_class\n";
41293: goto Template_Class;
41294: case uninstantiated_template_class:
41295: *arg->output_stream << "uninstantiated_template_class\n";
41296: goto Template_Class;
41297: case relationship_class:
41298: *arg->output_stream << "relationship_class\n";
41299: break;
41300: case defining_class:
41301: *arg->output_stream << "defining_class\n";
41302: break;
41303: }
41304:
41305: nz_printf( "c_body:\t\t%d", c.c_body);
41306: printf("csu:\t\t%s",
41307: token_name(c.csu));
41308: nz_printf( "obj_align:\t%d", c.obj_align);
41309: if(c.c_xref) {
41310: ind();
41311: catprintf( "c_xref:\t%x", c.c_xref);
41312: flag(c.c_xref & 1, "has-vptr ");
41313: flag(c.c_xref & 2, "X(X&)-defined ");
41314: flag(c.c_xref & 4, "operator=(X&)-defined ");
41315: flag(c.c_xref & 8, "has-vbaseptr(s) ");
41316: *arg->output_stream << "\n";
41317: }
41318: nz_printf( "virt_count:\t%d", c.virt_count);
41319: nz_printf( "virt_merge:\t%d", c.virt_merge);
41320: nz_printf( "c_abstract:\t%d", c.c_abstract);
41321: nz_printf( "has_vvtab:\t%d", c.has_vvtab);
41322: nz_printf( "strlen:\t%d", c.strlen);
41323: print_string ("string", (void *)c.string);
41324: nz_printf( "obj_size:\t%d", c.obj_size);
41325: nz_printf( "real_size:\t%d", c.real_size);
41326: nz_printf("lex_level:\t%d", c.lex_level);
41327: if(c.lcl)print_string("lcl", c.lcl);
41328:
41329: print_ptr("baselist", c.baselist);
41330: print_ptr("mem_list", c.mem_list);
41331: print_ptr("memtbl", c.memtbl);
41332: print_ptr("friend_list", c.friend_list);
41333: print_ptr("pubdef", c.pubdef);
41334: print_ptr("tn_list", c.tn_list); /* not brief */
41335: print_ptr("in_class", c.in_class);
41336: print_ptr("in_fct", c.in_fct);
41337: print_ptr("this_type", c.this_type);
41338: print_ptr("virt_list", c.virt_list);
41339: print_ptr("c_ctor", c.c_ctor);
41340: print_ptr("c_dtor", c.c_dtor);
41341: print_ptr("c_itor", c.c_itor);
41342: print_ptr("conv", c.conv);
41343: indent += Indent_Increment;
41344: a_type(); /* do the supertype. */
41345: indent -= Indent_Increment;
41346: }
41347:
41348:
41349: void
41350: displayer::a_virt()
41351: {
41352: virt& v = *Pvirt(node);
41353: void * vna;
41354: void * vna_e;
41355: int vx;
41356:
41357: printf("$virt %s |0x%p ",
41358: token_name(node->base),
41359: node_address);
41360:
41361: print_ptr("next", v.next);
41362: if(v.n_init) {
41363: printf("n_init:\t%d", v.n_init);
41364: printf("virt_init:");
41365: for (vna = v.virt_init, vx = 0; vx < (v.n_init - 1);
41366: vna = (char *)vna + sizeof (velem), vx++)
41367: {
41368: fetch(vna, sizeof (velem), vna_e);
41369: struct velem * ve = (struct velem *) vna_e;
41370: ind();
41371: catprintf("%d offset %d\t", vx, ve->offset);
41372: print_ptr(ve->n);
41373: free_fetched(vna_e);
41374: }
41375: }
41376: print_ptr("vclass", v.vclass);
41377: nz_printf( "\nis_vbase:\t %d", v.is_vbase);
41378: nz_printf( "\nprinted:\t %d", v.printed);
41379: }
41380:
41381: void
41382: displayer::a_table ()
41383: {
41384: struct table& t = *Ptable(node);
41385: int x;
41386: int y;
41387: void * nlist;
41388: void * slist;
41389:
41390: printf("$table %s |0x%p",
41391: token_name(node->base),
41392: node_address);
41393:
41394: printf("init_stat:\t%d%s", t.init_stat,
41395: t.init_stat == 0 ? " not simplified" :
41396: t.init_stat == 1 ? " simplified, no inits" :
41397: t.init_stat == 2 ? " simplified, inits" :
41398: "");
41399: printf("size:\t%d", t.size);
41400: printf("hashsize:\t%d", t.hashsize);
41401: printf("free_slot:\t%d", t.free_slot);
41402:
41403: /* it looks like there is an array of Pnames here ... */
41404: *arg->output_stream << "\n";
41405: ind();
41406: *arg->output_stream << "entries:\n";
41407: fetch((void *)t.entries, t.size * sizeof(Pname), nlist);
41408: Pname * tmp_nlist = (Pname *)nlist;
41409: for(x = 0; x < t.size; x ++) {
41410: if(tmp_nlist[x]) {
41411: ind();
41412: *arg->output_stream << x;
41413: *arg->output_stream << "\t";
41414: print_ptr(tmp_nlist[x]);
41415: unsigned char tmp_name_s[sizeof(name)];
41416: void * tmp_name;
41417: tmp_name = (void *)&tmp_name_s[0];
41418: fetch(tmp_nlist[x], sizeof(name), tmp_name);
41419: catprintf(" key %d\n", Pname(tmp_name)->n_key);
41420: }
41421: }
41422: free_fetched(nlist);
41423: /* and then an array of shorts for the hash table. */
41424: /* we really need a tabular format here, alright. */
41425: ind();
41426: *arg->output_stream << "hashtbl:\n";
41427: fetch(t.hashtbl, t.hashsize * sizeof(short), slist);
41428: short * tmp_slist = (short *)slist;
41429: for(x = 0;; x++ ) {
41430: for (y = 0; y < 11; y ++) {
41431: if(((x * 12) + y) > t.hashsize) break;
41432: catprintf("%6d ", tmp_slist[(x*12)+y]);
41433: }
41434: *arg->output_stream << "\n";
41435: if(((x * 12) + y) > t.hashsize) break;
41436: }
41437:
41438: free_fetched (slist);
41439:
41440: print_ptr("t_name", t.t_name);
41441: print_ptr("real_block", t.real_block);
41442: print_ptr("name", t.t_name);
41443: print_ptr("next", t.next);
41444: }
41445:
41446: void
41447: displayer::a_gen ()
41448: {
41449: struct gen& g = *Pgen(node);
41450:
41451: printf("$gen %s |0x%p",
41452: token_name(node->base),
41453: node_address);
41454:
41455: print_ptr ("fct_list", g.fct_list);
41456: indent += Indent_Increment;
41457: a_type(); /* do the supertype. */
41458: indent -= Indent_Increment;
41459: }
41460:
41461: void
41462: displayer::a_vec ()
41463: {
41464: struct vec& v = *Pvec(node);
41465:
41466: printf("$vec %s |0x%p",
41467: token_name(node->base),
41468: node_address);
41469: printf("size:\t\t%d", v.size);
41470: print_ptr ("typ", v.typ);
41471: print_ptr ("dim", v.dim);
41472: }
41473:
41474: void
41475: displayer::a_ptr ()
41476: {
41477: struct ptr& p = *Pptr(node);
41478:
41479: printf("$ptr %s |0x%p",
41480: token_name(node->base),
41481: node_address);
41482: ind();
41483: printf("rdo:\t\t%d", p.rdo);
41484: ind();
41485:
41486: print_ptr ("typ", p.typ);
41487: print_ptr ("memof", p.memof);
41488: }
41489:
41490:
41491: void
41492: displayer::a_nlist()
41493: {
41494: name_list& n = *Plist(node);
41495:
41496: printf("$name_list %s |0x%p ",
41497: token_name(node->base),
41498: node_address);
41499:
41500: print_ptr("f", n.f);
41501: print_ptr("l", n.l);
41502: }
41503:
41504: void
41505: displayer::a_iline()
41506: {
41507: struct iline& i = *(struct iline *)node;
41508:
41509: printf("$iline %s |0x%p ",
41510: token_name(node->base),
41511: node_address);
41512:
41513: print_ptr("fct_name", i.fct_name);
41514: print_ptr("i_next", i.i_next);
41515: print_ptr("i_table", i.i_table);
41516: nz_printf("i_slots:\t%d", i.i_slots);
41517: print_ptr("i_args", i.i_args);
41518: }
41519:
41520: void
41521: displayer::a_ia()
41522: {
41523: struct ia& i = *(struct ia *)node;
41524:
41525: printf("$ia %s |0x%p ",
41526: token_name(node->base),
41527: node_address);
41528:
41529: print_ptr("local", i.local);
41530: print_ptr("arg", i.arg);
41531: print_ptr("tp", i.tp);
41532: }
41533:
41534: static int fetcher (void * info,
41535: void * pointer,
41536: unsigned long length,
41537: int zero_stop, /* for character strings.*/
41538: void * target)
41539: {
41540: displayer * d = (displayer *)info;
41541: if(d->arg->fetcher)
41542: return d->arg->fetcher(d->arg->fetcher_info, pointer, length,
41543: zero_stop, target);
41544: }
41545:
41546: static void
41547: do_node (Pnode& node, node_class cl, void * info, tree_node_action& action,
41548: int depth, Pnode na, tree_walk_tree&, int&)
41549: {
41550: displayer * d = (displayer *)info;
41551: d->do_node(node, cl, action, depth, na);
41552: d->arg->output_stream->write("\n", 1);
41553: }
41554:
41555:
41556: /* Note -- declared extern "C" in tree_dump.h. */
41557:
41558: void
41559: display_cfront_node (dcn_arg& arg, Pnode n)
41560: {
41561: tree_walk_control twc;
41562: displayer d (arg);
41563:
41564: if(arg.verbose == dt_normal)arg.max_depth = 0;
41565: twc.callback_info = (void *)&d;
41566: if(arg.fetcher) twc.fetcher = fetcher;
41567: twc.action_proc = do_node;
41568: twc.error_stream = arg.error_stream;
41569: twc.nodes_seen_hash = arg.nodes_seen_hash;
41570: twc.resolve_by_name = 0; /* we want to display the by_name nodes */
41571: twc.dont_chase_lists_top = 1; /* don't display n_list or s_list peers
41572: at the top level. */
41573:
41574: walk_tree(twc, n);
41575:
41576: arg.error_stream->flush();
41577: arg.output_stream->flush();
41578: }
41579:
41580:
41581: extern "C" void _fcout();
41582: void _fcout () { cout.flush(); }
41583: 0707071010112046001004440001630000160000010207660466055415100001400000003407tree_dump.h /* ident "@(#)ctrans:src/tree_dump.h 1.2" */
41584: /* -*- Mode: C -*- Begin tree_dump.h */
41585:
41586: #ifndef _DUMP_TREE
41587: #define _DUMP_TREE
41588:
41589: #include "tree_walk.h"
41590: #include <iostream.h>
41591: #include "hash.h"
41592:
41593: enum dump_tree_verbosity {
41594: dt_brief = 1, /* minimal identification */
41595: dt_normal = 2, /* all data, outpointers Brief (one level) */
41596: dt_recursive_0 = 3, /* minimal, but recurse down.
41597: (outpointers Recursive_0) */
41598: dt_recursive_1 = 4, /* all data, outpointers Recursive_2. */
41599: };
41600:
41601: class dcn_arg {
41602: public:
41603: int version;
41604: dump_tree_verbosity verbose;
41605: tree_fetch_proc fetcher;
41606: void * fetcher_info;
41607: ostream* output_stream;
41608: ostream* error_stream;
41609: int max_depth;
41610: Hash * nodes_seen_hash;
41611: /* end of version 1 */
41612: int walk_tables;
41613: /* end of version 2 */
41614: int stop_at_top;
41615: dcn_arg () { version = 2;
41616: nodes_seen_hash = 0;
41617: fetcher = null_tfp;
41618: output_stream = &cout;
41619: error_stream = &cerr;
41620: max_depth = -1;
41621: walk_tables = 1;
41622: stop_at_top = 0;
41623: };
41624: };
41625:
41626:
41627: extern "C" {
41628: void display_cfront_node (dcn_arg&, Pnode);
41629: }
41630: #else
41631:
41632: typedef enum dump_tree_verbosity {
41633: dt_brief = 1, /* minimal identification */
41634: dt_normal = 2, /* all data, outpointers Brief (one level) */
41635: dt_recursive_0 = 3, /* minimal, but recurse down.
41636: (outpointers Recursive_0) */
41637: dt_recursive_1 = 4, /* all data, outpointers Recursive_2. */
41638: } dump_tree_verbosity;
41639:
41640: struct dcn_arg {
41641: int version; /* must be 1 for now. */
41642: dump_tree_verbosity verbose;
41643: int (*fetcher) ();
41644: void * fetcher_info;
41645: void * output_stream; /* these are c++ streams */
41646: void * error_stream;
41647: int max_depth;
41648: void * nodes_seen_hash;
41649: int walk_tables;
41650: int stop_at_top;
41651: };
41652:
41653: void display_cfront_node ();
41654: #endif
41655:
41656: /* End tree_dump.h */
41657: 0707071010112046051004440001630000160000010212000466055417300001400000066517tree_walk.c /* ident "@(#)ctrans:src/tree_walk.c 1.2" */
41658: /*
41659: tree_walk.c
41660: Utilities for tree-walking
41661: */
41662:
41663: #include "cfront.h"
41664: #include "tree_walk.h"
41665: #include <stdarg.h>
41666: #include "hash.h"
41667: // #include <alloca.h>
41668: // ************ need to add an explicit call of free
41669: // ************ make it an ifdef
41670: // ??? #include <streamdefs.h>
41671: #include <malloc.h>
41672:
41673: class walker {
41674: tree_walk_control control;
41675: Pnode orig_addr;
41676: Hash *nodes_seen_hash;
41677: int depth;
41678: int made_ht;
41679: tree_walk_tree * cur_tree;
41680: public:
41681: walker(tree_walk_control& c) ;
41682:
41683: ~walker () {
41684: if(made_ht) delete nodes_seen_hash;
41685: }
41686: tree_node_action walk (Pnode&);
41687: tree_node_action walk_ (Pnode& n)
41688: {
41689: if(n) {
41690: int save_depth = depth;
41691: tree_walk_tree * save_cur_tree = cur_tree;
41692:
41693: depth ++;
41694: if(control.alloc_stack_bytes) {
41695: cur_tree = (tree_walk_tree *)
41696: // alloca (control.alloc_stack_bytes + sizeof (tree_walk_tree));
41697: malloc(control.alloc_stack_bytes + sizeof (tree_walk_tree));
41698: cur_tree->parent = save_cur_tree;
41699: }
41700: tree_node_action r = walk(n);
41701: depth = save_depth;
41702: return r;
41703: } else return tna_continue;
41704: }
41705:
41706: tree_node_action walk(Pgen& n)
41707: { return walk_ ((struct node * &)n); };
41708: tree_node_action walk(Pvec& n)
41709: { return walk_ ((struct node * &)n); };
41710: tree_node_action walk(Pptr& n)
41711: { return walk_ ((struct node * &)n); };
41712: tree_node_action walk(Ptype& n)
41713: { return walk_ ((struct node * &)n); };
41714: tree_node_action walk(Pfct& n)
41715: { return walk_ ((struct node * &)n); };
41716: tree_node_action walk(Ptable& n)
41717: { return walk_ ((struct node * &)n); };
41718: tree_node_action walk(Pbase& n)
41719: { return walk_ ((struct node * &)n); };
41720: tree_node_action walk(Pname& n)
41721: { return walk_ ((struct node * &)n); };
41722: tree_node_action walk(Pexpr& n)
41723: { return walk_ ((struct node * &)n); };
41724: tree_node_action walk(Pstmt& n)
41725: { return walk_ ((struct node * &)n); };
41726: tree_node_action walk(Pblock& n)
41727: { return walk_ ((struct node * &)n); };
41728: tree_node_action walk(Penum& n)
41729: { return walk_ ((struct node * &)n); };
41730: tree_node_action walk(Pclass& n)
41731: { return walk_ ((struct node * &)n); };
41732: tree_node_action walk(Pvirt& n)
41733: { return walk_ ((struct node * &)n); };
41734: tree_node_action walk(Plist& n)
41735: { return walk_ ((struct node * &)n); };
41736: tree_node_action walk(Pin& n)
41737: { return walk_ ((struct node * &)n); };
41738: tree_node_action walk(struct ia * & n)
41739: { return walk_ ((struct node * &)n); };
41740: tree_node_action walk(Pbcl& n)
41741: { return walk_ ((struct node * &)n); };
41742: private:
41743: int fetching () { return (control.fetcher != null_tfp); } ;
41744: void free_fetched (void *);
41745: int fetch (void *, unsigned long, void *&);
41746: int fetch (void * a, unsigned long l, Pnode& p)
41747: {
41748: int ret;
41749: void * t; /* this is an output argument */
41750: ret = fetch(a,l,t);
41751: if(!ret) {
41752: p = Pnode(t);
41753: }
41754: return ret;
41755: };
41756: // void error (const char *,...); ?? at&t -- to get it up quick, line 155
41757: void error ( char *, unsigned long=0 );
41758: tree_node_action pre_act_on_node (Pnode node, node_class nc,
41759: Pnode node_copy, Pnode& replacement);
41760:
41761: tree_node_action a_gen (Pnode, Pgen, Pnode&);
41762: tree_node_action a_vec (Pnode, Pvec, Pnode&);
41763: tree_node_action a_ptr (Pnode, Pptr, Pnode&);
41764: tree_node_action a_fct (Pnode, Pfct, Pnode&);
41765: tree_node_action a_table (Pnode, Ptable, Pnode&);
41766: tree_node_action a_basetype (Pnode, Pbase, Pnode&);
41767: tree_node_action a_name(Pnode, Pname, Pnode&);
41768: tree_node_action a_expr (Pnode, Pexpr, Pnode&);
41769: tree_node_action a_stmt (Pnode, Pstmt, Pnode&);
41770: tree_node_action a_enumdef (Pnode, Penum, Pnode&);
41771: tree_node_action a_classdef (Pnode, Pclass, Pnode&);
41772: tree_node_action a_virt (Pnode, Pvirt, Pnode&);
41773: tree_node_action a_name_list (Pnode, Plist, Pnode&);
41774: tree_node_action a_iline (Pnode, Pin, Pnode&);
41775: tree_node_action a_ia (Pnode, struct ia *, Pnode&);
41776: tree_node_action a_baseclass (Pnode, Pbcl, Pnode&);
41777: tree_node_action a_expr_guts (Pexpr);
41778: };
41779:
41780:
41781: walker::walker(tree_walk_control& c)
41782: { control = c;
41783: made_ht = 0;
41784: if (c.nodes_seen_hash)
41785: nodes_seen_hash = c.nodes_seen_hash;
41786: else {
41787: nodes_seen_hash = new pointer_hash (100);
41788: made_ht = 1;
41789: }
41790: depth = 0;
41791: cur_tree = 0;
41792: }
41793:
41794:
41795: tree_node_action
41796: walk_tree (tree_walk_control& c, Pnode& n)
41797: {
41798: walker w (c);
41799: return w.walk(n);
41800: }
41801:
41802:
41803: /* error messages are of finite length, so no need to run
41804: around mallocing strings */
41805:
41806: // void walker::error (const char * format, ...)
41807: void walker::error (char *format, unsigned long v)
41808: {
41809: va_list args;
41810: va_start(args, format);
41811: if(control.call_i_error) {
41812: char buf[1000];
41813: // vsprintf(buf, format, args);
41814: // vsprintf not universal: by inspection
41815: // all calls are currently of 1 or 0 arguments
41816: sprintf(buf, format, v);
41817: (*control.i_error)('i', buf);
41818: } else {
41819: vostream_printf (format, args, *control.error_stream);
41820: *control.error_stream << "\n";
41821: control.error_stream->flush();
41822: }
41823: va_end (args);
41824: }
41825:
41826:
41827: void
41828: walker::free_fetched (void * addr)
41829: {
41830: if (control.fetcher != null_tfp) /* null indicates no cross-address-space */
41831: free ((char *)addr);
41832: }
41833:
41834: int
41835: walker::fetch (void * addr, unsigned long length, void*& taddr)
41836: {
41837: int err;
41838:
41839: if (control.fetcher == null_tfp) {
41840: taddr = addr;
41841: return 0;
41842: } else {
41843: taddr = (void *)malloc ((unsigned int)length);
41844: if(taddr == 0) {
41845: error ("walker::fetch: failed to malloc %d bytes.", length);
41846: return 1;
41847: }
41848:
41849: err = (*control.fetcher) (control.callback_info, addr, length, 0, taddr);
41850: if(err) {
41851: error("walker::fetch: fetcher returned %d.", err);
41852: return 1;
41853: }
41854: }
41855: }
41856:
41857: /* ::walk is called with a node pointer and a reference to
41858: a replacement node pointer. When it returns,
41859: replacement will be set if the action procedure
41860: called on the node decided to copy it or replace it.
41861: There are two possible modularities.
41862: In case there is cross-address-space action,
41863: ::walk can't call the action procedure until it has
41864: entered the case on node bases. Once it has,
41865: it calls the per-structure-type procedure,
41866: which calls the action proc. If the action
41867: proc supplies a replacement, then that replacement
41868: will be returned up via the reference parameters to
41869: the per-structure procedures.
41870:
41871: It the action procedure returns tna_continue,
41872: then the walk continues against the new copy of the node
41873: so that further replacements are reflected in the new copies.
41874: This prevents replacement from being meaningful cross-address-space,
41875: since the new copy will presumably be in the current
41876: (and not the cross) address space. That is, if the node
41877: is replaced by the action proc, the pointers in the new
41878: node will drive the subsequent tree walk. Usually one
41879: would just bitcopy, and then they would be replaced in turn.
41880: */
41881:
41882: tree_node_action
41883: walker::walk (Pnode& top)
41884: {
41885: Pnode replacement = 0;
41886: tree_node_action err;
41887: int class_err;
41888: node_class nclass;
41889: Pnode node = 0; /* assign to shut up compiler,
41890: which dosen't recognize pass-by-reference as a set */
41891:
41892: orig_addr = top;
41893:
41894: if(fetching ()) {
41895: if(fetch((void *)top, sizeof (struct node), node))
41896: return tna_error;
41897: } else node = top;
41898:
41899: /* This has a complete catalog of bases, rather than just a list
41900: of those associated with data structures. Its important
41901: to detect the errs.
41902: */
41903:
41904: nclass = classify_node (node, class_err);
41905:
41906: if(class_err) {
41907: error("walker::walk: unknown node type %d.", node->base);
41908: free_fetched ((void *)node);
41909: err = tna_error;
41910: goto Return;
41911: }
41912:
41913: switch(nclass)
41914: {
41915: default:
41916: case nc_unused:
41917: error("walker::walk: unused node type %d.", node->base);
41918: err = tna_error;
41919: goto Return;
41920:
41921: case nc_eof:
41922: break;
41923:
41924: case nc_virt:
41925: fetch((void *)top, sizeof (struct virt), node);
41926: err = a_virt(top, Pvirt (node), replacement);
41927: break;
41928:
41929: case nc_nlist:
41930: fetch((void *)top, sizeof (struct name_list), node);
41931: err = a_name_list(top, (struct name_list *)node, replacement);
41932: break;
41933:
41934: case nc_iline:
41935: fetch((void *)top, sizeof (struct iline), node);
41936: err = a_iline(top, (struct iline *)node, replacement);
41937: break;
41938:
41939: case nc_gen:
41940: fetch((void *)top, sizeof (struct gen), node);
41941: err = a_gen(top, Pgen (node), replacement);
41942: break;
41943:
41944: case nc_vec:
41945: fetch((void *)top, sizeof (struct vec), node);
41946: err = a_vec(top, Pvec(node), replacement);
41947: break;
41948:
41949: case nc_ptr:
41950: fetch((void *)top, sizeof (struct ptr), node);
41951: err = a_ptr(top, Pptr(node), replacement);
41952: break;
41953:
41954: case nc_fct:
41955: fetch((void *)top, sizeof (struct fct), node);
41956: err = a_fct(top, Pfct(node), replacement);
41957: break;
41958:
41959: case nc_table:
41960: fetch((void *)top, sizeof (struct table), node);
41961: err = a_table(top, Ptable(node), replacement);
41962: break;
41963:
41964: case nc_basetype:
41965: fetch((void *)top, sizeof (struct basetype), node);
41966: err = a_basetype(top, Pbase(node), replacement);
41967: break;
41968:
41969: case nc_name:
41970: fetch((void *)top, sizeof (struct name), node);
41971: err = a_name(top, Pname(node), replacement);
41972: break;
41973:
41974: case nc_expr:
41975: fetch((void *)top, sizeof (struct expr), node);
41976: err = a_expr(top, Pexpr(node), replacement);
41977: break;
41978:
41979: case nc_stmt:
41980: fetch((void *)top, sizeof (struct stmt), node);
41981: err = a_stmt(top, Pstmt(node), replacement);
41982: break;
41983:
41984: case nc_enumdef:
41985: fetch((void *)top, sizeof (struct enumdef), node);
41986: err = a_enumdef(top, Penum(node), replacement);
41987: break;
41988:
41989: case nc_classdef:
41990: fetch((void *)top, sizeof (struct classdef), node);
41991: err = a_classdef(top, Pclass(node), replacement);
41992: break;
41993:
41994: case nc_ia:
41995: fetch((void *)top, sizeof (struct ia), node);
41996: err = a_ia(top, (struct ia *)node, replacement);
41997: break;
41998:
41999: case nc_baseclass:
42000: fetch((void *)top, sizeof (struct basecl), node);
42001: err = a_baseclass(top, Pbcl(node), replacement);
42002: break;
42003:
42004: }
42005:
42006: if(replacement) {
42007: if (fetching ()) {
42008: error
42009: ("walker::walk: Attempt to replace tree in cross-address space mode.");
42010: err = tna_error;
42011: }
42012: else top = replacement;
42013: }
42014:
42015: if (control.post_action_proc && err != tna_error) {
42016: tree_node_action post_err;
42017: Pnode& post_repl = node;
42018:
42019: (*control.post_action_proc) (post_repl, nclass, control.callback_info, post_err,
42020: depth, orig_addr, *cur_tree);
42021: if(post_err != tna_continue) err = post_err;
42022: if(post_repl != node) {
42023: if (fetching ()) {
42024: error
42025: ("walker::walk: Attempt to replace tree in cross-address space mode.");
42026: err = tna_error;
42027: }
42028: else top = post_repl;
42029: }
42030: }
42031:
42032: free_fetched((void *) node);
42033:
42034: Return:
42035: return err;
42036: }
42037:
42038: /* This is called in pre-order for each node. Then
42039: post_act_on_node is called after whatever recursive
42040: processing ensues.
42041:
42042: This is called from each of the structure-specific procedures
42043: to give the action procedure an opportunity to act.
42044: It can return a replacement pointer and control
42045: whether to examine the insides of the node.
42046: */
42047:
42048: tree_node_action
42049: walker::pre_act_on_node (Pnode node, node_class nc,
42050: Pnode node_copy, Pnode& replacement)
42051: {
42052: /* If we have been here before, then we never proceed */
42053: /* node_copy is != node when a fetcher is in use */
42054:
42055: int found;
42056: int old_node;
42057: tree_node_action action;
42058: Pnode new_node;
42059: int register_in_hash = 1;
42060:
42061: nodes_seen_hash->action((int)node, 0, Hash::probe, found, old_node);
42062:
42063: if(found) {
42064: new_node = Pnode(old_node);
42065: if(new_node != node) replacement = new_node;
42066: return tna_stop; /* no need to proceed */
42067: }
42068:
42069: /* OK, we don't know from a previous pass. Call our actor */
42070:
42071: new_node = fetching () && node_copy ? node_copy : node;
42072:
42073: (*control.action_proc)(new_node, nc, control.callback_info, action,
42074: depth, orig_addr, *cur_tree,
42075: register_in_hash);
42076:
42077: if(action != tna_error && !fetching () && new_node != node) {
42078: replacement = new_node;
42079: if(register_in_hash)
42080: nodes_seen_hash->action((int)node,
42081: (int)new_node,
42082: Hash::insert, 0, 0);
42083: }
42084: else {
42085: if(register_in_hash)
42086: nodes_seen_hash->action((int)node, (int) node, Hash::insert, 0, 0);
42087: }
42088: return action;
42089: }
42090:
42091: tree_node_action walker::a_table(Pnode ta, Ptable t, Pnode& replacement)
42092: {
42093: /* no unions */
42094:
42095: tree_node_action action;
42096: action = pre_act_on_node(ta, nc_table, Pnode(t), replacement);
42097: if(action != tna_continue) return action;
42098:
42099: /* -----------------------------*/
42100: /* For Now, Never Walk a Table. */
42101:
42102: action = tna_stop; return action;
42103:
42104: /* An array of pointers.
42105: * The action procedure is responsible for allocating a new one
42106: * of those if it replaced and continued.
42107: * *** end of comment
42108:
42109: if(!fetching () && replacement)
42110: t = Ptable(replacement);
42111:
42112: Pname * t_entries;
42113:
42114: if(fetching ()) {
42115: void * temp;
42116: fetch((void *)t->entries, t->size * sizeof(Pname), temp);
42117: t_entries = (Pname *)temp;
42118: }
42119: else t_entries = t->entries;
42120:
42121: for(int nx = 0; nx < t->size; nx ++) {
42122: action = walk(t_entries[nx]);
42123: if(action == tna_error) return action;
42124: }
42125:
42126: if(fetching ()) free_fetched ((void *)t_entries);
42127:
42128: Pnode n = Pnode(t->real_block);
42129:
42130: action = walk(t->real_block);
42131: if(action == tna_error) return action;
42132:
42133: action = walk(t->next);
42134: action = walk(t->t_name);
42135: return tna_continue;
42136: */ // don't walk table
42137: }
42138:
42139: tree_node_action walker::a_enumdef (Pnode ta, Penum e, Pnode& replacement)
42140: {
42141: tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(e), replacement);
42142:
42143: action = walk(e->mem);
42144: if(action == tna_error) return action;
42145:
42146: action = walk(e->e_type);
42147:
42148: return tna_continue;
42149: }
42150:
42151: tree_node_action walker::a_virt(Pnode ta, Pvirt v, Pnode& replacement)
42152: {
42153: /* no unions */
42154:
42155: int nx;
42156: tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(v), replacement);
42157:
42158: if(action != tna_continue) return action;
42159:
42160: if(!fetching () && replacement)
42161: v = Pvirt(replacement);
42162:
42163: /* an array of velem structures. */
42164:
42165: velem * v_virt_init;
42166:
42167: if(fetching ()) {
42168: void * t;
42169: fetch((void *)v->virt_init, v->n_init * sizeof(velem), t);
42170: v_virt_init = (velem *)t;
42171: }
42172: else v_virt_init = v->virt_init;
42173:
42174: for(nx = 0; nx < v->n_init; nx ++) {
42175: action = walk(v_virt_init[nx].n);
42176: if(action == tna_error) return action;
42177: }
42178:
42179: if(fetching ()) free_fetched ((void *)v_virt_init);
42180:
42181: action = walk(v->vclass);
42182:
42183: return tna_continue;
42184: }
42185:
42186: tree_node_action walker::a_classdef(Pnode ta, Pclass c, Pnode& replacement)
42187: {
42188:
42189: tree_node_action action = pre_act_on_node(ta, nc_classdef, Pnode(c), replacement);
42190:
42191: if(action != tna_continue) return action;
42192:
42193: if(!fetching () && replacement)
42194: c = Pclass(replacement);
42195:
42196: action = walk(c->baselist);
42197: if(action == tna_error) return action;
42198:
42199: action=walk(c->mem_list);
42200: if(action == tna_error) return action;
42201:
42202: action=walk(c->memtbl);
42203: if(action == tna_error) return action;
42204:
42205: action=walk(c->friend_list);
42206: if(action == tna_error) return action;
42207:
42208: action=walk(c->pubdef);
42209: if(action == tna_error) return action;
42210:
42211: action=walk(c->tn_list);
42212: if(action == tna_error) return action;
42213:
42214: action=walk(c->in_class);
42215: if(action == tna_error) return action;
42216:
42217: action=walk(c->in_fct);
42218: if(action == tna_error) return action;
42219:
42220: action=walk(c->this_type);
42221: if(action == tna_error) return action;
42222:
42223: action=walk(c->virt_list);
42224: if(action == tna_error) return action;
42225:
42226: action=walk(c->c_ctor);
42227: if(action == tna_error) return action;
42228: action=walk(c->c_dtor);
42229: if(action == tna_error) return action;
42230: action=walk(c->c_itor);
42231: if(action == tna_error) return action;
42232:
42233: action=walk(c->conv);
42234: if(action == tna_error) return action;
42235:
42236: return tna_continue;
42237: }
42238:
42239: tree_node_action walker::a_basetype(Pnode ta, Pbase b, Pnode& replacement)
42240: {
42241:
42242: tree_node_action action = pre_act_on_node(ta, nc_basetype, Pnode(b), replacement);
42243: int derr;
42244:
42245: if(action != tna_continue) return action;
42246:
42247: if(!fetching () && replacement)
42248: b = Pbase(replacement);
42249:
42250: action = walk(b->b_name);
42251: if(action == tna_error) return action;
42252:
42253: action = walk(b->b_table);
42254: if(action == tna_error) return action;
42255:
42256: // action = walk(b->b_field);
42257: // if(action == tna_error) return action;
42258:
42259: action = walk(b->b_xname);
42260: if(action == tna_error) return action;
42261:
42262: switch(derr = b->discriminator(0)) {
42263: case 0: break;
42264: case 1:
42265: action = walk(b->b_fieldtype);
42266: if(action == tna_error) return action;
42267: break;
42268: case 2: break;
42269: default:
42270: error ("a_basetype: discrim error %d.", derr);
42271: return tna_error;
42272: }
42273:
42274: return tna_continue;
42275: }
42276:
42277: tree_node_action walker::a_fct(Pnode ta, Pfct f, Pnode& replacement)
42278: {
42279:
42280: tree_node_action action = pre_act_on_node(ta, nc_fct, Pnode(f), replacement);
42281:
42282: if(action != tna_continue) return action;
42283:
42284: if(!fetching () && replacement)
42285: f = Pfct(replacement);
42286:
42287: action = walk(f->returns);
42288: if(action == tna_error) return action;
42289:
42290: action = walk(f->argtype);
42291: if(action == tna_error) return action;
42292:
42293: action = walk(f->s_returns);
42294: if(action == tna_error) return action;
42295:
42296: action = walk(f->f_this);
42297: if(action == tna_error) return action;
42298:
42299: action = walk(f->memof);
42300: if(action == tna_error) return action;
42301:
42302: action = walk(f->body);
42303: if(action == tna_error) return action;
42304:
42305: action = walk(f->f_init);
42306: if(action == tna_error) return action;
42307:
42308: action = walk(f->f_expr);
42309: if(action == tna_error) return action;
42310:
42311: action = walk(f->last_expanded);
42312: if(action == tna_error) return action;
42313:
42314: action = walk(f->f_result);
42315: if(action == tna_error) return action;
42316:
42317: action = walk(f->f_args);
42318: if(action == tna_error) return action;
42319:
42320: return tna_continue;
42321: }
42322:
42323: tree_node_action walker::a_name_list(Pnode ta, Plist l, Pnode& replacement)
42324: {
42325:
42326: int cl_error;
42327: tree_node_action action = pre_act_on_node(ta, nc_nlist, Pnode(l), replacement);
42328:
42329: if(action == tna_stop) {
42330: if(!fetching () && replacement)
42331: l = Plist(replacement);
42332: cl_error = 0;
42333: if((classify_node(Pnode(l), cl_error) == nc_nlist) && !cl_error) {
42334: action = walk(l->l);
42335: if(action == tna_error) return action;
42336: }
42337: }
42338:
42339: if(action != tna_continue) return action;
42340:
42341: if(!fetching () && replacement)
42342: l = Plist(replacement);
42343:
42344: action = walk(l->f);
42345: if(action == tna_error) return action;
42346:
42347: action = walk(l->l);
42348: if(action == tna_error) return action;
42349:
42350: return tna_continue;
42351: }
42352:
42353: tree_node_action walker::a_gen(Pnode ta, Pgen g, Pnode& replacement)
42354: {
42355:
42356: tree_node_action action = pre_act_on_node(ta, nc_gen, Pnode(g), replacement);
42357:
42358: if(action != tna_continue) return action;
42359:
42360: if(!fetching () && replacement)
42361: g = Pgen(replacement);
42362:
42363: action = walk(g->fct_list);
42364: if(action == tna_error) return action;
42365:
42366: return tna_continue;
42367: }
42368:
42369: tree_node_action walker::a_vec(Pnode ta, Pvec v, Pnode& replacement)
42370: {
42371:
42372: tree_node_action action = pre_act_on_node(ta, nc_vec, Pnode(v), replacement);
42373:
42374: if(action != tna_continue) return action;
42375:
42376: if(!fetching () && replacement)
42377: v = Pvec(replacement);
42378:
42379: action = walk(v->typ);
42380: if(action == tna_error) return action;
42381:
42382: action = walk(v->dim);
42383: if(action == tna_error) return action;
42384:
42385: return tna_continue;
42386: }
42387:
42388: tree_node_action walker::a_ptr(Pnode ta, Pptr p, Pnode& replacement)
42389: {
42390:
42391: tree_node_action action = pre_act_on_node(ta, nc_ptr, Pnode(p), replacement);
42392:
42393: if(action != tna_continue) return action;
42394:
42395: if(!fetching () && replacement)
42396: p = Pptr(replacement);
42397:
42398: action = walk(p->typ);
42399: if(action == tna_error) return action;
42400:
42401: action = walk(p->memof);
42402: if(action == tna_error) return action;
42403:
42404: return tna_continue;
42405: }
42406:
42407:
42408: tree_node_action walker::a_expr_guts(Pexpr e)
42409: {
42410: int derr;
42411: tree_node_action action;
42412:
42413: switch(derr = e->discriminator (0)) {
42414: case 1:
42415: action = walk(e->tp);
42416: if(action == tna_error) return action;
42417: break;
42418: case 0:
42419: break;
42420: default:
42421: error ("a_expr: discrim error %d on union 0.", derr);
42422: return tna_error;
42423: }
42424:
42425: switch(derr = e->discriminator (1)) {
42426: case 0:
42427: break;
42428: default:
42429: error ("a_expr: discrim error %d on union 1.", derr);
42430: return tna_error;
42431: case 1:
42432: action = walk(e->e1);
42433: if(action == tna_error) return action;
42434: break;
42435: case 2:
42436: break;
42437: case 3:
42438: break;
42439: }
42440:
42441: switch(derr = e->discriminator (2)) {
42442: case 0:
42443: break;
42444: default:
42445: error ("a_expr: discrim error %d on union 2.", derr);
42446: return tna_error;
42447: case 1:
42448: /* elists are special. e2 for an elist is a peer, not
42449: a child. */
42450: if(e->base != ELIST) {
42451: action = walk(e->e2);
42452: if(action == tna_error) return action;
42453: }
42454: break;
42455: case 2:
42456: break;
42457: case 3:
42458: break;
42459: case 4:
42460: action = walk(e->n_initializer);
42461: if(action == tna_error) return action;
42462: break;
42463: }
42464:
42465: switch(derr = e->discriminator (3)) {
42466: case 0:
42467: break;
42468: default:
42469: error ("a_expr: discrim error %d on union 3.", derr);
42470: return tna_error;
42471: case 1:
42472: action = walk(e->tp2);
42473: if(action == tna_error) return action;
42474: break;
42475: case 2:
42476: action = walk(e->fct_name);
42477: if(action == tna_error) return action;
42478: break;
42479: case 3:
42480: action = walk(e->cond);
42481: if(action == tna_error) return action;
42482: break;
42483: case 4:
42484: action = walk(e->mem);
42485: if(action == tna_error) return action;
42486: break;
42487: case 5:
42488: action = walk(e->as_type);
42489: if(action == tna_error) return action;
42490: break;
42491: case 6:
42492: action = walk(e->n_table);
42493: if(action == tna_error) return action;
42494: break;
42495: case 7:
42496: action = walk(e->il);
42497: if(action == tna_error) return action;
42498: break;
42499: case 8:
42500: action = walk(e->query_this);
42501: if(action == tna_error) return action;
42502: break;
42503: }
42504: return tna_continue;
42505: }
42506:
42507:
42508: tree_node_action walker::a_expr(Pnode ta, Pexpr e, Pnode& replacement)
42509: {
42510: tree_node_action action = pre_act_on_node(ta, nc_expr, Pnode(e), replacement);
42511:
42512: if(action == tna_stop) {
42513: if(!fetching () && replacement)
42514: e = Pexpr(replacement);
42515: /* ELIST implies that e2 is a peer, not a child */
42516: if(e->base == ELIST) {
42517: action = walk(e->e2);
42518: return action;
42519: }
42520: }
42521:
42522: if(action != tna_continue) return action;
42523:
42524: if(!fetching () && replacement)
42525: e = Pexpr(replacement);
42526:
42527: action = a_expr_guts(e);
42528: if (action == tna_error) return action;
42529: if(e->base == ELIST)
42530: action = walk(e->e2);
42531: return action;
42532: }
42533:
42534: tree_node_action walker::a_baseclass(Pnode ta, Pbcl b, Pnode& replacement)
42535: {
42536: tree_node_action action = pre_act_on_node(ta, nc_baseclass, Pnode(b), replacement);
42537:
42538: if(action != tna_continue) return action;
42539:
42540: if(!fetching () && replacement)
42541: b = Pbcl(replacement);
42542:
42543: action = walk(b->bclass);
42544: if(action == tna_error) return action;
42545:
42546: action = walk(b->init);
42547: if(action == tna_error) return action;
42548:
42549: action = walk(b->next);
42550: if(action == tna_error) return action;
42551:
42552: return tna_continue;
42553: }
42554:
42555:
42556: /* a name is also an expr. */
42557:
42558:
42559: tree_node_action walker::a_name(Pnode ta, Pname n, Pnode& replacement)
42560: {
42561: int derr;
42562: int cl_error;
42563: tree_node_action action = pre_act_on_node(ta, nc_name, Pnode(n), replacement);
42564:
42565: /* n_list is a sibling, not a child. We always process it
42566: except in case of an error. */
42567: if(action == tna_stop) {
42568: cl_error = 0;
42569: if(!fetching () && replacement)
42570: n = Pname(replacement);
42571: if((classify_node(Pnode(n), cl_error) == nc_name) && !cl_error) {
42572: if(depth > 0 || !control.dont_chase_lists_top) {
42573: action = walk(n->n_list);
42574: if(action == tna_error) return action;
42575: }
42576: }
42577: return tna_stop;
42578: }
42579:
42580: if(action != tna_continue) return action;
42581:
42582: if(!fetching () && replacement)
42583: n = Pname(replacement);
42584:
42585: /* We don't walk n_tbl_list. Its not part of the graph.
42586: */
42587:
42588: switch(derr = n->discriminator(0)) {
42589: case 0:
42590: break;
42591: case 1:
42592: action = walk(n->n_qualifier);
42593: if(action == tna_error) return action;
42594: break;
42595: case 2:
42596: action = walk(n->n_realscope);
42597: if(action == tna_error) return action;
42598: break;
42599: default:
42600: error ("a_name: discrim error %d on union 0.", derr);
42601: return tna_error;
42602: }
42603:
42604: action = a_expr_guts(Pexpr(n));
42605: if(action == tna_error) return action;
42606:
42607: if(depth > 0 || !control.dont_chase_lists_top) {
42608: action = walk(n->n_list);
42609: if(action == tna_error) return action;
42610: }
42611:
42612: return action;
42613: }
42614:
42615: /* --- NOTE: s_list should be deferred until AFTER the post-action
42616: procedure is called, if there is one. Since no one uses
42617: post-actions yet I haven't bothered to make this fix.
42618: --benson */
42619:
42620: tree_node_action walker::a_stmt(Pnode ta, Pstmt s, Pnode& replacement)
42621: {
42622: int cl_error;
42623: int derr;
42624: tree_node_action action = pre_act_on_node(ta, nc_stmt, Pnode(s), replacement);
42625:
42626: if(action == tna_stop) {
42627: if(!fetching () && replacement)
42628: s = Pstmt(replacement);
42629: cl_error = 0;
42630: if((classify_node(Pnode(s), cl_error) == nc_stmt) && !cl_error) {
42631: /* s_list is not our subordinate, it is our peer */
42632: if(depth > 0 || !control.dont_chase_lists_top) {
42633: action = walk(s->s_list); /* continue walk of sibs */
42634: if (action == tna_error) return tna_error;
42635: }
42636: }
42637: return tna_stop;
42638: }
42639:
42640: if(action != tna_continue) return action;
42641:
42642: if(!fetching () && replacement)
42643: s = Pstmt(replacement);
42644:
42645: action = walk(s->s);
42646: if(action == tna_error) return action;
42647:
42648: action = walk(s->memtbl);
42649: if(action == tna_error) return action;
42650:
42651: switch(derr = s->discriminator(0)) {
42652: default:
42653: error ("a_stmt: discrim error %d on union 0.", derr);
42654: return tna_error;
42655: case 4:
42656: case 0: break;
42657: case 1:
42658: action = walk(s->d);
42659: if(action == tna_error) return action;
42660: break;
42661: case 2:
42662: action = walk(s->e2);
42663: if(action == tna_error) return action;
42664: break;
42665: case 3:
42666: action = walk(s->has_default);
42667: if(action == tna_error) return action;
42668: break;
42669: case 5:
42670: action = walk(s->ret_tp);
42671: if(action == tna_error) return action;
42672: break;
42673: }
42674:
42675: switch(derr = s->discriminator(1)) {
42676: default:
42677: error ("a_stmt: discrim error %d on union 1.", derr);
42678: return tna_error;
42679: case 2:
42680: case 0: break;
42681: case 1:
42682: action = walk(s->e);
42683: if(action == tna_error) return action;
42684: break;
42685: case 3:
42686: action = walk(s->s2);
42687: if(action == tna_error) return action;
42688: break;
42689: }
42690:
42691: switch(derr = s->discriminator(2)) {
42692: default:
42693: error ("a_stmt: discrim error %d on union 2.", derr);
42694: return tna_error;
42695: case 0: break;
42696: case 1:
42697: action = walk(s->for_init);
42698: if(action == tna_error) return action;
42699: break;
42700: case 2:
42701: action = walk(s->else_stmt);
42702: if(action == tna_error) return action;
42703: break;
42704: case 3:
42705: action = walk(s->case_list);
42706: if(action == tna_error) return action;
42707: break;
42708: }
42709:
42710: if(depth > 0 || !control.dont_chase_lists_top) {
42711: action = walk(s->s_list);
42712: if(action == tna_error) return action;
42713: }
42714:
42715: return tna_continue;
42716: }
42717:
42718: tree_node_action walker::a_ia(Pnode ta, struct ia * ia, Pnode& replacement)
42719: {
42720: tree_node_action action = pre_act_on_node(ta, nc_ia, Pnode(ia), replacement);
42721:
42722: if(action != tna_continue) return action;
42723:
42724: if(!fetching () && replacement)
42725: ia = (struct ia *)&replacement;
42726:
42727: action = walk(ia->local);
42728: if(action == tna_error) return action;
42729:
42730: action = walk(ia->arg);
42731: if(action == tna_error) return action;
42732:
42733: action = walk(ia->tp);
42734: if(action == tna_error) return action;
42735:
42736: return tna_continue;
42737: }
42738:
42739: tree_node_action walker::a_iline(Pnode ta, Pin iline, Pnode& replacement)
42740: {
42741: tree_node_action action = pre_act_on_node(ta, nc_iline, Pnode(iline), replacement);
42742:
42743: if(action != tna_continue) return action;
42744:
42745: if(!fetching () && replacement)
42746: iline = Pin(replacement);
42747:
42748: action = walk(iline->fct_name);
42749: if(action == tna_error) return action;
42750:
42751: action = walk(iline->i_next);
42752: if(action == tna_error) return action;
42753:
42754: action = walk(iline->i_table);
42755: if(action == tna_error) return action;
42756:
42757: action = walk(iline->i_args);
42758: if(action == tna_error) return action;
42759:
42760: return tna_continue;
42761: }
42762: 0707071010112046151004440001630000160000010107200466055423100001400000004551tree_walk.h /* ident "@(#)ctrans:src/tree_walk.h 1.2" */
42763: /* -*- Mode: C -*- Begin include file tree_walk.H */
42764: /*
42765: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_walk.H,v $ $RCSfile: tree_walk.H,v $
42766: $Revision: 1.1 $ $Date: 89/11/20 08:51:05 $
42767: $Author: benson $ $Locker: $
42768: $State: Exp $
42769: */
42770:
42771: #ifndef _TREE_WALK
42772: #define _TREE_WALK
42773:
42774: #include "cfront.h"
42775: #include "node_classes.h"
42776: #include <iostream.h>
42777: #include "ios_printf.h"
42778: #include "hash.h"
42779:
42780: enum tree_node_action {
42781: tna_continue = 0, /* plain vanilla */
42782: tna_stop = 1, /* don't proceed */
42783: tna_error = 2, /* stop entire walk now. */
42784: };
42785:
42786: /* procedural interface to indirect via a pointer. */
42787: typedef int (*tree_fetch_proc) (void * info,
42788: void * pointer,
42789: unsigned long length,
42790: int zero_stop, /* for character strings.*/
42791: void * target);
42792:
42793:
42794: const tree_fetch_proc null_tfp = (tree_fetch_proc) 0;
42795:
42796: class tree_walk_tree {
42797: public:
42798: tree_walk_tree * parent;
42799: char storage[1]; /* variable amt, specified by caller. */
42800: };
42801:
42802: /* The trailing int here controls whether to remember the
42803: node in the hash table to short-circuit meeting it again */
42804:
42805: typedef void (*tree_pre_action)
42806: (Pnode&, node_class, void *, tree_node_action&, int, Pnode,
42807: tree_walk_tree&, int&);
42808:
42809:
42810: typedef void (*tree_post_action)
42811: (Pnode&, node_class, void *, tree_node_action&, int, Pnode,
42812: tree_walk_tree&);
42813:
42814: typedef void (*errorp) (char, const char *);
42815:
42816: class tree_walk_control {
42817: public:
42818: int version;
42819: void * callback_info;
42820: tree_fetch_proc fetcher;
42821: tree_pre_action action_proc;
42822: tree_post_action post_action_proc;
42823: int (*i_error) (int, const char *); /* usually part of cfront */
42824: int call_i_error; /* if 0, just use the following */
42825: ostream * error_stream;
42826: Hash * nodes_seen_hash; /* allows this to be global over
42827: more than one call to the walker. */
42828: int resolve_by_name;
42829: int alloc_stack_bytes;
42830: /* if on, n_list and s_list are ignored for the very top node.
42831: this is for the benefit of the printer. */
42832: int dont_chase_lists_top;
42833: tree_walk_control () {
42834: version = 1;
42835: callback_info = 0;
42836: fetcher = null_tfp;
42837: call_i_error = 0;
42838: error_stream = &cerr;
42839: nodes_seen_hash = 0;
42840: resolve_by_name = 1; /* the dumper turns this off */
42841: alloc_stack_bytes = 0;
42842: post_action_proc = 0;
42843: dont_chase_lists_top = 0;
42844: }
42845: };
42846:
42847: tree_node_action walk_tree (tree_walk_control& c, Pnode& n);
42848:
42849: #endif
42850: 0707071010112045721004440001630000160000010210200466055412600000600000054504typ.c /*ident "@(#)ctrans:src/typ.c 1.4" */
42851: /**************************************************************************
42852:
42853: C++ source for cfront, the C++ compiler front-end
42854: written in the computer science research center of Bell Labs
42855:
42856: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
42857: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
42858:
42859: typ.c:
42860:
42861:
42862: ***************************************************************************/
42863:
42864: #include "cfront.h"
42865: #include "size.h"
42866:
42867: Pbase short_type;
42868: Pbase int_type;
42869: Pbase char_type;
42870: Pbase long_type;
42871:
42872: Pbase uchar_type;
42873: Pbase ushort_type;
42874: Pbase uint_type;
42875: Pbase ulong_type;
42876:
42877: Pbase zero_type;
42878: Pbase float_type;
42879: Pbase double_type;
42880: Pbase ldouble_type;
42881: Pbase void_type;
42882: Pbase any_type;
42883:
42884: Ptype Pint_type;
42885: Ptype Pchar_type;
42886: Ptype Pvoid_type;
42887: Ptype Pfctvec_type;
42888:
42889: Ptable gtbl;
42890: Ptable ptbl;
42891:
42892: Pname Cdcl;
42893: Pstmt Cstmt;
42894:
42895: bit new_type;
42896:
42897: void echeck(Ptype t1, Ptype t2)
42898: /*
42899: t1 is an enum, t2 is assigned to it
42900: */
42901: {
42902: if (t1 == t2) return;
42903:
42904: //error('d',"echeck(%t,%t) %d %d",t1,t2,t1->base,t2->base);
42905: //error('d',"se %d promote: %d",suppress_error, enum_promote);
42906: if (t1->base==EOBJ
42907: && t2->base==EOBJ
42908: && Pbase(t1)->b_name->tp == Pbase(t2)->b_name->tp) return;
42909:
42910: if (enum_promote) return;
42911: error(strict_opt?0:'w',"%t assigned to %t (anachronism)",t2,t1);
42912: }
42913:
42914:
42915: Ptype np_promote(TOK oper, TOK r1, TOK r2, Ptype t1, Ptype t2, TOK p)
42916: /*
42917: an arithmetic operator "oper" is applied to "t1" and "t2",
42918: types t1 and t2 has been checked and belongs to catagories
42919: "r1" and "r2", respectively:
42920: A ANY
42921: Z ZERO
42922: I CHAR, SHORT, INT, LONG, FIELD, or EOBJ
42923: F FLOAT DOUBLE LDOUBLE
42924: P PTR (to something) or VEC (of something)
42925: test for compatability of the operands,
42926: if (p) return the promoted result type
42927: */
42928: {
42929: if (r2 == 'A') return t1;
42930:
42931: //error('d',"promote(%t,%t,%k)",t1,t2,oper);
42932:
42933: switch (r1) {
42934: case 'A': return t2;
42935: case 'Z':
42936: switch (r2) {
42937: case 'Z': return int_type;
42938: case 'I':
42939: case 'F':
42940: if(oper==DEREF) return any_type;
42941: return (p) ? Pbase(t2)->arit_conv(0) : 0;
42942: case 'P': switch (oper) {
42943: case PLUS:
42944: case ASPLUS: if(t2!=Pvoid_type) break;
42945: default: return any_type;
42946: }
42947: return t2;
42948: case FCT: error("zero%kF",oper); return any_type;
42949: default: error('i',"zero(%d)",r2);
42950: }
42951: case 'I':
42952: switch (r2) {
42953: case 'Z': t2 = 0;
42954: case 'I':
42955: case 'F':
42956: if(oper==DEREF) return any_type;
42957: return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0;
42958: case 'P': switch (oper) {
42959: case PLUS:
42960: case ASPLUS: if(t2!=Pvoid_type) break;
42961: default: error("int%kP",oper); return any_type;
42962: }
42963: return t2;
42964: case FCT: error("int%kF",oper); return any_type;
42965: default: error('i',"int(%d)",r2); return any_type;
42966: }
42967: case 'F':
42968: switch (r2) {
42969: case 'Z': t2 = 0;
42970: case 'I':
42971: case 'F':
42972: if(oper==DEREF) return any_type;
42973: return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0;
42974: case 'P': error("float%kP",oper); return any_type;
42975: case FCT: error("float%kF",oper); return any_type;
42976: default: error('i',"float(%d)",r2); return any_type;
42977: }
42978: case 'P':
42979: switch (r2) {
42980: case 'Z': return t1;
42981: case 'I':
42982: switch (oper) {
42983: case PLUS:
42984: case MINUS:
42985: case ASPLUS:
42986: case ASMINUS:
42987: if (t1->check(Pvoid_type,0)==0) {
42988: return any_type;
42989: }
42990: break;
42991: default: error("P%k int",oper); return any_type;
42992: }
42993: return t1;
42994: case 'F': error("P%k float",oper); return any_type;
42995: case 'P':
42996: if (t1->check(t2,ASSIGN)) {
42997: switch (oper) {
42998: case EQ:
42999: case NE:
43000: case LE:
43001: case GE:
43002: case GT:
43003: case LT:
43004: case QUEST:
43005: if (t2->check(t1,ASSIGN) == 0) goto zz;
43006: }
43007: error("T mismatch:%t %k%t",t1,oper,t2);
43008: return any_type;
43009: }
43010: zz:
43011: switch (oper) {
43012: case MINUS:
43013: return (t2!=Pvoid_type) ? int_type : any_type;
43014: case ASMINUS: error("P -=P"); return any_type;
43015: case PLUS: error("P +P"); return any_type;
43016: case ASPLUS: error("P +=P"); return any_type;
43017: case LS:
43018: case RS: return any_type;
43019: default: return (t1!=Pvoid_type) ? t1 : any_type;
43020: }
43021: case FCT: return t1;
43022: default: error('i',"P(%d)",r2);
43023: }
43024: case FCT:
43025: if(oper == QUEST) {
43026: switch (r2) {
43027: case 'Z':
43028: return any_type;
43029: case 'P':
43030: return t2;
43031: case 'I':
43032: case 'F':
43033: error("F%k%t",oper,t2);
43034: default:
43035: return t1;
43036: }
43037: }
43038: error("F%k%t",oper,t2);
43039: return any_type;
43040: default:
43041: error('i',"np_promote(%d,%d)",r1,r2);
43042: }
43043: }
43044:
43045: TOK type::kind(TOK oper, TOK v)
43046: /* v == 'I' integral
43047: 'N' numeric
43048: 'P' numeric or pointer
43049: */
43050: {
43051: Ptype t = this;
43052: if (this == 0) error('i',"type::kind(): this==0");
43053: xx:
43054: switch (t->base) {
43055: case ANY: return 'A';
43056: case ZTYPE: return 'Z';
43057: case FIELD:
43058: case CHAR:
43059: case SHORT:
43060: case INT:
43061: case LONG:
43062: case EOBJ: return 'I';
43063: case FLOAT:
43064: case LDOUBLE:
43065: case DOUBLE: if (v == 'I') error("float operand for %k",oper); return 'F';
43066: case VEC:
43067: case PTR: if (v != 'P') error("P operand for %k",oper);
43068: switch (oper) {
43069: case INCR:
43070: case DECR:
43071: case MINUS:
43072: case PLUS:
43073: case ASMINUS:
43074: case ASPLUS:
43075: if (t->base==PTR
43076: && (Pptr(t)->memof || Pptr(t)->typ->base==FCT))
43077: error("%t operand of%k",this,oper);
43078: else
43079: Pptr(t)->typ->tsizeof(); // get increment
43080: break;
43081: default:
43082: if (t->base==PTR
43083: && (Pptr(t)->memof || Pptr(t)->typ->base==FCT))
43084: error("%t operand of%k",this,oper);
43085: case ANDAND:
43086: case OROR:
43087: case ASSIGN:
43088: case NE:
43089: case EQ:
43090: case IF:
43091: case WHILE:
43092: case DO:
43093: case FOR:
43094: case QUEST:
43095: case NOT:
43096: break;
43097: }
43098: return 'P';
43099: case RPTR: error("R operand for %k",oper); return 'A';
43100: case TYPE: t = Pbase(t)->b_name->tp; goto xx;
43101: case FCT: if (v != 'P') error("F operand for %k",oper); return FCT;
43102: case OVERLOAD: error("overloaded operand for %k",oper); return 'A';
43103: case CLASS:
43104: case ENUM: error("%k operand for %k",base,oper); return 'A';
43105: default: error("%t operand for %k",this,oper); return 'A';
43106: }
43107: }
43108:
43109: void type::dcl(Ptable tbl)
43110: /*
43111: go through the type (list) and
43112: (1) evaluate vector dimensions
43113: (2) evaluate field sizes
43114: (3) lookup struct tags, etc.
43115: (4) handle implicit tag declarations
43116: */
43117: {
43118: static arg_fudge;
43119:
43120: Ptype t = this;
43121:
43122: if (this == 0) error('i',"T::dcl(this==0)");
43123: if (tbl->base != TABLE) error('i',"T::dcl(%d)",tbl->base);
43124:
43125: xx:
43126: //error('d',"type::dcl %k",t->base);
43127: switch (t->base) {
43128: case TYPE:
43129: t = Pbase(t)->b_name->tp;
43130: goto xx;
43131: case PTR:
43132: case RPTR:
43133: { Pptr p = Pptr(t);
43134: t = p->typ;
43135: if (t->base == TYPE) {
43136: Ptype tt = Pbase(t)->b_name->tp;
43137: if (tt->base == FCT) p->typ = tt;
43138: return;
43139: }
43140: goto xx;
43141: }
43142:
43143: case VEC:
43144: { Pvec v = Pvec(t);
43145: Pexpr e = v->dim;
43146: if (e) {
43147: Ptype et;
43148: v->dim = e = e->typ(tbl);
43149: et = e->tp;
43150: if (et->integral(0) == 'A') {
43151: error("UN in array dimension");
43152: }
43153: else {
43154: long i;
43155: Neval = 0;
43156: i = e->eval();
43157: if (Neval == 0) {
43158: if (largest_int<i)
43159: error("array dimension too large");
43160: v->size = int(i);
43161:
43162: if ( lcl_tbl == 0 )
43163:
43164: DEL(v->dim);
43165: v->dim = 0;
43166: }
43167:
43168: if (new_type) {
43169: if (Neval)
43170: ;
43171: else if (i == 0)
43172: v->dim = zero;
43173: else if (i < 0) {
43174: error("negative array dimension");
43175: i = 1;
43176: }
43177: }
43178: else {
43179: if (Neval)
43180: error("%s",Neval);
43181: else if (i == 0)
43182: error('w',"array dimension == 0");
43183: else if (i < 0) {
43184: error("negative array dimension");
43185: i = 1;
43186: }
43187: }
43188: }
43189: }
43190: t = v->typ;
43191: llx:
43192: switch (t->base) {
43193: case TYPE:
43194: t = Pbase(t)->b_name->tp;
43195: goto llx;
43196: case FCT:
43197: v->typ = t;
43198: break;
43199: case VEC:
43200: if (Pvec(t)->dim==0 && Pvec(t)->size==0) error("null dimension (something like [][] seen)");
43201: if (arg_fudge) {
43202: v->base = PTR; // X[12][10] ==> X(*)[10]
43203: Pptr(v)->rdo = 0;
43204: Pptr(v)->memof = 0;
43205: }
43206: }
43207: goto xx;
43208: }
43209:
43210: case FCT:
43211: { Pfct f = Pfct(t);
43212: void dargs(Pname, Pfct, Ptable);
43213: if (f->argtype) dargs(0,f,tbl);
43214: for (Pname n=f->argtype; n; n = n->n_list) {
43215: arg_fudge++;
43216: n->tp->dcl(tbl);
43217: arg_fudge--;
43218: }
43219: Pname cn = f->returns->is_cl_obj();
43220: if (cn && Pclass(cn->tp)->has_itor())
43221: make_res(f);
43222: else if (f->f_this == 0)
43223: f->f_args = f->argtype;
43224: t = f->returns;
43225: goto xx;
43226: }
43227:
43228: case FIELD:
43229: { Pbase f = Pbase(t);
43230: Pexpr e = Pexpr(f->b_name);
43231: long i;
43232: Ptype et;
43233: e = e->typ(tbl);
43234: f->b_name = Pname(e);
43235: et = e->tp;
43236: if (et->integral(0) == 'A') {
43237: error("UN in field size");
43238: i = 1;
43239: }
43240: else {
43241: Neval = 0;
43242: i = e->eval();
43243: if (Neval)
43244: error("%s",Neval);
43245: else if (i < 0) {
43246: error("negative field size");
43247: i = 1;
43248: }
43249: else if (f->b_fieldtype->tsizeof()*BI_IN_BYTE < i)
43250: error("field size > sizeof(%t)",f->b_fieldtype);
43251: DEL(e);
43252: }
43253: f->b_bits = int(i);
43254: f->b_name = 0;
43255: break;
43256: }
43257: }
43258: }
43259:
43260: bit vrp_equiv; // vector == pointer equivalence used in check()
43261: bit const_problem; // types differs only in const
43262: int Vcheckerror;
43263:
43264: bit type::check(Ptype t, TOK oper)
43265: /*
43266: check if "this" can be combined with "t" by the operator "oper"
43267:
43268: used for check of
43269: assignment types (oper==ASSIGN)
43270: declaration compatability (oper==0)
43271: parameterized type formals (oper==255)
43272: as for (oper==0) but
43273: special checking for ANY types
43274: argument types (oper==ARG)
43275: return types (oper==RETURN)
43276: overloaded function name match (oper==OVERLOAD)
43277: overloaded function coercion (oper==COERCE)
43278: virtual function match (oper==VIRTUAL)
43279:
43280: NOT for arithmetic operators
43281:
43282: return 1 if the check failed
43283:
43284: checking of const const* and *const is a mess
43285: */
43286: {
43287: const unsigned int strict_any_check = (oper == 255);
43288:
43289: Ptype t1 = this;
43290: Ptype t2 = t;
43291: Ptype tt1 = this;
43292: Ptype tt2 = t;
43293: int cnst1 = 0;
43294: int cnst2 = 0;
43295: TOK b1, b2;
43296: bit first = 1;
43297: TOK r;
43298: int vv;
43299: int ptr_count = 0;
43300: int fct_seen = 0;
43301: int over;
43302: Pptr p1 = 0;
43303: Pptr p2 = 0;
43304: int p_count = 0;
43305:
43306: if (strict_any_check) oper = 0;
43307:
43308: //error('d',"check %k %t %t",oper,t1,t2);
43309: if (t1==0 || t2==0) error('i',"check(%p,%p,%d)",t1,t2,oper);
43310:
43311: if (oper==VIRTUAL) {
43312: vv = 1;
43313: Vcheckerror = 0;
43314: oper = 0;
43315: }
43316: else
43317: vv = 0;
43318:
43319: if (oper == OVERLOAD) {
43320: over = 1;
43321: oper = 0;
43322: }
43323: else
43324: over = 0;
43325:
43326: const_problem = 0;
43327:
43328: while (t1 && t2) {
43329: top:
43330: //error('d',"top: %t (%d) %t (%d)",t1,t1->base,t2,t2->base);
43331: if (t1 == t2) {
43332: if (cnst1==cnst2) return 0;
43333: if (oper) {
43334: //error('d',"oper %d cnst1 %d cnst2 %d ptr %d",oper,cnst1,cnst2,tt1->is_ptr());
43335: if (tt1 = tt1->is_ptr()) {
43336:
43337: // const* = int*
43338: if (cnst2<cnst1) return 0;
43339:
43340: // int* = int *const
43341: if (cnst2==1 && tt2->tconst()) {
43342: // check for int* = const *const
43343: tt2 = tt2->is_ptr();
43344: if (tt2->tconst()) return 1;
43345: return 0;
43346: }
43347: }
43348: else { // int = const allowed
43349: if (oper==ARG || cnst1<cnst2) return 0;
43350: }
43351: }
43352: else {
43353: if (p_count) {
43354: int pr1 = p1->rdo ? 1 : 0;
43355: int pr2 = p2->rdo ? 1 : 0;
43356: if (pr1+cnst1==pr2+cnst2)
43357: return 0;
43358: }
43359: // const_problem = 1;
43360: }
43361:
43362: const_problem = 1;
43363: return 1;
43364: }
43365:
43366: if ((t1->base == ANY || t2->base == ANY)) {
43367: if (! strict_any_check) return 0;
43368: // Perform the check for strict_any, ie. the
43369: return ((t1 == t2) ? 0 : 1) ;
43370: }
43371:
43372: b1 = t1->base;
43373: switch (b1) {
43374: case TYPE:
43375: if (Pbase(t1)->b_const) cnst1++;
43376: t1 = Pbase(t1)->b_name->tp;
43377: goto top;
43378: }
43379:
43380: b2 = t2->base;
43381: switch (b2) {
43382: case TYPE:
43383: if (Pbase(t2)->b_const) cnst2++;
43384: t2 = Pbase(t2)->b_name->tp;
43385: goto top;
43386: }
43387:
43388: //error('d',"oper %k b1 %k b2 %k",oper,b1,b2);
43389: if (b1 != b2) {
43390: switch (b1) {
43391: case PTR:
43392: switch (b2) {
43393: case VEC:
43394: if (ptr_count) return 1;
43395: // ptr/vec equivalence does not
43396: // apply to declaration matching
43397: t1 = Pptr(t1)->typ;
43398: t2 = Pvec(t2)->typ;
43399: if (oper == 0 && over==0) return 1;
43400: ptr_count++;
43401: first = 0;
43402: goto top;
43403: case FCT:
43404: t1 = Pptr(t1)->typ;
43405: if (t1->base!=VOID)
43406: if (first==0 || t1->base!=b2) return 1;
43407: first = 0;
43408: goto top;
43409: }
43410: first = 0;
43411: break;
43412:
43413: case FCT:
43414: switch( b2 ) {
43415: case PTR:
43416: t2 = Pptr(t2)->typ;
43417: if (t1->base!=VOID
43418: && (first==0||t2->base!=b1)) return 1;
43419: first = 0;
43420: goto top;
43421: }
43422: first = 0;
43423: break;
43424:
43425: case VEC:
43426: switch (b2) {
43427: case PTR:
43428: if (ptr_count) return 1;
43429: t1 = Pvec(t1)->typ;
43430: t2 = Pptr(t2)->typ;
43431: switch (oper) {
43432: case ARG:
43433: case ASSIGN:
43434: case COERCE:
43435: break;
43436: case 0:
43437: if (over) break;
43438: default:
43439: return 1;
43440: }
43441: ptr_count++;
43442: first = 0;
43443: goto top;
43444: }
43445: first = 0;
43446: break;
43447: }
43448: goto base_check;
43449: }
43450:
43451: switch (b1) {
43452: case VEC:
43453: //error('d',"vec %k %d %d",oper,Pvec(t1)->size,Pvec(t2)->size);
43454: if (first==0 && Pvec(t1)->size!=Pvec(t2)->size) return 1;
43455: first = 0;
43456: t1 = Pvec(t1)->typ;
43457: t2 = Pvec(t2)->typ;
43458: ptr_count++;
43459: break;
43460:
43461: case PTR:
43462: case RPTR:
43463: first = 0;
43464: p1 = Pptr(t1);
43465: p2 = Pptr(t2);
43466: p_count++;
43467:
43468: if (p1->memof != p2->memof) {
43469:
43470: if(p1->memof!=0 && p2->memof!=0
43471: && p1->memof->baseof(p2->memof)==0)
43472: return 1;
43473:
43474: int flag1=0,flag2=0;
43475: t1 = p1->typ;
43476: t2 = p2->typ;
43477: while (t1->base == TYPE) {
43478: flag1++;
43479: t1 = Pbase(t1)->b_name->tp;
43480: }
43481: while (t2->base == TYPE) {
43482: flag2++;
43483: t2 = Pbase(t2)->b_name->tp;
43484: }
43485: if (t1 != t2 || (!flag1 && !flag2)) {
43486: if (p1->memof==0
43487: || p2->memof==0
43488: || p1->memof->baseof(p2->memof)==0)
43489: return 1;
43490: Nstd++;
43491: }
43492: }
43493:
43494: t1 = p1->typ;
43495: t2 = p2->typ;
43496: ptr_count++;
43497:
43498: if (oper==0) {
43499: int pr1 = p1->rdo ? 1 : 0;
43500: int pr2 = p2->rdo ? 1 : 0;
43501: if (pr1+cnst1!=pr2+cnst2
43502: && cnst1+Pbase(t1)->b_const!=cnst2+Pbase(t2)->b_const) {
43503: // const_problem only if nothing
43504: // more serious is wrong
43505: if (t1->check(t2,0) == 0) const_problem = 1;
43506: return 1;
43507: }
43508:
43509: if (b1==RPTR && t1->tconst()!=t2->tconst())
43510: const_problem = 1;
43511: }
43512: break;
43513:
43514: case FCT:
43515: first = 0;
43516: { Pfct f1 = Pfct(t1);
43517: Pfct f2 = Pfct(t2);
43518: Pname a1 = f1->argtype;
43519: Pname a2 = f2->argtype;
43520: TOK k1 = f1->nargs_known;
43521: TOK k2 = f2->nargs_known;
43522: int n1 = f1->nargs;
43523: int n2 = f2->nargs;
43524: //error('d',"f1%t f2%t",f1,f2);
43525: if (f1->memof != f2->memof) {
43526: if (f1->memof==0 && f2->f_this==0) //SSS
43527: goto sss;
43528: if (vv == 0) // match even if private base class
43529: if (f1->memof==0
43530: || f2->memof==0
43531: || f1->memof->baseof(f2->memof)==0) return 1;
43532: Nstd++;
43533: sss:; //SSS
43534: }
43535:
43536: if (k1 != k2) return 1;
43537:
43538: if (n1!=n2 && k1 && k2) {
43539: goto aaa;
43540: }
43541: else if (a1 && a2) {
43542: int i = 0;
43543: while (a1 && a2) {
43544: i++;
43545: if (a1->tp->check(a2->tp,over?OVERLOAD:0)) return 1;
43546: a1 = a1->n_list;
43547: a2 = a2->n_list;
43548: }
43549: if (a1 || a2) goto aaa;
43550: }
43551: else if (a1 || a2) {
43552: aaa:
43553: //error('d',"aaa k1 %d k2 %d",k1,k2);
43554: if (k1 == ELLIPSIS) {
43555: switch (oper) {
43556: case 0:
43557: if (a2 && k2==0) break;
43558: return 1;
43559: case ASSIGN:
43560: if (a2 && k2==0) break;
43561: return 1;
43562: case ARG:
43563: if (a1) return 1;
43564: break;
43565: // case OVERLOAD:
43566: case COERCE:
43567: return 1;
43568: }
43569: }
43570: else if (k2 == ELLIPSIS) {
43571: return 1;
43572: }
43573: else if (k1 || k2) {
43574: return 1;
43575: }
43576: }
43577:
43578: t1 = f1->returns;
43579: t2 = f2->returns;
43580: fct_seen = 1;
43581:
43582: switch (oper) { //CCC
43583: case 0:
43584: if (f1->f_const!=f2->f_const) {
43585: if (t1->check(t2,0)==0) const_problem = 1;
43586: return 1;
43587: // if (vv == 0) return 1;
43588: // Vcheckerror = 1;
43589: }
43590: break;
43591: default: // really pointer to function
43592: if (f1->f_const && f2->f_const==0) return 1;
43593: }
43594:
43595:
43596: if (vv && t1->check(t2,0)) { Vcheckerror = 1; return 1; }
43597: }
43598: break;
43599:
43600: case FIELD:
43601: goto field_check;
43602: case CHAR:
43603: case SHORT:
43604: case INT:
43605: case LONG:
43606: goto int_check;
43607: case FLOAT:
43608: case DOUBLE:
43609: case LDOUBLE:
43610: goto float_check;
43611: case EOBJ:
43612: goto enum_check;
43613: case COBJ:
43614: goto cla_check;
43615: case ZTYPE:
43616: case VOID:
43617: return 0;
43618: default:
43619: error('i',"T::check(o=%d %d %d)",oper,b1,b2);
43620: }
43621: }
43622:
43623: if (t1 || t2) {
43624: const_problem = 0; // not a problem: the type itself is bad
43625: return 1;
43626: }
43627: return 0;
43628:
43629: field_check:
43630: switch (oper) {
43631: case 0:
43632: case ARG:
43633: error('i',"check field?");
43634: }
43635: return 0;
43636:
43637: enum_check:
43638: //error('d',"enum check %t %t",t1,t2);
43639: if (Pbase(t1)->b_name->tp != Pbase(t2)->b_name->tp) goto base_check;
43640: goto const_check;
43641:
43642: float_check:
43643: if (first==0 && b1!=b2 && b2!=ZTYPE) return 1;
43644: // no break
43645:
43646: int_check:
43647: //error('d',"int_check");
43648: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) {
43649: if (first == 0) return 1;
43650: if (oper /*&& oper!=OVERLOAD*/)
43651: Nstd++;
43652: else
43653: return 1;
43654: }
43655: // no break
43656:
43657: const_check:
43658: //error('d',"const_check %t (%d) %t (%d)",t1,t1->tconst(),t2,t2->tconst());
43659: if (oper==0) {
43660: //error('d',"oper==0: t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
43661: if (t1->tconst()+cnst1!=t2->tconst()+cnst2) {
43662: const_problem = 1;
43663: return 1;
43664: }
43665: }
43666: else if (first==0) {
43667: if (t1->tconst()+cnst1==0 && t2->tconst()+cnst2) {
43668: //error('d',"t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
43669: //error('d',"tt1 %t %d cnst1 %d cnst2 %d",tt1,tt1->is_ptr(),cnst1,cnst2);
43670: //error('d',"tt2 %t",tt2);
43671: if (tt1->is_ptr()) {
43672: if (fct_const || vec_const) cnst2--;
43673:
43674: // const* = int*
43675: if (cnst2-tt2->tconst()<cnst1-tt1->tconst()) return 0;
43676:
43677: // int* = *const
43678: //if (cnst2==1 && tt2->tconst()) return 0;
43679:
43680: // const T* = const T*
43681: if (t2->tconst()+cnst2==t1->tconst()+cnst1) return 0;
43682: }
43683: else { // int = const allowed
43684: if (cnst1<cnst2) return 0;
43685: }
43686: const_problem = 1;
43687: return 1;
43688: }
43689: else { // const* vs int *const
43690: /*
43691: //error('d',"t1 %t cnst1 %d t2 %t cnst2 %d",t1,cnst1,t2,cnst2);
43692: if (tt1->is_ptr()) {
43693: int tt1c = tt1->tconst();
43694: int tt2c = tt2->tconst() - fct_const - vec_const;
43695: //error('d',"tt1c %d tt2c %d",tt1c,tt2c);
43696: if (tt1c<tt2c) return 1;
43697: int t1c = t1->tconst();
43698: int t2c = t2->tconst() - fct_const - vec_const;
43699: //error('d',"t1c %d t2c %d",t1c,t2c);
43700: if (cnst1+t1c<cnst2+t2c) return 1;
43701: if (tt2c<tt1c // *const = *
43702: && cnst1+t1c>cnst2+t2c) // T = constT
43703: return 1;
43704: }
43705: */
43706:
43707: }
43708: }
43709: else {
43710: //error('d',"first t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
43711: }
43712: //error('d',"return 0");
43713: return 0;
43714:
43715: cla_check:
43716: { Pname n1 = Pbase(t1)->b_name;
43717: Pname n2 = Pbase(t2)->b_name;
43718: //error('d',"cla_check %n %n ptr_count %d",n1,n2,ptr_count);
43719: if (n1 == n2) goto const_check;
43720:
43721: // once again, a more comprehensive check for classes,
43722: // since they may be parametrized.
43723: if ((t1->base == COBJ) && (t2->base == COBJ) &&
43724: ((Pclass(n1->tp)->same_class(Pclass(n2->tp)))))
43725: goto const_check;
43726:
43727: if (/*first || */1<ptr_count || fct_seen) return 1;
43728:
43729: switch (oper) {
43730: case ARG:
43731: case ASSIGN:
43732: case RETURN:
43733: case COERCE:
43734: {
43735: ppbase = PUBLIC;
43736: if (Pclass(n2->tp)->is_base(n1->string)) {
43737: if (ppbase!=PUBLIC) {
43738: const_problem = 0;
43739: // vrp_equiv = 0;
43740: return 1; // private or protected base
43741: }
43742: Nstd++;
43743: goto const_check;
43744: }
43745: }
43746: // no break
43747: case 0:
43748: case OVERLOAD:
43749: const_problem = 0;
43750: // vrp_equiv = 0;
43751: return 1;
43752: }
43753:
43754: goto const_check;
43755: }
43756:
43757: base_check:
43758: //error('d',"base_check t1=%t t2=%t oper=%d %s",t1,t2,oper,first?"first":"");
43759: //error('d',"ptr_count %d",ptr_count);
43760: if (oper)
43761: if (first || 1!=ptr_count) {
43762: if (b1==VOID || b2==VOID) return 1;
43763: }
43764: else {
43765: if (b1 == VOID) { // check for void* = T*
43766: register Ptype tpx = this;
43767: tpxloop:
43768: switch (tpx->base) { // t1 == void*
43769: default:
43770: const_problem = 0;
43771: return 1;
43772: case VOID: break;
43773: case PTR:
43774: case VEC: tpx = Pvec(tpx)->typ;
43775: goto tpxloop;
43776: case TYPE: tpx = Pbase(tpx)->b_name->tp;
43777: goto tpxloop;
43778: }
43779:
43780: tpx = t;
43781: bloop:
43782: switch (tpx->base) { // t2 == T*
43783: default:
43784: const_problem = 0;
43785: return 1;
43786: case VEC:
43787: case PTR:
43788: case FCT: Nstd++;
43789: // return 0;
43790: goto const_check; // prevent void* = const*
43791: case TYPE: tpx = Pbase(tpx)->b_name->tp;
43792: goto bloop;
43793: }
43794: }
43795:
43796: if (b2 != ZTYPE) {
43797: const_problem = 0;
43798: return 1;
43799: }
43800: }
43801: //error('d',"oper %d b1 %d b2 %d cp %d",oper,b1,b2,const_problem);
43802: switch (oper) {
43803: case 0:
43804: if (b1 != b2) {
43805: const_problem = 0; // we have a bigger problem
43806: // vrp_equiv = 0;
43807: }
43808: return 1;
43809: case COERCE: // could probably be merged with the cases below
43810: switch (b1) {
43811: case EOBJ:
43812: case ZTYPE:
43813: case CHAR:
43814: case SHORT:
43815: case INT:
43816: switch (b2) {
43817: case LONG:
43818: case FLOAT:
43819: case DOUBLE:
43820: case LDOUBLE:
43821: case EOBJ:
43822: case ZTYPE:
43823: case CHAR:
43824: case SHORT:
43825: case INT:
43826: case FIELD:
43827: Nstd++;
43828: suppress_error++;
43829: if (b1 == EOBJ) echeck(t1,t2);
43830: suppress_error--;
43831: goto const_check;
43832: }
43833: return 1;
43834: case LONG: // char, short, and int promotes to long
43835: switch (b2) {
43836: case FLOAT:
43837: case DOUBLE:
43838: case LDOUBLE:
43839: case ZTYPE:
43840: case EOBJ:
43841: case CHAR:
43842: case SHORT:
43843: case INT:
43844: case FIELD:
43845: Nstd++;
43846: goto const_check;
43847: }
43848: return 1;
43849: case FLOAT:
43850: // switch (b2) {
43851: // case ZTYPE:
43852: // Nstd++;
43853: // case FLOAT:
43854: // case DOUBLE:
43855: // goto const_check;
43856: // }
43857: // return 1;
43858: case DOUBLE: // char, short, int, and float promotes to double
43859: case LDOUBLE:
43860: switch (b2) {
43861: case LONG:
43862: case ZTYPE:
43863: case EOBJ:
43864: case CHAR:
43865: case SHORT:
43866: case INT:
43867: // Nstd++;
43868: case FLOAT:
43869: case DOUBLE:
43870: case LDOUBLE:
43871: Nstd++;
43872: goto const_check;
43873: }
43874: return 1;
43875: case PTR:
43876: switch (b2) {
43877: case ZTYPE:
43878: Nstd++;
43879: goto const_check;
43880: }
43881: case RPTR:
43882: case VEC:
43883: case COBJ:
43884: case FCT:
43885: return 1;
43886: }
43887: case ARG:
43888: case ASSIGN:
43889: case RETURN:
43890: switch (b1) {
43891: case COBJ:
43892: return 1;
43893: case EOBJ:
43894: case ZTYPE:
43895: case CHAR:
43896: case SHORT:
43897: case INT:
43898: case LONG:
43899: suppress_error++;
43900: r = t2->num_ptr(ASSIGN);
43901: suppress_error--;
43902: switch (r) {
43903: case 'F':
43904: // if (oper!=ARG) error('w',"%t assigned to%t",t2,t1);
43905: break;
43906: case 'A':
43907: case 'P':
43908: case FCT: return 1;
43909: }
43910: if (b1 == EOBJ) echeck(t1,t2);
43911: break;
43912: case FLOAT:
43913: case DOUBLE:
43914: case LDOUBLE:
43915: suppress_error++;
43916: r = t2->numeric(ASSIGN);
43917: suppress_error--;
43918: switch (r) {
43919: case 'A':
43920: case 'P':
43921: case FCT: return 1;
43922: }
43923: break;
43924: case VEC:
43925: if(oper==ARG && b2==ZTYPE) goto const_check;
43926: return 1;
43927: case PTR:
43928: suppress_error++;
43929: r = t2->num_ptr(ASSIGN);
43930: suppress_error--;
43931: switch (r) {
43932: case 'A':
43933: case 'I':
43934: case 'F': return 1;
43935: case FCT: if (Pptr(t1)->typ->base != FCT) return 1;
43936: }
43937: break;
43938: case RPTR:
43939: return 1;
43940: case FCT:
43941: switch (oper) {
43942: case ARG:
43943: case ASSIGN:
43944: return 1;
43945: }
43946: }
43947: break;
43948: }
43949: goto const_check;
43950: }
43951:
43952: 0707071010112045731004440001630000160000010210500466055413100000700000022542typ2.c /*ident "@(#)ctrans:src/typ2.c 1.3" */
43953: /**************************************************************************
43954:
43955: C++ source for cfront, the C++ compiler front-end
43956: written in the computer science research center of Bell Labs
43957:
43958: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
43959: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
43960:
43961: typ2.c:
43962:
43963: ***************************************************************************/
43964:
43965: #include "cfront.h"
43966: #include "size.h"
43967:
43968: extern int chars_in_largest;
43969: int largest_int;
43970:
43971: void typ_init()
43972: {
43973: chars_in_largest = strlen(LARGEST_INT);
43974: largest_int = int(str_to_long(LARGEST_INT));
43975:
43976: defa_type = new basetype(INT,0); // note defa_type!=int_type
43977: int_type = new basetype(INT,0); // but they both represent `int'
43978:
43979: PERM(int_type); int_type->defined = DEFINED ;
43980: PERM(defa_type); defa_type->defined = DEFINED ;
43981:
43982: moe_type = new basetype(INT,0);
43983: PERM(moe_type); moe_type->defined = DEFINED ;
43984: moe_type->b_const = 1;
43985: moe_type->check(0);
43986:
43987: uint_type = new basetype(INT,0);
43988: PERM(uint_type); uint_type->defined = DEFINED ;
43989: uint_type->type_adj(UNSIGNED);
43990: uint_type->check(0);
43991:
43992: long_type = new basetype(LONG,0);
43993: PERM(long_type); long_type->defined = DEFINED ;
43994: long_type->check(0);
43995:
43996: ulong_type = new basetype(LONG,0);
43997: PERM(ulong_type); ulong_type->defined = DEFINED ;
43998: ulong_type->type_adj(UNSIGNED);
43999: ulong_type->check(0);
44000:
44001: short_type = new basetype(SHORT,0);
44002: PERM(short_type); short_type->defined = DEFINED ;
44003: short_type->check(0);
44004:
44005: ushort_type = new basetype(SHORT,0);
44006: PERM(ushort_type); ushort_type->defined = DEFINED ;
44007: ushort_type->type_adj(UNSIGNED);
44008: ushort_type->check(0);
44009:
44010: float_type = new basetype(FLOAT,0);
44011: PERM(float_type); float_type->defined = DEFINED ;
44012:
44013: double_type = new basetype(DOUBLE,0);
44014: PERM(double_type); double_type->defined = DEFINED ;
44015:
44016: ldouble_type = new basetype(LDOUBLE,0);
44017: PERM(ldouble_type); ldouble_type->defined = DEFINED ;
44018:
44019: zero_type = new basetype(ZTYPE,0);
44020: PERM(zero_type); zero_type->defined = DEFINED ;
44021: zero->tp = zero_type;
44022:
44023: void_type = new basetype(VOID,0);
44024: PERM(void_type); void_type->defined = DEFINED ;
44025:
44026: char_type = new basetype(CHAR,0);
44027: PERM(char_type); char_type->defined = DEFINED ;
44028:
44029: uchar_type = new basetype(CHAR,0);
44030: PERM(uchar_type); uchar_type->defined = DEFINED ;
44031: uchar_type->type_adj(UNSIGNED);
44032: uchar_type->check(0);
44033:
44034: Pchar_type = char_type->addrof();
44035: PERM(Pchar_type); Pchar_type->defined = DEFINED ;
44036:
44037: Pint_type = int_type->addrof();
44038: PERM(Pint_type); Pint_type->defined = DEFINED ;
44039:
44040: Pvoid_type = void_type->addrof();
44041: PERM(Pvoid_type); Pvoid_type->defined = DEFINED ;
44042:
44043: Pfctvec_type = new fct(int_type,0,0); // must be last, see basetype::normalize()
44044: Pfctvec_type = Pfctvec_type->addrof();
44045: Pfctvec_type = Pfctvec_type->addrof();
44046: PERM(Pfctvec_type); Pfctvec_type->defined = DEFINED ;
44047:
44048: gtbl = new table(GTBLSIZE,0,0);
44049: gtbl->t_name = new name("global");
44050: ptbl = new table(CTBLSIZE,0,0);
44051: ptbl->t_name = new name("ptbl");
44052: }
44053:
44054: bit enum_promote;
44055:
44056: Pbase basetype::arit_conv(Pbase t)
44057: /*
44058: perform the "usual arithmetic conversions" C ref Manual 6.6
44059: on "this" op "t"
44060: "this" and "t" are integral or floating
44061: "t" may be 0
44062: */
44063: {
44064: while (base == TYPE) this = Pbase(Pbase(this)->b_name->tp);
44065: // error('d', "arit_conv: this: %k %d %t %d", base, base, this, this );
44066:
44067: bit l;
44068: bit u;
44069: bit f;
44070: bit l1 = (base == LONG);
44071: bit u1 = b_unsigned;
44072: bit f1 = (base==FLOAT || base==DOUBLE || base==LDOUBLE);
44073: if (t) {
44074: while (t->base == TYPE) t = Pbase(Pbase(t)->b_name->tp);
44075: // error('d', "arit_conv: t: %k %d %t %d", t->base, t->base, t, t );
44076:
44077: bit l2 = (t->base == LONG);
44078: bit u2 = t->b_unsigned;
44079: bit f2 = (t->base==FLOAT || t->base==DOUBLE || base==LDOUBLE);
44080: l = l1 || l2;
44081: u = u1 || u2;
44082: f = f1 || f2;
44083: }
44084: else {
44085: l = l1;
44086: u = u1;
44087: f = f1;
44088: }
44089:
44090: if (f) {
44091: if (base==LDOUBLE || (t && t->base==LDOUBLE)) return ldouble_type;
44092: if (base==DOUBLE || (t && t->base==DOUBLE)) return double_type;
44093: return float_type;
44094: }
44095: if (l & u) return ulong_type;
44096: if (l & !u) return long_type;
44097: if (u) {
44098: if (base==INT || (t && t->base==INT)) return uint_type;
44099: if (SZ_SHORT==SZ_INT) // ANSIism
44100: if (base==SHORT || (t && t->base==SHORT)) return uint_type;
44101: return int_type;
44102: }
44103:
44104: if (t && t->base == EOBJ && base == EOBJ) enum_promote = 1;
44105: return int_type;
44106: }
44107:
44108: bit vec_const = 0;
44109: bit fct_const = 0;
44110:
44111: bit type::tconst()
44112: /*
44113: is this type a constant
44114: */
44115: {
44116: Ptype t = this;
44117: vec_const = 0;
44118: fct_const = 0;
44119: //error('d',"tconst %t",t);
44120: xxx:
44121: switch (t->base) {
44122: case TYPE:
44123: if (Pbase(t)->b_const) return 1;
44124: t = Pbase(t)->b_name->tp;
44125: goto xxx;
44126: case VEC:
44127: vec_const = 1;
44128: return 1;
44129: case PTR:
44130: case RPTR:
44131: return Pptr(t)->rdo;
44132: case FCT:
44133: case OVERLOAD:
44134: fct_const = 1;
44135: return 1;
44136: default:
44137: return Pbase(t)->b_const;
44138: }
44139: }
44140:
44141: TOK type::set_const(bit mode)
44142: /*
44143: make someting a constant or variable, return old status
44144: */
44145: {
44146: Ptype t = this;
44147: int m;
44148: xxx:
44149: switch (t->base) {
44150: case TYPE:
44151: m = Pbase(t)->b_const;
44152: Pbase(t)->b_const = mode;
44153: t = Pbase(t)->b_name->tp;
44154: goto xxx;
44155: case ANY:
44156: case RPTR:
44157: case VEC:
44158: return t->base; // constant by definition
44159: case PTR:
44160: m = Pptr(t)->rdo;
44161: Pptr(t)->rdo = mode;
44162: return m;
44163: default:
44164: m = Pbase(t)->b_const;
44165: Pbase(t)->b_const = mode;
44166: return m;
44167: }
44168: }
44169:
44170: Pptr type::is_ref()
44171: {
44172: Ptype t = this;
44173: xxx:
44174: switch (t->base) {
44175: case TYPE: t = Pbase(t)->b_name->tp; goto xxx;
44176: case RPTR: return Pptr(t);
44177: default: return 0;
44178: }
44179: }
44180:
44181: Pclass Mptr;
44182:
44183: Pptr type::is_ptr()
44184: {
44185: Ptype t = this;
44186: xxx:
44187: switch (t->base) {
44188: case TYPE: t = Pbase(t)->b_name->tp; goto xxx;
44189: case PTR:
44190: case VEC: Mptr = Pptr(t)->memof;
44191: return Pptr(t);
44192: default: return 0;
44193: }
44194: }
44195:
44196: Pptr type::is_ptr_or_ref()
44197: {
44198: Ptype t = this;
44199: xxx:
44200: switch (t->base) {
44201: case TYPE: t = Pbase(t)->b_name->tp; goto xxx;
44202: case PTR:
44203: case RPTR:
44204: case VEC: Mptr = Pptr(t)->memof;
44205: return Pptr(t);
44206: default: return 0;
44207: }
44208: }
44209:
44210: int type::align()
44211: {
44212: Ptype t = this;
44213: xx:
44214: /*fprintf(stderr,"align %d %d\n",t,t->base);*/
44215: switch (t->base) {
44216: case TYPE: t = Pbase(t)->b_name->tp; goto xx;
44217: case COBJ: t = Pbase(t)->b_name->tp; goto xx;
44218: case VEC: t = Pvec(t)->typ; goto xx;
44219: case ANY: return 1;
44220: case CHAR: return AL_CHAR;
44221: case SHORT: return AL_SHORT;
44222: case INT: return AL_INT;
44223: case LONG: return AL_LONG;
44224: case FLOAT: return AL_FLOAT;
44225: case DOUBLE: return AL_DOUBLE;
44226: case LDOUBLE: return AL_LDOUBLE;
44227: case PTR:
44228: case RPTR: return AL_WPTR;
44229: case CLASS: return Pclass(t)->obj_align;
44230: case ENUM:
44231: case EOBJ: return AL_INT;
44232: case VOID: error("illegal use of void"); return AL_INT;
44233: default: error('i',"(%d,%k)->type::align",t,t->base);
44234: }
44235: }
44236:
44237: bit fake_sizeof;
44238:
44239: int type::tsizeof(int ptmc)
44240: /*
44241: the sizeof type operator
44242: return the size in bytes of the types representation
44243: */
44244: {
44245: Ptype t = this;
44246: zx:
44247: //error('d',"zx %t %d",t,t->base);
44248: if (t == 0) error('i',"typ.tsizeof(t==0)");
44249: switch (t->base) {
44250: case TYPE:
44251: t = Pbase(t)->b_name->tp;
44252: goto zx;
44253: case COBJ:
44254: t = Pbase(t)->b_name->tp;
44255: if (t == 0) return 0; // ``fake'' generated classes: _Sdd
44256: goto zx;
44257:
44258: case ANY: return 1;
44259: case VOID: return 0;
44260: case ZTYPE: return SZ_WPTR; /* assume pointer */
44261: case CHAR: return SZ_CHAR;
44262: case SHORT: return SZ_SHORT;
44263: case INT: return SZ_INT;
44264: case LONG: return SZ_LONG;
44265: case FLOAT: return SZ_FLOAT;
44266: case DOUBLE: return SZ_DOUBLE;
44267: case LDOUBLE: return SZ_LDOUBLE;
44268:
44269: case VEC:
44270: { Pvec v = Pvec(t);
44271: if (v->size == 0) {
44272: if (fake_sizeof == 0) error('w',"sizeof array with undeclared dimension");
44273: return SZ_WPTR; // vector argument has sizeof ptr
44274: }
44275: return v->size * v->typ->tsizeof();
44276: }
44277: case RPTR:
44278: case PTR:
44279: {
44280: int k = (Pptr(t)->memof && !ptmc)?sizeof(short)+sizeof(short):0;
44281: t = Pptr(t)->typ;
44282: xxx:
44283: switch (t->base) {
44284: default: return SZ_WPTR;
44285: case CHAR: return SZ_BPTR;
44286: case FCT: return SZ_WPTR+k;
44287: case TYPE: t = Pbase(t)->b_name->tp; goto xxx;
44288: }
44289: }
44290: case FIELD:
44291: error("sizeof(field)");
44292: return Pbase(t)->b_bits/BI_IN_BYTE+1;
44293: case FCT:
44294: error("sizeof(function)");
44295: return 0;
44296:
44297: case CLASS:
44298: {
44299: Pclass cl = Pclass(t);
44300: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
44301: error("%tU, size not known",cl);
44302: return SZ_INT;
44303: }
44304: if (cl->c_body == 1) // detect first allocation or sizeof
44305: cl->dcl_print(0);
44306: return cl->obj_size;
44307: }
44308:
44309: case EOBJ:
44310: case ENUM: return SZ_INT;
44311:
44312: default: return 0; // deref can be called for any type
44313: //error('i',"sizeof(%d)",t->base);
44314: }
44315: }
44316:
44317: bit type::vec_type()
44318: {
44319: Ptype t = this;
44320: xx:
44321: switch (t->base) {
44322: case ANY:
44323: case VEC:
44324: case PTR:
44325: case RPTR: return 1;
44326: case TYPE: t = Pbase(t)->b_name->tp; goto xx;
44327: default: return 0;
44328: }
44329: }
44330:
44331: int ref_initializer;
44332:
44333: Ptype type::deref()
44334: /* index==1: *p
44335: index==0: p[expr]
44336: */
44337: {
44338: //error('d',"%t -> deref() refd %d",this,ref_initializer);
44339: Ptype t = this;
44340: xx:
44341: switch (t->base) {
44342: case TYPE:
44343: t = Pbase(t)->b_name->tp;
44344: goto xx;
44345: case PTR:
44346: case RPTR:
44347: case VEC:
44348: { if (t == Pvoid_type) error("void* dereferenced");
44349: Ptype tt = t = Pvec(t)->typ;
44350: if (ref_initializer == 0) {
44351: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
44352: if (tt->base == COBJ) {
44353: tt = Pbase(tt)->b_name->tp;
44354: if (tt && Pclass(tt)->defined&(DEFINED|SIMPLIFIED))
44355: (void) t->tsizeof();
44356: }
44357: }
44358: // no break
44359: }
44360: case ANY:
44361: return t;
44362: default:
44363: error("nonP dereferenced");
44364: return any_type;
44365: }
44366: }
44367:
44368: Pfct type::memptr()
44369: // is ``this'' a pointer to member function
44370: {
44371: Ptype t = this;
44372: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
44373: if (t->base != PTR || Pptr(t)->memof==0) return 0;
44374:
44375: t = Pptr(t)->typ;
44376: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
44377: return (t->base == FCT) ? Pfct(t) : 0;
44378: }
44379: 0707071010112045741004440001630000160000010177160466055413400001200000002731typedef.h /*ident "@(#)ctrans:src/typedef.h 1.2" */
44380: /**************************************************************************
44381:
44382: C++ source for cfront, the C++ compiler front-end
44383: written in the computer science research center of Bell Labs
44384:
44385: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
44386: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
44387:
44388: typedef.h:
44389:
44390: *****************************************************************************/
44391:
44392: typedef unsigned char TOK;
44393: typedef unsigned char bit; // sometimes used as bits
44394: typedef class node * PP;
44395: typedef int (*PFI)();
44396: typedef void (*PFV)();
44397: typedef class node * Pnode;
44398: typedef struct key * Pkey;
44399: typedef class name * Pname;
44400: typedef class basetype * Pbase;
44401: typedef class basecl* Pbcl;
44402: typedef class type * Ptype;
44403: typedef class fct * Pfct;
44404: typedef class field * Pfield;
44405: typedef class expr * Pexpr;
44406: typedef class qexpr * Pqexpr;
44407: typedef class texpr * Ptexpr;
44408: typedef class classdef * Pclass;
44409: typedef class enumdef * Penum;
44410: typedef class stmt * Pstmt;
44411: typedef class estmt * Pestmt;
44412: typedef class tstmt * Ptstmt;
44413: typedef class vec * Pvec;
44414: typedef class ptr * Pptr;
44415: typedef class block * Pblock;
44416: typedef class table * Ptable;
44417: typedef struct loc Loc;
44418: typedef class call * Pcall;
44419: typedef class gen* Pgen;
44420: typedef class ref * Pref;
44421: typedef class name_list * Plist;
44422: typedef class iline * Pin;
44423: typedef class nlist * Pnlist;
44424: typedef class slist * Pslist;
44425: typedef class elist * Pelist;
44426: typedef class virt * Pvirt;
44427: typedef char* Pchar;
44428:
44429: 0707071010112045751004440001630000160000010201670466055413700001200000001374yystype.h /*ident "@(#)ctrans:src/yystype.h 1.2" */
44430: /**************************************************************************
44431:
44432: C++ source for cfront, the C++ compiler front-end
44433: written in the computer science research center of Bell Labs
44434:
44435: Copyright (c) 1984 AT&T, Inc. All Rights Reserved
44436: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
44437:
44438: yystype:
44439:
44440: *****************************************************************************/
44441:
44442: typedef union {
44443: char* s;
44444: TOK t;
44445: int i;
44446: loc l;
44447: Pname pn;
44448: Ptype pt;
44449: Pexpr pe;
44450: Pstmt ps;
44451: Pbase pb;
44452: Pnlist nl;
44453: Pslist sl;
44454: Pelist el;
44455: Pbcl pbc;
44456: Pptr pp;
44457: PP p; // fudge: pointer to all class node objects
44458: Plist pl; // fudge: pointer to all class node objects
44459: } YYSTYPE;
44460: extern YYSTYPE yylval;
44461: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects
44462: } YYSTYPE;
44463: extern YYSTYPE yylval;
44464: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects
44465: } YYSTYPE;
44466: extern YYSTYPE yylval;
44467: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects
44468: } YYSTYPE;
44469: extern YYSTYPE yylval;
44470: 070707101011204575100444000163000016000001020167046
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.