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
12 Eventually this becomes a parser for LWC declarations.
14 ******************************************************************************/
16 recID current_scope
[16];
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
30 bool istypedef
, isvirtual
, isextern
, isstatic
, isauto
, isvolatile
, is__noctor__
,
31 isinline
, isconst
, islinkonce
, ismodular
, is__unwind__
, isfinal
, is__emit_vtbl__
;
35 bool anon_union
, maybe_ctor
;
38 static Dclbase
*outer_dclqual
;
43 static NormPtr
collect_dclqual (Dclbase
*b
, NormPtr p
, int remove_attributes
)
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];
56 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
57 if (remove_attributes
&& CODE
[p
] == RESERVED___attribute__
) {
58 /* cygwin: uses attributes between dclquals. Ignore it */
59 p
= skip_parenthesis (p
+ 2);
65 /* Take the declaration qualifiers from a decl and
66 * enable them for another decl */
67 static void append_dclqual (Dclbase
*b
, Dclbase
*m
)
70 if (!intchr (m
->dclqual
, RESERVED_extern
)
71 && !intchr (m
->dclqual
, RESERVED_static
))
72 intcatc (m
->dclqual
, RESERVED_static
);
76 if (!intchr (m
->dclqual
, RESERVED_inline
))
77 intcatc (m
->dclqual
, RESERVED_inline
);
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))
91 for (i
= RESERVED_auto
+ 1; ISCDCLFLAG (i
); i
++)
92 if ((b
->dclqual_i
& (1 << (i
- RESERVED_auto
))))
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
++)
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
];
120 b
->basetype
= B_FLOAT
;
121 b
->shortname
[i
++] = RESERVED_float
;
123 b
->basetype
= B_VOID
;
124 b
->shortname
[i
++] = RESERVED_void
;
125 ncase RESERVED_double
:
127 b
->basetype
= B_LDOUBLE
;
128 b
->shortname
[i
++] = RESERVED_long
;
129 b
->shortname
[i
++] = RESERVED_double
;
131 b
->basetype
= B_DOUBLE
;
132 b
->shortname
[i
++] = RESERVED_double
;
136 b
->basetype
= B_UCHAR
;
137 b
->shortname
[i
++] = RESERVED_unsigned
;
139 b
->basetype
= B_SCHAR
;
140 b
->shortname
[i
++] = RESERVED_char
;
144 b
->basetype
= lo
> 1 ? B_ULLONG
: B_ULONG
;
145 b
->shortname
[i
++] = RESERVED_unsigned
;
147 b
->basetype
= lo
> 1 ? B_SLLONG
: B_SLONG
;
148 b
->shortname
[i
++] = RESERVED_long
;
150 b
->shortname
[i
++] = RESERVED_long
;
153 b
->basetype
= B_USINT
;
154 b
->shortname
[i
++] = RESERVED_unsigned
;
156 b
->basetype
= B_SSINT
;
157 b
->shortname
[i
++] = RESERVED_short
;
158 b
->shortname
[i
++] = RESERVED_int
;
161 b
->basetype
= B_UINT
;
162 b
->shortname
[i
++] = RESERVED_unsigned
;
164 b
->basetype
= B_SINT
;
165 b
->shortname
[i
++] = RESERVED_int
;
168 parse_error (p
, "BUG");
170 b
->shortname
[i
] = -1;
174 static recID
is_object_in_global (NormPtr p
)
176 while (CODE
[p
] != '.' && CODE
[p
] != '(' && CODE
[p
] != ';' && CODE
[p
] != ',')
178 if (CODE
[p
] != '.') return 0;
179 return lookup_struct (CODE
[p
- 1]);
182 static NormPtr
bt_name (Dclbase
*b
, NormPtr p
)
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
);
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;
205 if (objective
.recording
)
212 redo
: iname
= 1; switch (y
= is_typename (x
)) {
214 /* Feature: template abstract classes */
215 if (bt_macro
&& x
== bt_macro
) {
219 /* Feature: local typedefs in global scope */
222 for (i
= top_scope
; i
; --i
)
223 if (t
= lookup_local_typedef (current_scope
[i
], x
)) {
228 if ((r
= is_object_in_global (p
)))
229 if (x
= lookup_local_typedef (r
, x
))
231 /* - - - - - - - - - - - - - - - - - - - - */
232 if (is_extern_templ_func (&p
)) {
233 b
->basetype
= BASETYPE_SKIP
;
236 /* ////////////////////////////////// */
237 parse_error_pt (p
, x
, "Not good for a base type");
239 typeID tt
= b
->basetype2
= lookup_typedef (x
);
241 if (iname
&& open_typeID (tt
)[1] == -1)
242 name_of_simple_type (b
->shortname
, tt
);
244 b
->shortname
[0] = x
;
245 b
->shortname
[1] = -1;
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;
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;
267 b
->basetype
= B_SINT
;
268 b
->shortname
[0] = RESERVED_enum
;
269 b
->shortname
[1] = x
;
270 b
->shortname
[2] = -1;
272 /* local typedef redirection */
273 /* XXXX: could we loop ??? */
280 /* Feature: do typeof */
281 static NormPtr
bt_typeof (Dclbase
*b
, NormPtr p
)
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);
295 b
->basetype2
= E
.type
;
299 /* ~~~~~~~~~~~~~~~~~ */
301 static NormPtr
enum_dcl (Dclbase
*b
, NormPtr p
, bool benum
, enumID e
)
306 ev
[j
++] = b
->shortname
[1];
307 outprintf (GLOBAL
, ISTR (b
->shortname
), '{', -1);
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
++]);
315 outprintf (GLOBAL
, '=', binshift
[31 & i
++], -1);
316 else if (CODE
[p
] == '=') {
318 p
= parse_const_expression (1 + p
, &E
);
320 outprintf (GLOBAL
, '=', ISTR (E
.newExpr
), - 1);
325 if (CODE
[p
] == ',') {
326 output_itoken (GLOBAL
, ',');
332 parse_error_ll ("error in enum");
334 outprintf (GLOBAL
, '}', ';', -1);
336 enter_enum_syms (e
, ev
, j
);
340 static NormPtr
bt_enum (Dclbase
*b
, NormPtr p
, bool benum
)
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
++]);
355 return enum_dcl (b
, p
+ 1, benum
, e
);
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 */
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
,
399 if (need_fwd
&& !is_aliasclass (b
->basetype
))
400 outprintf (GLOBAL
, ISTR (b
->shortname
), ';', -1);
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
))
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);
437 /* Feature: Base type abstract class */
438 static NormPtr
bt_abstract (Dclbase
*b
, NormPtr p
)
440 Token an
, par
[32], c
;
445 if (!ISSYMBOL (CODE
[p
]))
446 parse_error (p
, "anonymous abstract not possible");
449 if (CODE
[p
] == ':') {
451 do if ((c
= CODE
[p
++]) == RESERVED_virtual
)
452 if (!issymbol (c
= CODE
[p
++]) || !lookup_object (c
))
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
))
461 else parse_error_tok (c
, "No such class/template-class defined");
462 while (CODE
[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
;
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
)
486 b
->anon_union
= false;
487 b
->maybe_ctor
= false;
489 p
= collect_dclqual (b
, p
, 1);
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
:
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);
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
,
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);
529 p
= collect_dclqual (b
, p
, 0);
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
;
560 Token
*dflt_arge
[32];
568 // these are drivers for dirdcl()
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
)
580 Token
*tmp
= allocaint (intlen (d
->dclstr
));
582 /* alter the output declaration */
583 if (d
->dclstr
[d
->objp
+ 1] != '(') parse_error_ll ("BUG 234");
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
;
593 d
->dclstr
[i
++] = ',';
594 intcpy (d
->dclstr
+ i
, tmp
);
595 d
->ip
= intlen (d
->dclstr
);
596 intcpy (tmp
, d
->argv
);
601 static typeID
dcltype (Dclbase
*b
, Dclobj
*d
)
604 if (b
->basetype
== -1) {
605 int *td
= open_typeID (b
->basetype2
);
607 intcpy (typet
+ 1, d
->dclhype
);
608 intcat (typet
, td
+ 1);
610 typet
[0] = b
->basetype
;
612 if (d
) intcat (typet
, d
->dclhype
);
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
)
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;
644 static NormPtr
arglist (Dclobj
*, NormPtr
);
646 static int count_argc (NormPtr p
)
648 if (CODE
[p
] == ')') return 0;
650 while (CODE
[p
] != ')')
651 switch (CODE
[p
++]) {
652 case '(': p
= skip_parenthesis (p
);
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} ();'");
666 bool postfix
= CODE
[p
] == RESERVED_postfix
;
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!
675 if (!isoperator (op
))
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.");
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] == '.') {
704 if (bn
== bt_macro
) bn
= bt_replace
;
705 /* Feature: ctor with class name */
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");
715 d
->ctordtor
= CODE
[p
] == RESERVED_ctor
? 1 :
716 CODE
[p
] == RESERVED_dtor
? 2 : 0;
717 d
->rec
= lookup_object (bn
);
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
;
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
);
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
;
743 } else d
->dclstr
[d
->objp
= d
->ip
++] = BLANKT
;
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
;
754 /* + + + + + + + + + + + + + + + + + + + + + + + +*/
755 d
->dclstr
[d
->ip
++] = '(';
756 p
= arglist (d
, p
+ 1);
757 if (d
->rec
) POP_CURRENT_SCOPE
;
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
;
767 /* ......................... */
768 d
->dclstr
[d
->ip
++] = '[';
769 d
->dclhype
[d
->dclhi
] = d
->dclhi
|| inargs
? '*' : '[';
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
;
780 p
= parse_expression (p
, &E
, NORMAL_EXPR
) + 1;
781 if (E
.ok
&& !E
.isconstant
) {
782 /* Feature: store VLA info */
784 parse_error (p
, "non-constant [expression]");
786 d
->dclhype
[0] = '*';
787 d
->dclstr
[d
->ip
- 1] = d
->dclstr
[d
->ip
- 2];
788 d
->dclstr
[d
->ip
- 2] = '*';
792 /* * * * * * * * * */
796 for (ps
= 0; E
.newExpr
[ps
] != -1;)
797 d
->dclstr
[d
->ip
++] = E
.newExpr
[ps
++];
801 d
->dclstr
[d
->ip
++] = ']';
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);
815 d
->dclstr
[d
->ip
++] = CODE
[p
++];
820 static NormPtr
parse_dcl (Dclobj
*d
, NormPtr p
, bool inargs
)
824 d
->rec
= 0, d
->objp
= -1;
825 d
->dclhi
= d
->ip
= 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;
841 static NormPtr
arglist (Dclobj
*d
, NormPtr p
)
847 Dclobj di
= DCLOBJ_INIT
;
850 d
->dclhype
[d
->dclhi
++] = '(';
853 di
.allowed_va
= true;
855 if (CODE
[p
] == RESERVED_void
&& CODE
[p
+ 1] == ')') {
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");
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
++);
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!");
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
++] = ',';
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;
927 static inline NormPtr
parse_bitfield (Dclobj
*d
, NormPtr p
)
929 if (CODE
[p
] == ':') {
930 d
->dclstr
[d
->ip
++] = ':';
932 p
= parse_const_expression (++p
, &E
);
935 for (ps
= 0; E
.newExpr
[ps
] != -1;)
936 d
->dclstr
[d
->ip
++] = E
.newExpr
[ps
++];
939 d
->dclstr
[d
->ip
] = -1;
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
)
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
,
974 static void add_dclqual (Token q
, Token
*ts
)
977 for (i
= 0; ts
[i
] != -1; i
++)
978 if (ts
[i
] == q
) return;
983 static Token
pdcl_function (Dclbase
*b
, Dclobj
*d
, typeID t
, int fflagz
)
985 Token f
= d
->dclstr
[d
->objp
];
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;
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
*));
1005 tmpargv
= allocaint (intlen (d
->argv
) + 2);
1006 tmpargv
[0] = RESERVED_this
;
1007 intcpy (tmpargv
+ 1, d
->argv
);
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
)
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
)
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
);
1038 if (CODE
[p
] != RESERVED_typedef
)
1040 p
= skip_declaration (p
);
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
;
1049 p
= parse_basetype (&b
, last_location
= p
);
1050 d
.const_in_base
= b
.isconst
;
1052 if (b
.basetype
== BASETYPE_ABSTRACT
)
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
])
1067 have
[i
++] = d
.dclstr
[d
.objp
];
1069 strcat (strcat (strcat (nm
, "_"),
1070 expand (d
.dclstr
[d
.objp
])), nametype (tmp
, dt
));
1073 if (CODE
[p
] == ';') break;
1074 if (CODE
[p
++] != ',')
1075 parse_error_pt (p
, CODE
[p
-1], "parse error in declaration separator(3)");
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
)
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
)
1110 Dclobj d
= DCLOBJ_INIT
;
1114 /* Feature: skip local typedefs */
1115 if (CODE
[p
] == RESERVED_typedef
)
1116 return skip_declaration (p
);
1117 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
1123 /* Decorative feature: private && public disappear */
1124 if ((CODE
[p
] == RESERVED_public
|| CODE
[p
] == RESERVED_private
)
1125 && CODE
[p
+ 1] == ':')
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)] == ';') {
1135 parse_error (p
, "bad specifications");
1136 Here_virtualtable (D
, r
, b
.isinline
, b
.isconst
, b
.isvolatile
);
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 ';'");
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
)
1167 if (CODE
[p
] == ':') {
1169 p
= parse_bitfield (&d
, p
);
1170 outprintf (D
, ISTR (b
.dclqual
), ISTR (b
.shortname
),
1171 ISTR (d
.dclstr
), ';', -1);
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
);
1183 /* ..................................... */
1184 parse_error_pt (p
, name_of_struct (r
),"Abstract declaration in structure?");
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
)) {
1210 /* Feature: class's qualifiers apply to member functions */
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
;
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
)
1234 /* ^^^^^^^^^^^^^^^^^^^^^ */
1236 /* Feature: member functions */
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
;
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
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 */
1282 Make_virtual_table (D
, r
, fname
, dt
);
1284 /* % % % % % % % % % % % % % % % % % % % % % */
1286 /* Feature: auto functions */
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
);
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 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
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
);
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
)) {
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
,
1334 /* %%%%%%%%%%%%%%%%%%%%%%%%%% */
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
]),
1343 add_variable_member (r
, rn
, dt
, d
.dclstr
[d
.objp
], false, 0);
1344 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1346 add_variable_member (r
, d
.dclstr
[d
.objp
], dt
, 0, d
.constant
,
1349 outprintf (D
, ISTR (b
.dclqual
), ISTR (b
.shortname
),
1350 ISTR (d
.dclstr
), ';', -1);
1354 if (CODE
[p
] == ';') break;
1355 if (CODE
[p
++] != ',')
1356 parse_error_pt (p
, CODE
[p
-1], "parse error in declaration separator(1)");
1362 /* Feature: parse local typedef member */
1363 static NormPtr
struct_typedef (recID r
, NormPtr p
)
1366 Dclobj d
= DCLOBJ_INIT
;
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
);
1380 /* ^^^^^^^^^^^^^^^^^^^^^^ */
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");
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)");
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
;
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
);
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
)
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
);
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
));
1477 if (debugflag
.DCL_TRACE
)
1478 PRINTF ("Entering structure ["COLS
"%s"COLE
"]\n", expand (name_of_struct (r
)));
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
);
1515 alias
= complete_structure (STRUCTDCL
, r
);
1516 output_itoken (STRUCTDCL
, '}');
1517 if (CODE
[p
] == RESERVED___attribute__
) {
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
, ';');
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);
1533 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
1534 } else dcl
= combine_output (STRUCTDCL
);
1536 set_declaration (r
, dcl
);
1540 /* * * Parse the inheritance specifications * * */
1541 /* * * support for abstract classes * * */
1542 static NormPtr
parse_inheritance (NormPtr p
, recID r
, Token aparents
[])
1545 recID parents
[32], iparents
[32];
1546 int i
= 0, j
= 0, k
;
1549 if ((vp
= CODE
[p
] == RESERVED_virtual
))
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
++];
1560 parents
[i
] = lookup_object (CODE
[p
++]);
1562 parse_error_pt (p
, CODE
[p
-1], "No such class");
1563 if (vp
) parents
[i
] += VIRTUALPAR_BOOST
;
1567 if (CODE
[p
] != ',') break;
1570 if (CODE
[p
] != '{')
1571 parse_error (p
, "Syntax error after parent classes");
1574 set_parents (r
, parents
);
1578 /* -------------------------------------------- */
1580 static NormPtr
copy_designator (NormPtr p
, Token des
[])
1583 while (1) switch (CODE
[p
++]) {
1586 des
[i
++] = CODE
[p
++];
1591 p
= skip_expression (CODE
, p
, NORMAL_EXPR
);
1592 if (CODE
[p
++] != ']')
1593 parse_error (p
, "Das is verbotten");
1595 des
[i
++] = CODE
[p2
++];
1607 static NormPtr
aggregate_initializer (OUTSTREAM O
, NormPtr p
, typeID ret
)
1611 typeID t
, t1
= isstructure (ret
) ? ret
: ptrdown (ret
);
1613 output_itoken (O
, '{');
1615 if (CODE
[p
] == '}') {
1616 output_itoken (O
, '}');
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);
1625 if (CODE
[p
] == '{')
1626 p
= aggregate_initializer (O
, p
+ 1, t
);
1628 p
= parse_expression_retconv (p2
= p
, &E
, t
, INIT_EXPR
);
1630 outprintf (O
, ISTR (E
.newExpr
), -1);
1634 if (CODE
[p
] == '}') {
1635 output_itoken (O
, '}');
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
)
1649 Token designator
[256];
1652 if (CODE
[p
] == '}') {
1653 output_itoken (O
, '}');
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
);
1663 intcat (designator
, E
.newExpr
);
1665 rewrite_designator (t
, designator
);
1666 outprintf (O
, ISTR (designator
), ';', -1);
1668 if (CODE
[p
] == '}')
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
);
1681 p
= parse_expression_retconv (p
, &E
, t
, INIT_EXPR
);
1683 outprintf (O
, ISTR (E
.newExpr
), -1);
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
)
1697 if (O
== GLOBAL_INIT_FUNC
) GlobInitUsed
= true;
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
);
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
, ')');
1715 ctexpr
= allocaint (6);
1716 sintprintf (ctexpr
, obj
, '.', RESERVED_ctor
, '(', ')', -1);
1718 if ((ctexpr
= rewrite_ctor_expr (ctexpr
))) {
1719 outprintf (O
, ISTR (ctexpr
), ';', -1);
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
)
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
));
1743 if (dstruct
) dto
= i_arrdtor_func (base_of (t
));
1745 if (isstructarr (t
) && always_unwind (base_of (t
))) throwing
= true;
1746 throwing
&= dstruct
;
1750 outprintf (O
, RESERVED_struct
, arrdtor
, u1
, cleanup_func (dto
), '=', '{',
1751 obj
, ',', RESERVED_0
, '}', ';', -1);
1753 outprintf (O
, RESERVED_struct
, arrdtor
, u1
, '=', '{', obj
, ',', RESERVED_0
,
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
, ')');
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);
1776 } else TEST_MAYTHROW
;
1777 if (CODE
[p
] == ',') ++p
;
1778 else if (CODE
[p
] != '}') parse_error (p
, "Initializer expression separator");
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);
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);
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 ();
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
);
1826 outprintf (O
, BACKSPACE
, new_value_int (cnt
), ']', -1);
1830 static void vla2alloca (OUTSTREAM O
, Token obj
, NormPtr ep
)
1832 outprintf (O
, '=', '(', RESERVED___typeof__
, '(', obj
, ')', ')',
1833 INTERN_alloca
, '(', RESERVED_sizeof
, '*', obj
, '*', '(', -1);
1835 parse_expression_retconv (ep
, &E
, typeID_int
, NORMAL_EXPR
);
1837 outprintf (O
, ISTR (E
.newExpr
), ')', ')', -1);
1839 } else outprintf (O
, RESERVED_0
, ')', ')', -1);
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
;
1853 Dclobj d
= DCLOBJ_INIT
;
1855 Token
*para_code
=para_code
;
1856 bool specialization
= CODE
[p
] == RESERVED_specialize
;
1858 if (CODE
[p
] == ';') return p
+ 1;
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
)
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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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");
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
),
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) ';'");
1929 parse_error (p
, "Abstract declaration in local");
1930 /* * * * * * * * * * * * * * * * * * * * */
1934 if (isfunction (dt
)) {
1935 pdcl_function (&b
, &d
, dt
, 0);
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
));
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
, ¶_code
, b
.is__unwind__
);
1970 RESTOR_VAR (local_name
);
1971 RESTOR_VAR (local_type
);
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 */
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 */
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);
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
)
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);
2051 push_unwind (O
, base_of (dt
), d
.dclstr
[d
.objp
]);
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 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
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;");
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);
2085 p
= parse_expression_retconv (p
, &E
, t
, INIT_EXPR
);
2088 outprintf (OSTR
, '=', ISTR (E
.newExpr
), - 1);
2090 outprintf (GLOBAL_INIT_FUNC
, obj
, '=', ISTR (E
.newExpr
), ';', - 1);
2091 GlobInitUsed
= true;
2098 static NormPtr
global_declaration (NormPtr p
, bool linkonce
)
2102 Dclobj d
= DCLOBJ_INIT
;
2106 if (CODE
[p
] == ';') return p
+ 1;
2108 d
.begins
= last_location
= p
;
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
)
2122 p
= parse_dcl (&d
, p
, 0);
2124 /* Skip extern abstract func */
2125 if (d
.ctordtor
== BASETYPE_SKIP
)
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;
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
;
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
)
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
;
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);
2176 /* *************************** */
2179 flagz
|= FUNCP_NOTHROW
;
2182 d
.cname
= d
.dclstr
[d
.objp
];
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);
2191 possible_keyfunc (d
.rec
, d
.dclstr
[d
.objp
]);
2192 if (b
.islinkonce
|| linkonce
)
2193 xmark_section_linkonce (FSP (d
.rec
), d
.cname
,
2195 return skip_braces (p
);
2199 OUTSTREAM OSTR
= b
.istypedef
? GLOBAL
: GVARS
;
2202 parse_error (p
, "VLA in global not possible");
2205 if (enter_typedef (d
.dclstr
[d
.objp
], dt
))
2206 outprintf (OSTR
, ISTR (b
.dclqual
), ISTR (b
.shortname
),
2207 ISTR (d
.dclstr
), -1);
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 */
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
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);
2246 output_itoken (OSTR
, ';');
2248 if (CODE
[p
] == ';') break;
2249 if (CODE
[p
++] != ',')
2250 parse_error_pt (p
, CODE
[p
-1], "invalid declaration separator");
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);
2265 RESTOR_VAR (bt_macro
);
2266 RESTOR_VAR (bt_replace
);
2269 typeID
eval_cast (Token
**t
)
2272 Dclobj d
= DCLOBJ_INIT
;
2274 SAVE_VAR (CODE
, *t
);
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
);
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\" '{'");
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
);
2315 RESTOR_VAR (StructByRef
);
2316 RESTOR_VAR (Streams_Closed
);
2317 RESTOR_VAR (GoodOldC
);
2322 void translation_unit ()
2326 while (CODE
[p
] != -1)
2328 case RESERVED__lwc_config_
:
2329 p
= lwc_config (p
+ 1);
2330 ncase RESERVED___C__
:
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);
2339 p
= global_declaration (p
, 0);