]>
Commit | Line | Data |
---|---|---|
703d89ab | 1 | /* Process source files and output type information. |
a945c346 | 2 | Copyright (C) 2006-2024 Free Software Foundation, Inc. |
703d89ab | 3 | |
e1b793e7 | 4 | This file is part of GCC. |
703d89ab | 5 | |
e1b793e7 BS |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
703d89ab | 10 | |
e1b793e7 BS |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
703d89ab | 15 | |
e1b793e7 BS |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
703d89ab | 19 | |
d6d34aa9 | 20 | #ifdef HOST_GENERATOR_FILE |
f142b5bc | 21 | #include "config.h" |
d6d34aa9 JJ |
22 | #define GENERATOR_FILE 1 |
23 | #else | |
24 | #include "bconfig.h" | |
f142b5bc | 25 | #endif |
703d89ab ZW |
26 | #include "system.h" |
27 | #include "gengtype.h" | |
28 | ||
29 | /* This is a simple recursive-descent parser which understands a subset of | |
30 | the C type grammar. | |
31 | ||
32 | Rule functions are suffixed _seq if they scan a sequence of items; | |
33 | _opt if they may consume zero tokens; _seqopt if both are true. The | |
34 | "consume_" prefix indicates that a sequence of tokens is parsed for | |
35 | syntactic correctness and then thrown away. */ | |
36 | ||
37 | /* Simple one-token lookahead mechanism. */ | |
38 | ||
39 | struct token | |
40 | { | |
41 | const char *value; | |
42 | int code; | |
43 | bool valid; | |
44 | }; | |
45 | static struct token T; | |
46 | ||
47 | /* Retrieve the code of the current token; if there is no current token, | |
48 | get the next one from the lexer. */ | |
49 | static inline int | |
50 | token (void) | |
51 | { | |
52 | if (!T.valid) | |
53 | { | |
54 | T.code = yylex (&T.value); | |
55 | T.valid = true; | |
56 | } | |
57 | return T.code; | |
58 | } | |
59 | ||
60 | /* Retrieve the value of the current token (if any) and mark it consumed. | |
61 | The next call to token() will get another token from the lexer. */ | |
62 | static inline const char * | |
63 | advance (void) | |
64 | { | |
65 | T.valid = false; | |
66 | return T.value; | |
67 | } | |
68 | ||
69 | /* Diagnostics. */ | |
70 | ||
71 | /* This array is indexed by the token code minus CHAR_TOKEN_OFFSET. */ | |
da5f6d9c | 72 | /* Keep in sync with 'gengtype.h:enum gty_token'. */ |
703d89ab ZW |
73 | static const char *const token_names[] = { |
74 | "GTY", | |
75 | "typedef", | |
76 | "extern", | |
77 | "static", | |
78 | "union", | |
79 | "struct", | |
80 | "enum", | |
703d89ab ZW |
81 | "...", |
82 | "ptr_alias", | |
83 | "nested_ptr", | |
da5f6d9c | 84 | "user", |
703d89ab ZW |
85 | "a number", |
86 | "a scalar type", | |
87 | "an identifier", | |
88 | "a string constant", | |
89 | "a character constant", | |
90 | "an array declarator", | |
313465bb | 91 | "a C++ keyword to ignore" |
703d89ab ZW |
92 | }; |
93 | ||
94 | /* This array is indexed by token code minus FIRST_TOKEN_WITH_VALUE. */ | |
da5f6d9c | 95 | /* Keep in sync with 'gengtype.h:enum gty_token'. */ |
703d89ab | 96 | static const char *const token_value_format[] = { |
703d89ab ZW |
97 | "'%s'", |
98 | "'%s'", | |
99 | "'%s'", | |
100 | "'\"%s\"'", | |
101 | "\"'%s'\"", | |
102 | "'[%s]'", | |
313465bb | 103 | "'%s'", |
703d89ab ZW |
104 | }; |
105 | ||
106 | /* Produce a printable representation for a token defined by CODE and | |
107 | VALUE. This sometimes returns pointers into malloc memory and | |
108 | sometimes not, therefore it is unsafe to free the pointer it | |
109 | returns, so that memory is leaked. This does not matter, as this | |
110 | function is only used for diagnostics, and in a successful run of | |
111 | the program there will be none. */ | |
112 | static const char * | |
113 | print_token (int code, const char *value) | |
114 | { | |
115 | if (code < CHAR_TOKEN_OFFSET) | |
116 | return xasprintf ("'%c'", code); | |
117 | else if (code < FIRST_TOKEN_WITH_VALUE) | |
118 | return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]); | |
119 | else if (!value) | |
e1b793e7 | 120 | return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */ |
703d89ab ZW |
121 | else |
122 | return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE], | |
123 | value); | |
124 | } | |
125 | ||
126 | /* Convenience wrapper around print_token which produces the printable | |
127 | representation of the current token. */ | |
128 | static inline const char * | |
129 | print_cur_token (void) | |
130 | { | |
131 | return print_token (T.code, T.value); | |
132 | } | |
133 | ||
134 | /* Report a parse error on the current line, with diagnostic MSG. | |
135 | Behaves as standard printf with respect to additional arguments and | |
136 | format escapes. */ | |
137 | static void ATTRIBUTE_PRINTF_1 | |
138 | parse_error (const char *msg, ...) | |
139 | { | |
140 | va_list ap; | |
141 | ||
14c4815e BS |
142 | fprintf (stderr, "%s:%d: parse error: ", |
143 | get_input_file_name (lexer_line.file), lexer_line.line); | |
703d89ab ZW |
144 | |
145 | va_start (ap, msg); | |
146 | vfprintf (stderr, msg, ap); | |
147 | va_end (ap); | |
148 | ||
ad58aabe DN |
149 | fputc ('\n', stderr); |
150 | ||
703d89ab ZW |
151 | hit_error = true; |
152 | } | |
153 | ||
154 | /* If the next token does not have code T, report a parse error; otherwise | |
155 | return the token's value. */ | |
156 | static const char * | |
157 | require (int t) | |
158 | { | |
159 | int u = token (); | |
160 | const char *v = advance (); | |
161 | if (u != t) | |
162 | { | |
163 | parse_error ("expected %s, have %s", | |
164 | print_token (t, 0), print_token (u, v)); | |
165 | return 0; | |
166 | } | |
167 | return v; | |
168 | } | |
169 | ||
18aa2b04 DM |
170 | /* As per require, but do not advance. */ |
171 | static const char * | |
172 | require_without_advance (int t) | |
173 | { | |
174 | int u = token (); | |
175 | const char *v = T.value; | |
176 | if (u != t) | |
177 | { | |
178 | parse_error ("expected %s, have %s", | |
179 | print_token (t, 0), print_token (u, v)); | |
180 | return 0; | |
181 | } | |
182 | return v; | |
183 | } | |
184 | ||
703d89ab ZW |
185 | /* If the next token does not have one of the codes T1 or T2, report a |
186 | parse error; otherwise return the token's value. */ | |
187 | static const char * | |
188 | require2 (int t1, int t2) | |
189 | { | |
190 | int u = token (); | |
191 | const char *v = advance (); | |
192 | if (u != t1 && u != t2) | |
193 | { | |
194 | parse_error ("expected %s or %s, have %s", | |
195 | print_token (t1, 0), print_token (t2, 0), | |
196 | print_token (u, v)); | |
197 | return 0; | |
198 | } | |
199 | return v; | |
200 | } | |
201 | ||
9aa54cc9 | 202 | /* If the next token does not have one of the codes T1, T2, T3 or T4, report a |
807e902e KZ |
203 | parse error; otherwise return the token's value. */ |
204 | static const char * | |
9aa54cc9 | 205 | require4 (int t1, int t2, int t3, int t4) |
807e902e KZ |
206 | { |
207 | int u = token (); | |
208 | const char *v = advance (); | |
9aa54cc9 | 209 | if (u != t1 && u != t2 && u != t3 && u != t4) |
807e902e | 210 | { |
9aa54cc9 | 211 | parse_error ("expected %s, %s, %s or %s, have %s", |
807e902e | 212 | print_token (t1, 0), print_token (t2, 0), |
9aa54cc9 DM |
213 | print_token (t3, 0), print_token (t4, 0), |
214 | print_token (u, v)); | |
807e902e KZ |
215 | return 0; |
216 | } | |
217 | return v; | |
218 | } | |
219 | ||
703d89ab ZW |
220 | /* Near-terminals. */ |
221 | ||
222 | /* C-style string constant concatenation: STRING+ | |
223 | Bare STRING should appear nowhere else in this file. */ | |
224 | static const char * | |
225 | string_seq (void) | |
226 | { | |
227 | const char *s1, *s2; | |
228 | size_t l1, l2; | |
229 | char *buf; | |
230 | ||
231 | s1 = require (STRING); | |
232 | if (s1 == 0) | |
233 | return ""; | |
234 | while (token () == STRING) | |
235 | { | |
236 | s2 = advance (); | |
237 | ||
238 | l1 = strlen (s1); | |
239 | l2 = strlen (s2); | |
e1b793e7 | 240 | buf = XRESIZEVEC (char, CONST_CAST (char *, s1), l1 + l2 + 1); |
703d89ab | 241 | memcpy (buf + l1, s2, l2 + 1); |
b1d5455a | 242 | XDELETE (CONST_CAST (char *, s2)); |
703d89ab ZW |
243 | s1 = buf; |
244 | } | |
245 | return s1; | |
246 | } | |
247 | ||
0823efed DN |
248 | |
249 | /* The caller has detected a template declaration that starts | |
250 | with TMPL_NAME. Parse up to the closing '>'. This recognizes | |
9aa54cc9 DM |
251 | simple template declarations of the form ID<ID1,ID2,...,IDn>, |
252 | potentially with a single level of indirection e.g. | |
253 | ID<ID1 *, ID2, ID3 *, ..., IDn>. | |
0823efed DN |
254 | It does not try to parse anything more sophisticated than that. |
255 | ||
256 | Returns the template declaration string "ID<ID1,ID2,...,IDn>". */ | |
257 | ||
258 | static const char * | |
259 | require_template_declaration (const char *tmpl_name) | |
260 | { | |
261 | char *str; | |
9aa54cc9 | 262 | int num_indirections = 0; |
0823efed DN |
263 | |
264 | /* Recognize the opening '<'. */ | |
265 | require ('<'); | |
266 | str = concat (tmpl_name, "<", (char *) 0); | |
267 | ||
268 | /* Read the comma-separated list of identifiers. */ | |
807e902e KZ |
269 | int depth = 1; |
270 | while (depth > 0) | |
0823efed | 271 | { |
807e902e KZ |
272 | if (token () == ENUM) |
273 | { | |
274 | advance (); | |
275 | str = concat (str, "enum ", (char *) 0); | |
276 | continue; | |
277 | } | |
e0702244 RS |
278 | if (token () == NUM |
279 | || token () == ':' | |
280 | || token () == '+') | |
807e902e KZ |
281 | { |
282 | str = concat (str, advance (), (char *) 0); | |
283 | continue; | |
284 | } | |
807e902e KZ |
285 | if (token () == '<') |
286 | { | |
287 | advance (); | |
288 | str = concat (str, "<", (char *) 0); | |
289 | depth += 1; | |
290 | continue; | |
291 | } | |
292 | if (token () == '>') | |
293 | { | |
294 | advance (); | |
295 | str = concat (str, ">", (char *) 0); | |
296 | depth -= 1; | |
297 | continue; | |
298 | } | |
9aa54cc9 | 299 | const char *id = require4 (SCALAR, ID, '*', ','); |
0823efed | 300 | if (id == NULL) |
9aa54cc9 DM |
301 | { |
302 | if (T.code == '*') | |
303 | { | |
304 | id = "*"; | |
305 | if (num_indirections++) | |
306 | parse_error ("only one level of indirection is supported" | |
307 | " in template arguments"); | |
308 | } | |
309 | else | |
310 | id = ","; | |
311 | } | |
312 | else | |
313 | num_indirections = 0; | |
0823efed DN |
314 | str = concat (str, id, (char *) 0); |
315 | } | |
0823efed DN |
316 | return str; |
317 | } | |
318 | ||
319 | ||
9771b263 DN |
320 | /* typedef_name: either an ID, or a template type |
321 | specification of the form ID<t1,t2,...,tn>. */ | |
0823efed | 322 | |
703d89ab ZW |
323 | static const char * |
324 | typedef_name (void) | |
325 | { | |
0823efed DN |
326 | const char *id = require (ID); |
327 | if (token () == '<') | |
328 | return require_template_declaration (id); | |
703d89ab | 329 | else |
0823efed | 330 | return id; |
703d89ab ZW |
331 | } |
332 | ||
333 | /* Absorb a sequence of tokens delimited by balanced ()[]{}. */ | |
334 | static void | |
335 | consume_balanced (int opener, int closer) | |
336 | { | |
337 | require (opener); | |
338 | for (;;) | |
339 | switch (token ()) | |
340 | { | |
e1b793e7 BS |
341 | default: |
342 | advance (); | |
343 | break; | |
344 | case '(': | |
345 | consume_balanced ('(', ')'); | |
346 | break; | |
347 | case '[': | |
348 | consume_balanced ('[', ']'); | |
349 | break; | |
350 | case '{': | |
351 | consume_balanced ('{', '}'); | |
352 | break; | |
703d89ab ZW |
353 | |
354 | case '}': | |
355 | case ']': | |
356 | case ')': | |
357 | if (token () != closer) | |
358 | parse_error ("unbalanced delimiters - expected '%c', have '%c'", | |
359 | closer, token ()); | |
e1b793e7 BS |
360 | advance (); |
361 | return; | |
703d89ab ZW |
362 | |
363 | case EOF_TOKEN: | |
364 | parse_error ("unexpected end of file within %c%c-delimited construct", | |
365 | opener, closer); | |
366 | return; | |
367 | } | |
368 | } | |
369 | ||
370 | /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
313465bb DN |
371 | expressions, until we encounter an end-of-statement marker (a ';' or |
372 | a '}') outside any such delimiters; absorb that too. */ | |
373 | ||
703d89ab | 374 | static void |
313465bb | 375 | consume_until_eos (void) |
703d89ab | 376 | { |
703d89ab ZW |
377 | for (;;) |
378 | switch (token ()) | |
379 | { | |
e1b793e7 BS |
380 | case ';': |
381 | advance (); | |
382 | return; | |
313465bb DN |
383 | |
384 | case '{': | |
385 | consume_balanced ('{', '}'); | |
386 | return; | |
703d89ab | 387 | |
e1b793e7 BS |
388 | case '(': |
389 | consume_balanced ('(', ')'); | |
390 | break; | |
313465bb | 391 | |
e1b793e7 BS |
392 | case '[': |
393 | consume_balanced ('[', ']'); | |
394 | break; | |
703d89ab ZW |
395 | |
396 | case '}': | |
397 | case ']': | |
398 | case ')': | |
399 | parse_error ("unmatched '%c' while scanning for ';'", token ()); | |
313465bb | 400 | return; |
703d89ab ZW |
401 | |
402 | case EOF_TOKEN: | |
403 | parse_error ("unexpected end of file while scanning for ';'"); | |
404 | return; | |
313465bb DN |
405 | |
406 | default: | |
407 | advance (); | |
408 | break; | |
703d89ab ZW |
409 | } |
410 | } | |
411 | ||
412 | /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
413 | expressions, until we encounter a comma or semicolon outside any | |
313465bb DN |
414 | such delimiters; absorb that too. Returns true if the loop ended |
415 | with a comma. */ | |
416 | ||
703d89ab | 417 | static bool |
313465bb | 418 | consume_until_comma_or_eos () |
703d89ab | 419 | { |
703d89ab ZW |
420 | for (;;) |
421 | switch (token ()) | |
422 | { | |
e1b793e7 BS |
423 | case ',': |
424 | advance (); | |
425 | return true; | |
313465bb | 426 | |
e1b793e7 BS |
427 | case ';': |
428 | advance (); | |
429 | return false; | |
313465bb DN |
430 | |
431 | case '{': | |
432 | consume_balanced ('{', '}'); | |
433 | return false; | |
703d89ab | 434 | |
e1b793e7 BS |
435 | case '(': |
436 | consume_balanced ('(', ')'); | |
437 | break; | |
313465bb | 438 | |
e1b793e7 BS |
439 | case '[': |
440 | consume_balanced ('[', ']'); | |
441 | break; | |
703d89ab ZW |
442 | |
443 | case '}': | |
444 | case ']': | |
445 | case ')': | |
446 | parse_error ("unmatched '%s' while scanning for ',' or ';'", | |
447 | print_cur_token ()); | |
e1b793e7 | 448 | return false; |
703d89ab ZW |
449 | |
450 | case EOF_TOKEN: | |
451 | parse_error ("unexpected end of file while scanning for ',' or ';'"); | |
452 | return false; | |
313465bb | 453 | |
ebe7c586 RS |
454 | case '=': |
455 | advance (); | |
456 | if (token () == '{') | |
457 | consume_balanced ('{', '}'); | |
458 | break; | |
459 | ||
313465bb DN |
460 | default: |
461 | advance (); | |
462 | break; | |
703d89ab ZW |
463 | } |
464 | } | |
703d89ab | 465 | \f |
e1b793e7 | 466 | |
703d89ab ZW |
467 | /* GTY(()) option handling. */ |
468 | static type_p type (options_p *optsp, bool nested); | |
469 | ||
470 | /* Optional parenthesized string: ('(' string_seq ')')? */ | |
471 | static options_p | |
472 | str_optvalue_opt (options_p prev) | |
473 | { | |
474 | const char *name = advance (); | |
475 | const char *value = ""; | |
476 | if (token () == '(') | |
477 | { | |
478 | advance (); | |
479 | value = string_seq (); | |
480 | require (')'); | |
481 | } | |
412dc29d | 482 | return create_string_option (prev, name, value); |
703d89ab ZW |
483 | } |
484 | ||
485 | /* absdecl: type '*'* | |
486 | -- a vague approximation to what the C standard calls an abstract | |
487 | declarator. The only kinds that are actually used are those that | |
488 | are just a bare type and those that have trailing pointer-stars. | |
489 | Further kinds should be implemented if and when they become | |
490 | necessary. Used only within GTY(()) option values, therefore | |
491 | further GTY(()) tags within the type are invalid. Note that the | |
492 | return value has already been run through adjust_field_type. */ | |
493 | static type_p | |
494 | absdecl (void) | |
495 | { | |
496 | type_p ty; | |
497 | options_p opts; | |
498 | ||
499 | ty = type (&opts, true); | |
500 | while (token () == '*') | |
501 | { | |
502 | ty = create_pointer (ty); | |
503 | advance (); | |
504 | } | |
505 | ||
506 | if (opts) | |
507 | parse_error ("nested GTY(()) options are invalid"); | |
508 | ||
509 | return adjust_field_type (ty, 0); | |
510 | } | |
511 | ||
512 | /* Type-option: '(' absdecl ')' */ | |
513 | static options_p | |
514 | type_optvalue (options_p prev, const char *name) | |
515 | { | |
516 | type_p ty; | |
517 | require ('('); | |
518 | ty = absdecl (); | |
519 | require (')'); | |
412dc29d | 520 | return create_type_option (prev, name, ty); |
703d89ab ZW |
521 | } |
522 | ||
523 | /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */ | |
524 | static options_p | |
525 | nestedptr_optvalue (options_p prev) | |
526 | { | |
527 | type_p ty; | |
528 | const char *from, *to; | |
529 | ||
530 | require ('('); | |
531 | ty = absdecl (); | |
532 | require (','); | |
533 | to = string_seq (); | |
534 | require (','); | |
535 | from = string_seq (); | |
536 | require (')'); | |
537 | ||
538 | return create_nested_ptr_option (prev, ty, to, from); | |
539 | } | |
540 | ||
541 | /* One GTY(()) option: | |
e1b793e7 BS |
542 | ID str_optvalue_opt |
543 | | PTR_ALIAS type_optvalue | |
e1b793e7 BS |
544 | | NESTED_PTR nestedptr_optvalue |
545 | */ | |
703d89ab ZW |
546 | static options_p |
547 | option (options_p prev) | |
548 | { | |
549 | switch (token ()) | |
550 | { | |
551 | case ID: | |
552 | return str_optvalue_opt (prev); | |
553 | ||
554 | case PTR_ALIAS: | |
555 | advance (); | |
556 | return type_optvalue (prev, "ptr_alias"); | |
557 | ||
703d89ab ZW |
558 | case NESTED_PTR: |
559 | advance (); | |
560 | return nestedptr_optvalue (prev); | |
561 | ||
0823efed DN |
562 | case USER_GTY: |
563 | advance (); | |
564 | return create_string_option (prev, "user", ""); | |
565 | ||
703d89ab | 566 | default: |
e1b793e7 | 567 | parse_error ("expected an option keyword, have %s", print_cur_token ()); |
703d89ab | 568 | advance (); |
412dc29d | 569 | return create_string_option (prev, "", ""); |
703d89ab ZW |
570 | } |
571 | } | |
572 | ||
573 | /* One comma-separated list of options. */ | |
574 | static options_p | |
575 | option_seq (void) | |
576 | { | |
577 | options_p o; | |
578 | ||
579 | o = option (0); | |
580 | while (token () == ',') | |
581 | { | |
582 | advance (); | |
583 | o = option (o); | |
584 | } | |
585 | return o; | |
586 | } | |
587 | ||
588 | /* GTY marker: 'GTY' '(' '(' option_seq? ')' ')' */ | |
589 | static options_p | |
590 | gtymarker (void) | |
591 | { | |
592 | options_p result = 0; | |
593 | require (GTY_TOKEN); | |
594 | require ('('); | |
595 | require ('('); | |
596 | if (token () != ')') | |
597 | result = option_seq (); | |
598 | require (')'); | |
599 | require (')'); | |
600 | return result; | |
601 | } | |
602 | ||
603 | /* Optional GTY marker. */ | |
604 | static options_p | |
605 | gtymarker_opt (void) | |
606 | { | |
607 | if (token () != GTY_TOKEN) | |
608 | return 0; | |
609 | return gtymarker (); | |
610 | } | |
313465bb DN |
611 | |
612 | ||
703d89ab | 613 | \f |
e53b6e56 | 614 | /* Declarators. The logic here is largely lifted from c-parser.cc. |
703d89ab ZW |
615 | Note that we do not have to process abstract declarators, which can |
616 | appear only in parameter type lists or casts (but see absdecl, | |
617 | above). Also, type qualifiers are thrown out in gengtype-lex.l so | |
618 | we don't have to do it. */ | |
619 | ||
620 | /* array_and_function_declarators_opt: | |
e1b793e7 BS |
621 | \epsilon |
622 | array_and_function_declarators_opt ARRAY | |
623 | array_and_function_declarators_opt '(' ... ')' | |
703d89ab ZW |
624 | |
625 | where '...' indicates stuff we ignore except insofar as grouping | |
626 | symbols ()[]{} must balance. | |
627 | ||
628 | Subroutine of direct_declarator - do not use elsewhere. */ | |
629 | ||
630 | static type_p | |
631 | array_and_function_declarators_opt (type_p ty) | |
632 | { | |
633 | if (token () == ARRAY) | |
634 | { | |
635 | const char *array = advance (); | |
636 | return create_array (array_and_function_declarators_opt (ty), array); | |
637 | } | |
638 | else if (token () == '(') | |
639 | { | |
640 | /* We don't need exact types for functions. */ | |
641 | consume_balanced ('(', ')'); | |
642 | array_and_function_declarators_opt (ty); | |
643 | return create_scalar_type ("function type"); | |
644 | } | |
645 | else | |
646 | return ty; | |
647 | } | |
648 | ||
313465bb | 649 | static type_p inner_declarator (type_p, const char **, options_p *, bool); |
703d89ab ZW |
650 | |
651 | /* direct_declarator: | |
e1b793e7 | 652 | '(' inner_declarator ')' |
313465bb | 653 | '(' \epsilon ')' <-- C++ ctors/dtors |
e1b793e7 | 654 | gtymarker_opt ID array_and_function_declarators_opt |
703d89ab ZW |
655 | |
656 | Subroutine of declarator, mutually recursive with inner_declarator; | |
313465bb DN |
657 | do not use elsewhere. |
658 | ||
659 | IN_STRUCT is true if we are called while parsing structures or classes. */ | |
660 | ||
703d89ab | 661 | static type_p |
313465bb DN |
662 | direct_declarator (type_p ty, const char **namep, options_p *optsp, |
663 | bool in_struct) | |
703d89ab ZW |
664 | { |
665 | /* The first token in a direct-declarator must be an ID, a | |
666 | GTY marker, or an open parenthesis. */ | |
667 | switch (token ()) | |
668 | { | |
669 | case GTY_TOKEN: | |
670 | *optsp = gtymarker (); | |
671 | /* fall through */ | |
313465bb | 672 | |
703d89ab ZW |
673 | case ID: |
674 | *namep = require (ID); | |
313465bb DN |
675 | /* If the next token is '(', we are parsing a function declaration. |
676 | Functions are ignored by gengtype, so we return NULL. */ | |
677 | if (token () == '(') | |
678 | return NULL; | |
703d89ab ZW |
679 | break; |
680 | ||
681 | case '(': | |
313465bb DN |
682 | /* If the declarator starts with a '(', we have three options. We |
683 | are either parsing 'TYPE (*ID)' (i.e., a function pointer) | |
684 | or 'TYPE(...)'. | |
685 | ||
686 | The latter will be a constructor iff we are inside a | |
687 | structure or class. Otherwise, it could be a typedef, but | |
688 | since we explicitly reject typedefs inside structures, we can | |
689 | assume that we found a ctor and return NULL. */ | |
703d89ab | 690 | advance (); |
313465bb DN |
691 | if (in_struct && token () != '*') |
692 | { | |
693 | /* Found a constructor. Find and consume the closing ')'. */ | |
694 | while (token () != ')') | |
695 | advance (); | |
696 | advance (); | |
697 | /* Tell the caller to ignore this. */ | |
698 | return NULL; | |
699 | } | |
700 | ty = inner_declarator (ty, namep, optsp, in_struct); | |
703d89ab ZW |
701 | require (')'); |
702 | break; | |
703 | ||
313465bb DN |
704 | case IGNORABLE_CXX_KEYWORD: |
705 | /* Any C++ keyword like 'operator' means that we are not looking | |
706 | at a regular data declarator. */ | |
707 | return NULL; | |
708 | ||
703d89ab | 709 | default: |
313465bb | 710 | parse_error ("expected '(', ')', 'GTY', or an identifier, have %s", |
703d89ab ZW |
711 | print_cur_token ()); |
712 | /* Do _not_ advance if what we have is a close squiggle brace, as | |
713 | we will get much better error recovery that way. */ | |
714 | if (token () != '}') | |
715 | advance (); | |
716 | return 0; | |
717 | } | |
718 | return array_and_function_declarators_opt (ty); | |
719 | } | |
720 | ||
721 | /* The difference between inner_declarator and declarator is in the | |
722 | handling of stars. Consider this declaration: | |
723 | ||
e1b793e7 | 724 | char * (*pfc) (void) |
703d89ab ZW |
725 | |
726 | It declares a pointer to a function that takes no arguments and | |
727 | returns a char*. To construct the correct type for this | |
728 | declaration, the star outside the parentheses must be processed | |
729 | _before_ the function type, the star inside the parentheses must | |
730 | be processed _after_ the function type. To accomplish this, | |
731 | declarator() creates pointers before recursing (it is actually | |
732 | coded as a while loop), whereas inner_declarator() recurses before | |
733 | creating pointers. */ | |
734 | ||
735 | /* inner_declarator: | |
e1b793e7 BS |
736 | '*' inner_declarator |
737 | direct_declarator | |
703d89ab ZW |
738 | |
739 | Mutually recursive subroutine of direct_declarator; do not use | |
313465bb DN |
740 | elsewhere. |
741 | ||
742 | IN_STRUCT is true if we are called while parsing structures or classes. */ | |
703d89ab ZW |
743 | |
744 | static type_p | |
313465bb DN |
745 | inner_declarator (type_p ty, const char **namep, options_p *optsp, |
746 | bool in_struct) | |
703d89ab ZW |
747 | { |
748 | if (token () == '*') | |
749 | { | |
750 | type_p inner; | |
751 | advance (); | |
313465bb | 752 | inner = inner_declarator (ty, namep, optsp, in_struct); |
703d89ab ZW |
753 | if (inner == 0) |
754 | return 0; | |
755 | else | |
756 | return create_pointer (ty); | |
757 | } | |
758 | else | |
313465bb | 759 | return direct_declarator (ty, namep, optsp, in_struct); |
703d89ab ZW |
760 | } |
761 | ||
762 | /* declarator: '*'+ direct_declarator | |
763 | ||
764 | This is the sole public interface to this part of the grammar. | |
765 | Arguments are the type known so far, a pointer to where the name | |
766 | may be stored, and a pointer to where GTY options may be stored. | |
313465bb DN |
767 | |
768 | IN_STRUCT is true when we are called to parse declarators inside | |
769 | a structure or class. | |
770 | ||
771 | Returns the final type. */ | |
703d89ab ZW |
772 | |
773 | static type_p | |
313465bb DN |
774 | declarator (type_p ty, const char **namep, options_p *optsp, |
775 | bool in_struct = false) | |
703d89ab ZW |
776 | { |
777 | *namep = 0; | |
778 | *optsp = 0; | |
779 | while (token () == '*') | |
780 | { | |
781 | advance (); | |
782 | ty = create_pointer (ty); | |
783 | } | |
313465bb | 784 | return direct_declarator (ty, namep, optsp, in_struct); |
703d89ab ZW |
785 | } |
786 | \f | |
787 | /* Types and declarations. */ | |
788 | ||
789 | /* Structure field(s) declaration: | |
790 | ( | |
e1b793e7 BS |
791 | type bitfield ';' |
792 | | type declarator bitfield? ( ',' declarator bitfield? )+ ';' | |
c180e495 | 793 | )* |
703d89ab ZW |
794 | |
795 | Knows that such declarations must end with a close brace (or, | |
796 | erroneously, at EOF). | |
e1b793e7 | 797 | */ |
703d89ab ZW |
798 | static pair_p |
799 | struct_field_seq (void) | |
800 | { | |
801 | pair_p f = 0; | |
802 | type_p ty, dty; | |
803 | options_p opts, dopts; | |
804 | const char *name; | |
805 | bool another; | |
806 | ||
c180e495 | 807 | while (token () != '}' && token () != EOF_TOKEN) |
703d89ab ZW |
808 | { |
809 | ty = type (&opts, true); | |
703d89ab | 810 | |
c22df64f DM |
811 | /* Ignore access-control keywords ("public:" etc). */ |
812 | while (!ty && token () == IGNORABLE_CXX_KEYWORD) | |
813 | { | |
814 | const char *keyword = advance (); | |
815 | if (strcmp (keyword, "public:") != 0 | |
816 | && strcmp (keyword, "private:") != 0 | |
817 | && strcmp (keyword, "protected:") != 0) | |
818 | break; | |
819 | ty = type (&opts, true); | |
820 | } | |
821 | ||
703d89ab ZW |
822 | if (!ty || token () == ':') |
823 | { | |
313465bb | 824 | consume_until_eos (); |
703d89ab ZW |
825 | continue; |
826 | } | |
827 | ||
828 | do | |
829 | { | |
313465bb DN |
830 | dty = declarator (ty, &name, &dopts, true); |
831 | ||
703d89ab ZW |
832 | /* There could be any number of weird things after the declarator, |
833 | notably bitfield declarations and __attribute__s. If this | |
834 | function returns true, the last thing was a comma, so we have | |
835 | more than one declarator paired with the current type. */ | |
313465bb | 836 | another = consume_until_comma_or_eos (); |
703d89ab ZW |
837 | |
838 | if (!dty) | |
839 | continue; | |
840 | ||
841 | if (opts && dopts) | |
842 | parse_error ("two GTY(()) options for field %s", name); | |
843 | if (opts && !dopts) | |
844 | dopts = opts; | |
845 | ||
846 | f = create_field_at (f, dty, name, dopts, &lexer_line); | |
847 | } | |
848 | while (another); | |
849 | } | |
703d89ab ZW |
850 | return nreverse_pairs (f); |
851 | } | |
852 | ||
0823efed DN |
853 | /* Return true if OPTS contain the option named STR. */ |
854 | ||
52a7fb3c | 855 | bool |
0823efed DN |
856 | opts_have (options_p opts, const char *str) |
857 | { | |
858 | for (options_p opt = opts; opt; opt = opt->next) | |
859 | if (strcmp (opt->name, str) == 0) | |
860 | return true; | |
861 | return false; | |
862 | } | |
863 | ||
864 | ||
703d89ab ZW |
865 | /* This is called type(), but what it parses (sort of) is what C calls |
866 | declaration-specifiers and specifier-qualifier-list: | |
867 | ||
e1b793e7 | 868 | SCALAR |
703d89ab ZW |
869 | | ID // typedef |
870 | | (STRUCT|UNION) ID? gtymarker? ( '{' gtymarker? struct_field_seq '}' )? | |
871 | | ENUM ID ( '{' ... '}' )? | |
872 | ||
873 | Returns a partial type; under some conditions (notably | |
874 | "struct foo GTY((...)) thing;") it may write an options | |
875 | structure to *OPTSP. | |
313465bb DN |
876 | |
877 | NESTED is true when parsing a declaration already known to have a | |
878 | GTY marker. In these cases, typedef and enum declarations are not | |
879 | allowed because gengtype only understands types at the global | |
880 | scope. */ | |
881 | ||
703d89ab ZW |
882 | static type_p |
883 | type (options_p *optsp, bool nested) | |
884 | { | |
885 | const char *s; | |
703d89ab ZW |
886 | *optsp = 0; |
887 | switch (token ()) | |
888 | { | |
889 | case SCALAR: | |
890 | s = advance (); | |
891 | return create_scalar_type (s); | |
892 | ||
893 | case ID: | |
703d89ab ZW |
894 | s = typedef_name (); |
895 | return resolve_typedef (s, &lexer_line); | |
896 | ||
313465bb DN |
897 | case IGNORABLE_CXX_KEYWORD: |
898 | /* By returning NULL here, we indicate to the caller that they | |
899 | should ignore everything following this keyword up to the | |
900 | next ';' or '}'. */ | |
901 | return NULL; | |
902 | ||
703d89ab ZW |
903 | case STRUCT: |
904 | case UNION: | |
905 | { | |
18aa2b04 | 906 | type_p base_class = NULL; |
703d89ab | 907 | options_p opts = 0; |
e1b793e7 BS |
908 | /* GTY annotations follow attribute syntax |
909 | GTY_BEFORE_ID is for union/struct declarations | |
910 | GTY_AFTER_ID is for variable declarations. */ | |
911 | enum | |
912 | { | |
913 | NO_GTY, | |
914 | GTY_BEFORE_ID, | |
915 | GTY_AFTER_ID | |
916 | } is_gty = NO_GTY; | |
0823efed | 917 | enum typekind kind = (token () == UNION) ? TYPE_UNION : TYPE_STRUCT; |
703d89ab ZW |
918 | advance (); |
919 | ||
703d89ab ZW |
920 | /* Top-level structures that are not explicitly tagged GTY(()) |
921 | are treated as mere forward declarations. This is because | |
922 | there are a lot of structures that we don't need to know | |
313465bb DN |
923 | about, and some of those have C++ and macro constructs that |
924 | we cannot handle. */ | |
703d89ab ZW |
925 | if (nested || token () == GTY_TOKEN) |
926 | { | |
e1b793e7 BS |
927 | is_gty = GTY_BEFORE_ID; |
928 | opts = gtymarker_opt (); | |
703d89ab | 929 | } |
d1b38208 TG |
930 | |
931 | if (token () == ID) | |
932 | s = advance (); | |
933 | else | |
a618dbe3 L |
934 | s = xasprintf ("anonymous:%s:%d", |
935 | get_input_file_name (lexer_line.file), | |
936 | lexer_line.line); | |
d1b38208 | 937 | |
e1b793e7 BS |
938 | /* Unfortunately above GTY_TOKEN check does not capture the |
939 | typedef struct_type GTY case. */ | |
d1b38208 TG |
940 | if (token () == GTY_TOKEN) |
941 | { | |
e1b793e7 BS |
942 | is_gty = GTY_AFTER_ID; |
943 | opts = gtymarker_opt (); | |
d1b38208 | 944 | } |
b8698a0f | 945 | |
18aa2b04 DM |
946 | bool is_user_gty = opts_have (opts, "user"); |
947 | ||
313465bb DN |
948 | if (token () == ':') |
949 | { | |
18aa2b04 DM |
950 | if (is_gty && !is_user_gty) |
951 | { | |
952 | /* For GTY-marked types that are not "user", parse some C++ | |
953 | inheritance specifications. | |
954 | We require single-inheritance from a non-template type. */ | |
955 | advance (); | |
956 | const char *basename = require (ID); | |
957 | /* This may be either an access specifier, or the base name. */ | |
01512446 JJ |
958 | if (strcmp (basename, "public") == 0 |
959 | || strcmp (basename, "protected") == 0 | |
960 | || strcmp (basename, "private") == 0) | |
18aa2b04 DM |
961 | basename = require (ID); |
962 | base_class = find_structure (basename, TYPE_STRUCT); | |
963 | if (!base_class) | |
964 | parse_error ("unrecognized base class: %s", basename); | |
965 | require_without_advance ('{'); | |
966 | } | |
967 | else | |
968 | { | |
969 | /* For types lacking GTY-markings, skip over C++ inheritance | |
970 | specification (and thus avoid having to parse e.g. template | |
971 | types). */ | |
972 | while (token () != '{') | |
973 | advance (); | |
974 | } | |
313465bb DN |
975 | } |
976 | ||
e1b793e7 BS |
977 | if (is_gty) |
978 | { | |
979 | if (token () == '{') | |
980 | { | |
981 | pair_p fields; | |
982 | ||
983 | if (is_gty == GTY_AFTER_ID) | |
984 | parse_error ("GTY must be specified before identifier"); | |
985 | ||
0823efed DN |
986 | if (!is_user_gty) |
987 | { | |
988 | advance (); | |
989 | fields = struct_field_seq (); | |
990 | require ('}'); | |
991 | } | |
992 | else | |
993 | { | |
994 | /* Do not look inside user defined structures. */ | |
995 | fields = NULL; | |
996 | kind = TYPE_USER_STRUCT; | |
997 | consume_balanced ('{', '}'); | |
9771b263 | 998 | return create_user_defined_type (s, &lexer_line); |
0823efed DN |
999 | } |
1000 | ||
18aa2b04 DM |
1001 | return new_structure (s, kind, &lexer_line, fields, opts, |
1002 | base_class); | |
e1b793e7 BS |
1003 | } |
1004 | } | |
1005 | else if (token () == '{') | |
1006 | consume_balanced ('{', '}'); | |
703d89ab ZW |
1007 | if (opts) |
1008 | *optsp = opts; | |
0823efed | 1009 | return find_structure (s, kind); |
703d89ab ZW |
1010 | } |
1011 | ||
313465bb DN |
1012 | case TYPEDEF: |
1013 | /* In C++, a typedef inside a struct/class/union defines a new | |
1014 | type for that inner scope. We cannot support this in | |
1015 | gengtype because we have no concept of scoping. | |
1016 | ||
1017 | We handle typedefs in the global scope separately (see | |
1018 | parse_file), so if we find a 'typedef', we must be inside | |
1019 | a struct. */ | |
1020 | gcc_assert (nested); | |
1021 | parse_error ("typedefs not supported in structures marked with " | |
1022 | "automatic GTY markers. Use GTY((user)) to mark " | |
1023 | "this structure."); | |
1024 | advance (); | |
1025 | return NULL; | |
1026 | ||
703d89ab ZW |
1027 | case ENUM: |
1028 | advance (); | |
e1b793e7 BS |
1029 | if (token () == ID) |
1030 | s = advance (); | |
1031 | else | |
a618dbe3 L |
1032 | s = xasprintf ("anonymous:%s:%d", |
1033 | get_input_file_name (lexer_line.file), | |
1034 | lexer_line.line); | |
703d89ab ZW |
1035 | |
1036 | if (token () == '{') | |
e1b793e7 | 1037 | consume_balanced ('{', '}'); |
313465bb DN |
1038 | |
1039 | /* If after parsing the enum we are at the end of the statement, | |
1040 | and we are currently inside a structure, then this was an | |
1041 | enum declaration inside this scope. | |
1042 | ||
1043 | We cannot support this for the same reason we cannot support | |
1044 | 'typedef' inside structures (see the TYPEDEF handler above). | |
1045 | If this happens, emit an error and return NULL. */ | |
1046 | if (nested && token () == ';') | |
1047 | { | |
1048 | parse_error ("enum definitions not supported in structures marked " | |
1049 | "with automatic GTY markers. Use GTY((user)) to mark " | |
1050 | "this structure."); | |
1051 | advance (); | |
1052 | return NULL; | |
1053 | } | |
1054 | ||
703d89ab ZW |
1055 | return create_scalar_type (s); |
1056 | ||
1057 | default: | |
1058 | parse_error ("expected a type specifier, have %s", print_cur_token ()); | |
1059 | advance (); | |
1060 | return create_scalar_type ("erroneous type"); | |
1061 | } | |
1062 | } | |
1063 | \f | |
1064 | /* Top level constructs. */ | |
1065 | ||
1066 | /* Dispatch declarations beginning with 'typedef'. */ | |
1067 | ||
1068 | static void | |
1069 | typedef_decl (void) | |
1070 | { | |
1071 | type_p ty, dty; | |
1072 | const char *name; | |
1073 | options_p opts; | |
1074 | bool another; | |
1075 | ||
1076 | gcc_assert (token () == TYPEDEF); | |
1077 | advance (); | |
1078 | ||
1079 | ty = type (&opts, false); | |
1080 | if (!ty) | |
1081 | return; | |
1082 | if (opts) | |
1083 | parse_error ("GTY((...)) cannot be applied to a typedef"); | |
1084 | do | |
1085 | { | |
1086 | dty = declarator (ty, &name, &opts); | |
1087 | if (opts) | |
1088 | parse_error ("GTY((...)) cannot be applied to a typedef"); | |
1089 | ||
1090 | /* Yet another place where we could have junk (notably attributes) | |
1091 | after the declarator. */ | |
313465bb | 1092 | another = consume_until_comma_or_eos (); |
703d89ab ZW |
1093 | if (dty) |
1094 | do_typedef (name, dty, &lexer_line); | |
1095 | } | |
1096 | while (another); | |
1097 | } | |
1098 | ||
1099 | /* Structure definition: type() does all the work. */ | |
1100 | ||
1101 | static void | |
1102 | struct_or_union (void) | |
1103 | { | |
1104 | options_p dummy; | |
1105 | type (&dummy, false); | |
1106 | /* There may be junk after the type: notably, we cannot currently | |
1107 | distinguish 'struct foo *function(prototype);' from 'struct foo;' | |
1108 | ... we could call declarator(), but it's a waste of time at | |
1109 | present. Instead, just eat whatever token is currently lookahead | |
1110 | and go back to lexical skipping mode. */ | |
1111 | advance (); | |
1112 | } | |
1113 | ||
1114 | /* GC root declaration: | |
e1b793e7 | 1115 | (extern|static) gtymarker? type ID array_declarators_opt (';'|'=') |
703d89ab ZW |
1116 | If the gtymarker is not present, we ignore the rest of the declaration. */ |
1117 | static void | |
1118 | extern_or_static (void) | |
1119 | { | |
1120 | options_p opts, opts2, dopts; | |
1121 | type_p ty, dty; | |
1122 | const char *name; | |
1123 | require2 (EXTERN, STATIC); | |
1124 | ||
1125 | if (token () != GTY_TOKEN) | |
1126 | { | |
1127 | advance (); | |
1128 | return; | |
1129 | } | |
1130 | ||
1131 | opts = gtymarker (); | |
e1b793e7 BS |
1132 | ty = type (&opts2, true); /* if we get here, it's got a GTY(()) */ |
1133 | dty = declarator (ty, &name, &dopts); | |
703d89ab ZW |
1134 | |
1135 | if ((opts && dopts) || (opts && opts2) || (opts2 && dopts)) | |
1136 | parse_error ("GTY((...)) specified more than once for %s", name); | |
1137 | else if (opts2) | |
1138 | opts = opts2; | |
1139 | else if (dopts) | |
1140 | opts = dopts; | |
1141 | ||
1142 | if (dty) | |
1143 | { | |
1144 | note_variable (name, adjust_field_type (dty, opts), opts, &lexer_line); | |
1145 | require2 (';', '='); | |
1146 | } | |
1147 | } | |
1148 | ||
703d89ab ZW |
1149 | /* Parse the file FNAME for GC-relevant declarations and definitions. |
1150 | This is the only entry point to this file. */ | |
1151 | void | |
1152 | parse_file (const char *fname) | |
1153 | { | |
1154 | yybegin (fname); | |
1155 | for (;;) | |
1156 | { | |
1157 | switch (token ()) | |
1158 | { | |
1159 | case EXTERN: | |
1160 | case STATIC: | |
1161 | extern_or_static (); | |
1162 | break; | |
1163 | ||
1164 | case STRUCT: | |
1165 | case UNION: | |
1166 | struct_or_union (); | |
1167 | break; | |
1168 | ||
1169 | case TYPEDEF: | |
1170 | typedef_decl (); | |
1171 | break; | |
1172 | ||
703d89ab ZW |
1173 | case EOF_TOKEN: |
1174 | goto eof; | |
1175 | ||
1176 | default: | |
1177 | parse_error ("unexpected top level token, %s", print_cur_token ()); | |
1178 | goto eof; | |
1179 | } | |
1180 | lexer_toplevel_done = 1; | |
1181 | } | |
1182 | ||
1183 | eof: | |
1184 | advance (); | |
1185 | yyend (); | |
1186 | } |