Added package with the documentation and the examples
[lwc.git] / dcl.c
blob93d2fc4633f2c300aea151f0ef53528438d25c80
1 #include "global.h"
3 /******************************************************************************
5 Welcome to the dcl module. A parser of C declarations.
7 This is what's called `a kludge'.
8 However, based on the good foundaries of the other modules
9 we can advance adding extensions here, making the code even
10 more hairy.
12 Eventually this becomes a parser for LWC declarations.
14 ******************************************************************************/
16 recID current_scope [16];
17 int top_scope;
18 #define PUSH_CURRENT_SCOPE(x) current_scope[++top_scope]=x
19 #define POP_CURRENT_SCOPE --top_scope
21 #define BASETYPE_ABSTRACT -2
22 #define BASETYPE_SKIP -3
24 typedef struct {
25 int dclqual_i;
26 Token dclqual [8];
27 Token shortname [80];
28 recID basetype;
29 typeID basetype2;
30 bool istypedef, isvirtual, isextern, isstatic, isauto, isvolatile, is__noctor__,
31 isinline, isconst, islinkonce, ismodular, is__unwind__, isfinal, is__emit_vtbl__;
32 Token section;
33 Token class_name;
34 Token btname;
35 bool anon_union, maybe_ctor;
36 } Dclbase;
38 static Dclbase *outer_dclqual;
40 Token bt_macro;
41 Token bt_replace;
43 static NormPtr collect_dclqual (Dclbase *b, NormPtr p, int remove_attributes)
45 more:
46 while (ISDCLFLAG (CODE [p]))
47 b->dclqual_i |= 1 << (CODE [p++] - RESERVED_auto);
48 /* Feature: __section__ ("foo") declaration spec */
49 if (CODE [p] == RESERVED___section__) {
50 if (CODE [p + 1] != '(' || !is_literal (CODE [p + 2]) || CODE [p + 3] != ')')
51 parse_error (p, "__section__ '(' 'string literal' ')'");
52 b->section = CODE [p + 2];
53 p += 4;
54 goto more;
56 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
57 if (remove_attributes && CODE [p] == RESERVED___attribute__) {
58 /* cygwin: uses attributes between dclquals. Ignore it */
59 p = skip_parenthesis (p + 2);
60 goto more;
62 return p;
65 /* Take the declaration qualifiers from a decl and
66 * enable them for another decl */
67 static void append_dclqual (Dclbase *b, Dclbase *m)
69 if (b->isstatic) {
70 if (!intchr (m->dclqual, RESERVED_extern)
71 && !intchr (m->dclqual, RESERVED_static))
72 intcatc (m->dclqual, RESERVED_static);
73 m->isstatic = 1;
75 if (b->isinline) {
76 if (!intchr (m->dclqual, RESERVED_inline))
77 intcatc (m->dclqual, RESERVED_inline);
78 m->isinline = 1;
80 if (b->isvirtual) m->isvirtual = 1;
81 if (b->isauto) m->isauto = 1;
82 if (b->ismodular) m->ismodular = 1;
83 if (b->isfinal) m->isfinal = 1;
84 if (b->section && !m->section) m->section = b->section;
87 static void sumup_dclqual (Dclbase *b)
89 #define ADDFLAG(x) b->is ## x = b->dclqual_i & (1 << (RESERVED_ ## x - RESERVED_auto))
90 int i, j = 0;
91 for (i = RESERVED_auto + 1; ISCDCLFLAG (i); i++)
92 if ((b->dclqual_i & (1 << (i - RESERVED_auto))))
93 b->dclqual [j++] = i;
94 b->dclqual [j] = -1;
95 ADDFLAG(typedef); ADDFLAG(virtual);
96 ADDFLAG(extern); ADDFLAG(static);
97 ADDFLAG(auto); ADDFLAG(inline);
98 ADDFLAG(const); ADDFLAG(linkonce);
99 ADDFLAG(modular); ADDFLAG(__unwind__);
100 ADDFLAG(volatile); ADDFLAG(final);
101 ADDFLAG(__noctor__); ADDFLAG(__emit_vtbl__);
104 static NormPtr bt_builtin (Dclbase *b, NormPtr p)
106 Token bt = RESERVED_int;
107 int sh, lo, si, us, i = 0;
109 for (sh = lo = si = us = 0; ISTBASETYPE (CODE [p]); p++)
110 switch (CODE [p]) {
111 case RESERVED_short: sh++;
112 ncase RESERVED_long: lo++;
113 ncase RESERVED_signed: si++;
114 ncase RESERVED_unsigned: us++;
115 ndefault: bt = CODE [p];
118 switch (bt) {
119 case RESERVED_float:
120 b->basetype = B_FLOAT;
121 b->shortname [i++] = RESERVED_float;
122 ncase RESERVED_void:
123 b->basetype = B_VOID;
124 b->shortname [i++] = RESERVED_void;
125 ncase RESERVED_double:
126 if (lo) {
127 b->basetype = B_LDOUBLE;
128 b->shortname [i++] = RESERVED_long;
129 b->shortname [i++] = RESERVED_double;
130 } else {
131 b->basetype = B_DOUBLE;
132 b->shortname [i++] = RESERVED_double;
134 ncase RESERVED_char:
135 if (us) {
136 b->basetype = B_UCHAR;
137 b->shortname [i++] = RESERVED_unsigned;
138 } else
139 b->basetype = B_SCHAR;
140 b->shortname [i++] = RESERVED_char;
141 ncase RESERVED_int:
142 if (lo) {
143 if (us) {
144 b->basetype = lo > 1 ? B_ULLONG : B_ULONG;
145 b->shortname [i++] = RESERVED_unsigned;
146 } else
147 b->basetype = lo > 1 ? B_SLLONG : B_SLONG;
148 b->shortname [i++] = RESERVED_long;
149 if (lo > 1)
150 b->shortname [i++] = RESERVED_long;
151 } else if (sh) {
152 if (us) {
153 b->basetype = B_USINT;
154 b->shortname [i++] = RESERVED_unsigned;
155 } else
156 b->basetype = B_SSINT;
157 b->shortname [i++] = RESERVED_short;
158 b->shortname [i++] = RESERVED_int;
159 } else {
160 if (us) {
161 b->basetype = B_UINT;
162 b->shortname [i++] = RESERVED_unsigned;
163 } else
164 b->basetype = B_SINT;
165 b->shortname [i++] = RESERVED_int;
167 ndefault:
168 parse_error (p, "BUG");
170 b->shortname [i] = -1;
171 return p;
174 static recID is_object_in_global (NormPtr p)
176 while (CODE [p] != '.' && CODE [p] != '(' && CODE [p] != ';' && CODE [p] != ',')
177 p++;
178 if (CODE [p] != '.') return 0;
179 return lookup_struct (CODE [p - 1]);
182 static NormPtr bt_name (Dclbase *b, NormPtr p)
184 recID r;
185 Token x, y, t;
186 bool iname = false;
188 if ((x = CODE [p]) == RESERVED__CLASS_) {
189 if ((x = name_of_struct (current_scope [top_scope])) == NOOBJ)
190 if (r = is_object_in_global (p)) {
191 x = name_of_struct (r);
192 goto keep;
193 } else parse_error (p, "_CLASS_ invalid here");
194 if (PARENT_AUTOFUNCS) keep: {
195 /* Special case: _CLASS_ in the prototype of an
196 auto-function. Leave it as _CLASS_ and later
197 at commit_auto, replace with actual type. The
198 problem is that we don't yet know if this is
199 an aliasclass or not. */
200 b->basetype = lookup_struct (x) ?: x;
201 sintprintf (b->shortname, RESERVED__CLASS_, -1);
202 b->maybe_ctor = true;
203 return p + 1;
205 if (objective.recording)
206 usage_notok ();
209 b->btname = x;
211 if (0)
212 redo: iname = 1; switch (y = is_typename (x)) {
213 case 0:
214 /* Feature: template abstract classes */
215 if (bt_macro && x == bt_macro) {
216 x = bt_replace;
217 goto renamed;
219 /* Feature: local typedefs in global scope */
220 if (top_scope) {
221 int i;
222 for (i = top_scope; i; --i)
223 if (t = lookup_local_typedef (current_scope [i], x)) {
224 x = t;
225 goto redo;
228 if ((r = is_object_in_global (p)))
229 if (x = lookup_local_typedef (r, x))
230 goto redo;
231 /* - - - - - - - - - - - - - - - - - - - - */
232 if (is_extern_templ_func (&p)) {
233 b->basetype = BASETYPE_SKIP;
234 return p;
236 /* ////////////////////////////////// */
237 parse_error_pt (p, x, "Not good for a base type");
238 ncase 1:;
239 typeID tt = b->basetype2 = lookup_typedef (x);
240 b->basetype = -1;
241 if (iname && open_typeID (tt)[1] == -1)
242 name_of_simple_type (b->shortname, tt);
243 else {
244 b->shortname [0] = x;
245 b->shortname [1] = -1;
247 ncase 2:
248 renamed:
249 /* Feature: structure.constructor not a base type */
250 if (CODE [p + 1] == '.') {
251 Token t = CODE [p + 2];
252 if (t == RESERVED_ctor
253 || t == RESERVED_dtor || t == CODE [p]
254 || (t == '~' && in2 (CODE [p + 3], CODE [p], RESERVED_dtor))) {
255 b->basetype = B_VOID;
256 b->shortname [0] = -1;
257 return p;
260 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
261 b->basetype = lookup_struct (x) ?: x;
262 if (lookup_struct (x) && is_aliasclass (b->basetype))
263 sintprintf (b->shortname, x, -1);
264 else sintprintf (b->shortname, RESERVED_struct, x, -1);
265 b->maybe_ctor = true;
266 ncase 3:
267 b->basetype = B_SINT;
268 b->shortname [0] = RESERVED_enum;
269 b->shortname [1] = x;
270 b->shortname [2] = -1;
271 ndefault:
272 /* local typedef redirection */
273 /* XXXX: could we loop ??? */
274 x = y;
275 goto redo;
277 return p + 1;
280 /* Feature: do typeof */
281 static NormPtr bt_typeof (Dclbase *b, NormPtr p)
283 exprret E;
285 if (CODE [p++] != '(')
286 parse_error (p, "typeof '('");
287 p = parse_expression (p, &E, NORMAL_EXPR);
288 if (!E.ok) parse_error (p, "compilation halted due to expression error");
289 if (CODE [p++] != ')')
290 parse_error (p, "typeof (...')'");
292 sintprintf (b->shortname, RESERVED___typeof__, '(', ISTR (E.newExpr), ')', -1);
293 free (E.newExpr);
294 b->basetype = -1;
295 b->basetype2 = E.type;
297 return p;
299 /* ~~~~~~~~~~~~~~~~~ */
301 static NormPtr enum_dcl (Dclbase *b, NormPtr p, bool benum, enumID e)
303 int i = 0, j = 0;
304 Token ev [2048];
306 ev [j++] = b->shortname [1];
307 outprintf (GLOBAL, ISTR (b->shortname), '{', -1);
308 for (;; p++) {
309 if (CODE [p] == '}') break;
310 if (!ISSYMBOL (CODE [p]))
311 parse_error (p, "enum noise internal");
312 enter_enumconst (ev [j++] = CODE [p], e);
313 output_itoken (GLOBAL, CODE [p++]);
314 if (benum)
315 outprintf (GLOBAL, '=', binshift [31 & i++], -1);
316 else if (CODE [p] == '=') {
317 exprret E;
318 p = parse_const_expression (1 + p, &E);
319 if (E.ok) {
320 outprintf (GLOBAL, '=', ISTR (E.newExpr), - 1);
321 free (E.newExpr);
325 if (CODE [p] == ',') {
326 output_itoken (GLOBAL, ',');
327 continue;
330 if (CODE [p] == '}')
331 break;
332 parse_error_ll ("error in enum");
334 outprintf (GLOBAL, '}', ';', -1);
335 ev [j++] = -1;
336 enter_enum_syms (e, ev, j);
337 return p + 1;
340 static NormPtr bt_enum (Dclbase *b, NormPtr p, bool benum)
342 enumID e;
344 b->basetype = B_SINT;
345 b->shortname [0] = RESERVED_enum;
346 b->shortname [2] = -1;
347 if (CODE [p] == '{') {
348 e = enter_enum (b->shortname [1] = name_anonymous_enum ());
349 return enum_dcl (b, p + 1, benum, e);
351 if (!ISSYMBOL (CODE [p]))
352 parse_error_ll ("erroneous enum declaration");
353 e = enter_enum (b->shortname [1] = CODE [p++]);
354 if (CODE [p] == '{')
355 return enum_dcl (b, p + 1, benum, e);
356 return p;
359 static NormPtr parse_structure (Token, Dclbase*, NormPtr, Token, Token*);
360 static NormPtr parse_inheritance (NormPtr, recID, Token[]);
362 static NormPtr bt_struct (Dclbase *b, NormPtr p, Token struct_or_union)
364 Token abstract_parents [64] = { -1, };
365 Token tag = struct_or_union == RESERVED_union ? RESERVED_union : RESERVED_struct;
367 bool anon = CODE [p] == '{' || CODE [p] == ':';
369 if (!anon && !ISSYMBOL (CODE [p]))
370 parse_error_ll ("Das is verbotten");
371 Token name = anon ? name_anonymous_struct () : CODE [p++];
373 if (anon) b->anon_union = true;
375 bool need_fwd = !lookup_struct (name);
377 if (have_abstract (name))
378 parse_error_tok (name, "already have abstract class named that");
380 b->basetype = enter_struct (name, struct_or_union, b->is__unwind__, b->is__noctor__,
381 b->is__emit_vtbl__, b->isstatic);
383 /* Feature: Inheritance */
384 if (CODE [p] == ':')
385 p = parse_inheritance (p + 1, b->basetype, abstract_parents);
386 /* # # # # # # # # # # #*/
388 if (CODE [p] == '{') {
389 p = parse_structure (name, b, p + 1, tag, abstract_parents);
391 if (is_dcl_start (CODE [p]) && CODE [p] != name)
392 warning_tok ("(?) Forgot semicolon after the"
393 " definition of class", name);
396 sintprintf (b->shortname, is_aliasclass (b->basetype) ? BLANKT : tag,
397 name, -1);
399 if (need_fwd && !is_aliasclass (b->basetype))
400 outprintf (GLOBAL, ISTR (b->shortname), ';', -1);
402 return p;
405 static Token specialized (Token, NormPtr);
407 /* Feature: Unique Specialization for template class */
408 static NormPtr bt_specialize (Dclbase *b, NormPtr p)
410 Token abstract_parents [64] = { -1, };
411 Token c = CODE [p++], sp;
413 if (!ISSYMBOL (c) || !have_abstract (c) || CODE [p] != '{')
414 parse_error (p, "No such abstract class");
416 /* * * * * * * * * * * */
417 sp = specialized (c, ++p);
418 /* * * * * * * * * * * */
420 b->basetype = enter_struct (sp, true, b->is__unwind__, 0, 0, 0);
421 parse_inheritance (p - 2, b->basetype, abstract_parents);
423 if (abstract_has_special (c, b->basetype))
424 p = skip_braces (p);
425 else {
426 Token abp [] = { c, -1 };
427 outprintf (GLOBAL, iRESERVED_struct (b->basetype), sp, ';', -1);
428 SAVE_VARC (b->isstatic, 0, s);
429 p = parse_structure (sp, b, p, RESERVED_struct, abp);
430 RESTOR_VARC (b->isstatic, s);
432 sintprintf (b->shortname, iRESERVED_struct (b->basetype), sp, -1);
434 return p;
437 /* Feature: Base type abstract class */
438 static NormPtr bt_abstract (Dclbase *b, NormPtr p)
440 Token an, par [32], c;
441 recID rpar [32];
442 int pc = 0, rc = 0;
443 NormPtr p1;
445 if (!ISSYMBOL (CODE [p]))
446 parse_error (p, "anonymous abstract not possible");
448 an = CODE [p++];
449 if (CODE [p] == ':') {
450 ++p;
451 do if ((c = CODE [p++]) == RESERVED_virtual)
452 if (!issymbol (c = CODE [p++]) || !lookup_object (c))
453 goto err;
454 else rpar [rc++] = lookup_object (c) + VIRTUALPAR_BOOST;
455 else if (!issymbol (c)) err:
456 parse_error (p, "Symbol expected");
457 else if (lookup_object (c))
458 rpar [rc++] = lookup_object (c);
459 else if (have_abstract (c))
460 par [pc++] = c;
461 else parse_error_tok (c, "No such class/template-class defined");
462 while (CODE [p++] == ',');
463 --p;
465 par [pc] = rpar [rc] = -1;
466 if (CODE [p++] != '{')
467 parse_error (p, "template class ... '{'");
468 p = skip_braces (p1 = p);
469 enter_abstract (an, par, rpar, p1);
470 b->basetype = BASETYPE_ABSTRACT;
471 return p;
473 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
475 /* Feature: RegExp as a basetype. send to regexp.c */
476 static NormPtr bt_regexp (Dclbase *b, NormPtr p)
478 b->basetype = BASETYPE_SKIP;
479 return parse_RegExp (p, (b->isstatic!=0) + 2 * (b->isextern!=0) + 4 * (b->isinline!=0));
482 static NormPtr parse_basetype (Dclbase *b, NormPtr p)
484 b->section = 0;
485 b->dclqual_i = 0;
486 b->anon_union = false;
487 b->maybe_ctor = false;
488 b->btname = 0;
489 p = collect_dclqual (b, p, 1);
490 sumup_dclqual (b);
492 switch (CODE [p]) {
493 case RESERVED_ctor: b->basetype = B_VOID, b->shortname [0] = -1;
494 ncase RESERVED_dtor: b->basetype = typeID_voidP, b->shortname [0] = -1;
495 ncase RESERVED_enum: p = bt_enum (b, p + 1, false);
496 ncase RESERVED_benum: p = bt_enum (b, p + 1, true);
497 ncase RESERVED_struct:
498 case RESERVED_class:
499 case RESERVED_union: p = bt_struct (b, p + 1, CODE [p]);
500 ncase RESERVED_template: p = bt_abstract (b, p + 2);
501 ncase RESERVED_specialize: p = bt_specialize (b, p + 1);
502 ncase RESERVED_typeof: p = bt_typeof (b, p + 1);
503 ncase RESERVED_RegExp: p = bt_regexp (b, p + 1);
504 ndefault:
505 if (ISTBASETYPE (CODE [p]))
506 p = bt_builtin (b, p);
507 else if (ISSYMBOL (CODE [p]))
508 /* Feature: constructor with class name */
509 if (in2 (CODE [p], b->class_name, bt_macro)
510 && CODE [p + 1] == '(') {
511 b->basetype = B_VOID;
512 b->shortname [0] = -1;
513 CODE [p] = RESERVED_ctor;
514 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
515 } else p = bt_name (b, p);
516 else if (CODE [p] == '~' && in3 (CODE [p + 1], RESERVED_dtor, b->class_name,
517 bt_macro)) {
518 /* Feature: ~obj is a dtor */
519 b->basetype = typeID_voidP;
520 b->shortname [0] = -1;
521 CODE [p + 1] = RESERVED_dtor;
522 } else parse_error_pt (p, CODE [p], "Bad basetype");
525 if (b->basetype == BASETYPE_SKIP) return p;
527 p = collect_dclqual (b, p, 0);
528 sumup_dclqual (b);
529 p = collect_dclqual (b, p, 0);
530 return p;
533 static void ctor_basetype (Dclbase *b, recID r)
535 if (b->shortname [0] != -1)
536 parse_error_ll ("Constructor may not have return type");
537 b->shortname [0] = RESERVED_void;
538 b->shortname [1] = -1;
539 b->basetype = B_VOID;
542 static void dtor_basetype (Dclbase *b, recID r)
544 if (b->shortname [0] != -1)
545 parse_error_ll ("Constructor may not have return type");
546 sintprintf (b->shortname, RESERVED_void, '*', -1);
547 b->basetype = typeID_voidP;
550 typedef struct {
551 Token cname;
552 recID rec;
553 int dclhype [128];
554 Token dclstr [512];
555 int dclhi, ip;
556 NormPtr objp;
557 int argc;
558 Token argv [32];
559 NormPtr argp [32];
560 Token *dflt_arge [32];
561 int dflt_argc;
562 bool reference;
563 bool constant;
564 int ctordtor;
565 NormPtr begins;
566 bool have_this;
567 NormPtr VLA_expr;
568 // these are drivers for dirdcl()
569 bool const_in_base;
570 bool maybe_ctor;
571 bool allowed_va;
572 } Dclobj;
574 #define DCLOBJ_INIT { .const_in_base = 0, .maybe_ctor = 0, .allowed_va = 0 }
576 /* add 'this' keyword in function prototype */
577 static void add_this (Dclobj *d, bool const_this)
579 int i;
580 Token *tmp = allocaint (intlen (d->dclstr));
582 /* alter the output declaration */
583 if (d->dclstr [d->objp + 1] != '(') parse_error_ll ("BUG 234");
584 i = d->objp + 2;
585 intcpy (tmp, d->dclstr + i);
586 if (const_this) d->dclstr [i++] = RESERVED_const;
587 d->dclstr [i++] = RESERVED_struct;
588 d->dclstr [i++] = name_of_struct (d->rec);
589 d->dclstr [i++] = '*';
590 d->dclstr [i++] = RESERVED_const;
591 d->dclstr [i++] = RESERVED_this;
592 if (tmp [0] != ')')
593 d->dclstr [i++] = ',';
594 intcpy (d->dclstr + i, tmp);
595 d->ip = intlen (d->dclstr);
596 intcpy (tmp, d->argv);
597 d->have_this = true;
601 static typeID dcltype (Dclbase *b, Dclobj *d)
603 int typet [64];
604 if (b->basetype == -1) {
605 int *td = open_typeID (b->basetype2);
606 typet [0] = td [0];
607 intcpy (typet + 1, d->dclhype);
608 intcat (typet, td + 1);
609 } else {
610 typet [0] = b->basetype;
611 typet [1] = -1;
612 if (d) intcat (typet, d->dclhype);
614 if (d->reference)
615 typet [0] += REFERENCE_BOOST;
616 return enter_type (typet);
619 static NormPtr dirdcl (Dclobj *d, NormPtr p, int inargs);
621 static NormPtr dcl (Dclobj *d, NormPtr p, int inargs)
623 int ns = 0, ps;
625 /* Feature: references */
626 if (!d->ip && (d->reference = CODE [p] == '&'))
627 ++ns, ++p, d->dclstr [d->ip++] = '*';
628 /* &-&-&-&-&-&-&-&-&-& */
630 for (;; d->dclstr [d->ip++] = CODE [p++])
631 if (CODE [p] == '*') ns++;
632 else if (CODE [p] == RESERVED___attribute__) {
633 ps = skip_parenthesis (p + 2) - 1;
634 while (p < ps) d->dclstr [d->ip++] = CODE [p++];
635 } else if (CODE [p] != RESERVED_const
636 && CODE [p] != RESERVED_volatile
637 && CODE [p] != RESERVED___restrict) break;
638 p = dirdcl (d, ps = p, inargs);
639 while (ns--) d->dclhype [d->dclhi++] = '*';
640 d->constant = CODE [ps - 1] == RESERVED_const && p - ps == 1;
641 return p;
644 static NormPtr arglist (Dclobj*, NormPtr);
646 static int count_argc (NormPtr p)
648 if (CODE [p] == ')') return 0;
649 int c = 1;
650 while (CODE [p] != ')')
651 switch (CODE [p++]) {
652 case '(': p = skip_parenthesis (p);
653 ncase ',': ++c;
655 return c;
658 static NormPtr operator_overload (NormPtr p, int memb)
660 if (in2 (CODE [p], RESERVED_new, RESERVED_delete)) {
661 if (CODE [p + 1] != '(' || CODE [p + 2] != ')')
662 parse_error (p, "the syntax is 'operator {new|delete} ();'");
663 return p;
666 bool postfix = CODE [p] == RESERVED_postfix;
668 if (postfix) ++p;
669 Token op = CODE [p];
670 if (op == '[' || op == '(' && in2 (CODE [p + 1], ')', RESERVED_oper_fcall)) ++p;
672 /*** kludgy: "operator +" is replaced by "operator operfunc_name" in
673 *** the CODE[] so next time we return early. A premature optimization!
674 ***/
675 if (!isoperator (op))
676 if (isoperfunc (op))
677 return p;
678 else parse_error_pt (p, op, "not an operator");
679 if (CODE [p + 1] != '(')
680 parse_error (p, "operator overload is a function");
681 memb += count_argc (p + 2);
682 CODE [p] = op == '(' ? RESERVED_oper_fcall :
683 memb == 1 ? postfix ? isunary_postfix_overloadable (op) :
684 isunary_overloadable (op) : memb == 2 ? isbinary_overloadable (op) : 0;
685 if (!CODE [p]) parse_error (p, "Can't overload that.");
686 return p;
689 static NormPtr dirdcl (Dclobj *d, NormPtr p, int inargs)
691 if (CODE [p] == '(' && (d->maybe_ctor ? !is_expression (p) : 1)) {
692 d->dclstr [d->ip++] = '(';
693 p = dcl (d, p + 1, inargs);
694 d->dclstr [d->ip++] = CODE [p];
695 if (CODE [p++] != ')')
696 parse_error (p, "Missing parenthesis in declaration");
697 } else if (ISSYMBOL (CODE [p])) {
698 /* Feature: member functions in global */
699 if (CODE [p + 1] == '.') {
700 Token bn, n, bm;
701 NormPtr ppp = p;
702 bn = bm = CODE [p];
703 p += 2;
704 if (bn == bt_macro) bn = bt_replace;
705 /* Feature: ctor with class name */
706 if (CODE [p] == bm)
707 CODE [p] = RESERVED_ctor;
708 else if (CODE [p] == '~' && in2 (CODE [p + 1], bm, RESERVED_dtor))
709 CODE [++p] = RESERVED_dtor;
710 else if (CODE [p] == RESERVED_operator)
711 p = operator_overload (p + 1, 1);
712 else if (!ISSYMBOL (CODE [p]))
713 parse_error (p, "Missing member");
714 d->cname = CODE [p];
715 d->ctordtor = CODE [p] == RESERVED_ctor ? 1 :
716 CODE [p] == RESERVED_dtor ? 2 : 0;
717 d->rec = lookup_object (bn);
718 if (!d->rec) {
719 /* Feature: out-of-class template func */
720 if (!is_template_function (&ppp, d->begins))
721 parse_error_pt (p, bn, "No such class");
722 d->ctordtor = BASETYPE_SKIP;
723 return ppp;
725 d->dclstr [d->objp = d->ip++] =
726 n = name_member_function (d->rec, CODE [p]);
727 if (in2 (CODE [p], RESERVED_new, RESERVED_delete))
728 enter_newdel_overload (CODE [p], d->rec, n);
729 ++p;
730 } else
731 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
732 d->dclstr [d->objp = d->ip++] = CODE [p++];
733 } else if (CODE [p] == RESERVED_this)
734 d->dclstr [d->objp = d->ip++] = CODE [p++];
735 else if (CODE [p] == RESERVED_operator) {
736 /* Feature: operator overloading */
737 p = operator_overload (p + 1, top_scope > 0);
738 d->dclstr [d->objp = d->ip++] = CODE [p++];
739 /* *+*+*+*+*+*+*+*+*+*+*+*+*+*+* */
740 } else if (CODE [p] == '~' && CODE [p + 1] == RESERVED_dtor) {
741 d->dclstr [d->objp = d->ip++] = RESERVED_dtor;
742 p += 2;
743 } else d->dclstr [d->objp = d->ip++] = BLANKT;
745 for (;;) {
746 switch (CODE [p]) {
747 case '(':
748 if (d->rec) PUSH_CURRENT_SCOPE(d->rec);
749 /* Constructor: stop at constructor initialization */
750 if (!is_dcl_start (CODE [p+1]) && CODE [p+1] != ')' && CODE [p+1] != '.'){
751 if (d->rec) POP_CURRENT_SCOPE;
752 return p;
754 /* + + + + + + + + + + + + + + + + + + + + + + + +*/
755 d->dclstr [d->ip++] = '(';
756 p = arglist (d, p + 1);
757 if (d->rec) POP_CURRENT_SCOPE;
758 continue;
759 case '[':
760 /* Feature: elliptic varargs */
761 if (CODE [p + 1] == ELLIPSIS && CODE [p + 2] == ']') {
762 sintprintf (&d->dclstr [d->ip], '[', ']', ',', RESERVED_int, 0, -1);
763 d->ip = intlen (d->dclstr);
764 d->dclhype [d->dclhi++] = B_ELLIPSIS;
765 return p + 3;
767 /* ......................... */
768 d->dclstr [d->ip++] = '[';
769 d->dclhype [d->dclhi] = d->dclhi || inargs ? '*' : '[';
770 d->dclhi++;
771 if (CODE [++p] == ']') p += 1;
772 else if (CODE [p] == RESERVED___restrict) {
773 /* int foo (char a[__restrict]); is allowed */
774 d->dclstr [d->ip++] = RESERVED___restrict;
775 p += 2;
776 } else {
777 exprret E;
778 NormPtr p0 = p;
780 p = parse_expression (p, &E, NORMAL_EXPR) + 1;
781 if (E.ok && !E.isconstant) {
782 /* Feature: store VLA info */
783 if (d->dclhi > 1)
784 parse_error (p, "non-constant [expression]");
785 d->VLA_expr = p0;
786 d->dclhype [0] = '*';
787 d->dclstr [d->ip - 1] = d->dclstr [d->ip - 2];
788 d->dclstr [d->ip - 2] = '*';
789 ++d->objp;
790 free (E.newExpr);
791 continue;
792 /* * * * * * * * * */
794 if (E.ok) {
795 NormPtr ps;
796 for (ps = 0; E.newExpr [ps] != -1;)
797 d->dclstr [d->ip++] = E.newExpr [ps++];
798 free (E.newExpr);
801 d->dclstr [d->ip++] = ']';
802 continue;
804 break;
806 return p;
809 static NormPtr append_attributes (Dclobj *d, NormPtr p)
811 while (CODE [p] == RESERVED___attribute__) {
812 if (CODE [p + 1] != '(') parse_error (p, "__attribute__ '('");
813 NormPtr p2 = skip_parenthesis (p + 2);
814 while (p < p2)
815 d->dclstr [d->ip++] = CODE [p++];
817 return p;
820 static NormPtr parse_dcl (Dclobj *d, NormPtr p, bool inargs)
822 d->have_this = 0;
823 d->argc = -1;
824 d->rec = 0, d->objp = -1;
825 d->dclhi = d->ip = 0;
826 d->cname = -1;
827 d->ctordtor = 0;
828 d->argv [0] = -1;
829 d->VLA_expr = 0;
830 p = dcl (d, p, inargs);
831 p = append_attributes (d, p);
832 if (!d->constant && !d->dclhi)
833 d->constant = d->const_in_base;
834 d->dclhype [d->dclhi] = -1;
835 if (!d->allowed_va && d->dclhype [d->dclhi - 1] == ELLIPSIS)
836 parse_error (p, "[...] not allowed here");
837 d->dclstr [d->ip] = -1;
838 return p;
841 static NormPtr arglist (Dclobj *d, NormPtr p)
843 int i, nb = 0;
844 bool elliptic;
845 typeID t;
846 Dclbase b;
847 Dclobj di = DCLOBJ_INIT;
849 b.class_name = 0;
850 d->dclhype [d->dclhi++] = '(';
851 d->dflt_argc = 0;
853 di.allowed_va = true;
855 if (CODE [p] == RESERVED_void && CODE [p + 1] == ')') {
856 ++p;
857 } else while (CODE [p] != ')') {
858 if (CODE [p] == ELLIPSIS) {
859 d->dclstr [d->ip++] = ELLIPSIS;
860 d->dclhype [d->dclhi++] = B_ELLIPSIS;
861 if (CODE [++p] != ')')
862 parse_error (p, "'...' must be last");
863 break;
865 p = parse_dcl (&di, parse_basetype (&b, p), 1);
866 if (b.basetype == BASETYPE_ABSTRACT)
867 parse_error (p, "abstract is not a real base type");
869 t = d->dclhype [d->dclhi++] = dcltype (&b, &di);
871 /* Feature: elliptic varargs */
872 elliptic = typeID_elliptic (t);
873 if (elliptic && CODE [p] != ')')
874 parse_error (p, "[...] must be last");
875 /* ......................... */
877 for (i = 0; b.dclqual [i] != -1; i++)
878 d->dclstr [d->ip++] = b.dclqual [i];
879 for (i = 0; b.shortname [i] != -1; i++)
880 d->dclstr [d->ip++] = b.shortname [i];
882 /* Feature: structure by reference */
883 if (isstructure (t) && StructByRef) {
884 d->dclstr [d->ip++] = '*';
885 d->dclstr [d->ip++] = RESERVED_const;
887 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
889 if (di.dclstr [di.objp] == BLANKT)
890 di.dclstr [di.objp] = internal_identifiern (nb++);
892 if (elliptic) {
893 Token n = di.dclstr [di.objp];
894 di.dclstr [di.objp] = token_addchar (n, 'v');
895 di.dclstr [intlen (di.dclstr) - 1] = token_addchar (n, 'c');
896 d->dclhype [d->dclhi++] = typeID_int;
899 for (i = 0; di.dclstr [i] != -1; i++)
900 d->dclstr [d->ip++] = di.dclstr [i];
902 d->argv [++d->argc] = di.dclstr [di.objp];
903 if (elliptic) d->argv [++d->argc] = di.dclstr [intlen (di.dclstr) - 1];
905 /* Feature: default function arguments */
906 if (CODE [p] == '=') {
907 if (elliptic) parse_error (p, "Doh! default varargs!");
908 NormPtr p2;
909 p = skip_expression (CODE, p2 = p + 1, INIT_EXPR);
910 d->dflt_arge [d->dflt_argc++] = intndup (CODE + p2, p - p2);
911 } else if (d->dflt_argc)
912 parse_error (p, "Default arguments ought to be last");
913 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
915 if (CODE [p] == ',') {
916 d->dclstr [d->ip++] = ',';
917 p++;
920 d->dflt_arge [d->dflt_argc] = 0;
921 d->dclstr [d->ip++] = ')';
922 d->dclhype [d->dclhi++] = INTERNAL_ARGEND;
923 d->argv [++d->argc] = -1;
924 return p + 1;
927 static inline NormPtr parse_bitfield (Dclobj *d, NormPtr p)
929 if (CODE [p] == ':') {
930 d->dclstr [d->ip++] = ':';
931 exprret E;
932 p = parse_const_expression (++p, &E);
933 if (E.ok) {
934 NormPtr ps;
935 for (ps = 0; E.newExpr [ps] != -1;)
936 d->dclstr [d->ip++] = E.newExpr [ps++];
937 free (E.newExpr);
939 d->dclstr [d->ip] = -1;
941 return p;
944 bool is_array_of_ctorable_objects (typeID t)
946 int *tt = open_typeID (t);
947 return tt [1] == '[' && tt [2] == -1 && tt [0] >= 0 && need_construction (tt [0]);
950 bool is_array_of_objects (typeID t)
952 int *tt = open_typeID (t);
953 return tt [1] == '[' && tt [2] == -1 && tt [0] >= 0;
956 /* mark the position of a function definition to be parsed later */
957 static void mark_function_def
958 (Dclbase *b, Dclobj *d, NormPtr p, recID r, typeID rett, Token cname, bool dto)
960 if (Streams_Closed)
961 return;
963 Token *tmp = allocaint (intlen (b->dclqual) +
964 intlen (b->shortname) + intlen (d->dclstr) + 3);
965 intcpy (tmp, b->dclqual);
966 intcat (tmp, b->shortname);
967 intcat (tmp, d->dclstr);
968 (CODE [p - 1] == RESERVED_alias ? store_definition_alias : store_definition)
969 (d->dclstr [d->objp], tmp, d->argv, d->dclhype + 1,
970 p, r, rett, cname, dto, b->isauto ? DT_AUTO : DT_NORM,
971 !b->ismodular);
974 static void add_dclqual (Token q, Token *ts)
976 int i;
977 for (i = 0; ts [i] != -1; i++)
978 if (ts [i] == q) return;
979 ts [i++] = q;
980 ts [i] = -1;
983 static Token pdcl_function (Dclbase *b, Dclobj *d, typeID t, int fflagz)
985 Token f = d->dclstr [d->objp];
986 Token **dflt_arg;
987 Token *tmp = allocaint (intlen (b->dclqual) +
988 intlen (b->shortname) + intlen (d->dclstr) + 3);
989 Token *tmpargv = d->argv;
991 if (d->cname == RESERVED_oper_pointsat
992 && (!isstructptr (funcreturn (t)) || isreference (funcreturn (t))))
993 parse_error_ll ("overloaded operator -> must return pointer to struct");
994 intcpy (tmp, b->dclqual);
995 intcat (tmp, b->shortname);
996 intcat (tmp, d->dclstr);
997 if (d->dflt_argc == 0) dflt_arg = 0;
998 else {
999 int i = d->dflt_argc;
1000 dflt_arg = (Token**) malloc ((i + 1) * sizeof (Token*));
1001 memcpy (dflt_arg, d->dflt_arge, i * sizeof (Token*));
1002 dflt_arg [i] = 0;
1004 if (d->have_this) {
1005 tmpargv = allocaint (intlen (d->argv) + 2);
1006 tmpargv [0] = RESERVED_this;
1007 intcpy (tmpargv + 1, d->argv);
1009 return d->rec ?
1010 declare_function_member (d->rec, d->cname, t, tmp, tmpargv, fflagz, dflt_arg, b->section) :
1011 xdeclare_function (&Global, f, f, t, tmp, tmpargv, fflagz, dflt_arg, b->section)->name;
1014 static NormPtr virtual_class_fwd (recID r, OUTSTREAM D, NormPtr p)
1016 for (;;) {
1017 if (!ISSYMBOL (CODE [p]))
1018 parse_error (p, "name expected");
1019 virtual_inheritance_decl (D, r, CODE [p++]);
1020 if (CODE [p] == ';') return p + 1;
1021 if (CODE [p++] != ',')
1022 parse_error (p, "separator");
1026 /* * * * * * Get the name of a class based on the local typedefs * * * * * */
1027 static void mk_specialized (char nm[], NormPtr p, Token have[], bool anydcl)
1029 char tmp [64];
1030 int i;
1031 while (CODE [p] != '}' && CODE [p] != -1) {
1032 if (CODE [p] == RESERVED_const
1033 && ISSYMBOL (CODE [p + 1]) && CODE [p + 3] == ';') {
1034 p = skip_declaration (p);
1035 continue;
1038 if (CODE [p] != RESERVED_typedef)
1039 if (anydcl) {
1040 p = skip_declaration (p);
1041 continue;
1042 } else parse_error (p, "specialized object may not have"
1043 " declarations other than typedefs");
1045 Dclbase b = { .dclqual_i = 0, .section = 0, .class_name = -1 };
1046 Dclobj d = DCLOBJ_INIT;
1047 typeID dt;
1049 p = parse_basetype (&b, last_location = p);
1050 d.const_in_base = b.isconst;
1052 if (b.basetype == BASETYPE_ABSTRACT)
1053 return;
1055 for (;;) {
1056 p = parse_dcl (&d, p, 0);
1058 if (d.dclstr [d.objp] == BLANKT)
1059 parse_error (p, "Abstract typedef declaration in structure?");
1061 dt = dcltype (&b, &d);
1063 for (i = 0; have [i] != -1; i++)
1064 if (have [i] == d.dclstr [d.objp])
1065 goto do_not;
1067 have [i++] = d.dclstr [d.objp];
1068 have [i] = -1;
1069 strcat (strcat (strcat (nm, "_"),
1070 expand (d.dclstr [d.objp])), nametype (tmp, dt));
1072 do_not:
1073 if (CODE [p] == ';') break;
1074 if (CODE [p++] != ',')
1075 parse_error_pt (p, CODE [p-1], "parse error in declaration separator(3)");
1077 ++p;
1081 static void specialize_do (char nm[], Token a, Token have[])
1083 SAVE_VAR (bt_macro, a);
1084 SAVE_VAR (bt_replace, a);
1085 Token *ab_par = parents_of_abstract (a);
1086 mk_specialized (nm, dcl_of_abstract (a), have, true);
1087 while (*ab_par != -1)
1088 specialize_do (nm, *ab_par++, have);
1089 RESTOR_VAR (bt_macro);
1090 RESTOR_VAR (bt_replace);
1093 static Token specialized (Token c, NormPtr p)
1095 char name [1024];
1096 Token have [64] = { -1, };
1098 sprintf (name, "%s_SpEc_", expand (c));
1099 mk_specialized (name, p, have, false);
1100 specialize_do (name, c, have);
1101 return new_symbol (strdup (name));
1103 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1104 #define INHERIT_FLAG(x, y) b.x |= flagz & FUNCP_ ## y; if (b.x) flagz |= FUNCP_ ## y
1106 NormPtr struct_declaration (recID r, OUTSTREAM D, NormPtr p)
1108 NormPtr ps, dstart;
1109 Dclbase b;
1110 Dclobj d = DCLOBJ_INIT;
1111 typeID dt;
1112 bool isdtor;
1114 /* Feature: skip local typedefs */
1115 if (CODE [p] == RESERVED_typedef)
1116 return skip_declaration (p);
1117 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
1119 b.dclqual_i = 0;
1120 b.section = 0;
1121 last_location = p;
1123 /* Decorative feature: private && public disappear */
1124 if ((CODE [p] == RESERVED_public || CODE [p] == RESERVED_private)
1125 && CODE [p + 1] == ':')
1126 return p + 2;
1127 /* ::::::::::::::::::::::::::::::::::::::::::::::: */
1129 if (CODE [p] == ';') return p + 1;
1131 /* Feature: force creation of virtual table at object */
1132 if (CODE [ps = collect_dclqual (&b, p, 0)] == ';') {
1133 sumup_dclqual (&b);
1134 if (!b.isvirtual)
1135 parse_error (p, "bad specifications");
1136 Here_virtualtable (D, r, b.isinline, b.isconst, b.isvolatile);
1137 return ps + 1;
1139 /* /////////////////////////////////////////////// */
1141 /* Feature: "virtual class" */
1142 if (CODE [p] == RESERVED_virtual && CODE [p + 1] == RESERVED_class)
1143 return virtual_class_fwd (r, D, p + 2);
1144 /* //////////////////////// */
1146 /* Feature: class const macros */
1147 if (CODE [p] == RESERVED_const && ISSYMBOL (CODE [p + 1]) && !is_typename (CODE [p + 1])) {
1148 enter_class_const (r, CODE [p + 1], CODE [p + 2]);
1149 if (CODE [p + 3] != ';')
1150 parse_error (p, "const X Y ';'");
1151 return p + 4;
1153 /* ////////////////////////// */
1155 b.class_name = name_of_struct (r);
1156 p = parse_basetype (&b, dstart = p);
1157 d.maybe_ctor = b.maybe_ctor;
1158 d.const_in_base = b.isconst;
1160 if (b.basetype == BASETYPE_ABSTRACT)
1161 if (CODE [p] == ';') return p + 1;
1162 else parse_error (p, "It is not possible to have objects of abstract classes");
1163 if (b.basetype == BASETYPE_SKIP)
1164 return p;
1166 for (;;) {
1167 if (CODE [p] == ':') {
1168 d.ip = 0;
1169 p = parse_bitfield (&d, p);
1170 outprintf (D, ISTR (b.dclqual), ISTR (b.shortname),
1171 ISTR (d.dclstr), ';', -1);
1172 goto skippy;
1175 p = parse_bitfield (&d, parse_dcl (&d, ps = p, 0));
1177 if (d.dclstr [d.objp] == BLANKT) {
1178 /* Feature: anonymous transparent unions */
1179 if (b.anon_union && d.dclstr [1] == -1) {
1180 d.dclstr [d.objp] = add_anonymous_union (r, b.basetype);
1181 goto print_member;
1183 /* ..................................... */
1184 parse_error_pt (p, name_of_struct (r),"Abstract declaration in structure?");
1187 isdtor = false;
1189 /* Constructors: add return type to ctor function */
1190 if (d.dclstr [d.objp] == RESERVED_ctor) {
1191 ctor_basetype (&b, r);
1192 if (d.dclhype [0] != '(')
1193 parse_error (p, "Constructor is a function");
1195 /* +^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+^+ */
1196 if ((isdtor = d.dclstr [d.objp] == RESERVED_dtor)) {
1197 dtor_basetype (&b, r);
1198 if (d.dclhype [0] != '(')
1199 parse_error (p, "Destructor is a function");
1200 if (d.dclhype [1] != INTERNAL_ARGEND)
1201 parse_error (p, "Destructor may not have arguments");
1203 /* -^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^- */
1205 dt = dcltype (&b, &d);
1206 if (isfunction (dt)) {
1208 int flagz = 0;
1210 /* Feature: class's qualifiers apply to member functions */
1211 if (outer_dclqual)
1212 append_dclqual (outer_dclqual, &b);
1213 /* ------------------------------- */
1215 /* Feature: some specifiers *after* arglist */
1216 bool const_fn = false, final_fn = b.isfinal;
1217 for (;; p++) switch (CODE [p]) {
1218 default: goto break2;
1219 ncase RESERVED_const: const_fn = true, flagz |= FUNCP_CTHIS;
1220 ncase RESERVED_final: final_fn = true;
1221 ncase RESERVED_nothrow: flagz |= FUNCP_NOTHROW;
1223 break2:
1224 if (final_fn) flagz |= FUNCP_FINAL;
1225 /* ---------------------------------------- */
1227 bool pure_virtual = CODE [p] == '=' && CODE [p + 1] == RESERVED_0;
1229 Token fname = d.cname = d.dclstr [d.objp], mfname;
1231 /* Feature: operator new */
1232 if (fname == RESERVED_new)
1233 b.ismodular = true;
1234 /* ^^^^^^^^^^^^^^^^^^^^^ */
1236 /* Feature: member functions */
1237 d.rec = r;
1238 dt = makemember (dt, r);
1239 /* Inherited specifiers */
1240 flagz |= inherited_flagz (r, fname, dt);
1241 INHERIT_FLAG (isvirtual, VIRTUAL);
1242 INHERIT_FLAG (isauto, AUTO);
1243 INHERIT_FLAG (ismodular, MODULAR);
1244 if (b.isstatic) flagz |= FUNCP_STATIC;
1245 if (b.isinline) flagz |= FUNCP_INLINE;
1246 if (pure_virtual) flagz |= FUNCP_PURE;
1247 if (!b.ismodular)
1248 add_this (&d, const_fn);
1250 /* definitions in-class, add static inline */
1251 if (CODE [p] == '{') {
1252 if (!(issymbol (CODE [p + 1]) && lookup_object (CODE [p + 1])
1253 && CODE [p + 2] == '}')) /* special syntax for autos */ {
1254 add_dclqual (RESERVED_static, b.dclqual);
1255 add_dclqual (RESERVED_inline, b.dclqual);
1257 /*** XXX: we could put these in linkonce because they
1258 *** won't go away by inlinement because they are needed
1259 *** as their address is put in vtbl initialization.
1260 *** otoh, they are usually small, so... let them be
1261 ***/
1262 //if (!OneBigFile && b.isvirtual)
1263 // flagz |= FUNCP_LINKONCE, b.islinkonce = 1;
1265 /* ^^^^^^^^^^^^^^^^^^^^^^^^^ */
1267 mfname = d.dclstr [d.objp] = name_member_function (r, d.dclstr [d.objp]);
1268 d.dclstr [d.objp] = pdcl_function (&b, &d, dt, flagz);
1269 if (isdtor) set_dfunc (r, mfname, flagz | FUNCP_NOTHROW, b.isauto);
1271 /* Feature: new/delete */
1272 if (in2 (fname, RESERVED_new, RESERVED_delete))
1273 enter_newdel_overload (fname, r, d.dclstr [d.objp]);
1274 /* ~~~~~~~~~~~~~~~~~~~ */
1277 if (pure_virtual) p += 2;
1279 /* Feature: virtual nd pure virtual function */
1280 if (b.isvirtual) {
1281 last_location = p;
1282 Make_virtual_table (D, r, fname, dt);
1284 /* % % % % % % % % % % % % % % % % % % % % % */
1286 /* Feature: auto functions */
1287 if (b.isauto) {
1288 Token proto [256];
1289 sintprintf (proto, ISTR (b.dclqual), ISTR (b.shortname),
1290 ISTR (d.dclstr), -1);
1291 add_auto_f (d.dclstr [d.objp], fname, r, dt, b.isvirtual,
1292 pure_virtual, dstart, proto, d.argv);
1294 /* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ */
1296 /* Feature: inline members + aliases */
1297 if (CODE [p] == '{' || (CODE [p] == RESERVED_alias && CODE [p + 1] == '(')){
1298 mark_function_def (&b, &d, ++p, r, funcreturn (dt), fname, isdtor);
1299 if (b.islinkonce)
1300 xmark_section_linkonce (FSP (r), fname, d.dclstr [d.objp]);
1301 return CODE [p - 1] == '{' ? skip_braces (p) :
1302 skip_parenthesis (p + 1);
1303 } else if (!b.isauto && !b.islinkonce)
1304 keyfunc_candidate (r, d.dclstr [d.objp]);
1305 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
1307 } else {
1309 if (d.VLA_expr)
1310 parse_error (p, "VLA in structure not possible");
1312 if (isstructure (dt)) /* has virtual table && ok */
1313 Can_instantiate (base_of (dt));
1315 /* Feature: pure data members */
1316 if (base_of (dt) == B_PURE) {
1317 add_variable_member (r, d.dclstr [d.objp], dt, 0, d.constant, 0);
1318 add_pure_dm (r, b.btname, dstart);
1319 } else
1320 /* Feature: Virtual variables */
1321 if (b.isvirtual || Is_implied_virtual_variable (r, d.dclstr [d.objp])) {
1322 Token *proto = allocaint (intlen (d.dclstr) + 16);
1323 sintprintf (proto, ISTR (b.dclqual), ISTR (b.shortname),
1324 ISTR (d.dclstr), -1);
1325 intsubst (proto, d.dclstr [d.objp], MARKER);
1326 Token *expr = 0, asgn = CODE [p];
1327 if (in3 (CODE [p], '=', ASSIGNBO, ASSIGNBA)) {
1328 exprret E;
1329 p = parse_expression (p + 1, &E, NORMAL_EXPR);
1330 if (E.ok) expr = E.newExpr;
1332 add_virtual_varmemb (r, d.dclstr [d.objp], asgn, dt,
1333 expr, proto, 1, D);
1334 /* %%%%%%%%%%%%%%%%%%%%%%%%%% */
1335 } else
1336 /* Feature: modular data members */
1337 if (b.ismodular || outer_dclqual->ismodular) {
1338 Token rn = d.dclstr [d.objp];
1339 d.dclstr [d.objp] = name_member_function (r, rn);
1340 outprintf (GVARS, ISTR (b.dclqual), ISTR (b.shortname),
1341 ISTR (d.dclstr), linkonce_data (d.dclstr [d.objp]),
1342 ';', -1);
1343 add_variable_member (r, rn, dt, d.dclstr [d.objp], false, 0);
1344 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1345 } else {
1346 add_variable_member (r, d.dclstr [d.objp], dt, 0, d.constant,
1347 b.is__noctor__);
1348 print_member:
1349 outprintf (D, ISTR (b.dclqual), ISTR (b.shortname),
1350 ISTR (d.dclstr), ';', -1);
1353 skippy:
1354 if (CODE [p] == ';') break;
1355 if (CODE [p++] != ',')
1356 parse_error_pt (p, CODE [p-1], "parse error in declaration separator(1)");
1359 return p + 1;
1362 /* Feature: parse local typedef member */
1363 static NormPtr struct_typedef (recID r, NormPtr p)
1365 Dclbase b;
1366 Dclobj d = DCLOBJ_INIT;
1367 typeID dt;
1369 if (CODE [p] != RESERVED_typedef)
1370 return skip_declaration (p);
1372 /* Feature: pure typedefs */
1373 if (issymbol (CODE [p + 1]) && CODE [p + 2] == '=' && CODE [p + 3] == RESERVED_0) {
1374 if (CODE [p + 4] != ';')
1375 parse_error (p, "typedef NAME = 0 ';'");
1376 if (!have_local_typedef (r, CODE [++p]))
1377 enter_typedef (add_local_typedef (r, CODE [p]), typeID_NOTYPE);
1378 return p + 4;
1380 /* ^^^^^^^^^^^^^^^^^^^^^^ */
1382 b.dclqual_i = 0;
1383 b.section = 0;
1384 b.class_name = name_of_struct (r);
1385 p = parse_basetype (&b, last_location = p);
1386 d.const_in_base = b.isconst;
1388 if (b.basetype == BASETYPE_ABSTRACT)
1389 if (CODE [p] == ';') return p + 1;
1390 else parse_error (p, "It is not possible to have objects of abstract classes");
1392 for (;;) {
1394 p = parse_dcl (&d, p, 0);
1396 if (d.dclstr [d.objp] == BLANKT)
1397 parse_error (p, "Abstract typedef declaration in structure?");
1399 dt = dcltype (&b, &d);
1401 if (!have_local_typedef (r, d.dclstr [d.objp])) {
1402 enter_typedef (d.dclstr [d.objp] = add_local_typedef
1403 (r, d.dclstr [d.objp]), dt);
1404 outprintf (GLOBAL, ISTR (b.dclqual), ISTR (b.shortname),
1405 ISTR (d.dclstr), ';', -1);
1408 if (CODE [p] == ';') break;
1409 if (CODE [p++] != ',')
1410 parse_error_pt (p, CODE [p-1], "parse error in declaration separator(2)");
1413 return p + 1;
1415 /* ----------------------------- */
1417 static void parse_all_typedefs (recID r, NormPtr p)
1419 while (CODE [p] != '}' && CODE [p] != -1)
1420 p = struct_typedef (r, p);
1423 static NormPtr parse_all_declarations (recID r, OUTSTREAM o, NormPtr p)
1425 static recID parsing;
1426 if (parsing)
1427 set_depend (parsing, r);
1428 SAVE_VAR (parsing, r);
1430 while (CODE [p] != '}' && CODE [p] != -1)
1431 p = struct_declaration (r, o, p);
1432 if (CODE [p++] == -1)
1433 parse_error_ll ("missing '}' in structure declaration");
1435 RESTOR_VAR (parsing);
1436 return p;
1439 static void include_abstract (Token a, recID r, OUTSTREAM o, bool typedefs)
1441 SAVE_VAR (bt_macro, a);
1443 if (!typedefs) enter_abstract_derrived (a, r);
1444 Token *ab_par = parents_of_abstract (a);
1445 if (typedefs) parse_all_typedefs (r, dcl_of_abstract (a));
1446 else parse_all_declarations (r, o, dcl_of_abstract (a));
1447 while (*ab_par != -1)
1448 include_abstract (*ab_par++, r, o, typedefs);
1450 RESTOR_VAR (bt_macro);
1453 static void reparse_auto_functions (recID r, OUTSTREAM o)
1455 NormPtr rep [256];
1456 int i;
1458 borrow_auto_decls (r, rep);
1460 PUSH_CURRENT_SCOPE (r);
1461 SAVE_VAR (PARENT_AUTOFUNCS, true);
1462 for (i = 0; rep [i] != -1; i++)
1463 struct_declaration (r, o, rep [i]);
1464 RESTOR_VAR (PARENT_AUTOFUNCS);
1465 POP_CURRENT_SCOPE;
1468 static NormPtr parse_structure (Token name, Dclbase *b, NormPtr p, Token s_or_u, Token *ab_par)
1470 recID r = b->basetype, alias;
1472 PUSH_CURRENT_SCOPE (r);
1473 SAVE_VAR (outer_dclqual, b);
1474 SAVE_VAR (bt_replace, name_of_struct (r));
1476 #ifdef DEBUG
1477 if (debugflag.DCL_TRACE)
1478 PRINTF ("Entering structure ["COLS"%s"COLE"]\n", expand (name_of_struct (r)));
1479 #endif
1481 OUTSTREAM STRUCTDCL = Streams_Closed ? 0 : new_stream ();
1482 outprintf (STRUCTDCL, s_or_u, name, '{', -1);
1484 /* Feature: Inheritance */
1485 output_parents (STRUCTDCL, r);
1486 /* ^^^^^^^^^^^^^^^^^^^^ */
1488 /* Feature: one pass for typedefs */
1489 SAVE_VAR (ab_par, ab_par);
1490 parse_all_typedefs (r, p);
1491 while (*ab_par != -1)
1492 include_abstract (*ab_par++, r, STRUCTDCL, 1);
1493 RESTOR_VAR (ab_par);
1494 /* + + + + + + + + + + + + + + + + */
1496 /* Feature: realize pure data from parents */
1497 gen_pure_dm (r, STRUCTDCL);
1498 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
1500 /* Feature: expand abstract parents */
1501 while (*ab_par != -1)
1502 include_abstract (*ab_par++, r, STRUCTDCL, 0);
1503 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
1505 p = parse_all_declarations (r, STRUCTDCL, p);
1507 /* Feature: reparse auto functions from parent decls */
1508 reparse_auto_functions (r, STRUCTDCL);
1509 /* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ */
1511 RESTOR_VAR (outer_dclqual);
1512 RESTOR_VAR (bt_replace);
1513 POP_CURRENT_SCOPE;
1515 alias = complete_structure (STRUCTDCL, r);
1516 output_itoken (STRUCTDCL, '}');
1517 if (CODE [p] == RESERVED___attribute__) {
1518 NormPtr p2 = p++;
1519 if (CODE [p++] != '(') parse_error (p, "__attribute__ '('");
1520 p = skip_parenthesis (p);
1521 outprintf (STRUCTDCL, NSTRNEXT, CODE + p2, p - p2, - 1);
1523 output_itoken (STRUCTDCL, ';');
1525 Token *dcl;
1526 if (alias) {
1527 /* Feature: alias classes are just typedefs */
1528 free_stream (STRUCTDCL);
1529 outprintf (GLOBAL, RESERVED_typedef,
1530 RESERVED_struct, name_of_struct (alias),
1531 name_of_struct (r), ';', -1);
1532 dcl = 0;
1533 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
1534 } else dcl = combine_output (STRUCTDCL);
1536 set_declaration (r, dcl);
1537 return p;
1540 /* * * Parse the inheritance specifications * * */
1541 /* * * support for abstract classes * * */
1542 static NormPtr parse_inheritance (NormPtr p, recID r, Token aparents[])
1544 bool vp;
1545 recID parents [32], iparents [32];
1546 int i = 0, j = 0, k;
1548 for (;;p++) {
1549 if ((vp = CODE [p] == RESERVED_virtual))
1550 ++p;
1551 if (!ISSYMBOL (CODE [p]))
1552 parse_error_pt (p, CODE [p], "Expected parent class");
1554 if (have_abstract (CODE [p])) {
1555 real_abstract_parents (CODE [p], iparents);
1556 for (k = 0; iparents [k] != -1; k++)
1557 parents [i++] = iparents [k];
1558 aparents [j++] = CODE [p++];
1559 } else {
1560 parents [i] = lookup_object (CODE [p++]);
1561 if (!parents [i])
1562 parse_error_pt (p, CODE [p-1], "No such class");
1563 if (vp) parents [i] += VIRTUALPAR_BOOST;
1564 ++i;
1567 if (CODE [p] != ',') break;
1570 if (CODE [p] != '{')
1571 parse_error (p, "Syntax error after parent classes");
1573 parents [i] = -1;
1574 set_parents (r, parents);
1575 aparents [j] = -1;
1576 return p;
1578 /* -------------------------------------------- */
1580 static NormPtr copy_designator (NormPtr p, Token des [])
1582 int i = 0;
1583 while (1) switch (CODE [p++]) {
1584 case '.':
1585 des [i++] = '.';
1586 des [i++] = CODE [p++];
1587 continue;
1588 case '[': {
1589 NormPtr p2 = p;
1590 des [i++] = '[';
1591 p = skip_expression (CODE, p, NORMAL_EXPR);
1592 if (CODE [p++] != ']')
1593 parse_error (p, "Das is verbotten");
1594 while (p2 < p)
1595 des [i++] = CODE [p2++];
1597 continue;
1598 default: --p;
1599 case '=':
1600 des [i++] = '=';
1601 des [i] = -1;
1602 return p;
1607 static NormPtr aggregate_initializer (OUTSTREAM O, NormPtr p, typeID ret)
1609 exprret E;
1610 NormPtr p2;
1611 typeID t, t1 = isstructure (ret) ? ret : ptrdown (ret);
1613 output_itoken (O, '{');
1614 while (1) {
1615 if (CODE [p] == '}') {
1616 output_itoken (O, '}');
1617 return p + 1;
1619 if (CODE [p] == '.' || CODE [p] == '[') {
1620 Token designator [128];
1621 p = copy_designator (p, designator);
1622 t = typeof_designator (ret, designator);
1623 outprintf (O, ISTR (designator), -1);
1624 } else t = t1;
1625 if (CODE [p] == '{')
1626 p = aggregate_initializer (O, p + 1, t);
1627 else {
1628 p = parse_expression_retconv (p2 = p, &E, t, INIT_EXPR);
1629 if (E.ok) {
1630 outprintf (O, ISTR (E.newExpr), -1);
1631 free (E.newExpr);
1634 if (CODE [p] == '}') {
1635 output_itoken (O, '}');
1636 return p + 1;
1638 if (CODE [p++] != ',')
1639 parse_error (p, "X Verbotten X");
1640 output_itoken (O, ',');
1644 /* Feature: initialize an (no-POD) object with designators */
1645 static NormPtr special_initializer (OUTSTREAM O, NormPtr p, typeID t, Token obj)
1647 exprret E;
1648 NormPtr p2;
1649 Token designator [256];
1651 while (1) {
1652 if (CODE [p] == '}') {
1653 output_itoken (O, '}');
1654 return p + 1;
1656 designator [0] = obj;
1657 if (CODE [p] == '.' || CODE [p] == '[')
1658 p = copy_designator (p, designator + 1);
1659 else parse_error (p, "This object can only be initialized with designators!");
1661 p = parse_expression (p2 = p, &E, INIT_EXPR);
1662 if (E.ok) {
1663 intcat (designator, E.newExpr);
1664 free (E.newExpr);
1665 rewrite_designator (t, designator);
1666 outprintf (O, ISTR (designator), ';', -1);
1668 if (CODE [p] == '}')
1669 return p + 1;
1670 if (CODE [p++] != ',')
1671 parse_error (p, "X Verbotten X");
1675 static NormPtr local_initializer (OUTSTREAM O, NormPtr p, typeID t)
1677 output_itoken (O, '=');
1678 if (CODE [p] == '{')
1679 return aggregate_initializer (O, p + 1, t);
1680 exprret E;
1681 p = parse_expression_retconv (p, &E, t, INIT_EXPR);
1682 if (E.ok) {
1683 outprintf (O, ISTR (E.newExpr), -1);
1684 free (E.newExpr);
1686 return p;
1689 /* Generate code for a constructor call. p points to the ctor
1690 arguments code. if p is -1 then it's the implict constructor
1691 added automatically. */
1692 static NormPtr call_ctor (OUTSTREAM O, Token obj, NormPtr p)
1694 Token *ctexpr;
1695 NormPtr ps;
1697 if (O == GLOBAL_INIT_FUNC) GlobInitUsed = true;
1699 if (p != -1)
1700 if (CODE [p] != '=') {
1701 Token ctor = CODE [p] == '(' ? RESERVED_ctor : CODE [p++];
1703 p = skip_parenthesis ((ps = p) + 1);
1704 ctexpr = allocaint (p - ps + 5);
1705 sintprintf (ctexpr, obj, '.', ctor, -1);
1706 intextract (ctexpr + 3, CODE + ps, p - ps);
1707 } else {
1708 p = skip_expression (CODE, ps = p + 1, INIT_EXPR);
1709 ctexpr = allocaint (p - ps + 7);
1710 sintprintf (ctexpr, obj, '.', RESERVED_ctor, '(', -1);
1711 intextract (ctexpr + 4, CODE + ps, p - ps);
1712 intcatc (ctexpr, ')');
1714 else {
1715 ctexpr = allocaint (6);
1716 sintprintf (ctexpr, obj, '.', RESERVED_ctor, '(', ')', -1);
1718 if ((ctexpr = rewrite_ctor_expr (ctexpr))) {
1719 outprintf (O, ISTR (ctexpr), ';', -1);
1720 free (ctexpr);
1722 return p;
1725 static inline bool isstructarr (typeID t)
1727 int *s = open_typeID (t);
1728 return base_of (t) >= 0 && in2 (s [1], '[', '*') && s [2] == -1;
1731 /* Feature: call the ctor for each element of array of objects */
1732 NormPtr gen_array_ctors (OUTSTREAM O, NormPtr p, typeID t, Token obj, int *N, bool throwing)
1734 NormPtr ps;
1735 int rest = *N;
1736 int cnt = 0;
1737 bool enc, dot, autosize = rest == 0;
1738 Token *ctexpr, cexpr [128];
1739 Token u1 = name_arrdto_var (obj);
1740 bool dstruct = has_dtor (base_of (t));
1741 Token dto=0, tcnt;
1743 if (dstruct) dto = i_arrdtor_func (base_of (t));
1745 if (isstructarr (t) && always_unwind (base_of (t))) throwing = true;
1746 throwing &= dstruct;
1748 if (dstruct)
1749 if (EHUnwind)
1750 outprintf (O, RESERVED_struct, arrdtor, u1, cleanup_func (dto), '=', '{',
1751 obj, ',', RESERVED_0, '}', ';', -1);
1752 else {
1753 outprintf (O, RESERVED_struct, arrdtor, u1, '=', '{', obj, ',', RESERVED_0,
1754 '}', ';', -1);
1755 add_auto_destruction (u1, dto, throwing);
1756 if (throwing) push_unwind (O, dto, u1);
1759 open_local_scope ();
1760 enter_local_obj (obj, t);
1761 while (CODE [p] != '}') {
1762 dot = CODE [p] == '.';
1763 p = skip_expression (CODE, ps = p + dot, INIT_EXPR);
1764 sintprintf (cexpr, obj, '[', tcnt = new_value_int (cnt++), ']', '.', -1);
1765 if (!dot) intcatc (cexpr, RESERVED_ctor);
1766 if (enc = (CODE [ps] != '(' || CODE [p - 1] != ')') && !dot)
1767 intcatc (cexpr, '(');
1768 intextract (cexpr + intlen (cexpr), &CODE [ps], p - ps);
1769 if (enc) intcatc (cexpr, ')');
1770 CLEAR_MAYTHROW;
1771 if (ctexpr = rewrite_ctor_expr (intdup (cexpr))) {
1772 if (throwing && !TEST_MAYTHROW)
1773 outprintf (O, u1, '.', RESERVED_i, '=', tcnt, ';', -1);
1774 outprintf (O, '{', ISTR (ctexpr), ';', '}', -1);
1775 free (ctexpr);
1776 } else TEST_MAYTHROW;
1777 if (CODE [p] == ',') ++p;
1778 else if (CODE [p] != '}') parse_error (p, "Initializer expression separator");
1781 if (throwing)
1782 outprintf (O, u1, '.', RESERVED_i, '=', new_value_int (cnt), ';', -1);
1784 if (autosize) *N = cnt;
1785 else if (rest > cnt) {
1786 Token cc = internal_identifiern (4);
1788 outprintf (O, RESERVED_int, cc, ';',
1789 RESERVED_for, '(', cc, '=', new_value_int (cnt), ';',
1790 cc, '<', new_value_int (rest), ';', cc, PLUSPLUS, -1);
1791 if (throwing)
1792 outprintf (O, ',', PLUSPLUS, u1, '.', RESERVED_i, -1);
1793 output_itoken (O, ')');
1794 enter_local_obj (cc, typeID_int);
1795 sintprintf (cexpr, obj, '[', cc, ']', '.', RESERVED_ctor, '(', ')', -1);
1796 if (ctexpr = rewrite_ctor_expr (intdup (cexpr))) {
1797 outprintf (O, ISTR (ctexpr), ';', -1);
1798 free (ctexpr);
1800 cnt = rest;
1801 } else if (rest < cnt)
1802 parse_error_ll ("Excess elements in array ctors!");
1804 if (dstruct && !throwing)
1805 outprintf (O, u1, '.', RESERVED_i, '=', new_value_int (cnt), ';', -1);
1806 close_local_scope ();
1808 return p + 1;
1811 static NormPtr multiple_array_ctors (OUTSTREAM O, NormPtr p, typeID t, Token obj, Token *n, Token **M, bool isunwind)
1813 int cnt = 0, have_cnt;
1815 if ((have_cnt = n [intlen (n) - 2] != '[')) {
1816 if (n [intlen (n) - 3] != '[')
1817 parse_error_tok (obj, "Can't evaluate complex expression for sizeof :(");
1818 cnt = eval_int (n [intlen (n) - 2]);
1821 OUTSTREAM N = new_stream ();
1822 p = gen_array_ctors (N, p + 1, t, obj, &cnt, isunwind);
1823 *M = combine_output (N);
1825 if (!have_cnt)
1826 outprintf (O, BACKSPACE, new_value_int (cnt), ']', -1);
1827 return p;
1830 static void vla2alloca (OUTSTREAM O, Token obj, NormPtr ep)
1832 outprintf (O, '=', '(', RESERVED___typeof__, '(', obj, ')', ')',
1833 INTERN_alloca, '(', RESERVED_sizeof, '*', obj, '*', '(', -1);
1834 exprret E;
1835 parse_expression_retconv (ep, &E, typeID_int, NORMAL_EXPR);
1836 if (E.ok) {
1837 outprintf (O, ISTR (E.newExpr), ')', ')', -1);
1838 free (E.newExpr);
1839 } else outprintf (O, RESERVED_0, ')', ')', -1);
1842 // avoid warning
1843 #define NW(x) x=x
1845 Token local_name;
1846 typeID local_type;
1848 NormPtr local_declaration (OUTSTREAM O, NormPtr p)
1850 bool hadinit, NW(spec_init), isdefinition, NW(mult_init), NW(ctor_assign);
1851 int static_ctorable;
1852 Dclbase b;
1853 Dclobj d = DCLOBJ_INIT;
1854 typeID dt;
1855 Token *para_code=para_code;
1856 bool specialization = CODE [p] == RESERVED_specialize;
1858 if (CODE [p] == ';') return p + 1;
1860 last_location = p;
1861 b.class_name = 0;
1862 p = parse_basetype (&b, p);
1863 d.maybe_ctor = b.maybe_ctor;
1864 d.const_in_base = b.isconst;
1866 if (b.basetype == BASETYPE_ABSTRACT)
1867 parse_error (p, "It is not possible to have objects of abstract classes");
1868 if (b.basetype == BASETYPE_SKIP)
1869 return p;
1871 if (CODE [p] == ';') {
1872 /* Feature: abstract declaration for an object with a constructor */
1873 if (!specialization && b.basetype >= 0 && has_void_ctor (b.basetype)) {
1874 Token t = internal_identifier1 ();
1876 Can_instantiate (b.basetype);
1877 open_local_scope ();
1878 enter_local_obj (t, dcltype (&b, 0));
1879 outprintf (O, '{', ISTR (b.dclqual), ISTR (b.shortname), t, ';', -1);
1880 if (need_construction (b.basetype))
1881 alloc_and_init_dcl (O, b.basetype, t, false);
1882 call_ctor (O, t, -1);
1883 if (has_dtor (b.basetype))
1884 outprintf (O, dtor_name (b.basetype),
1885 '(', '&', t, ')', ';', -1);
1886 outprintf (O, '}', -1);
1887 close_local_scope ();
1889 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1890 return p + 1;
1893 for (;; p++) {
1894 p = parse_dcl (&d, p, 0);
1896 dt = dcltype (&b, &d);
1898 /* Feature: pure typedefs */
1899 if (base_of (dt) == B_PURE) {
1900 if (!objective.recording)
1901 parse_error (p, "Only auto-functions may use pure typedefs");
1902 usage_call_pure ();
1905 if (d.dclstr [d.objp] == BLANKT || d.dclstr [d.objp] == RESERVED__) {
1906 /* Feature: anoymous obj call ctor thingy */
1907 if (isstructure (dt) && (CODE [p] == '('
1908 || CODE [p + 1] == '(' && ISSYMBOL (CODE [p]))) {
1909 Token t = internal_identifier1 ();
1910 int basetype = base_of (dt);
1912 Can_instantiate (basetype);
1913 open_local_scope ();
1914 enter_local_obj (t, dt);
1915 outprintf (O, '{', ISTR (b.dclqual), ISTR (b.shortname),
1916 t, ';', -1);
1917 if (need_construction (basetype))
1918 alloc_and_init_dcl (O, basetype, t, false);
1919 p = call_ctor (O, t, p);
1920 if (has_dtor (basetype))
1921 outprintf (O, dtor_name (basetype),
1922 '(', '&', t, ')', ';', -1);
1923 outprintf (O, '}', -1);
1924 close_local_scope ();
1925 if (CODE [p] != ';')
1926 parse_error (p, "Anonymous object (constructor) ';'");
1927 break;
1928 } else
1929 parse_error (p, "Abstract declaration in local");
1930 /* * * * * * * * * * * * * * * * * * * * */
1934 if (isfunction (dt)) {
1935 pdcl_function (&b, &d, dt, 0);
1936 } else {
1938 OUTSTREAM D = b.isstatic ? new_stream () : O;
1940 outprintf (D, ISTR (b.dclqual), ISTR (b.shortname),
1941 ISTR (d.dclstr), -1);
1943 /* Feature: linkonce statics */
1944 if (!b.istypedef && b.islinkonce)
1945 output_itoken (D, linkonce_data_f (d.dclstr [d.objp]));
1946 /* ^^^^^^^^^^^^^^^^^^^^^^^^^ */
1948 if ((hadinit = CODE [p] == '=')) {
1949 SAVE_VAR (local_name, d.dclstr [d.objp]);
1950 SAVE_VAR (local_type, dt);
1952 /* Cases of initialization */
1953 spec_init = CODE [p + 1] == '{' &&
1954 isstructure (dt) && need_construction (base_of (dt));
1955 //|| has_parents (base_of (dt)));
1956 mult_init = d.dclstr [intlen (d.dclstr) - 1] == ']' &&
1957 is_array_of_objects (dt) && CODE [p + 1] == '{' &&
1958 has_ctors (base_of (dt)) && CODE [p + 2] != '{';
1959 ctor_assign = CODE [p + 1] != '{' && isstructure (dt) &&
1960 has_ctors (base_of (dt));
1961 if (ctor_assign)
1962 if (typeof_expression (p + 1, INIT_EXPR) == dt
1963 && !has_copy_ctor (base_of (dt)))
1964 ctor_assign = false;
1965 if (!spec_init && !ctor_assign)
1966 if (!mult_init) p = local_initializer (D, p + 1, dt);
1967 else p = multiple_array_ctors (D, p + 1, dt, d.dclstr
1968 [d.objp], d.dclstr, &para_code, b.is__unwind__);
1970 RESTOR_VAR (local_name);
1971 RESTOR_VAR (local_type);
1973 if (d.VLA_expr)
1974 vla2alloca (D, d.dclstr [d.objp], d.VLA_expr);
1976 output_itoken (D, ';');
1978 isdefinition = !b.istypedef && !b.isextern;
1979 static_ctorable = 2;
1981 /* name is declared after initialization expression
1982 therefore int x = x; is ok where the local x is
1983 assigned the value of the global x */
1984 if (b.istypedef) enter_typedef (d.dclstr [d.objp], dt);
1985 else enter_local_obj (d.dclstr [d.objp], dt);
1988 OUTSTREAM I = new_stream ();
1990 if (isstructure (dt) && isdefinition) /* has virtual table && ok */
1991 Can_instantiate (base_of (dt));
1993 /* Feature: Set virtual table */
1994 if (isdefinition) {
1995 if (isstructure (dt) && need_construction (base_of (dt)))
1996 alloc_and_init_dcl (I, base_of (dt), d.dclstr [d.objp], false);
1997 else if (is_array_of_ctorable_objects (dt))
1998 alloc_and_init_dcl (I, base_of (dt), d.dclstr [d.objp], true);
1999 else static_ctorable--;
2001 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2003 /* Feature: aggregate initializer opened */
2004 if (hadinit && spec_init)
2005 p = special_initializer (I, p + 2, dt, d.dclstr [d.objp]);
2006 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2008 /* Feature: append code for multiple array ctors */
2009 if (hadinit && mult_init) outprintf (I, ISTR (para_code), -1);
2010 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2012 /* Feature: construction of objects */
2013 if (CODE [p] == '(' || CODE [p + 1] == '(' && ISSYMBOL (CODE [p]))
2014 p = call_ctor (I, d.dclstr [d.objp], p);
2015 else if (!hadinit && isstructure (dt)
2016 && has_void_ctor (base_of (dt)))
2017 call_ctor (I, d.dclstr [d.objp], -1);
2018 else if (hadinit && ctor_assign)
2019 p = call_ctor (I, d.dclstr [d.objp], p);
2020 else static_ctorable--;
2021 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2023 Token *initcode = combine_output (I);
2025 /* Feature: static objects that are ctored once */
2026 if (b.isstatic)
2027 if ((static_ctorable = b.isstatic && static_ctorable)) {
2028 Token nn = name_glob_static_local (d.dclstr [d.objp]);
2029 Token *dc = combine_output (D);
2030 intsubst (dc, d.dclstr [d.objp], nn);
2031 intsubst (initcode, d.dclstr [d.objp], nn);
2032 outprintf (GVARS, ISTR (dc), -1);
2033 outprintf (GLOBAL_INIT_FUNC, ISTR (initcode), -1);
2034 GlobInitUsed = 1;
2035 free (dc);
2036 initcode [0] = -1;
2037 globalized_recent_obj (nn);
2038 } else outprintf (O, ISTR (combine_output (D)), -1);
2039 /* ++++++++++++++++++++++++++++++++++++++++++++ */
2042 /* Feature: mark for auto-destruction */
2043 if (isstructure (dt) && has_dtor (base_of (dt))
2044 && !b.isstatic && isdefinition)
2045 if (!EHUnwind) {
2046 bool unwd = b.is__unwind__ || always_unwind (base_of (dt));
2047 add_auto_destruction (d.dclstr [d.objp], base_of (dt),unwd);
2048 if (initcode [0] != -1)
2049 outprintf (O, ISTR (initcode), -1);
2050 if (unwd)
2051 push_unwind (O, base_of (dt), d.dclstr [d.objp]);
2052 } else {
2053 outprintf (O, BACKSPACE, cleanup_func (dtor_name
2054 (base_of (dt))), -1);
2055 if (initcode [0] == -1)
2056 output_itoken (O, ';');
2057 else outprintf (O, '=', '(', '{', ISTR (initcode),
2058 d.dclstr [d.objp], ';', '}', ')', ';',-1);
2060 else if (initcode [0] != -1)
2061 outprintf (O, ISTR (initcode), -1);
2062 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2064 free (initcode);
2066 if (CODE [p] == '{') parse_error (0, "Nested functions ?");
2067 if (CODE [p] == ';') break;
2068 if (CODE [p] != ',')
2069 parse_error_pt (p, CODE [p], "unacceptable declaration, separator;");
2072 return p + 1;
2075 static NormPtr global_initializer (OUTSTREAM OSTR, Token obj, NormPtr p, typeID t)
2077 if (CODE [p] == '{') {
2078 output_itoken (OSTR, '=');
2079 return aggregate_initializer (OSTR, p + 1, t);
2080 //NormPtr p2 = skip_braces (p + 1);
2081 //outprintf (OSTR, '=', NSTRNEXT, CODE + p, p2 - p, - 1);
2082 //return p2;
2084 exprret E;
2085 p = parse_expression_retconv (p, &E, t, INIT_EXPR);
2086 if (E.ok) {
2087 if (E.isconstant)
2088 outprintf (OSTR, '=', ISTR (E.newExpr), - 1);
2089 else {
2090 outprintf (GLOBAL_INIT_FUNC, obj, '=', ISTR (E.newExpr), ';', - 1);
2091 GlobInitUsed = true;
2093 free (E.newExpr);
2095 return p;
2098 static NormPtr global_declaration (NormPtr p, bool linkonce)
2100 static int ctorno;
2101 Dclbase b;
2102 Dclobj d = DCLOBJ_INIT;
2103 typeID dt;
2104 bool isdefinition;
2106 if (CODE [p] == ';') return p + 1;
2108 d.begins = last_location = p;
2109 b.class_name = 0;
2110 p = parse_basetype (&b, p);
2111 d.maybe_ctor = b.maybe_ctor;
2112 d.const_in_base = b.isconst;
2114 if (CODE [p] == ';') return p + 1;
2116 if (b.basetype == BASETYPE_ABSTRACT)
2117 parse_error (p, "It is not possible to have objects of abstract classes");
2118 if (b.basetype == BASETYPE_SKIP)
2119 return p;
2121 for (;;) {
2122 p = parse_dcl (&d, p, 0);
2124 /* Skip extern abstract func */
2125 if (d.ctordtor == BASETYPE_SKIP)
2126 return p;
2127 /* - - - - - */
2129 if (d.dclstr [d.objp] == BLANKT)
2130 parse_error (p, "Missing object name");
2132 /* Constructors: add type to ctor function */
2133 if (d.ctordtor && d.rec)
2134 (d.ctordtor == 1 ? ctor_basetype : dtor_basetype) (&b, d.rec);
2135 /* + + + + + + + + + + + + + + + + + + + + */
2137 dt = dcltype (&b, &d);
2138 if (isfunction (dt) && !b.istypedef) {
2139 bool abstract = false, const_fn = false;
2140 int flagz = 0;
2142 /* Feature: adding '*this' */
2143 while (in2 (CODE [p], RESERVED_const, RESERVED_nothrow))
2144 if (CODE [p++] == RESERVED_const) const_fn = true;
2145 else flagz |= FUNCP_NOTHROW;
2146 if (d.rec) {
2147 dt = makemember (dt, d.rec);
2148 flagz |= exported_flagz (d.rec, d.cname, dt) |
2149 inherited_flagz (d.rec, d.cname, dt);
2151 if (flagz & FUNCP_VIRTUAL && flagz & FUNCP_UNDEF)
2152 parse_error (p, "Declare in the class: virtual!");
2154 if (d.cname == RESERVED_new)
2155 b.ismodular = true;
2157 /* Feature: auto function definition ? */
2158 b.isauto |= flagz & FUNCP_AUTO;
2159 const_fn |= flagz & FUNCP_CTHIS;
2160 b.ismodular |= flagz & FUNCP_MODULAR;
2161 if (b.isstatic) flagz |= FUNCP_STATIC;
2162 if (b.isinline) flagz |= FUNCP_INLINE;
2163 if (!b.ismodular) {
2164 add_this (&d, const_fn);
2165 if (is_aliasclass (d.rec))
2166 remove_struct_from_this (d.dclstr, d.rec);
2167 } else flagz |= FUNCP_MODULAR;
2169 /* ^^^^^^^^^^^^^^^^^^^^^^^ */
2170 /* Feature: ctor() as a global */
2171 if (d.dclstr [d.objp] == RESERVED_ctor && !d.rec) {
2172 outprintf (GLOBAL_INIT_FUNC, d.dclstr [d.objp] = d.cname =
2173 name_global_ctor (ctorno++), '(', ')', ';', -1);
2174 GlobInitUsed = 1;
2176 /* *************************** */
2178 if (GoodOldC)
2179 flagz |= FUNCP_NOTHROW;
2181 if (d.cname == -1)
2182 d.cname = d.dclstr [d.objp];
2184 if (!abstract)
2185 d.dclstr [d.objp] = pdcl_function (&b, &d, dt, flagz);
2187 if (CODE [p] == '{') {
2188 mark_function_def (&b, &d, ++p, d.rec,
2189 funcreturn (dt), d.cname, d.ctordtor == 2);
2190 if (d.rec)
2191 possible_keyfunc (d.rec, d.dclstr [d.objp]);
2192 if (b.islinkonce || linkonce)
2193 xmark_section_linkonce (FSP (d.rec), d.cname,
2194 d.dclstr [d.objp]);
2195 return skip_braces (p);
2198 } else {
2199 OUTSTREAM OSTR = b.istypedef ? GLOBAL : GVARS;
2201 if (d.VLA_expr)
2202 parse_error (p, "VLA in global not possible");
2204 if (b.istypedef) {
2205 if (enter_typedef (d.dclstr [d.objp], dt))
2206 outprintf (OSTR, ISTR (b.dclqual), ISTR (b.shortname),
2207 ISTR (d.dclstr), -1);
2208 goto skipper;
2209 } else enter_global_object (d.dclstr [d.objp], dt);
2211 outprintf (OSTR, ISTR (b.dclqual), ISTR (b.shortname),
2212 ISTR (d.dclstr), -1);
2214 if (!b.istypedef && b.islinkonce)
2215 output_itoken (OSTR, linkonce_data (d.dclstr [d.objp]));
2218 isdefinition = !b.istypedef && !b.isextern;
2220 if (isstructure (dt) && isdefinition) /* if has virtual table ok */
2221 Can_instantiate (base_of (dt));
2223 /* Feature: Set virtual table and/or virtual base class */
2224 if (isdefinition) {
2225 if (isstructure (dt) && need_construction (base_of (dt)))
2226 alloc_and_init_dcl (GLOBAL_INIT_FUNC, base_of (dt),
2227 d.dclstr [d.objp], false);
2228 else if (is_array_of_ctorable_objects (dt))
2229 alloc_and_init_dcl (GLOBAL_INIT_FUNC, base_of (dt),
2230 d.dclstr [d.objp], true);
2232 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2234 /* here we don't need to parse initialization expression
2235 before declaring the object name because it's global
2236 and the object name could not possibly refer to
2237 an outer scope */
2238 if (CODE [p] == '(' || ISSYMBOL (CODE [p]) && CODE [p + 1] == '(')
2239 p = call_ctor (GLOBAL_INIT_FUNC, d.dclstr [d.objp], p);
2240 else if (CODE [p] == '=')
2241 p = global_initializer (OSTR, d.dclstr [d.objp], p + 1, dt);
2242 else if (isstructure (dt) && has_void_ctor (base_of (dt)) && !b.isextern)
2243 call_ctor (GLOBAL_INIT_FUNC, d.dclstr [d.objp], -1);
2245 skipper:
2246 output_itoken (OSTR, ';');
2248 if (CODE [p] == ';') break;
2249 if (CODE [p++] != ',')
2250 parse_error_pt (p, CODE [p-1], "invalid declaration separator");
2253 return p + 1;
2256 void reparse_template_func (Token m, recID r, NormPtr p)
2258 SAVE_VAR (bt_macro, m);
2259 SAVE_VAR (bt_replace, name_of_struct (r));
2260 PUSH_CURRENT_SCOPE (r);
2262 global_declaration (p, 1);
2264 POP_CURRENT_SCOPE;
2265 RESTOR_VAR (bt_macro);
2266 RESTOR_VAR (bt_replace);
2269 typeID eval_cast (Token **t)
2271 Dclbase b;
2272 Dclobj d = DCLOBJ_INIT;
2274 SAVE_VAR (CODE, *t);
2276 b.class_name = -1;
2278 parse_dcl (&d, parse_basetype (&b, 0), 0);
2279 if (b.basetype == BASETYPE_ABSTRACT)
2280 parse_error_ll ("abstract is not a real base type");
2281 frealloc (t, intlen (b.shortname) + intlen (d.dclstr) + 1);
2282 intcpy (*t, b.shortname);
2283 intcat (*t, d.dclstr);
2285 RESTOR_VAR (CODE);
2287 return dcltype (&b, &d);
2290 static NormPtr alt_translation_unit (NormPtr p)
2292 if (CODE [p] != RESERVED_C)
2293 output_itoken (INCLUDE, include_sys_header (CODE [p]));
2295 if (CODE [++p] != '{')
2296 parse_error (p, "extern \"string\" '{'");
2297 ++p;
2299 SAVE_VAR (GLOBAL, 0);
2300 SAVE_VAR (STRUCTS, 0);
2301 SAVE_VAR (GVARS, 0);
2302 SAVE_VAR (StructByRef, false);
2303 SAVE_VAR (Streams_Closed, true);
2304 SAVE_VAR (GoodOldC, true);
2306 while (CODE [p] != '}' && CODE [p] != -1)
2307 p = global_declaration (p, 0);
2309 if (CODE [p++] != '}')
2310 parse_error (p, "missing '}' in extern header region");
2312 RESTOR_VAR (GLOBAL);
2313 RESTOR_VAR (STRUCTS);
2314 RESTOR_VAR (GVARS);
2315 RESTOR_VAR (StructByRef);
2316 RESTOR_VAR (Streams_Closed);
2317 RESTOR_VAR (GoodOldC);
2319 return p;
2322 void translation_unit ()
2324 NormPtr p = 0;
2326 while (CODE [p] != -1)
2327 switch (CODE [p]) {
2328 case RESERVED__lwc_config_:
2329 p = lwc_config (p + 1);
2330 ncase RESERVED___C__:
2331 p = __C__ (p + 1);
2332 ncase RESERVED_extern:
2333 if (ISVALUE (CODE [p + 1])
2334 && type_of_const (CODE [p + 1]) == typeID_charP) {
2335 p = alt_translation_unit (p + 1);
2336 continue;
2338 default:
2339 p = global_declaration (p, 0);