Added package with the documentation and the examples
[lwc.git] / hier.c
blob6b44cb7e03b75b90fa52acf7cc9971a8d381337b
1 #include "global.h"
3 typedef int initID, vtblID;
5 typedef struct member_t {
6 struct member_t *next;
7 Token m, gn;
8 typeID t;
9 } member;
11 typedef struct puredm_t {
12 struct puredm_t *next;
13 Token bt;
14 NormPtr dcls [16];
15 } puredm;
17 typedef struct tconst_t {
18 struct tconst_t *next;
19 Token m, r;
20 } tconst;
22 typedef struct anonunion_t {
23 struct anonunion_t *next;
24 Token n;
25 recID r;
26 } anonunion;
28 typedef struct localtdef_t {
29 struct localtdef_t *next;
30 Token tn, gn;
31 } localtdef;
33 typedef struct {
34 recID to;
35 Token fwd_dcl;
36 initID vti;
37 Token entry;
38 } rtti_downcast;
40 typedef struct {
41 recID ot;
42 bool array;
43 Token obn;
44 } ctorable_t;
46 enum { ASTATUS_NORM, ASTATUS_VIRT, ASTATUS_VIRT2, ASTATUS_FSCKD }; // ancestor.status
48 typedef struct {
49 recID rec;
50 int status;
51 Token *path;
52 recID vbase;
53 Token *cpath;
54 bool zero_displace;
55 bool direct;
56 int depth;
57 } ancestor;
59 enum { AU_STATUS_ND, AU_STATUS_DD, AU_STATUS_NU, AU_STATUS_PV, AU_STATUS_PEND }; // autofunc.status
61 typedef struct autofunct_t {
62 struct autofunct_t *next;
63 Token name;
64 typeID *arglist;
65 Token dname, fname, pname;
66 int status;
67 bool virtual;
68 NormPtr dclPtr;
69 Token *proto, *argv;
70 typeID type;
71 } autofunc;
73 enum { OK_CAN, CANT_INCOMPL, CANT_PUREV, CANT_NUFO }; // structure.caninst
75 typedef struct {
76 Token name;
77 Token *code;
79 bool notunion, incomplete, deftype, class;
80 Token dtor_name;
81 bool has_dtor, dtor_nothrow;
82 bool has_dtorable, autodtor;
83 bool unwind, noctor, evt;
84 Token idtor, vdtor;
86 Token keyfunc;
87 bool havekey;
89 bool used, printed, vt_inthis;
91 // object has const members
92 bool constd;
94 typeID type_pthis;
95 member *firstmember, *lastmember;
97 // pure data members
98 puredm *pm;
100 // member function space
101 fspace Funcs;
103 // anonymous unions
104 anonunion *anonunions;
105 int nanons;
107 // depends on declaration of these
108 recID *depends;
110 // ancestors
111 ancestor *ancestors;
113 // auto functions
114 autofunc *autofuncs;
116 // class constants
117 tconst *consts;
119 // virtual table initializers
120 initID *vtis;
122 // local typedefs
123 localtdef *ltdef;
125 // has virtual ancestors
126 bool has_vbase, has_vbase2;
128 // downcast info for virtual inheritance
129 rtti_downcast *rtti;
130 bool need_recalc_offsets;
131 bool have_vi_decls;
133 // members that need vt initialization
134 ctorable_t *ctorables;
135 bool ancestors_have_ctors;
137 // can instantiate object
138 int caninst;
140 // class is merely an alias?
141 recID alias_class;
142 } structure;
144 static structure *structs;
146 /******************************************************************************
148 database of structures, members and hierarchies
150 ******************************************************************************/
152 #define STAR_IF(x) x ? '*' : BLANKT
153 #define COMMA_IF(x) x ? ',' : BLANKT
154 #define ADDR_IF(x) x ? '&' : BLANKT
155 #define DOT_IF(x) x ? '.' : BLANKT
156 #define POINTSAT_IF(x) x ? POINTSAT : BLANKT
157 #define CONST_IF(x) (x) ? RESERVED_const : BLANKT
158 #define STATIC_IF(x) (x) ? RESERVED_static : BLANKT
160 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
161 // structure structs
162 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
164 #ifdef DEBUG
165 static void show_ancest (recID r)
167 int i;
169 ancestor *a = structs [r].ancestors;
170 PRINTF ("Ancestors of "COLS"%s"COLE"\n", SNM (r));
172 for (i = 0; a [i].rec != -1; i++) {
174 PRINTF (" ["COLS"%s"COLE"]", SNM (a [i].rec));
176 if (a [i].status == ASTATUS_VIRT)
177 PRINTF ("\t[virtual"COLS" %s"COLE"]\n\t"COLS, SNM (a [i].vbase));
178 else if (a [i].status == ASTATUS_VIRT2)
179 PRINTF ("\t[virtual"COLS" %s"COLE"] "COLS"-no data-"COLE"\n\t"COLS, SNM (a [i].vbase));
180 else if (a [i].status == ASTATUS_FSCKD)
181 PRINTF (" -"COLS"* fsckd *"COLE" -\n\t"COLS);
182 else PRINTF ("\n\t"COLS);
184 INTPRINT (a [i].path);
186 if (a [i].cpath) {
188 PRINTF (COLE"\n Dirct\t"COLS);
189 INTPRINT (a [i].cpath);
193 PRINTF (COLE"\n");
196 #endif
198 static inline bool vparent (int i)
200 return in2 (i, ASTATUS_VIRT, ASTATUS_VIRT2);
203 inline bool direct_ancest (ancestor*);
204 #include "vtbl.ch"
206 inline bool direct_ancest (ancestor *a)
208 return a->direct;
211 static ctorable_t *add_ctorable (recID r)
213 if (!structs [r].ctorables) {
214 structs [r].ctorables = (ctorable_t*) malloc (2 * sizeof (ctorable_t));
215 structs [r].ctorables [1].ot = -1;
216 return &structs [r].ctorables [0];
219 int i;
221 for (i = 0; structs [r].ctorables [i].ot != -1; i++);
223 structs [r].ctorables = (ctorable_t*) realloc (structs [r].ctorables, (i + 2) * sizeof (ctorable_t));
224 structs [r].ctorables [i + 1].ot = -1;
226 return &structs [r].ctorables [i];
229 static autofunc *add_autofunc (recID r)
231 autofunc *a = (autofunc*) malloc (sizeof * a);
232 a->next = structs [r].autofuncs;
233 return structs [r].autofuncs = a;
236 Token add_anonymous_union (recID r, recID u)
238 anonunion *a = (anonunion*) malloc (sizeof * a);
239 a->next = structs [r].anonunions;
240 a->r = u;
241 structs [r].anonunions = a;
242 return a->n = name_anon_union (structs [r].nanons++, name_of_struct (r));
245 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
246 // class constants
247 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
249 Token lookup_class_const (recID r, Token m)
251 tconst *t;
252 for (t = structs [r].consts; t; t = t->next)
253 if (t->m == m) return t->r;
254 return -1;
257 void enter_class_const (recID r, Token m, Token re)
259 tconst *t;
261 if (!structs [r].consts) {
262 structs [r].consts = (tconst*) malloc (sizeof (tconst));
263 structs [r].consts->m = m;
264 structs [r].consts->r = re;
265 structs [r].consts->next = 0;
266 return;
269 for (t = structs [r].consts; t; t = t->next)
270 if (t->m == m) {
271 t->r = re;
272 return;
275 t = (tconst*) malloc (sizeof (tconst));
276 t->next = structs [r].consts;
277 t->m = m;
278 t->r = re;
279 structs [r].consts = t;
282 static void inherit_class_consts (recID r)
284 tconst *t;
285 ancestor *a;
287 for (a = structs [r].ancestors; a->rec != -1; a++)
288 if (direct_ancest (a))
289 for (t = structs [a->rec].consts; t; t = t->next)
290 enter_class_const (r, t->m, t->r);
293 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
294 // local typedefs
295 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
297 Token add_local_typedef (recID r, Token tn)
299 localtdef *t;
301 for (t = structs [r].ltdef; t; t = t->next)
302 if (t->tn == tn)
303 parse_error_toktok (tn, name_of_struct (r), "local typedef redef");
305 t = (localtdef*) malloc (sizeof * t);
306 t->next = structs [r].ltdef;
307 structs [r].ltdef = t;
308 t->tn = tn;
309 return t->gn = name_local_typedef (name_of_struct (r), tn);
312 bool have_local_typedef (recID r, Token tn)
314 localtdef *t;
315 for (t = structs [r].ltdef; t; t = t->next)
316 if (t->tn == tn)
317 return true;
318 return false;
321 static Token typedef_in (recID r, Token tn)
323 localtdef *t;
325 for (t = structs [r].ltdef; t; t = t->next)
326 if (t->tn == tn) return t->gn;
327 return 0;
330 Token lookup_local_typedef (recID r, Token tn)
332 ancestor *a;
333 Token ret, t;
334 int d = 0, d2;
335 bool e = false;
337 ret = typedef_in (r, tn);
338 if (a = structs [r].ancestors)
339 for (; a->rec != -1; a++)
340 if (t = typedef_in (a->rec, tn))
341 if (ret) {
342 d2 = a->depth;
343 if (d2 < d) {
344 ret = t;
345 d = d2;
346 e = false;
347 } else if (d2 == d)
348 e = true;
349 } else {
350 d = a->depth;
351 ret = t;
354 if (e) expr_errort ("Ambiguous local typedef", tn);
356 if (ret && objective.recording)
357 usage_typeID (lookup_typedef (ret));
359 return ret;
362 static Token direct_vparent (recID rd, recID rb)
364 ancestor *a;
366 if (rd == rb) return 0;
368 if ((a = structs [rd].ancestors))
369 for (; a->rec != -1; a++)
370 if (a->rec == rb && a->status == ASTATUS_VIRT
371 && a->path [1] == -1) return a->path [0];
372 return 0;
375 /* generate the code which sets the address of the common shared
376 base class instance to the pointers that are supposed to point to it */
377 static void gen_construction_code_vb (OUTSTREAM o, recID r, Token obj)
379 int i, j;
380 Token *p, m;
381 ancestor *a = structs [r].ancestors;
383 r = aliasclass (r);
384 for (i = 0; a [i].rec != -1; i++)
385 if (a [i].status == ASTATUS_VIRT && a [i].vbase == a [i].rec) {
386 recID vr = a [i].vbase, r2;
387 for (j = 0; a [j].rec != -1; j++)
388 if (!is_aliasclass (a [j].rec))
389 if ((m = direct_vparent (r2 = aliasclass (a [j].rec), vr))) {
390 is_ancestor (r, r2, &p, true);
391 outprintf (o, obj, POINTSAT, ISTR (p),
392 '.', m, '=', -1);
394 if (direct_vparent (r, vr)) {
395 outprintf (o, obj, POINTSAT, a [i].path [0], '=', -1);
397 is_ancestor (r, vr, &p, true);
398 outprintf (o, '&', obj, POINTSAT, ISTR (p), ';', -1);
402 /* construction code in case base obj is just a vtable */
403 static void gen_construction_code_vb2 (OUTSTREAM o, recID r, Token obj)
405 int i, j;
406 Token *p, *p1, *p2;
407 ancestor *a = structs [r].ancestors;
409 r = aliasclass (r);
410 for (i = 0; a [i].rec != -1; i++)
411 if (a [i].status == ASTATUS_VIRT2) {
412 bool hp = 0;
414 p1 = a [i].cpath;
415 for (j = 0; a [j].rec != -1; j++)
416 if (a [j].rec != a [i].rec && direct_ancest (&a [j])
417 && is_ancestor (aliasclass (a [j].rec), a [i].rec, &p, 1)) {
418 p2 = a [j].cpath ?: a [j].path;
419 if (p1 [0] == p2 [0]) continue;
420 outprintf (o, obj, POINTSAT, ISTR (p2), '.',
421 ISTR (p), '.', RESERVED__v_p_t_r_, '=', -1);
422 hp = 1;
425 if (hp) outprintf (o, obj, POINTSAT, ISTR (a [i].cpath), '.',
426 RESERVED__v_p_t_r_, ';', -1);
430 /* generate the code that calls the init function for a ctorable */
431 static void call_init_func (OUTSTREAM o, Token obj, ctorable_t *c, Token *path)
433 if (c->array) outprintf (o, i_call_initialization (c->ot), '(',
434 obj, POINTSAT, ISTR (path), DOT_IF (path [0] != -1), c->obn, ',',
435 RESERVED_sizeof, obj, POINTSAT, ISTR (path),
436 DOT_IF (path [0] != -1), c->obn, '/',
437 RESERVED_sizeof, '(', iRESERVED_struct (c->ot),
438 name_of_struct (c->ot), ')', ')', ';', -1);
439 else outprintf (o, i_call_initialization (c->ot), '(',
440 '&', obj, POINTSAT, ISTR (path), DOT_IF (path [0] != -1),
441 c->obn, ',', RESERVED_1, ')', ';', -1);
444 /* Construct all members that need construction indeed yes */
445 static void gen_member_construction (OUTSTREAM o, recID r, Token obj)
447 int i;
448 ctorable_t *c = structs [r].ctorables;
449 Token nopath [] = { -1 };
450 ancestor *a;
452 if (c) for (i = 0; c [i].ot != -1; i++)
453 call_init_func (o, obj, &c [i], nopath);
455 if (structs [r].ancestors_have_ctors)
456 for (a = structs [r].ancestors; a->rec != -1; a++)
457 if ((c = structs [a->rec].ctorables))
458 for (i = 0; c [i].ot != -1; i++)
459 call_init_func (o, obj, &c [i], a->cpath ?: a->path);
462 void gen_construction_code (OUTSTREAM o, recID r, Token obj)
464 if (structs [r].has_vbase)
465 gen_construction_code_vb (o, r, obj);
466 if (structs [r].vtis)
467 gen_vt_init (o, r, obj, true);
468 if (structs [r].has_vbase2)
469 gen_construction_code_vb2 (o, r, obj);
470 if (structs [r].ctorables || structs [r].ancestors_have_ctors)
471 gen_member_construction (o, r, obj);
473 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
474 // what is this?
475 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
477 static intnode *structtree;
478 static int nstructs, nallocstructs;
480 recID enter_struct (Token e, Token tag, bool unwind, bool noctor, bool evt, bool sclass)
482 intnode *in = intfind (structtree, e);
483 int pt [3] = { nstructs, '*', -1 };
485 if (in) {
486 recID r = in->v.i;
487 if (unwind && !always_unwind (r))
488 structs [r].unwind = true;
489 if (noctor)
490 structs [r].noctor = true;
491 return r;
494 if (nstructs == nallocstructs)
495 structs = (structure*) realloc (structs, (nallocstructs+=96) * sizeof (structure));
496 structs [nstructs].name = e;
497 structs [nstructs].notunion = tag != RESERVED_union;
498 structs [nstructs].deftype = false;
499 structs [nstructs].class = tag == RESERVED_class;
500 structs [nstructs].incomplete = true;
501 structs [nstructs].has_dtor = false;
502 structs [nstructs].idtor = 0;
503 structs [nstructs].vdtor = 0;
504 structs [nstructs].dtor_name = 0;
505 structs [nstructs].dtor_nothrow = false;
506 structs [nstructs].Funcs = 0;
507 structs [nstructs].has_dtorable = false;
508 structs [nstructs].firstmember = 0;
509 structs [nstructs].printed = false;
510 structs [nstructs].unwind = unwind;
511 structs [nstructs].noctor = noctor;
512 structs [nstructs].evt = evt;
513 structs [nstructs].has_vbase = 0;
514 structs [nstructs].has_vbase2 = 0;
515 structs [nstructs].rtti = 0;
516 structs [nstructs].vtis = 0;
517 structs [nstructs].ancestors = 0;
518 structs [nstructs].ctorables = 0;
519 structs [nstructs].autofuncs = 0;
520 structs [nstructs].anonunions = 0;
521 structs [nstructs].ltdef = 0;
522 structs [nstructs].nanons = 0;
523 structs [nstructs].consts = 0;
524 structs [nstructs].caninst = CANT_INCOMPL;
525 structs [nstructs].type_pthis = enter_type (pt);
526 structs [nstructs].used = false;
527 structs [nstructs].code = 0;
528 structs [nstructs].depends = 0;
529 structs [nstructs].ancestors_have_ctors = 0;
530 structs [nstructs].need_recalc_offsets = 0;
531 structs [nstructs].have_vi_decls = 0;
532 structs [nstructs].vt_inthis = false;
533 structs [nstructs].alias_class = nstructs;
534 structs [nstructs].constd = 0;
535 structs [nstructs].pm = 0;
536 structs [nstructs].keyfunc = sclass ? -1 : 0;
537 structs [nstructs].havekey = 0;
538 structs [nstructs].autodtor = 0;
539 union ival i = { i: nstructs };
540 intadd (&structtree, e, i);
541 return nstructs++;
544 void keyfunc_candidate (recID o, Token k)
546 if (!structs [o].keyfunc)
547 //{PRINTF ("Setting keyfunc of "COLS"%s"COLE":%s\n", SNM(o), expand (k));
548 structs [o].keyfunc = k;
552 void possible_keyfunc (recID o, Token k)
554 //PRINTF ("possible %s:%s ", SNM(o), expand(k));
555 if (structs [o].keyfunc == k)
556 //{PRINTF ("-ok-\n");
557 structs [o].havekey = 1;
558 //}else PRINTF ("\n");
561 void set_depend (recID o, recID i)
563 int j = 2;
564 if (structs [o].depends) {
565 for (j = 0; structs [o].depends [j] != -1; j++);
566 j += 2;
569 structs [o].depends = (recID*) realloc (structs [o].depends, j * sizeof (recID));
570 structs [o].depends [j - 2] = i;
571 structs [o].depends [j - 1] = -1;
574 static void export_struct (recID r)
576 int i;
578 if (structs [r].printed) return;
580 if (structs [r].depends)
581 for (i = 0; structs [r].depends [i] != -1; i++)
582 export_struct (structs [r].depends [i]);
584 if (structs [r].vtis)
585 export_virtual_table_declaration (r);
587 if (structs [r].Funcs)
588 export_fspace_lwc (structs [r].Funcs);
590 structs [r].printed = true;
591 if (structs [r].code)
592 outprintf (STRUCTS, ISTR (structs [r].code), -1);
595 void export_structs ()
597 int r;
598 for (r = 0; r < nstructs; r++)
599 export_struct (r);
602 static void commit_auto_functions (recID);
604 /////////////////////////////////////////////////
605 // some things when declaration completes
606 /////////////////////////////////////////////////
608 void remove_struct_from_this (Token *p, recID r)
610 int i, j;
611 if (intchr (p, RESERVED_this)) {
612 for (i = 0; p [i] != RESERVED_this; i++);
613 while (p [i] != RESERVED_struct && p [i] != '(') i--;
614 if (p [i] != '(')
615 intcpy (p + i, p + i + 1);
617 Token sn = name_of_struct (r);
618 for (i = 0; p [i] != -1; p++)
619 if (p [i] == RESERVED_struct && p [i + 1] == sn)
620 for (j = i; p [j] != -1; j++)
621 p [j] = p [j + 1];
624 static void adjust_protos (fspace S, recID r)
626 if (!S) return;
628 funcp *p = (funcp*) S->v.p;
629 for (; p; p = p->next)
630 if (p->prototype && !(p->flagz & FUNCP_MODULAR)) {
631 remove_struct_from_this (p->prototype, r);
632 remove_struct_from_def (p->name);
634 adjust_protos (S->less, r);
635 adjust_protos (S->more, r);
638 static void make_empty_dtor (recID r)
640 Token proto [] = { RESERVED_static, RESERVED_inline, RESERVED_dtor, '(', ')', ';', -1 };
641 SAVE_VAR (CODE, proto);
642 bool haskey = structs [r].keyfunc != 0;
643 struct_declaration (r, 0, 0);
644 if (!haskey && structs [r].keyfunc)
645 structs [r].keyfunc = 0;
646 RESTOR_VAR (CODE);
647 store_define_dtor (structs [r].dtor_name, r);
650 static void study_destruction (recID r)
652 bool b = false, v = false;
653 int i;
654 member *m;
655 ancestor *a = structs [r].ancestors;
657 for (m = structs [r].firstmember; m; m = m->next)
658 if (isstructure (m->t) && has_dtor (base_of (m->t))) {
659 b = true;
660 break;
663 if (a) for (i = 0; a [i].rec != -1; i++)
664 if (vparent (a [i].status)) v = true;
665 else if (direct_ancest (&a [i]) && has_dtor (a [i].rec))
666 b = true;
668 // - vdtor is the destructor that doesn't call the dtors
669 // of the virtual base classes
670 // - idtor calls dtors of dtorable members and vdtors (or normal
671 // dtors in not exist) of direct non virtual parents.
672 // - the real dtor calls vdtor and then calls the dtors
673 // of virtual parents
675 if (b) {
676 if (!structs [r].has_dtor)
677 make_empty_dtor (r);
678 structs [r].idtor = name_intern_dtor (r);
680 if (v) structs [r].vdtor = name_intern_vdtor (r);
683 OUTSTREAM dispatch_vdtor (recID r, OUTSTREAM o)
685 int i;
686 Token *vd = combine_output (o);
687 OUTSTREAM n = new_stream ();
688 ancestor *a = structs [r].ancestors;
690 for (i = 0; vd [i] != '{'; i++)
691 output_itoken (n, vd [i]);
692 outprintf (n, '{', structs [r].vdtor, '(', RESERVED_this, ')', ';', -1);
693 for (i = 0; a [i].rec != -1; i++)
694 if (vparent (a [i].status))
695 outprintf (n, structs [a [i].rec].vdtor ?:
696 structs [a [i].rec].dtor_name, '(',
697 ADDR_IF (a [i].cpath && a [i].cpath [0] != -1), RESERVED_this,
698 POINTSAT_IF ((a [i].cpath ?: a [i].path) [0] != -1),
699 ISTR (a [i].cpath ?: a [i].path), ')', ';', -1);
700 outprintf (n, RESERVED_return, RESERVED_this, ';', '}', -1);
702 intsubst1 (vd, structs [r].dtor_name, structs [r].vdtor);
703 outprintf (INTERNAL_CODE, ISTR (vd), -1);
704 free (vd);
706 return n;
709 void make_intern_dtor (recID r)
711 int i;
712 member *m;
713 ancestor *a = structs [r].ancestors;
714 Token do_alias = HaveAliases ? 0 : -1;
715 #ifdef BROKEN_ALIASES
716 do_alias = -1;
717 #endif
718 recID afcls = 0;
719 OUTSTREAM O = new_stream ();
721 outprintf (O, R(static), R(inline), R(void), structs [r].idtor, '(',
722 iRESERVED_struct (r), name_of_struct (r), '*', R(this), ')', '{', -1);
724 /* call dtors of dtorable data members */
725 for (m = structs [r].firstmember; m; m = m->next)
726 if (isstructure (m->t) && has_dtor (base_of (m->t))) {
727 outprintf (O, dtor_name (base_of (m->t)),
728 '(', '&', RESERVED_this, POINTSAT, m->m, ')', ';', -1);
729 do_alias = -1;
732 /* call vdtors of parents (non virtual parents that is) */
733 if (a) for (i = 0; a [i].rec != -1; i++)
734 if (direct_ancest (&a [i]) && has_dtor (a [i].rec) && !vparent (a [i].status)
735 && !(structs [a [i].rec].autodtor && !idtor (a [i].rec))) {
736 bool dointernal = structs [a [i].rec].autodtor;
737 outprintf (O,
738 /* If this is an auto function call only idtor of parent.
739 else if parent has vbases, call vdtor of parent.
740 else call dtor of parent */
741 dointernal ? idtor (a [i].rec) :
742 structs [a [i].rec].vdtor ?:
743 dtor_name (a [i].rec), '(',
744 ISTR (upcast1_this (r, a [i].rec)), ')', ';', -1);
745 if (do_alias) do_alias = -1;
746 else do_alias = zero_offset (r, a [i].rec) && !dointernal ?
747 dtor_name (afcls = a [i].rec) : -1;
749 output_itoken (O, '}');
751 /* do it with alias if all that has to be done is call the dtor of one parent
752 which is at offset 0 */
753 if (do_alias > 0) {
754 free_stream (O);
755 outprintf (O = new_stream (), R(static), R(inline), R(void), structs [r].idtor, '(',
756 iRESERVED_struct (r), name_of_struct (r), '*', R(this), ')',
757 alias_func (afcls, do_alias), ';', -1);
759 concate_streams (INTERNAL_CODE, O);
762 static void enter_virtuals (recID r, fspace S)
764 funcp *p;
766 for (p = S->v.p; p; p = p->next)
767 if ((p->flagz & FUNCP_VIRTUAL) && p->prototype) {
768 vf_args args;
769 Token *pr;
771 args.r = r;
772 args.fname = S->key;
773 args.ftype = p->type;
774 args.fmemb = p->flagz & FUNCP_PURE ? 0 : p->name;
775 args.flagz = p->flagz;
776 // pass prototype to make fptr from
777 for (pr = p->prototype; ISDCLFLAG (*pr); pr++);
778 args.prototype = allocaint (intlen (pr) + 1);
779 intcpy (args.prototype, pr);
780 intsubst1 (args.prototype, p->name, MARKER);
781 args.argv = allocaint (intlen (p->xargs) + 1);
782 intcpy (args.argv, p->xargs);
783 Enter_virtual_function (&args);
785 if (S->less) enter_virtuals (r, S->less);
786 if (S->more) enter_virtuals (r, S->more);
789 bool do_alias_class (recID r)
791 recID alias = 0, rr;
792 ancestor *a = structs [r].ancestors;
794 if (structs [r].firstmember || structs [r].vt_inthis || !a || structs [r].anonunions)
795 return false;
797 for (; a->rec != -1; a++)
798 if (direct_ancest (a)) {
799 rr = structs [a->rec].alias_class;
800 if (alias && rr != alias)
801 return false;
802 alias = rr;
804 structs [r].alias_class = alias;
805 return true;
808 recID is_aliasclass (recID r)
810 if (structs [r].incomplete && structs [r].class) {
811 structs [r].deftype = true;
812 return -1;
814 return structs [r].alias_class == r ? 0 : structs [r].alias_class;
817 recID aliasclass (recID r)
819 return structs [r].alias_class;
822 static void undo_paths (recID);
824 recID complete_structure (OUTSTREAM o, recID r)
826 structs [r].incomplete = false;
827 study_destruction (r);
828 if (do_alias_class (r)) {
829 undo_paths (r);
830 adjust_protos (structs [r].Funcs, r);
831 structs [r].has_vbase = 0;
832 structs [r].has_vbase2 = 0;
833 } else {
834 if (structs [r].class) {
835 if (structs [r].deftype) outprintf (GLOBAL, RESERVED_typedef,
836 RESERVED_struct, name_of_struct (r), name_of_struct (r), ';', -1);
837 //else outprintf (GLOBAL, RESERVED_struct, name_of_struct (r), ';', -1);
839 if (structs [r].ancestors) make_rtti (r);
841 if (structs [r].Funcs)
842 enter_virtuals (r, structs [r].Funcs);
843 //**+*+*+*+*+*+*+*+*+*+*+*+*
844 close_inits (&structs [r]);
845 mk_typeid (r);
846 if (can_instantiate (r)) {
847 if (structs [r].has_vbase)
848 decl_vballoc_rec (o, r);
850 commit_auto_functions (r);
852 if (structs [r].need_recalc_offsets)
853 fix_all_offsets (r);
854 #ifdef DEBUG
855 if (debugflag.VIRTUALTABLES)
856 show_vt (r);
857 #endif
858 return is_aliasclass (r);
861 #if 0
862 void produce_dtorables (OUTSTREAM o, recID r)
864 member *m;
865 for (m = structs [r].firstmember; m; m = m->next)
866 if (isstructure (m->t) && has_dtor (base_of (m->t)))
867 outprintf (o, structs [base_of (m->t)].dtor_name,
868 '(', '&', RESERVED_this, POINTSAT, m->m, ')', ';', -1);
870 #endif
872 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
873 // parental control
874 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
876 static Token *best_path (Token *p1, Token *p2)
878 int i, c1, c2;
880 if (!p1) return p2;
881 if (!p2) return p1;
883 for (i = c1 = 0; p1 [i] != -1; i++)
884 if (p1 [i] == POINTSAT) c1++;
885 for (i = c2 = 0; p2 [i] != -1; i++)
886 if (p2 [i] == POINTSAT) c2++;
888 if (c1 != c2)
889 return c1 < c2 ? p1 : p2;
891 for (i = c1 = 0; p1 [i] != -1; i++)
892 if (p1 [i] == '.') c1++;
893 for (i = c2 = 0; p2 [i] != -1; i++)
894 if (p2 [i] == '.') c2++;
896 if (c1 != c2)
897 return c1 < c2 ? p1 : p2;
899 i = 0;
900 do if (p1 [i] != p2 [i])
901 return strcmp (expand (p1 [i]), expand (p2 [i])) < 0 ? p1 : p2;
902 while (p1 [i++] != -1);
904 return p1;
907 #if 0
908 /* sort the ancestors from closest to oldest */
909 /* do we really need this? */
910 static void sort_ancestors (recID r)
912 int i, j;
913 ancestor *a, swp;
915 a = structs [r].ancestors;
916 for (i = 0; a [i].rec != -1; i++)
917 for (j = i + 1; a [j].rec != -1; j++)
918 if (intlen (a [i].path) > intlen (a [j].path)) {
919 swp = a [i];
920 a [i] = a [j];
921 a [j] = swp;
924 #endif
926 static Token *ext_path (Token nn, Token *p, bool v)
928 return p ? p [0] == -1 ? sintprintf (mallocint (2), nn, -1) :
929 sintprintf (mallocint (intlen (p)+3), nn, v ? POINTSAT:'.', ISTR (p), -1) : 0;
932 static bool make_ancestors (recID r, recID ps[], recID cvb[])
934 int i, j, t, k, l, c = 0;
935 structure *s;
936 ancestor *a, *a2;
937 bool hv = false, *vr = (bool*) alloca (sizeof (bool) * intlen (ps));
939 for (i = 0; ps [i] != -1; i++) {
940 if ((vr [i] = ps [i] >= VIRTUALPAR_BOOST)) {
941 ps [i] -= VIRTUALPAR_BOOST;
942 hv = true;
944 if (!structs [ps [i]].notunion)
945 parse_error_ll ("cannot inherit a union");
946 if (structs [ps [i]].incomplete)
947 parse_error (0, "You cannot inherit from something unborn");
948 if (structs [ps [i]].constd)
949 structs [r].constd = true;
950 set_depend (r, ps [i]);
953 for (i = 0, t = 1; ps [i] != -1; i++, t++)
954 if ((s = &structs [ps [i]])->ancestors)
955 for (j = 0; s->ancestors [j].rec != -1; j++)
956 t++;
958 a = structs [r].ancestors = (ancestor*) malloc (sizeof (ancestor) * t);
960 /* Somethings like mutliple non-virtual inheritace
961 * of common base class, really ought to be forbidden.
962 * we can parse_error on ASTATUS_FSCKD for that...
964 for (i = t = 0; ps [i] != -1; i++) {
965 recID rr = ps [i];
966 Token nn = name_inherited (name_of_struct (rr));
967 bool V = vr [i], V2;
968 bool zero_offset = i == 0 && !(V && vt_only (rr));
970 s = &structs [rr];
972 for (k = 0; k < t; k++)
973 if (a [k].rec == rr)
974 break;
976 // new ancestor or existing ?
977 if (k < t) {
978 // existing!
979 a [k].direct = true;
980 a [k].depth = 1;
981 V2 = vparent (a [k].status);
982 // both virtual
983 if (V && V2) {
984 a [k].zero_displace = false;
985 if (a [k].vbase != aliasclass (rr))
986 goto really_fsckd1;
987 free (a [k].path);
988 a [k].path = sintprintf (mallocint (2), nn, -1);
989 if (a [k].status == ASTATUS_VIRT2) {
990 free (a [k].cpath);
991 sintprintf (a [k].cpath = mallocint (2), nn, -1);
993 for (l = 0; l < c; l++)
994 if (cvb [l] == rr) break;
995 if (l == c) cvb [c++] = rr;
996 } else really_fsckd1: {
997 a [k].status = ASTATUS_FSCKD;
998 free (a [k].path);
999 a [k].path = sintprintf (mallocint (2), nn, -1);
1001 } else {
1002 a [t].rec = rr;
1003 a [t].status = V ? vt_only (rr) ? ASTATUS_VIRT : ASTATUS_VIRT2 : ASTATUS_NORM;
1004 a [t].zero_displace = zero_offset;
1005 a [t].direct = true;
1006 a [t].path = sintprintf (mallocint (2), nn, -1);
1007 a [t].depth = 1;
1008 if (V) a [t].vbase = aliasclass (rr);
1009 a [t].cpath = a [t].status != ASTATUS_VIRT2 ? 0 : sintprintf (mallocint (2), nn, -1);
1010 ++t;
1011 if (s->ctorables || s->ancestors_have_ctors)
1012 structs [r].ancestors_have_ctors = true;
1015 // add ancestors of ancestor
1016 if ((a2 = s->ancestors))
1017 for (j = 0; a2 [j].rec != -1; j++) {
1020 for (k = 0; k < t; k++)
1021 if (a [k].rec == a2 [j].rec)
1022 break;
1024 if (k < t) {
1025 if (vparent (a [k].status)) {
1026 a [k].zero_displace = false;
1027 if (a2 [j].status == a [k].status) {
1028 if (a [k].vbase != a2 [j].vbase)
1029 goto really_fsckd2;
1030 } else if (V) {
1031 if (a [k].vbase != aliasclass (rr))
1032 goto really_fsckd2;
1033 } else goto really_fsckd2;
1035 for (l = 0; l < c; l++)
1036 if (cvb [l] == a [k].vbase) break;
1037 if (l == c) cvb [c++] = a [k].vbase;
1039 Token *path = ext_path (nn, a2 [j].path, V);
1040 Token *cpath = ext_path (nn, a2 [j].cpath, V);
1042 if (best_path (a [k].path, path) == path) {
1043 free (a [k].path);
1044 a [k].path = path;
1045 } else free (path);
1047 if (cpath)
1048 if (best_path (a [k].cpath, cpath) == cpath) {
1049 if (a [k].cpath) free (a [k].cpath);
1050 a [k].cpath = cpath;
1051 } else free (cpath); else;
1052 } else really_fsckd2:
1053 a [k].status = ASTATUS_FSCKD;
1054 } else {
1055 a [t].rec = a2 [j].rec;
1056 a [t].status = a2 [j].status;
1057 a [t].path = ext_path (nn, a2 [j].path, V);
1058 a [t].vbase = a2 [j].vbase;
1059 a [t].zero_displace = a2 [j].zero_displace && zero_offset;
1060 a [t].depth = a2 [j].depth + 1;
1061 a [t].direct = false;
1062 if (V && !vparent (a2 [j].status)) {
1063 a [t].status = ASTATUS_VIRT;
1064 a [t].vbase = aliasclass (rr);
1066 a [t++].cpath = ext_path (nn, a2 [j].cpath, V);
1070 a [t].rec = -1;
1071 cvb [c] = -1;
1072 // sort_ancestors (r);
1074 for (i = 0; i < t; i++)
1075 if (a [i].status == ASTATUS_VIRT)
1076 structs [r].has_vbase = true;
1077 else if (a [i].status == ASTATUS_VIRT2)
1078 structs [r].has_vbase2 = true;
1079 #ifdef DEBUG
1080 if (debugflag.VIRTUALTABLES) show_ancest (r);
1081 #endif
1082 return hv;
1085 /* If something is an alias class (typedef), undo the path extensions */
1086 static void undo_path (Token *path)
1088 if (path [1] == -1) path [0] = -1;
1089 else intcpy (path, path + 2); // overlap but works
1092 static void undo_paths (recID r)
1094 ancestor *a = structs [r].ancestors;
1095 if (!a) return;
1097 for (; a->rec != -1; a++) {
1098 if (a->path) undo_path (a->path);
1099 if (a->cpath) undo_path (a->cpath);
1103 bool zero_offset (recID rder, recID rbase)
1105 ancestor *a;
1107 for (a = structs [rder].ancestors; a; a++)
1108 if (a->rec == rbase)
1109 return a->zero_displace;
1110 return false;
1113 static void inherit_auto_functions (recID);
1115 void set_parents (recID r, recID ps[])
1117 bool have_virtual_inh;
1118 recID collapsed [16];
1120 if (ps [0] != -1 && !structs [r].notunion)
1121 parse_error_ll ("union cannot be part of a hierarchy");
1123 have_virtual_inh = make_ancestors (r, ps, collapsed);
1124 inherit_all_virtuales (r);
1125 inherit_auto_functions (r);
1126 inherit_class_consts (r);
1127 // if (have_virtual_inh) // this is leftover from surgery while implementing
1128 // make_rtti (r); // aliasclasses. hmmmmmmmmmmmmmmm. who knows?
1129 if (collapsed [0] != -1)
1130 update_dcasts (r, collapsed);
1133 void output_parents (OUTSTREAM o, recID r)
1135 int i, ri = 0, j;
1136 ancestor *a;
1137 recID rp [64], rec;
1138 bool virt;
1140 if (!(a = structs [r].ancestors))
1141 return;
1143 for (i = 0; a [i].rec != -1; i++)
1144 if (direct_ancest (&a [i])) {
1145 if (is_aliasclass (a [i].rec)) {
1146 rec = is_aliasclass (a [i].rec);
1147 for (j = 0; a [j].rec != rec; ++j);;;
1148 virt = a [j].status == ASTATUS_VIRT;
1149 if (virt)
1150 for (j = 0; a [j].rec != -1; j++) {
1151 if (a [j].path [0] == a [i].path [0] && a [j].path [1] == '.')
1152 a [j].path [1] = POINTSAT;
1153 if (a [j].cpath)
1154 if (a [j].cpath [0] == a [i].path [0] && a [j].cpath [1] == '.')
1155 a [j].path [1] = POINTSAT;
1157 } else {
1158 rec = a [i].rec;
1159 virt = a [i].status == ASTATUS_VIRT;
1161 for (j = 0; j < ri; j++)
1162 if (rp [j] == rec) break;
1163 if (j < ri) continue;
1164 rp [ri++] = rec;
1165 outprintf (o, RESERVED_struct, name_of_struct (rec),
1166 STAR_IF (virt), a [i].path [0], ';', -1);
1169 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1170 // general queries
1171 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1173 int lookup_struct (Token e)
1175 intnode *n = intfind (structtree, e);
1176 return n ? n->v.i : 0;
1179 int is_struct (Token e)
1181 intnode *n = intfind (structtree, e);
1182 return n == NULL ? 0 : structs [n->v.i].notunion;
1185 Token name_of_struct (recID r)
1187 return structs [r].name;
1190 typeID pthis_of_struct (recID r)
1192 return structs [r].type_pthis;
1195 fspace FSP (recID r)
1197 return r ? structs [r].Funcs : Global;
1200 bool has_const_members (recID r)
1202 return structs [r].constd || structs [r].vt_inthis;
1204 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1205 // members
1206 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1208 static Token ancest_ptr (ancestor *a)
1210 return a->status == ASTATUS_VIRT && a->vbase == a->rec ? POINTSAT : '.';
1213 static typeID has_member (recID r, Token m, Token path[], Token *glob_name)
1215 member *M;
1217 for (M = structs [r].firstmember; M; M = M->next)
1218 if (M->m == m) {
1219 path [0] = m;
1220 path [1] = -1;
1221 if (glob_name) *glob_name = M->gn;
1222 return M->t;
1225 anonunion *a;
1226 typeID t;
1228 for (a = structs [r].anonunions; a; a = a->next)
1229 if ((t = has_member (a->r, m, path + 2, glob_name)) != -1) {
1230 path [0] = a->n;
1231 path [1] = '.';
1232 return t;
1235 return -1;
1238 typeID lookup_variable_member (recID r, Token m, Token *path, bool const_path, Token *glob_name)
1240 int i;
1241 typeID t, rt = -1;
1242 ancestor *a;
1243 Token p [64], nglob = 0;
1244 bool vptrm = m == RESERVED__v_p_t_r_;
1246 r = aliasclass (r);
1248 if ((t = has_member (r, m, p, glob_name)) != -1) {
1249 rt = t;
1250 if (path) sintprintf (path, ISTR (p), -1);
1253 if ((a = structs [r].ancestors))
1254 for (i = 0; a [i].rec != -1; i++)
1255 if ((t = has_member (a [i].rec, m, p, &nglob)) != -1) {
1256 if (rt != -1 || a [i].status == ASTATUS_FSCKD)
1257 if (base_of (t) == B_PURE) continue;
1258 else if (vptrm)
1259 expr_errort ("Ambiguous vptr for class",
1260 name_of_struct (r));
1261 else expr_errort ("Ambigous member", m);
1262 rt = t;
1263 if (glob_name) *glob_name = nglob;
1264 nglob = 0;
1265 if (path) sintprintf (path,
1266 ISTR (const_path && a [i].cpath ? a [i].cpath : a [i].path),
1267 const_path && a [i].cpath ? '.' : ancest_ptr (&a [i]),
1268 ISTR (p), -1);
1271 return rt;
1274 static bool is_ctorable (typeID t)
1276 return (isstructure (t) && need_construction (base_of (t)))
1277 || is_array_of_ctorable_objects (t);
1280 void add_variable_member (recID r, Token m, typeID t, Token gn, bool constant, bool ncto)
1282 typeID lt;
1284 if (!structs [r].incomplete)
1285 parse_error_ll ("structure closed");
1286 if (m != RESERVED__v_p_t_r_ && (lt = lookup_variable_member (r, m, 0, 0, 0)) != -1
1287 && base_of (lt) != B_PURE)
1288 parse_error_tok (m, "member duplicate");
1289 if (!gn && !ncto && is_ctorable (t)) {
1290 ctorable_t *cc = add_ctorable (r);
1291 cc->ot = base_of (t);
1292 cc->array = !isstructure (t);
1293 cc->obn = m;
1295 if (!gn && !structs [r].constd)
1296 if (constant || isstructure (t) && structs [base_of (t)].constd)
1297 structs [r].constd = true;
1298 member *M = (member*) malloc (sizeof *M);
1299 M->m = m;
1300 M->t = t;
1301 M->gn = gn;
1302 M->next = 0;
1303 if (structs [r].firstmember) {
1304 structs [r].lastmember->next = M;
1305 structs [r].lastmember = M;
1306 } else {
1307 structs [r].firstmember = structs [r].lastmember = M;
1310 // #|#|#|#|#|#|#|#|#|#|#|#|#|#|#
1311 // some stuff
1312 // #|#|#|#|#|#|#|#|#|#|#|#|#|#|#
1314 static bool have_exact_function_member (recID, Token, typeID[], flookup*);
1316 bool has_void_ctor (recID r)
1318 typeID args [] = { pthis_of_struct (r), INTERNAL_ARGEND };
1319 flookup F;
1321 bool re = have_exact_function_member (r, RESERVED_ctor, args, &F);
1322 if (re) SET_MAYTHROW (F);
1323 return re;
1326 bool has_copy_ctor (recID r)
1328 typeID args [] = { pthis_of_struct (r), pthis_of_struct (r), INTERNAL_ARGEND };
1329 flookup F;
1331 bool re = have_exact_function_member (r, RESERVED_ctor, args, &F);
1332 if (re) SET_MAYTHROW (F);
1333 return re;
1336 void set_dfunc (recID r, Token dn, bool nothrow, bool autodtor)
1338 structs [r].dtor_nothrow = nothrow;
1339 structs [r].dtor_name = dn;
1340 structs [r].has_dtor = true;
1341 structs [r].autodtor |= autodtor;
1344 bool isunion (recID r)
1346 return !structs [r].notunion;
1349 bool has_dtor (recID r)
1351 return structs [r].has_dtor;
1354 bool always_unwind (recID r)
1356 return structs [r].unwind;
1359 Token dtor_name (recID r)
1361 if (!structs [r].dtor_nothrow)
1362 may_throw = true;
1363 return structs [r].dtor_name;
1366 void set_dtor_nothrow (recID r)
1368 structs [r].dtor_nothrow = true;
1371 Token idtor (recID r)
1373 return structs [r].idtor;
1376 Token vdtor (recID r)
1378 return structs [r].vdtor;
1381 void set_declaration (recID r, Token *code)
1383 structs [r].code = code;
1386 static bool has_named_func (recID r, Token f)
1388 if (have_function (structs [r].Funcs, f)) return true;
1389 ancestor *a;
1390 if ((a = structs [r].ancestors))
1391 for (; a->rec != -1; a++)
1392 if (have_function (structs [a->rec].Funcs, f))
1393 return true;
1394 return false;
1397 bool has_ctors (recID r)
1399 return has_named_func (r, RESERVED_ctor);
1402 bool has_oper_fcall (recID r)
1404 return has_named_func (r, RESERVED_oper_fcall);
1406 // #+#+#+#+#+#+#+#+#+#+#+#+#
1407 // function members
1408 // #+#+#+#+#+#+#+#+#+#+#+#+#
1410 // lookup a function in parent classes and inherit the useful
1411 // flags: AUTO, VIRTUAL, MODULAR
1412 int inherited_flagz (recID r, Token f, typeID t)
1414 ancestor *a = structs [r].ancestors;
1416 if (!a) return 0;
1418 funcp *p;
1419 int flagz = 0;
1420 typeID *pargl = promoted_arglist_t (t);
1421 typeID *cargv = (typeID*) allocaint (intlen (pargl) + 3);
1422 intcpy (cargv, pargl);
1423 free (pargl);
1425 for (; a->rec != -1; a++) {
1426 cargv [0] = structs [a->rec].type_pthis;
1427 if (p = xlookup_function_dcl (structs [a->rec].Funcs, f, cargv))
1428 flagz |= p->flagz;
1431 return flagz & (FUNCP_AUTO | FUNCP_VIRTUAL | FUNCP_MODULAR);
1434 // lookup function flagz in declarations in class
1435 // useful flags: CONST-THIS, MODULAR, AUTO
1436 int exported_flagz (recID r, Token f, typeID t)
1438 typeID *argv = promoted_arglist_t (t);
1439 funcp *p;
1440 int ret = FUNCP_UNDEF;
1442 if (p = xlookup_function_dcl (structs [r].Funcs, f, argv))
1443 ret = p->flagz & (FUNCP_CTHIS | FUNCP_MODULAR | FUNCP_AUTO);
1444 free (argv);
1445 return ret;
1448 static int looking_for;
1450 static int has_fmember (recID r, Token f, typeID argv[], flookup *F)
1452 if (!structs [r].Funcs) return 0;
1453 argv [0] = structs [r].type_pthis;
1454 return xlookup_function (structs [r].Funcs, f, argv, F) == looking_for;
1457 static bool _lookup_function_member (recID r, Token f, typeID argv[], flookup *F)
1459 int i, lt;
1460 flookup tmp;
1461 recID rt = -1;
1462 ancestor *a;
1464 if (lt = has_fmember (r, f, argv, F))
1465 return true;
1467 if ((a = structs [r].ancestors))
1468 for (i = 0; a [i].rec != -1; i++)
1469 if (lt = has_fmember (a [i].rec, f, argv, &tmp)) {
1470 if (rt == -1 || isancestor (a [i].rec, rt)) {
1471 if (a [i].status == ASTATUS_FSCKD)
1472 goto really_fsckd;
1473 rt = lt == 1 ? a [i].rec : -2;
1474 *F = tmp;
1475 } else if (!isancestor (rt, a [i].rec)) really_fsckd:
1476 expr_errort ("Ambigous member function", f);
1479 if (rt == -1)
1480 return false;
1481 argv [0] = rt >= 0 ? structs [rt].type_pthis : -1;
1482 return true;
1485 int lookup_function_member (recID r, Token f, typeID argv[], flookup *F, bool definite)
1487 looking_for = 3;
1488 if (_lookup_function_member (r, f, argv, F))
1489 return 3;
1491 // global function exact match > member function overload promotion
1492 if (!definite && xlookup_function (Global, f, &argv [1], F) == 3)
1493 return 0;
1495 looking_for = 2;
1496 if (_lookup_function_member (r, f, argv, F))
1497 return 2;
1499 looking_for = 1;
1500 return _lookup_function_member (r, f, argv, F);
1503 static Token has_fmember_uname (recID r, Token f)
1505 if (!structs [r].Funcs) return 0;
1506 return xlookup_function_uname (structs [r].Funcs, f);
1509 Token lookup_function_member_uname (recID *r, Token f)
1511 int i, lt = 0, rr;
1512 recID rt = -1;
1513 ancestor *a;
1515 if (lt = has_fmember_uname (*r, f))
1516 return lt;
1518 if (a = structs [*r].ancestors)
1519 for (i = 0; a [i].rec != -1; i++)
1520 if (rr = has_fmember_uname (a [i].rec, f)) {
1521 if (rt == -1 || isancestor (a [i].rec, rt)) {
1522 if (a [i].status == ASTATUS_FSCKD)
1523 goto really_fsckd;
1524 rt = a [i].rec;
1525 lt = rr;
1526 } else if (!isancestor (rt, a [i].rec)) really_fsckd:
1527 parse_error_tok (f, "Ambigous member function");
1529 *r = rt;
1530 return lt;
1533 static bool have_exact_function_member (recID r, Token f, typeID argv[], flookup *F)
1535 looking_for = 2;
1536 return _lookup_function_member (r, f, argv, F)
1537 || (looking_for = 3, _lookup_function_member (r, f, argv, F));
1540 Token declare_function_member (recID r, Token f, typeID t, Token *p, Token *a, int fl,
1541 Token **d, Token section)
1543 if (!structs [r].notunion)
1544 parse_error_ll ("unions may not be have member functions");
1545 funcp *fp = xdeclare_function (&structs [r].Funcs, f,
1546 name_member_function (r, f), t, p, a, fl, d, section);
1547 fp->used = !(fl & FUNCP_AUTO);
1548 return fp->name;
1550 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1551 // misc
1552 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1554 bool Can_instantiate (recID r)
1556 switch (structs [r].caninst) {
1557 case CANT_INCOMPL:
1558 expr_errort ("Can't instantiate incomplete class", name_of_struct (r));
1559 case CANT_PUREV:
1560 expr_errort ("Can't instantiate class. Pure virtual functions still in there",
1561 name_of_struct (r));
1562 case CANT_NUFO:
1563 expr_errort ("Can't instantiate class."
1564 " No unique final overrider for virtual function", name_of_struct (r));
1565 case OK_CAN:
1566 return true;
1568 return true;
1571 recID ancest_named (recID r, Token t)
1573 ancestor *a = structs [r].ancestors;
1575 while (a->path [0] != t || a->path [1] != -1)
1576 ++a;
1577 return a->rec;
1580 bool isancestor (recID rder, recID rbase)
1582 ancestor *a = structs [rder].ancestors;
1584 if (a) while (a->rec != -1)
1585 if (a++->rec == rbase) return true;
1587 return rder == rbase;
1590 int is_ancestor (recID rder, recID rbase, Token **path, bool const_path)
1592 ancestor *a = structs [rder].ancestors;
1594 if (!a) return 0;
1596 for (; a->rec != -1; a++)
1597 if (a->rec == rbase) {
1598 if (path) *path = const_path && a->cpath ? a->cpath : a->path;
1599 if (a->status == ASTATUS_FSCKD)
1600 expr_errort ("Ambigouus relationship", name_of_struct (rbase));
1601 return a->status == ASTATUS_VIRT && a->vbase == a->rec && !const_path ? 2:1;
1603 return 0;
1606 /* HOWTO: anestor status flags.
1608 ASTATUS_NORM ASTATUS_VIRT ASTATUS_VIRT2
1609 ---------------------------------------------
1610 ! -> for members No Yes No
1611 ! collapse vtis No Yes Yes
1612 ! declare vbase No Yes No
1613 ! const path No Yes Yes
1614 ! vtable good Yes No No
1615 ! downcast rtti No Yes Yes
1617 ***************************************************************/
1619 /* this here returns true if downcast rtti is needed to go from rbase to rder */
1620 bool is_ancestor_runtime (recID rder, recID rbase, Token **path)
1622 if (is_ancestor (rder, rbase, path, false) == 2 || intchr (*path, POINTSAT))
1623 return true;
1624 ancestor *a = structs [rder].ancestors;
1625 while (a->rec != rbase) a++;
1626 return a->status == ASTATUS_VIRT2;
1629 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1631 // auto functions
1633 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1635 bool PARENT_AUTOFUNCS;
1637 void add_auto_f (Token ifn, Token fn, recID r, typeID t, bool virtual, bool pure, NormPtr dclPtr,
1638 Token *proto, Token *argv)
1640 autofunc *a;
1641 typeID *va = promoted_arglist_t (t);
1643 for (a = structs [r].autofuncs; a; a = a->next)
1644 if (a->name == fn && (arglist_compare (va, a->arglist)
1645 || (PARENT_AUTOFUNCS && dclPtr == a->dclPtr)))
1646 break;
1648 if (!a) {
1649 a = add_autofunc (r);
1650 a->name = fn;
1651 a->arglist = va;
1652 a->virtual = virtual;
1653 a->status = pure ? AU_STATUS_PV : AU_STATUS_DD;
1654 a->dname = a->fname = ifn;
1655 a->pname = -1;
1656 } else {
1657 free (va);
1659 //* commented out. does not allow to redefine an auto function
1660 //* with pure typedefs in its arguments in a class that they
1661 //* have been specialized... We only miss report of a rare error
1662 //if (a->status == AU_STATUS_DD)
1663 // parse_error_tok (fn, "auto-function redefined");
1665 if (virtual && !a->virtual)
1666 parse_error_tok (fn, "auto-function was not declared virtual");
1667 a->fname = ifn;
1668 // smart hack
1669 // PEND means it's inherited and we expect redef
1670 // !PEND means that user has supplied new definition
1671 // and we undo what we did the first time where PEND was true
1672 if (a->status != AU_STATUS_PEND)
1673 a->dname = ifn, a->pname = -1;
1674 a->status = pure ? AU_STATUS_PV : AU_STATUS_DD;
1676 a->dclPtr = dclPtr;
1677 a->proto = intdup (proto);
1678 a->argv = intdup (argv);
1679 a->type = t;
1682 int borrow_auto_decls (recID r, NormPtr ret[])
1684 int i;
1685 autofunc *a;
1687 for (i = 0, a = structs [r].autofuncs; a; a = a->next)
1688 if (a->status == AU_STATUS_ND) {
1689 a->status = AU_STATUS_PEND;
1690 ret [i++] = a->dclPtr;
1692 ret [i] = -1;
1693 return i;
1696 void repl__CLASS_ (Token **proto, recID r)
1698 if (is_aliasclass (r))
1699 intsubst (*proto, RESERVED__CLASS_, name_of_struct (r));
1700 else {
1701 Token tmp [200];
1702 int i = 0, j = 0;
1703 for (;;)
1704 if ((*proto) [i] == RESERVED__CLASS_) {
1705 tmp [j++] = RESERVED_struct;
1706 tmp [j++] = name_of_struct (r);
1707 ++i;
1708 } else if ((tmp [j++] = (*proto) [i++]) == -1) break;
1709 free (*proto);
1710 *proto = intdup (tmp);
1714 /* commit all the auto functions to require definition/instantiation */
1715 static void commit_auto_functions (recID r)
1717 autofunc *a;
1719 for (a = structs [r].autofuncs; a; a = a->next)
1720 if (a->status != AU_STATUS_NU) {
1721 if (is_aliasclass (r))
1722 remove_struct_from_this (a->proto, r);
1723 if (intchr (a->proto, RESERVED__CLASS_))
1724 repl__CLASS_ (&a->proto, r);
1725 commit_auto_define (a->dname, r, a->fname, a->pname, a->virtual,
1726 a->proto, a->argv, a->type);
1727 } else warning_tok ("No unique final overrider for auto function of",
1728 name_of_struct (r));
1731 /* inherit auto functions and change DD to ND (not declared) */
1732 static void inherit_auto_functions (recID r)
1734 ancestor *a;
1735 autofunc *af, *hf;
1736 int i;
1738 a = structs [r].ancestors;
1740 for (i = 0; a [i].rec != -1; i++)
1741 if (direct_ancest (&a [i])) {
1742 for (af = structs [a [i].rec].autofuncs; af; af = af->next) {
1743 for (hf = structs [r].autofuncs; hf; hf = hf->next)
1744 if (hf->name == af->name && arglist_compare (hf->arglist, af->arglist))
1745 break;
1746 if (hf) {
1747 if (af->status == AU_STATUS_PV) continue;
1748 if (hf->status == AU_STATUS_PV) goto wins;
1749 if (hf->status == AU_STATUS_ND && af->status == AU_STATUS_DD
1750 && hf->dclPtr == af->dclPtr) continue;
1751 hf->status = AU_STATUS_NU;
1752 } else {
1753 hf = add_autofunc (r);
1754 wins:
1755 hf->name = af->name;
1756 hf->dname = af->dname;
1757 hf->pname = hf->fname = af->fname;
1758 hf->virtual = af->virtual;
1759 hf->status = af->status;
1760 hf->arglist = intdup (af->arglist);
1761 hf->dclPtr = af->dclPtr;
1762 hf->proto = af->proto;
1763 hf->argv = af->argv;
1764 hf->type = af->type;
1765 if (hf->status == AU_STATUS_DD)
1766 hf->status = AU_STATUS_ND;
1769 if (structs [a [i].rec].autodtor)
1770 structs [r].autodtor = 1;
1774 /* upcast from this to a direct parent using constant path if avail */
1775 Token *upcast1_this (recID rder, recID rbase)
1777 static Token retp [15];
1778 ancestor *a = structs [rder].ancestors;
1780 if (aliasclass (rder) == aliasclass (rbase))
1781 sintprintf (retp, RESERVED_this, -1);
1782 else {
1783 while (a->rec != rbase) a++;
1785 if (a->status == ASTATUS_NORM)
1786 sintprintf (retp, '&', RESERVED_this, POINTSAT, a->path [0], -1);
1787 else if (a->cpath)
1788 sintprintf (retp, '&', RESERVED_this, POINTSAT, ISTR (a->cpath), -1);
1789 else sintprintf (retp, RESERVED_this, POINTSAT, a->path [0], -1);
1792 return retp;
1795 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1797 // pure data members
1799 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1801 void add_pure_dm (recID r, Token bt, NormPtr dcl)
1803 puredm *p;
1805 for (p = structs [r].pm; p; p = p->next)
1806 if (p->bt == bt) {
1807 if (!intchr (p->dcls, dcl))
1808 intcatc (p->dcls, dcl);
1809 return;
1811 p = (puredm*) malloc (sizeof *p);
1812 p->next = structs [r].pm;
1813 structs [r].pm = p;
1814 p->bt = bt;
1815 sintprintf (p->dcls, dcl, -1);
1818 void gen_pure_dm (recID r, OUTSTREAM O)
1820 puredm *p;
1821 ancestor *a = structs [r].ancestors;
1822 int i, j;
1823 Token t;
1825 if (a) for (i = 0; a [i].rec != -1; i++)
1826 if (direct_ancest (&a [i]))
1827 for (p = structs [a [i].rec].pm; p; p = p->next) {
1828 if ((t = lookup_local_typedef (r, p->bt))
1829 && base_of (lookup_typedef (t)) != B_PURE)
1830 for (j = 0; p->dcls [j] != -1; j++)
1831 struct_declaration (r, O, p->dcls [j]);
1832 else for (j = 0; p->dcls [j] != -1; j++)
1833 add_pure_dm (r, p->bt, p->dcls [j]);
1837 //************************************************************
1838 // renaming functions due to overload adds complexity
1839 //************************************************************
1841 void rename_hier (Token on, Token nn)
1843 int i;
1844 autofunc *a;
1846 for (i = 0; i < nstructs; i++)
1847 if (structs [i].incomplete) {
1848 for (a = structs [i].autofuncs; a; a = a->next) {
1849 // one of the two is redundant
1850 if (a->dname == on) a->dname = nn;
1851 if (a->fname == on) {
1852 a->fname = nn;
1853 if (intchr (a->proto, on))
1854 intsubst1 (a->proto, on, nn);
1857 if (structs [i].keyfunc == on)
1858 structs [i].keyfunc = nn;