added UGLY hacks to compile regexp code (look for 'k8:hack')
[k8-lwc.git] / src / hier.c
blobfcc2fd25e469b543a20a8d0204b282e713e9be8c
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 static inline bool direct_ancest (ancestor *a)
205 return a->direct;
208 #include "vtbl.c"
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;
350 } else {
351 d = a->depth;
352 ret = t;
356 if (e) expr_errort ("Ambiguous local typedef", tn);
358 if (ret && objective.recording)
359 usage_typeID (lookup_typedef (ret));
361 return ret;
364 static Token direct_vparent (recID rd, recID rb)
366 ancestor *a;
368 if (rd == rb) return 0;
370 if ((a = structs [rd].ancestors))
371 for (; a->rec != -1; a++)
372 if (a->rec == rb && a->status == ASTATUS_VIRT
373 && a->path [1] == -1) return a->path [0];
374 return 0;
377 /* generate the code which sets the address of the common shared
378 base class instance to the pointers that are supposed to point to it */
379 static void gen_construction_code_vb (OUTSTREAM o, recID r, Token obj)
381 int i, j;
382 Token *p, m;
383 ancestor *a = structs [r].ancestors;
385 r = aliasclass (r);
386 for (i = 0; a [i].rec != -1; i++)
387 if (a [i].status == ASTATUS_VIRT && a [i].vbase == a [i].rec) {
388 recID vr = a [i].vbase, r2;
389 for (j = 0; a [j].rec != -1; j++)
390 if (!is_aliasclass (a [j].rec))
391 if ((m = direct_vparent (r2 = aliasclass (a [j].rec), vr))) {
392 is_ancestor (r, r2, &p, true);
393 outprintf (o, obj, POINTSAT, ISTR (p),
394 '.', m, '=', -1);
396 if (direct_vparent (r, vr)) {
397 outprintf (o, obj, POINTSAT, a [i].path [0], '=', -1);
399 is_ancestor (r, vr, &p, true);
400 outprintf (o, '&', obj, POINTSAT, ISTR (p), ';', -1);
404 /* construction code in case base obj is just a vtable */
405 static void gen_construction_code_vb2 (OUTSTREAM o, recID r, Token obj)
407 int i, j;
408 Token *p, *p1, *p2;
409 ancestor *a = structs [r].ancestors;
411 r = aliasclass (r);
412 for (i = 0; a [i].rec != -1; i++)
413 if (a [i].status == ASTATUS_VIRT2) {
414 bool hp = 0;
416 p1 = a [i].cpath;
417 for (j = 0; a [j].rec != -1; j++)
418 if (a [j].rec != a [i].rec && direct_ancest (&a [j])
419 && is_ancestor (aliasclass (a [j].rec), a [i].rec, &p, 1)) {
420 p2 = a [j].cpath ?: a [j].path;
421 if (p1 [0] == p2 [0]) continue;
422 outprintf (o, obj, POINTSAT, ISTR (p2), '.',
423 ISTR (p), '.', RESERVED__v_p_t_r_, '=', -1);
424 hp = 1;
427 if (hp) outprintf (o, obj, POINTSAT, ISTR (a [i].cpath), '.',
428 RESERVED__v_p_t_r_, ';', -1);
432 /* generate the code that calls the init function for a ctorable */
433 static void call_init_func (OUTSTREAM o, Token obj, ctorable_t *c, Token *path)
435 if (c->array) outprintf (o, i_call_initialization (c->ot), '(',
436 obj, POINTSAT, ISTR (path), DOT_IF (path [0] != -1), c->obn, ',',
437 RESERVED_sizeof, obj, POINTSAT, ISTR (path),
438 DOT_IF (path [0] != -1), c->obn, '/',
439 RESERVED_sizeof, '(', iRESERVED_struct (c->ot),
440 name_of_struct (c->ot), ')', ')', ';', -1);
441 else outprintf (o, i_call_initialization (c->ot), '(',
442 '&', obj, POINTSAT, ISTR (path), DOT_IF (path [0] != -1),
443 c->obn, ',', RESERVED_1, ')', ';', -1);
446 /* Construct all members that need construction indeed yes */
447 static void gen_member_construction (OUTSTREAM o, recID r, Token obj)
449 int i;
450 ctorable_t *c = structs [r].ctorables;
451 Token nopath [] = { -1 };
452 ancestor *a;
454 if (c) for (i = 0; c [i].ot != -1; i++)
455 call_init_func (o, obj, &c [i], nopath);
457 if (structs [r].ancestors_have_ctors)
458 for (a = structs [r].ancestors; a->rec != -1; a++)
459 if ((c = structs [a->rec].ctorables))
460 for (i = 0; c [i].ot != -1; i++)
461 call_init_func (o, obj, &c [i], a->cpath ?: a->path);
464 void gen_construction_code (OUTSTREAM o, recID r, Token obj)
466 if (structs [r].has_vbase)
467 gen_construction_code_vb (o, r, obj);
468 if (structs [r].vtis)
469 gen_vt_init (o, r, obj, true);
470 if (structs [r].has_vbase2)
471 gen_construction_code_vb2 (o, r, obj);
472 if (structs [r].ctorables || structs [r].ancestors_have_ctors)
473 gen_member_construction (o, r, obj);
475 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
476 // what is this?
477 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
479 static intnode *structtree;
480 static int nstructs, nallocstructs;
482 recID enter_struct (Token e, Token tag, bool unwind, bool noctor, bool evt, bool sclass)
484 intnode *in = intfind (structtree, e);
485 int pt [3] = { nstructs, '*', -1 };
487 if (in) {
488 recID r = in->v.i;
489 if (unwind && !always_unwind (r))
490 structs [r].unwind = true;
491 if (noctor)
492 structs [r].noctor = true;
493 return r;
496 if (nstructs == nallocstructs)
497 structs = (structure*) realloc (structs, (nallocstructs+=96) * sizeof (structure));
498 structs [nstructs].name = e;
499 structs [nstructs].notunion = tag != RESERVED_union;
500 structs [nstructs].deftype = false;
501 structs [nstructs].class = tag == RESERVED_class;
502 structs [nstructs].incomplete = true;
503 structs [nstructs].has_dtor = false;
504 structs [nstructs].idtor = 0;
505 structs [nstructs].vdtor = 0;
506 structs [nstructs].dtor_name = 0;
507 structs [nstructs].dtor_nothrow = false;
508 structs [nstructs].Funcs = 0;
509 structs [nstructs].has_dtorable = false;
510 structs [nstructs].firstmember = 0;
511 structs [nstructs].printed = false;
512 structs [nstructs].unwind = unwind;
513 structs [nstructs].noctor = noctor;
514 structs [nstructs].evt = evt;
515 structs [nstructs].has_vbase = 0;
516 structs [nstructs].has_vbase2 = 0;
517 structs [nstructs].rtti = 0;
518 structs [nstructs].vtis = 0;
519 structs [nstructs].ancestors = 0;
520 structs [nstructs].ctorables = 0;
521 structs [nstructs].autofuncs = 0;
522 structs [nstructs].anonunions = 0;
523 structs [nstructs].ltdef = 0;
524 structs [nstructs].nanons = 0;
525 structs [nstructs].consts = 0;
526 structs [nstructs].caninst = CANT_INCOMPL;
527 structs [nstructs].type_pthis = enter_type (pt);
528 structs [nstructs].used = false;
529 structs [nstructs].code = 0;
530 structs [nstructs].depends = 0;
531 structs [nstructs].ancestors_have_ctors = 0;
532 structs [nstructs].need_recalc_offsets = 0;
533 structs [nstructs].have_vi_decls = 0;
534 structs [nstructs].vt_inthis = false;
535 structs [nstructs].alias_class = nstructs;
536 structs [nstructs].constd = 0;
537 structs [nstructs].pm = 0;
538 structs [nstructs].keyfunc = sclass ? -1 : 0;
539 structs [nstructs].havekey = 0;
540 structs [nstructs].autodtor = 0;
541 union ival i = { i: nstructs };
542 intadd (&structtree, e, i);
543 return nstructs++;
546 void keyfunc_candidate (recID o, Token k)
548 if (!structs [o].keyfunc)
549 //{PRINTF ("Setting keyfunc of "COLS"%s"COLE":%s\n", SNM(o), expand (k));
550 structs [o].keyfunc = k;
554 void possible_keyfunc (recID o, Token k)
556 //PRINTF ("possible %s:%s ", SNM(o), expand(k));
557 if (structs [o].keyfunc == k)
558 //{PRINTF ("-ok-\n");
559 structs [o].havekey = 1;
560 //}else PRINTF ("\n");
563 void set_depend (recID o, recID i)
565 int j = 2;
566 if (structs [o].depends) {
567 for (j = 0; structs [o].depends [j] != -1; j++);
568 j += 2;
571 structs [o].depends = (recID*) realloc (structs [o].depends, j * sizeof (recID));
572 structs [o].depends [j - 2] = i;
573 structs [o].depends [j - 1] = -1;
576 static void export_struct (recID r)
578 int i;
580 if (structs [r].printed) return;
582 //k8:hack!
584 const char *n = expand(structs[r].name);
585 if (strcmp(n, "__jmp_buf_tag") == 0) { structs [r].printed = true; return; }
587 ///k8:hack!
589 if (structs [r].depends)
590 for (i = 0; structs [r].depends [i] != -1; i++)
591 export_struct (structs [r].depends [i]);
593 if (structs [r].vtis)
594 export_virtual_table_declaration (r);
596 if (structs [r].Funcs)
597 export_fspace_lwc (structs [r].Funcs);
599 structs [r].printed = true;
600 if (structs [r].code)
601 outprintf (STRUCTS, ISTR (structs [r].code), -1);
604 void export_structs ()
606 int r;
607 for (r = 0; r < nstructs; r++)
608 export_struct (r);
611 static void commit_auto_functions (recID);
613 /////////////////////////////////////////////////
614 // some things when declaration completes
615 /////////////////////////////////////////////////
617 void remove_struct_from_this (Token *p, recID r)
619 int i, j;
620 if (intchr (p, RESERVED_this)) {
621 for (i = 0; p [i] != RESERVED_this; i++);
622 while (p [i] != RESERVED_struct && p [i] != '(') i--;
623 if (p [i] != '(')
624 intcpy (p + i, p + i + 1);
626 Token sn = name_of_struct (r);
627 for (i = 0; p [i] != -1; p++)
628 if (p [i] == RESERVED_struct && p [i + 1] == sn)
629 for (j = i; p [j] != -1; j++)
630 p [j] = p [j + 1];
633 static void adjust_protos (fspace S, recID r)
635 if (!S) return;
637 funcp *p = (funcp*) S->v.p;
638 for (; p; p = p->next)
639 if (p->prototype && !(p->flagz & FUNCP_MODULAR)) {
640 remove_struct_from_this (p->prototype, r);
641 remove_struct_from_def (p->name);
643 adjust_protos (S->less, r);
644 adjust_protos (S->more, r);
647 static void make_empty_dtor (recID r)
649 Token proto [] = { RESERVED_static, RESERVED_inline, RESERVED_dtor, '(', ')', ';', -1 };
650 SAVE_VAR (CODE, proto);
651 bool haskey = structs [r].keyfunc != 0;
652 struct_declaration (r, 0, 0);
653 if (!haskey && structs [r].keyfunc)
654 structs [r].keyfunc = 0;
655 RESTOR_VAR (CODE);
656 store_define_dtor (structs [r].dtor_name, r);
659 static void study_destruction (recID r)
661 bool b = false, v = false;
662 int i;
663 member *m;
664 ancestor *a = structs [r].ancestors;
666 for (m = structs [r].firstmember; m; m = m->next)
667 if (isstructure (m->t) && has_dtor (base_of (m->t))) {
668 b = true;
669 break;
672 if (a) for (i = 0; a [i].rec != -1; i++)
673 if (vparent (a [i].status)) v = true;
674 else if (direct_ancest (&a [i]) && has_dtor (a [i].rec))
675 b = true;
677 // - vdtor is the destructor that doesn't call the dtors
678 // of the virtual base classes
679 // - idtor calls dtors of dtorable members and vdtors (or normal
680 // dtors in not exist) of direct non virtual parents.
681 // - the real dtor calls vdtor and then calls the dtors
682 // of virtual parents
684 if (b) {
685 if (!structs [r].has_dtor)
686 make_empty_dtor (r);
687 structs [r].idtor = name_intern_dtor (r);
689 if (v) structs [r].vdtor = name_intern_vdtor (r);
692 OUTSTREAM dispatch_vdtor (recID r, OUTSTREAM o)
694 int i;
695 Token *vd = combine_output (o);
696 OUTSTREAM n = new_stream ();
697 ancestor *a = structs [r].ancestors;
699 for (i = 0; vd [i] != '{'; i++)
700 output_itoken (n, vd [i]);
701 outprintf (n, '{', structs [r].vdtor, '(', RESERVED_this, ')', ';', -1);
702 for (i = 0; a [i].rec != -1; i++)
703 if (vparent (a [i].status))
704 outprintf (n, structs [a [i].rec].vdtor ?:
705 structs [a [i].rec].dtor_name, '(',
706 ADDR_IF (a [i].cpath && a [i].cpath [0] != -1), RESERVED_this,
707 POINTSAT_IF ((a [i].cpath ?: a [i].path) [0] != -1),
708 ISTR (a [i].cpath ?: a [i].path), ')', ';', -1);
709 outprintf (n, RESERVED_return, RESERVED_this, ';', '}', -1);
711 intsubst1 (vd, structs [r].dtor_name, structs [r].vdtor);
712 outprintf (INTERNAL_CODE, ISTR (vd), -1);
713 free (vd);
715 return n;
718 void make_intern_dtor (recID r)
720 int i;
721 member *m;
722 ancestor *a = structs [r].ancestors;
723 Token do_alias = HaveAliases ? 0 : -1;
724 #ifdef BROKEN_ALIASES
725 do_alias = -1;
726 #endif
727 recID afcls = 0;
728 OUTSTREAM O = new_stream ();
730 outprintf (O, R(static), R(inline), R(void), structs [r].idtor, '(',
731 iRESERVED_struct (r), name_of_struct (r), '*', R(this), ')', '{', -1);
733 /* call dtors of dtorable data members */
734 for (m = structs [r].firstmember; m; m = m->next)
735 if (isstructure (m->t) && has_dtor (base_of (m->t))) {
736 outprintf (O, dtor_name (base_of (m->t)),
737 '(', '&', RESERVED_this, POINTSAT, m->m, ')', ';', -1);
738 do_alias = -1;
741 /* call vdtors of parents (non virtual parents that is) */
742 if (a) for (i = 0; a [i].rec != -1; i++)
743 if (direct_ancest (&a [i]) && has_dtor (a [i].rec) && !vparent (a [i].status)
744 && !(structs [a [i].rec].autodtor && !idtor (a [i].rec))) {
745 bool dointernal = structs [a [i].rec].autodtor;
746 outprintf (O,
747 /* If this is an auto function call only idtor of parent.
748 else if parent has vbases, call vdtor of parent.
749 else call dtor of parent */
750 dointernal ? idtor (a [i].rec) :
751 structs [a [i].rec].vdtor ?:
752 dtor_name (a [i].rec), '(',
753 ISTR (upcast1_this (r, a [i].rec)), ')', ';', -1);
754 if (do_alias) do_alias = -1;
755 else do_alias = zero_offset (r, a [i].rec) && !dointernal ?
756 dtor_name (afcls = a [i].rec) : -1;
758 output_itoken (O, '}');
760 /* do it with alias if all that has to be done is call the dtor of one parent
761 which is at offset 0 */
762 if (do_alias > 0) {
763 free_stream (O);
764 outprintf (O = new_stream (), R(static), R(inline), R(void), structs [r].idtor, '(',
765 iRESERVED_struct (r), name_of_struct (r), '*', R(this), ')',
766 alias_func (afcls, do_alias), ';', -1);
768 concate_streams (INTERNAL_CODE, O);
771 static void enter_virtuals (recID r, fspace S)
773 funcp *p;
775 for (p = S->v.p; p; p = p->next)
776 if ((p->flagz & FUNCP_VIRTUAL) && p->prototype) {
777 vf_args args;
778 Token *pr;
780 args.r = r;
781 args.fname = S->key;
782 args.ftype = p->type;
783 args.fmemb = p->flagz & FUNCP_PURE ? 0 : p->name;
784 args.flagz = p->flagz;
785 // pass prototype to make fptr from
786 for (pr = p->prototype; ISDCLFLAG (*pr); pr++);
787 args.prototype = allocaint (intlen (pr) + 1);
788 intcpy (args.prototype, pr);
789 intsubst1 (args.prototype, p->name, MARKER);
790 args.argv = allocaint (intlen (p->xargs) + 1);
791 intcpy (args.argv, p->xargs);
792 Enter_virtual_function (&args);
794 if (S->less) enter_virtuals (r, S->less);
795 if (S->more) enter_virtuals (r, S->more);
798 bool do_alias_class (recID r)
800 recID alias = 0, rr;
801 ancestor *a = structs [r].ancestors;
803 if (structs [r].firstmember || structs [r].vt_inthis || !a || structs [r].anonunions)
804 return false;
806 for (; a->rec != -1; a++)
807 if (direct_ancest (a)) {
808 rr = structs [a->rec].alias_class;
809 if (alias && rr != alias)
810 return false;
811 alias = rr;
813 structs [r].alias_class = alias;
814 return true;
817 recID is_aliasclass (recID r)
819 if (structs [r].incomplete && structs [r].class) {
820 structs [r].deftype = true;
821 return -1;
823 return structs [r].alias_class == r ? 0 : structs [r].alias_class;
826 recID aliasclass (recID r)
828 return structs [r].alias_class;
831 static void undo_paths (recID);
833 recID complete_structure (OUTSTREAM o, recID r)
835 structs [r].incomplete = false;
836 study_destruction (r);
837 if (do_alias_class (r)) {
838 undo_paths (r);
839 adjust_protos (structs [r].Funcs, r);
840 structs [r].has_vbase = 0;
841 structs [r].has_vbase2 = 0;
842 } else {
843 if (structs [r].class) {
844 if (structs [r].deftype) outprintf (GLOBAL, RESERVED_typedef,
845 RESERVED_struct, name_of_struct (r), name_of_struct (r), ';', -1);
846 //else outprintf (GLOBAL, RESERVED_struct, name_of_struct (r), ';', -1);
848 if (structs [r].ancestors) make_rtti (r);
850 if (structs [r].Funcs)
851 enter_virtuals (r, structs [r].Funcs);
852 //**+*+*+*+*+*+*+*+*+*+*+*+*
853 close_inits (&structs [r]);
854 mk_typeid (r);
855 if (can_instantiate (r)) {
856 if (structs [r].has_vbase)
857 decl_vballoc_rec (o, r);
859 commit_auto_functions (r);
861 if (structs [r].need_recalc_offsets)
862 fix_all_offsets (r);
863 #ifdef DEBUG
864 if (debugflag.VIRTUALTABLES)
865 show_vt (r);
866 #endif
867 return is_aliasclass (r);
870 #if 0
871 void produce_dtorables (OUTSTREAM o, recID r)
873 member *m;
874 for (m = structs [r].firstmember; m; m = m->next)
875 if (isstructure (m->t) && has_dtor (base_of (m->t)))
876 outprintf (o, structs [base_of (m->t)].dtor_name,
877 '(', '&', RESERVED_this, POINTSAT, m->m, ')', ';', -1);
879 #endif
881 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
882 // parental control
883 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
885 static Token *best_path (Token *p1, Token *p2)
887 int i, c1, c2;
889 if (!p1) return p2;
890 if (!p2) return p1;
892 for (i = c1 = 0; p1 [i] != -1; i++)
893 if (p1 [i] == POINTSAT) c1++;
894 for (i = c2 = 0; p2 [i] != -1; i++)
895 if (p2 [i] == POINTSAT) c2++;
897 if (c1 != c2)
898 return c1 < c2 ? p1 : p2;
900 for (i = c1 = 0; p1 [i] != -1; i++)
901 if (p1 [i] == '.') c1++;
902 for (i = c2 = 0; p2 [i] != -1; i++)
903 if (p2 [i] == '.') c2++;
905 if (c1 != c2)
906 return c1 < c2 ? p1 : p2;
908 i = 0;
909 do if (p1 [i] != p2 [i])
910 return strcmp (expand (p1 [i]), expand (p2 [i])) < 0 ? p1 : p2;
911 while (p1 [i++] != -1);
913 return p1;
916 #if 0
917 /* sort the ancestors from closest to oldest */
918 /* do we really need this? */
919 static void sort_ancestors (recID r)
921 int i, j;
922 ancestor *a, swp;
924 a = structs [r].ancestors;
925 for (i = 0; a [i].rec != -1; i++)
926 for (j = i + 1; a [j].rec != -1; j++)
927 if (intlen (a [i].path) > intlen (a [j].path)) {
928 swp = a [i];
929 a [i] = a [j];
930 a [j] = swp;
933 #endif
935 static Token *ext_path (Token nn, Token *p, bool v)
937 return p ? p [0] == -1 ? sintprintf (mallocint (2), nn, -1) :
938 sintprintf (mallocint (intlen (p)+3), nn, v ? POINTSAT:'.', ISTR (p), -1) : 0;
941 static bool make_ancestors (recID r, recID ps[], recID cvb[])
943 int i, j, t, k, l, c = 0;
944 structure *s;
945 ancestor *a, *a2;
946 bool hv = false, *vr = (bool*) alloca (sizeof (bool) * intlen (ps));
948 for (i = 0; ps [i] != -1; i++) {
949 if ((vr [i] = ps [i] >= VIRTUALPAR_BOOST)) {
950 ps [i] -= VIRTUALPAR_BOOST;
951 hv = true;
953 if (!structs [ps [i]].notunion)
954 parse_error_ll ("cannot inherit a union");
955 if (structs [ps [i]].incomplete)
956 parse_error (0, "You cannot inherit from something unborn");
957 if (structs [ps [i]].constd)
958 structs [r].constd = true;
959 set_depend (r, ps [i]);
962 for (i = 0, t = 1; ps [i] != -1; i++, t++)
963 if ((s = &structs [ps [i]])->ancestors)
964 for (j = 0; s->ancestors [j].rec != -1; j++)
965 t++;
967 a = structs [r].ancestors = (ancestor*) malloc (sizeof (ancestor) * t);
969 /* Somethings like mutliple non-virtual inheritace
970 * of common base class, really ought to be forbidden.
971 * we can parse_error on ASTATUS_FSCKD for that...
973 for (i = t = 0; ps [i] != -1; i++) {
974 recID rr = ps [i];
975 Token nn = name_inherited (name_of_struct (rr));
976 bool V = vr [i], V2;
977 bool zero_offset = i == 0 && !(V && vt_only (rr));
979 s = &structs [rr];
981 for (k = 0; k < t; k++)
982 if (a [k].rec == rr)
983 break;
985 // new ancestor or existing ?
986 if (k < t) {
987 // existing!
988 a [k].direct = true;
989 a [k].depth = 1;
990 V2 = vparent (a [k].status);
991 // both virtual
992 if (V && V2) {
993 a [k].zero_displace = false;
994 if (a [k].vbase != aliasclass (rr))
995 goto really_fsckd1;
996 free (a [k].path);
997 a [k].path = sintprintf (mallocint (2), nn, -1);
998 if (a [k].status == ASTATUS_VIRT2) {
999 free (a [k].cpath);
1000 sintprintf (a [k].cpath = mallocint (2), nn, -1);
1002 for (l = 0; l < c; l++)
1003 if (cvb [l] == rr) break;
1004 if (l == c) cvb [c++] = rr;
1005 } else really_fsckd1: {
1006 a [k].status = ASTATUS_FSCKD;
1007 free (a [k].path);
1008 a [k].path = sintprintf (mallocint (2), nn, -1);
1010 } else {
1011 a [t].rec = rr;
1012 a [t].status = V ? vt_only (rr) ? ASTATUS_VIRT : ASTATUS_VIRT2 : ASTATUS_NORM;
1013 a [t].zero_displace = zero_offset;
1014 a [t].direct = true;
1015 a [t].path = sintprintf (mallocint (2), nn, -1);
1016 a [t].depth = 1;
1017 if (V) a [t].vbase = aliasclass (rr);
1018 a [t].cpath = a [t].status != ASTATUS_VIRT2 ? 0 : sintprintf (mallocint (2), nn, -1);
1019 ++t;
1020 if (s->ctorables || s->ancestors_have_ctors)
1021 structs [r].ancestors_have_ctors = true;
1024 // add ancestors of ancestor
1025 if ((a2 = s->ancestors))
1026 for (j = 0; a2 [j].rec != -1; j++) {
1029 for (k = 0; k < t; k++)
1030 if (a [k].rec == a2 [j].rec)
1031 break;
1033 if (k < t) {
1034 if (vparent (a [k].status)) {
1035 a [k].zero_displace = false;
1036 if (a2 [j].status == a [k].status) {
1037 if (a [k].vbase != a2 [j].vbase)
1038 goto really_fsckd2;
1039 } else if (V) {
1040 if (a [k].vbase != aliasclass (rr))
1041 goto really_fsckd2;
1042 } else goto really_fsckd2;
1044 for (l = 0; l < c; l++)
1045 if (cvb [l] == a [k].vbase) break;
1046 if (l == c) cvb [c++] = a [k].vbase;
1048 Token *path = ext_path (nn, a2 [j].path, V);
1049 Token *cpath = ext_path (nn, a2 [j].cpath, V);
1051 if (best_path (a [k].path, path) == path) {
1052 free (a [k].path);
1053 a [k].path = path;
1054 } else free (path);
1056 if (cpath)
1057 if (best_path (a [k].cpath, cpath) == cpath) {
1058 if (a [k].cpath) free (a [k].cpath);
1059 a [k].cpath = cpath;
1060 } else free (cpath); else;
1061 } else really_fsckd2:
1062 a [k].status = ASTATUS_FSCKD;
1063 } else {
1064 a [t].rec = a2 [j].rec;
1065 a [t].status = a2 [j].status;
1066 a [t].path = ext_path (nn, a2 [j].path, V);
1067 a [t].vbase = a2 [j].vbase;
1068 a [t].zero_displace = a2 [j].zero_displace && zero_offset;
1069 a [t].depth = a2 [j].depth + 1;
1070 a [t].direct = false;
1071 if (V && !vparent (a2 [j].status)) {
1072 a [t].status = ASTATUS_VIRT;
1073 a [t].vbase = aliasclass (rr);
1075 a [t++].cpath = ext_path (nn, a2 [j].cpath, V);
1079 a [t].rec = -1;
1080 cvb [c] = -1;
1081 // sort_ancestors (r);
1083 for (i = 0; i < t; i++)
1084 if (a [i].status == ASTATUS_VIRT)
1085 structs [r].has_vbase = true;
1086 else if (a [i].status == ASTATUS_VIRT2)
1087 structs [r].has_vbase2 = true;
1088 #ifdef DEBUG
1089 if (debugflag.VIRTUALTABLES) show_ancest (r);
1090 #endif
1091 return hv;
1094 /* If something is an alias class (typedef), undo the path extensions */
1095 static void undo_path (Token *path)
1097 if (path [1] == -1) path [0] = -1;
1098 else intcpy (path, path + 2); // overlap but works
1101 static void undo_paths (recID r)
1103 ancestor *a = structs [r].ancestors;
1104 if (!a) return;
1106 for (; a->rec != -1; a++) {
1107 if (a->path) undo_path (a->path);
1108 if (a->cpath) undo_path (a->cpath);
1112 bool zero_offset (recID rder, recID rbase)
1114 ancestor *a;
1116 for (a = structs [rder].ancestors; a; a++)
1117 if (a->rec == rbase)
1118 return a->zero_displace;
1119 return false;
1122 static void inherit_auto_functions (recID);
1124 void set_parents (recID r, recID ps[])
1126 /*bool have_virtual_inh;*/
1127 recID collapsed [16];
1129 if (ps [0] != -1 && !structs [r].notunion)
1130 parse_error_ll ("union cannot be part of a hierarchy");
1132 /*have_virtual_inh =*/ make_ancestors (r, ps, collapsed);
1133 inherit_all_virtuales (r);
1134 inherit_auto_functions (r);
1135 inherit_class_consts (r);
1136 // if (have_virtual_inh) // this is leftover from surgery while implementing
1137 // make_rtti (r); // aliasclasses. hmmmmmmmmmmmmmmm. who knows?
1138 if (collapsed [0] != -1)
1139 update_dcasts (r, collapsed);
1142 void output_parents (OUTSTREAM o, recID r)
1144 int i, ri = 0, j;
1145 ancestor *a;
1146 recID rp [64], rec;
1147 bool virt;
1149 if (!(a = structs [r].ancestors))
1150 return;
1152 for (i = 0; a [i].rec != -1; i++)
1153 if (direct_ancest (&a [i])) {
1154 if (is_aliasclass (a [i].rec)) {
1155 rec = is_aliasclass (a [i].rec);
1156 for (j = 0; a [j].rec != rec; ++j);;;
1157 virt = a [j].status == ASTATUS_VIRT;
1158 if (virt)
1159 for (j = 0; a [j].rec != -1; j++) {
1160 if (a [j].path [0] == a [i].path [0] && a [j].path [1] == '.')
1161 a [j].path [1] = POINTSAT;
1162 if (a [j].cpath)
1163 if (a [j].cpath [0] == a [i].path [0] && a [j].cpath [1] == '.')
1164 a [j].path [1] = POINTSAT;
1166 } else {
1167 rec = a [i].rec;
1168 virt = a [i].status == ASTATUS_VIRT;
1170 for (j = 0; j < ri; j++)
1171 if (rp [j] == rec) break;
1172 if (j < ri) continue;
1173 rp [ri++] = rec;
1174 outprintf (o, RESERVED_struct, name_of_struct (rec),
1175 STAR_IF (virt), a [i].path [0], ';', -1);
1178 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1179 // general queries
1180 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1182 int lookup_struct (Token e)
1184 intnode *n = intfind (structtree, e);
1185 return n ? n->v.i : 0;
1188 int is_struct (Token e)
1190 intnode *n = intfind (structtree, e);
1191 return n == NULL ? 0 : structs [n->v.i].notunion;
1194 Token name_of_struct (recID r)
1196 return structs [r].name;
1199 typeID pthis_of_struct (recID r)
1201 return structs [r].type_pthis;
1204 fspace FSP (recID r)
1206 return r ? structs [r].Funcs : Global;
1209 bool has_const_members (recID r)
1211 return structs [r].constd || structs [r].vt_inthis;
1213 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1214 // members
1215 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1217 static Token ancest_ptr (ancestor *a)
1219 return a->status == ASTATUS_VIRT && a->vbase == a->rec ? POINTSAT : '.';
1222 static typeID has_member (recID r, Token m, Token path[], Token *glob_name)
1224 member *M;
1226 for (M = structs [r].firstmember; M; M = M->next)
1227 if (M->m == m) {
1228 path [0] = m;
1229 path [1] = -1;
1230 if (glob_name) *glob_name = M->gn;
1231 return M->t;
1234 anonunion *a;
1235 typeID t;
1237 for (a = structs [r].anonunions; a; a = a->next)
1238 if ((t = has_member (a->r, m, path + 2, glob_name)) != -1) {
1239 path [0] = a->n;
1240 path [1] = '.';
1241 return t;
1244 return -1;
1247 typeID lookup_variable_member (recID r, Token m, Token *path, bool const_path, Token *glob_name)
1249 int i;
1250 typeID t, rt = -1;
1251 ancestor *a;
1252 Token p [64], nglob = 0;
1253 bool vptrm = m == RESERVED__v_p_t_r_;
1255 r = aliasclass (r);
1257 if ((t = has_member (r, m, p, glob_name)) != -1) {
1258 rt = t;
1259 if (path) sintprintf (path, ISTR (p), -1);
1262 if ((a = structs [r].ancestors))
1263 for (i = 0; a [i].rec != -1; i++)
1264 if ((t = has_member (a [i].rec, m, p, &nglob)) != -1) {
1265 if (rt != -1 || a [i].status == ASTATUS_FSCKD) {
1266 if (base_of (t) == B_PURE) {
1267 continue;
1268 } else if (vptrm) {
1269 expr_errort ("Ambiguous vptr for class",
1270 name_of_struct (r));
1271 } else {
1272 expr_errort ("Ambigous member", m);
1275 rt = t;
1276 if (glob_name) *glob_name = nglob;
1277 nglob = 0;
1278 if (path) sintprintf (path,
1279 ISTR (const_path && a [i].cpath ? a [i].cpath : a [i].path),
1280 const_path && a [i].cpath ? '.' : ancest_ptr (&a [i]),
1281 ISTR (p), -1);
1284 return rt;
1287 static bool is_ctorable (typeID t)
1289 return (isstructure (t) && need_construction (base_of (t)))
1290 || is_array_of_ctorable_objects (t);
1293 void add_variable_member (recID r, Token m, typeID t, Token gn, bool constant, bool ncto)
1295 typeID lt;
1297 if (!structs [r].incomplete)
1298 parse_error_ll ("structure closed");
1299 if (m != RESERVED__v_p_t_r_ && (lt = lookup_variable_member (r, m, 0, 0, 0)) != -1
1300 && base_of (lt) != B_PURE)
1301 parse_error_tok (m, "member duplicate");
1302 if (!gn && !ncto && is_ctorable (t)) {
1303 ctorable_t *cc = add_ctorable (r);
1304 cc->ot = base_of (t);
1305 cc->array = !isstructure (t);
1306 cc->obn = m;
1308 if (!gn && !structs [r].constd)
1309 if (constant || (isstructure (t) && structs [base_of (t)].constd))
1310 structs [r].constd = true;
1311 member *M = (member*) malloc (sizeof *M);
1312 M->m = m;
1313 M->t = t;
1314 M->gn = gn;
1315 M->next = 0;
1316 if (structs [r].firstmember) {
1317 structs [r].lastmember->next = M;
1318 structs [r].lastmember = M;
1319 } else {
1320 structs [r].firstmember = structs [r].lastmember = M;
1323 // #|#|#|#|#|#|#|#|#|#|#|#|#|#|#
1324 // some stuff
1325 // #|#|#|#|#|#|#|#|#|#|#|#|#|#|#
1327 static bool have_exact_function_member (recID, Token, typeID[], flookup*);
1329 bool has_void_ctor (recID r)
1331 typeID args [] = { pthis_of_struct (r), INTERNAL_ARGEND };
1332 flookup F;
1334 bool re = have_exact_function_member (r, RESERVED_ctor, args, &F);
1335 if (re) SET_MAYTHROW (F);
1336 return re;
1339 bool has_copy_ctor (recID r)
1341 typeID args [] = { pthis_of_struct (r), pthis_of_struct (r), INTERNAL_ARGEND };
1342 flookup F;
1344 bool re = have_exact_function_member (r, RESERVED_ctor, args, &F);
1345 if (re) SET_MAYTHROW (F);
1346 return re;
1349 void set_dfunc (recID r, Token dn, bool nothrow, bool autodtor)
1351 structs [r].dtor_nothrow = nothrow;
1352 structs [r].dtor_name = dn;
1353 structs [r].has_dtor = true;
1354 structs [r].autodtor |= autodtor;
1357 bool isunion (recID r)
1359 return !structs [r].notunion;
1362 bool has_dtor (recID r)
1364 return structs [r].has_dtor;
1367 bool always_unwind (recID r)
1369 return structs [r].unwind;
1372 Token dtor_name (recID r)
1374 if (!structs [r].dtor_nothrow)
1375 may_throw = true;
1376 return structs [r].dtor_name;
1379 void set_dtor_nothrow (recID r)
1381 structs [r].dtor_nothrow = true;
1384 Token idtor (recID r)
1386 return structs [r].idtor;
1389 Token vdtor (recID r)
1391 return structs [r].vdtor;
1394 void set_declaration (recID r, Token *code)
1396 structs [r].code = code;
1399 static bool has_named_func (recID r, Token f)
1401 if (have_function (structs [r].Funcs, f)) return true;
1402 ancestor *a;
1403 if ((a = structs [r].ancestors))
1404 for (; a->rec != -1; a++)
1405 if (have_function (structs [a->rec].Funcs, f))
1406 return true;
1407 return false;
1410 bool has_ctors (recID r)
1412 return has_named_func (r, RESERVED_ctor);
1415 bool has_oper_fcall (recID r)
1417 return has_named_func (r, RESERVED_oper_fcall);
1419 // #+#+#+#+#+#+#+#+#+#+#+#+#
1420 // function members
1421 // #+#+#+#+#+#+#+#+#+#+#+#+#
1423 // lookup a function in parent classes and inherit the useful
1424 // flags: AUTO, VIRTUAL, MODULAR
1425 int inherited_flagz (recID r, Token f, typeID t)
1427 ancestor *a = structs [r].ancestors;
1429 if (!a) return 0;
1431 funcp *p;
1432 int flagz = 0;
1433 typeID *pargl = promoted_arglist_t (t);
1434 typeID *cargv = (typeID*) allocaint (intlen (pargl) + 3);
1435 intcpy (cargv, pargl);
1436 free (pargl);
1438 for (; a->rec != -1; a++) {
1439 cargv [0] = structs [a->rec].type_pthis;
1440 if ((p = xlookup_function_dcl (structs [a->rec].Funcs, f, cargv)))
1441 flagz |= p->flagz;
1444 return flagz & (FUNCP_AUTO | FUNCP_VIRTUAL | FUNCP_MODULAR);
1447 // lookup function flagz in declarations in class
1448 // useful flags: CONST-THIS, MODULAR, AUTO
1449 int exported_flagz (recID r, Token f, typeID t)
1451 typeID *argv = promoted_arglist_t (t);
1452 funcp *p;
1453 int ret = FUNCP_UNDEF;
1455 if ((p = xlookup_function_dcl (structs [r].Funcs, f, argv)))
1456 ret = p->flagz & (FUNCP_CTHIS | FUNCP_MODULAR | FUNCP_AUTO);
1457 free (argv);
1458 return ret;
1461 static int looking_for;
1463 static int has_fmember (recID r, Token f, typeID argv[], flookup *F)
1465 if (!structs [r].Funcs) return 0;
1466 argv [0] = structs [r].type_pthis;
1467 return xlookup_function (structs [r].Funcs, f, argv, F) == looking_for;
1470 static bool _lookup_function_member (recID r, Token f, typeID argv[], flookup *F)
1472 int i, lt;
1473 flookup tmp;
1474 recID rt = -1;
1475 ancestor *a;
1477 if ((lt = has_fmember (r, f, argv, F)))
1478 return true;
1480 if ((a = structs [r].ancestors))
1481 for (i = 0; a [i].rec != -1; i++)
1482 if ((lt = has_fmember (a [i].rec, f, argv, &tmp))) {
1483 if (rt == -1 || isancestor (a [i].rec, rt)) {
1484 if (a [i].status == ASTATUS_FSCKD)
1485 goto really_fsckd;
1486 rt = lt == 1 ? a [i].rec : -2;
1487 *F = tmp;
1488 } else if (!isancestor (rt, a [i].rec)) really_fsckd:
1489 expr_errort ("Ambigous member function", f);
1492 if (rt == -1)
1493 return false;
1494 argv [0] = rt >= 0 ? structs [rt].type_pthis : -1;
1495 return true;
1498 int lookup_function_member (recID r, Token f, typeID argv[], flookup *F, bool definite)
1500 looking_for = 3;
1501 if (_lookup_function_member (r, f, argv, F))
1502 return 3;
1504 // global function exact match > member function overload promotion
1505 if (!definite && xlookup_function (Global, f, &argv [1], F) == 3)
1506 return 0;
1508 looking_for = 2;
1509 if (_lookup_function_member (r, f, argv, F))
1510 return 2;
1512 looking_for = 1;
1513 return _lookup_function_member (r, f, argv, F);
1516 static Token has_fmember_uname (recID r, Token f)
1518 if (!structs [r].Funcs) return 0;
1519 return xlookup_function_uname (structs [r].Funcs, f);
1522 Token lookup_function_member_uname (recID *r, Token f)
1524 int i, lt = 0, rr;
1525 recID rt = -1;
1526 ancestor *a;
1528 if ((lt = has_fmember_uname (*r, f)))
1529 return lt;
1531 if ((a = structs [*r].ancestors))
1532 for (i = 0; a [i].rec != -1; i++)
1533 if ((rr = has_fmember_uname (a [i].rec, f))) {
1534 if (rt == -1 || isancestor (a [i].rec, rt)) {
1535 if (a [i].status == ASTATUS_FSCKD)
1536 goto really_fsckd;
1537 rt = a [i].rec;
1538 lt = rr;
1539 } else if (!isancestor (rt, a [i].rec)) really_fsckd:
1540 parse_error_tok (f, "Ambigous member function");
1542 *r = rt;
1543 return lt;
1546 static bool have_exact_function_member (recID r, Token f, typeID argv[], flookup *F)
1548 looking_for = 2;
1549 return _lookup_function_member (r, f, argv, F)
1550 || (looking_for = 3, _lookup_function_member (r, f, argv, F));
1553 Token declare_function_member (recID r, Token f, typeID t, Token *p, Token *a, int fl,
1554 Token **d, Token section)
1556 if (!structs [r].notunion)
1557 parse_error_ll ("unions may not be have member functions");
1558 funcp *fp = xdeclare_function (&structs [r].Funcs, f,
1559 name_member_function (r, f), t, p, a, fl, d, section);
1560 fp->used = !(fl & FUNCP_AUTO);
1561 return fp->name;
1563 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1564 // misc
1565 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
1567 bool Can_instantiate (recID r)
1569 switch (structs [r].caninst) {
1570 case CANT_INCOMPL:
1571 expr_errort ("Can't instantiate incomplete class", name_of_struct (r));
1572 case CANT_PUREV:
1573 expr_errort ("Can't instantiate class. Pure virtual functions still in there",
1574 name_of_struct (r));
1575 case CANT_NUFO:
1576 expr_errort ("Can't instantiate class."
1577 " No unique final overrider for virtual function", name_of_struct (r));
1578 case OK_CAN:
1579 return true;
1581 return true;
1584 recID ancest_named (recID r, Token t)
1586 ancestor *a = structs [r].ancestors;
1588 while (a->path [0] != t || a->path [1] != -1)
1589 ++a;
1590 return a->rec;
1593 bool isancestor (recID rder, recID rbase)
1595 ancestor *a = structs [rder].ancestors;
1597 if (a) while (a->rec != -1)
1598 if (a++->rec == rbase) return true;
1600 return rder == rbase;
1603 int is_ancestor (recID rder, recID rbase, Token **path, bool const_path)
1605 ancestor *a = structs [rder].ancestors;
1607 if (!a) return 0;
1609 for (; a->rec != -1; a++)
1610 if (a->rec == rbase) {
1611 if (path) *path = const_path && a->cpath ? a->cpath : a->path;
1612 if (a->status == ASTATUS_FSCKD)
1613 expr_errort ("Ambigouus relationship", name_of_struct (rbase));
1614 return a->status == ASTATUS_VIRT && a->vbase == a->rec && !const_path ? 2:1;
1616 return 0;
1619 /* HOWTO: anestor status flags.
1621 ASTATUS_NORM ASTATUS_VIRT ASTATUS_VIRT2
1622 ---------------------------------------------
1623 ! -> for members No Yes No
1624 ! collapse vtis No Yes Yes
1625 ! declare vbase No Yes No
1626 ! const path No Yes Yes
1627 ! vtable good Yes No No
1628 ! downcast rtti No Yes Yes
1630 ***************************************************************/
1632 /* this here returns true if downcast rtti is needed to go from rbase to rder */
1633 bool is_ancestor_runtime (recID rder, recID rbase, Token **path)
1635 if (is_ancestor (rder, rbase, path, false) == 2 || intchr (*path, POINTSAT))
1636 return true;
1637 ancestor *a = structs [rder].ancestors;
1638 while (a->rec != rbase) a++;
1639 return a->status == ASTATUS_VIRT2;
1642 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1644 // auto functions
1646 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1648 bool PARENT_AUTOFUNCS;
1650 void add_auto_f (Token ifn, Token fn, recID r, typeID t, bool virtual, bool pure, NormPtr dclPtr,
1651 Token *proto, Token *argv)
1653 autofunc *a;
1654 typeID *va = promoted_arglist_t (t);
1656 for (a = structs [r].autofuncs; a; a = a->next)
1657 if (a->name == fn && (arglist_compare (va, a->arglist)
1658 || (PARENT_AUTOFUNCS && dclPtr == a->dclPtr)))
1659 break;
1661 if (!a) {
1662 a = add_autofunc (r);
1663 a->name = fn;
1664 a->arglist = va;
1665 a->virtual = virtual;
1666 a->status = pure ? AU_STATUS_PV : AU_STATUS_DD;
1667 a->dname = a->fname = ifn;
1668 a->pname = -1;
1669 } else {
1670 free (va);
1672 //* commented out. does not allow to redefine an auto function
1673 //* with pure typedefs in its arguments in a class that they
1674 //* have been specialized... We only miss report of a rare error
1675 //if (a->status == AU_STATUS_DD)
1676 // parse_error_tok (fn, "auto-function redefined");
1678 if (virtual && !a->virtual)
1679 parse_error_tok (fn, "auto-function was not declared virtual");
1680 a->fname = ifn;
1681 // smart hack
1682 // PEND means it's inherited and we expect redef
1683 // !PEND means that user has supplied new definition
1684 // and we undo what we did the first time where PEND was true
1685 if (a->status != AU_STATUS_PEND)
1686 a->dname = ifn, a->pname = -1;
1687 a->status = pure ? AU_STATUS_PV : AU_STATUS_DD;
1689 a->dclPtr = dclPtr;
1690 a->proto = intdup (proto);
1691 a->argv = intdup (argv);
1692 a->type = t;
1695 int borrow_auto_decls (recID r, NormPtr ret[])
1697 int i;
1698 autofunc *a;
1700 for (i = 0, a = structs [r].autofuncs; a; a = a->next)
1701 if (a->status == AU_STATUS_ND) {
1702 a->status = AU_STATUS_PEND;
1703 ret [i++] = a->dclPtr;
1705 ret [i] = -1;
1706 return i;
1709 void repl__CLASS_ (Token **proto, recID r)
1711 if (is_aliasclass (r))
1712 intsubst (*proto, RESERVED__CLASS_, name_of_struct (r));
1713 else {
1714 Token tmp [200];
1715 int i = 0, j = 0;
1716 for (;;)
1717 if ((*proto) [i] == RESERVED__CLASS_) {
1718 tmp [j++] = RESERVED_struct;
1719 tmp [j++] = name_of_struct (r);
1720 ++i;
1721 } else if ((tmp [j++] = (*proto) [i++]) == -1) break;
1722 free (*proto);
1723 *proto = intdup (tmp);
1727 /* commit all the auto functions to require definition/instantiation */
1728 static void commit_auto_functions (recID r)
1730 autofunc *a;
1732 for (a = structs [r].autofuncs; a; a = a->next)
1733 if (a->status != AU_STATUS_NU) {
1734 if (is_aliasclass (r))
1735 remove_struct_from_this (a->proto, r);
1736 if (intchr (a->proto, RESERVED__CLASS_))
1737 repl__CLASS_ (&a->proto, r);
1738 commit_auto_define (a->dname, r, a->fname, a->pname, a->virtual,
1739 a->proto, a->argv, a->type);
1740 } else warning_tok ("No unique final overrider for auto function of",
1741 name_of_struct (r));
1744 /* inherit auto functions and change DD to ND (not declared) */
1745 static void inherit_auto_functions (recID r)
1747 ancestor *a;
1748 autofunc *af, *hf;
1749 int i;
1751 a = structs [r].ancestors;
1753 for (i = 0; a [i].rec != -1; i++)
1754 if (direct_ancest (&a [i])) {
1755 for (af = structs [a [i].rec].autofuncs; af; af = af->next) {
1756 for (hf = structs [r].autofuncs; hf; hf = hf->next)
1757 if (hf->name == af->name && arglist_compare (hf->arglist, af->arglist))
1758 break;
1759 if (hf) {
1760 if (af->status == AU_STATUS_PV) continue;
1761 if (hf->status == AU_STATUS_PV) goto wins;
1762 if (hf->status == AU_STATUS_ND && af->status == AU_STATUS_DD
1763 && hf->dclPtr == af->dclPtr) continue;
1764 hf->status = AU_STATUS_NU;
1765 } else {
1766 hf = add_autofunc (r);
1767 wins:
1768 hf->name = af->name;
1769 hf->dname = af->dname;
1770 hf->pname = hf->fname = af->fname;
1771 hf->virtual = af->virtual;
1772 hf->status = af->status;
1773 hf->arglist = intdup (af->arglist);
1774 hf->dclPtr = af->dclPtr;
1775 hf->proto = af->proto;
1776 hf->argv = af->argv;
1777 hf->type = af->type;
1778 if (hf->status == AU_STATUS_DD)
1779 hf->status = AU_STATUS_ND;
1782 if (structs [a [i].rec].autodtor)
1783 structs [r].autodtor = 1;
1787 /* upcast from this to a direct parent using constant path if avail */
1788 Token *upcast1_this (recID rder, recID rbase)
1790 static Token retp [15];
1791 ancestor *a = structs [rder].ancestors;
1793 if (aliasclass (rder) == aliasclass (rbase))
1794 sintprintf (retp, RESERVED_this, -1);
1795 else {
1796 while (a->rec != rbase) a++;
1798 if (a->status == ASTATUS_NORM)
1799 sintprintf (retp, '&', RESERVED_this, POINTSAT, a->path [0], -1);
1800 else if (a->cpath)
1801 sintprintf (retp, '&', RESERVED_this, POINTSAT, ISTR (a->cpath), -1);
1802 else sintprintf (retp, RESERVED_this, POINTSAT, a->path [0], -1);
1805 return retp;
1808 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1810 // pure data members
1812 // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1814 void add_pure_dm (recID r, Token bt, NormPtr dcl)
1816 puredm *p;
1818 for (p = structs [r].pm; p; p = p->next)
1819 if (p->bt == bt) {
1820 if (!intchr (p->dcls, dcl))
1821 intcatc (p->dcls, dcl);
1822 return;
1824 p = (puredm*) malloc (sizeof *p);
1825 p->next = structs [r].pm;
1826 structs [r].pm = p;
1827 p->bt = bt;
1828 sintprintf (p->dcls, dcl, -1);
1831 void gen_pure_dm (recID r, OUTSTREAM O)
1833 puredm *p;
1834 ancestor *a = structs [r].ancestors;
1835 int i, j;
1836 Token t;
1838 if (a) for (i = 0; a [i].rec != -1; i++)
1839 if (direct_ancest (&a [i]))
1840 for (p = structs [a [i].rec].pm; p; p = p->next) {
1841 if ((t = lookup_local_typedef (r, p->bt))
1842 && base_of (lookup_typedef (t)) != B_PURE)
1843 for (j = 0; p->dcls [j] != -1; j++)
1844 struct_declaration (r, O, p->dcls [j]);
1845 else for (j = 0; p->dcls [j] != -1; j++)
1846 add_pure_dm (r, p->bt, p->dcls [j]);
1850 //************************************************************
1851 // renaming functions due to overload adds complexity
1852 //************************************************************
1854 void rename_hier (Token on, Token nn)
1856 int i;
1857 autofunc *a;
1859 for (i = 0; i < nstructs; i++)
1860 if (structs [i].incomplete) {
1861 for (a = structs [i].autofuncs; a; a = a->next) {
1862 // one of the two is redundant
1863 if (a->dname == on) a->dname = nn;
1864 if (a->fname == on) {
1865 a->fname = nn;
1866 if (intchr (a->proto, on))
1867 intsubst1 (a->proto, on, nn);
1870 if (structs [i].keyfunc == on)
1871 structs [i].keyfunc = nn;