]>
Commit | Line | Data |
---|---|---|
703d89ab | 1 | /* Process source files and output type information. |
23a5b65a | 2 | Copyright (C) 2006-2014 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 | |
f142b5bc | 20 | #ifdef GENERATOR_FILE |
703d89ab | 21 | #include "bconfig.h" |
f142b5bc RG |
22 | #else |
23 | #include "config.h" | |
24 | #endif | |
703d89ab ZW |
25 | #include "system.h" |
26 | #include "gengtype.h" | |
27 | ||
28 | /* This is a simple recursive-descent parser which understands a subset of | |
29 | the C type grammar. | |
30 | ||
31 | Rule functions are suffixed _seq if they scan a sequence of items; | |
32 | _opt if they may consume zero tokens; _seqopt if both are true. The | |
33 | "consume_" prefix indicates that a sequence of tokens is parsed for | |
34 | syntactic correctness and then thrown away. */ | |
35 | ||
36 | /* Simple one-token lookahead mechanism. */ | |
37 | ||
38 | struct token | |
39 | { | |
40 | const char *value; | |
41 | int code; | |
42 | bool valid; | |
43 | }; | |
44 | static struct token T; | |
45 | ||
46 | /* Retrieve the code of the current token; if there is no current token, | |
47 | get the next one from the lexer. */ | |
48 | static inline int | |
49 | token (void) | |
50 | { | |
51 | if (!T.valid) | |
52 | { | |
53 | T.code = yylex (&T.value); | |
54 | T.valid = true; | |
55 | } | |
56 | return T.code; | |
57 | } | |
58 | ||
59 | /* Retrieve the value of the current token (if any) and mark it consumed. | |
60 | The next call to token() will get another token from the lexer. */ | |
61 | static inline const char * | |
62 | advance (void) | |
63 | { | |
64 | T.valid = false; | |
65 | return T.value; | |
66 | } | |
67 | ||
68 | /* Diagnostics. */ | |
69 | ||
70 | /* This array is indexed by the token code minus CHAR_TOKEN_OFFSET. */ | |
71 | static const char *const token_names[] = { | |
72 | "GTY", | |
73 | "typedef", | |
74 | "extern", | |
75 | "static", | |
76 | "union", | |
77 | "struct", | |
78 | "enum", | |
703d89ab ZW |
79 | "...", |
80 | "ptr_alias", | |
81 | "nested_ptr", | |
82 | "a param<N>_is option", | |
83 | "a number", | |
84 | "a scalar type", | |
85 | "an identifier", | |
86 | "a string constant", | |
87 | "a character constant", | |
88 | "an array declarator", | |
313465bb | 89 | "a C++ keyword to ignore" |
703d89ab ZW |
90 | }; |
91 | ||
92 | /* This array is indexed by token code minus FIRST_TOKEN_WITH_VALUE. */ | |
93 | static const char *const token_value_format[] = { | |
94 | "%s", | |
95 | "'%s'", | |
96 | "'%s'", | |
97 | "'%s'", | |
98 | "'\"%s\"'", | |
99 | "\"'%s'\"", | |
100 | "'[%s]'", | |
313465bb | 101 | "'%s'", |
703d89ab ZW |
102 | }; |
103 | ||
104 | /* Produce a printable representation for a token defined by CODE and | |
105 | VALUE. This sometimes returns pointers into malloc memory and | |
106 | sometimes not, therefore it is unsafe to free the pointer it | |
107 | returns, so that memory is leaked. This does not matter, as this | |
108 | function is only used for diagnostics, and in a successful run of | |
109 | the program there will be none. */ | |
110 | static const char * | |
111 | print_token (int code, const char *value) | |
112 | { | |
113 | if (code < CHAR_TOKEN_OFFSET) | |
114 | return xasprintf ("'%c'", code); | |
115 | else if (code < FIRST_TOKEN_WITH_VALUE) | |
116 | return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]); | |
117 | else if (!value) | |
e1b793e7 | 118 | return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */ |
703d89ab ZW |
119 | else |
120 | return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE], | |
121 | value); | |
122 | } | |
123 | ||
124 | /* Convenience wrapper around print_token which produces the printable | |
125 | representation of the current token. */ | |
126 | static inline const char * | |
127 | print_cur_token (void) | |
128 | { | |
129 | return print_token (T.code, T.value); | |
130 | } | |
131 | ||
132 | /* Report a parse error on the current line, with diagnostic MSG. | |
133 | Behaves as standard printf with respect to additional arguments and | |
134 | format escapes. */ | |
135 | static void ATTRIBUTE_PRINTF_1 | |
136 | parse_error (const char *msg, ...) | |
137 | { | |
138 | va_list ap; | |
139 | ||
14c4815e BS |
140 | fprintf (stderr, "%s:%d: parse error: ", |
141 | get_input_file_name (lexer_line.file), lexer_line.line); | |
703d89ab ZW |
142 | |
143 | va_start (ap, msg); | |
144 | vfprintf (stderr, msg, ap); | |
145 | va_end (ap); | |
146 | ||
ad58aabe DN |
147 | fputc ('\n', stderr); |
148 | ||
703d89ab ZW |
149 | hit_error = true; |
150 | } | |
151 | ||
152 | /* If the next token does not have code T, report a parse error; otherwise | |
153 | return the token's value. */ | |
154 | static const char * | |
155 | require (int t) | |
156 | { | |
157 | int u = token (); | |
158 | const char *v = advance (); | |
159 | if (u != t) | |
160 | { | |
161 | parse_error ("expected %s, have %s", | |
162 | print_token (t, 0), print_token (u, v)); | |
163 | return 0; | |
164 | } | |
165 | return v; | |
166 | } | |
167 | ||
18aa2b04 DM |
168 | /* As per require, but do not advance. */ |
169 | static const char * | |
170 | require_without_advance (int t) | |
171 | { | |
172 | int u = token (); | |
173 | const char *v = T.value; | |
174 | if (u != t) | |
175 | { | |
176 | parse_error ("expected %s, have %s", | |
177 | print_token (t, 0), print_token (u, v)); | |
178 | return 0; | |
179 | } | |
180 | return v; | |
181 | } | |
182 | ||
703d89ab ZW |
183 | /* If the next token does not have one of the codes T1 or T2, report a |
184 | parse error; otherwise return the token's value. */ | |
185 | static const char * | |
186 | require2 (int t1, int t2) | |
187 | { | |
188 | int u = token (); | |
189 | const char *v = advance (); | |
190 | if (u != t1 && u != t2) | |
191 | { | |
192 | parse_error ("expected %s or %s, have %s", | |
193 | print_token (t1, 0), print_token (t2, 0), | |
194 | print_token (u, v)); | |
195 | return 0; | |
196 | } | |
197 | return v; | |
198 | } | |
199 | ||
9aa54cc9 | 200 | /* If the next token does not have one of the codes T1, T2, T3 or T4, report a |
807e902e KZ |
201 | parse error; otherwise return the token's value. */ |
202 | static const char * | |
9aa54cc9 | 203 | require4 (int t1, int t2, int t3, int t4) |
807e902e KZ |
204 | { |
205 | int u = token (); | |
206 | const char *v = advance (); | |
9aa54cc9 | 207 | if (u != t1 && u != t2 && u != t3 && u != t4) |
807e902e | 208 | { |
9aa54cc9 | 209 | parse_error ("expected %s, %s, %s or %s, have %s", |
807e902e | 210 | print_token (t1, 0), print_token (t2, 0), |
9aa54cc9 DM |
211 | print_token (t3, 0), print_token (t4, 0), |
212 | print_token (u, v)); | |
807e902e KZ |
213 | return 0; |
214 | } | |
215 | return v; | |
216 | } | |
217 | ||
703d89ab ZW |
218 | /* Near-terminals. */ |
219 | ||
220 | /* C-style string constant concatenation: STRING+ | |
221 | Bare STRING should appear nowhere else in this file. */ | |
222 | static const char * | |
223 | string_seq (void) | |
224 | { | |
225 | const char *s1, *s2; | |
226 | size_t l1, l2; | |
227 | char *buf; | |
228 | ||
229 | s1 = require (STRING); | |
230 | if (s1 == 0) | |
231 | return ""; | |
232 | while (token () == STRING) | |
233 | { | |
234 | s2 = advance (); | |
235 | ||
236 | l1 = strlen (s1); | |
237 | l2 = strlen (s2); | |
e1b793e7 | 238 | buf = XRESIZEVEC (char, CONST_CAST (char *, s1), l1 + l2 + 1); |
703d89ab | 239 | memcpy (buf + l1, s2, l2 + 1); |
b1d5455a | 240 | XDELETE (CONST_CAST (char *, s2)); |
703d89ab ZW |
241 | s1 = buf; |
242 | } | |
243 | return s1; | |
244 | } | |
245 | ||
0823efed DN |
246 | |
247 | /* The caller has detected a template declaration that starts | |
248 | with TMPL_NAME. Parse up to the closing '>'. This recognizes | |
9aa54cc9 DM |
249 | simple template declarations of the form ID<ID1,ID2,...,IDn>, |
250 | potentially with a single level of indirection e.g. | |
251 | ID<ID1 *, ID2, ID3 *, ..., IDn>. | |
0823efed DN |
252 | It does not try to parse anything more sophisticated than that. |
253 | ||
254 | Returns the template declaration string "ID<ID1,ID2,...,IDn>". */ | |
255 | ||
256 | static const char * | |
257 | require_template_declaration (const char *tmpl_name) | |
258 | { | |
259 | char *str; | |
9aa54cc9 | 260 | int num_indirections = 0; |
0823efed DN |
261 | |
262 | /* Recognize the opening '<'. */ | |
263 | require ('<'); | |
264 | str = concat (tmpl_name, "<", (char *) 0); | |
265 | ||
266 | /* Read the comma-separated list of identifiers. */ | |
807e902e KZ |
267 | int depth = 1; |
268 | while (depth > 0) | |
0823efed | 269 | { |
807e902e KZ |
270 | if (token () == ENUM) |
271 | { | |
272 | advance (); | |
273 | str = concat (str, "enum ", (char *) 0); | |
274 | continue; | |
275 | } | |
276 | if (token () == NUM) | |
277 | { | |
278 | str = concat (str, advance (), (char *) 0); | |
279 | continue; | |
280 | } | |
281 | if (token () == ':') | |
282 | { | |
283 | advance (); | |
284 | str = concat (str, ":", (char *) 0); | |
285 | continue; | |
286 | } | |
287 | if (token () == '<') | |
288 | { | |
289 | advance (); | |
290 | str = concat (str, "<", (char *) 0); | |
291 | depth += 1; | |
292 | continue; | |
293 | } | |
294 | if (token () == '>') | |
295 | { | |
296 | advance (); | |
297 | str = concat (str, ">", (char *) 0); | |
298 | depth -= 1; | |
299 | continue; | |
300 | } | |
9aa54cc9 | 301 | const char *id = require4 (SCALAR, ID, '*', ','); |
0823efed | 302 | if (id == NULL) |
9aa54cc9 DM |
303 | { |
304 | if (T.code == '*') | |
305 | { | |
306 | id = "*"; | |
307 | if (num_indirections++) | |
308 | parse_error ("only one level of indirection is supported" | |
309 | " in template arguments"); | |
310 | } | |
311 | else | |
312 | id = ","; | |
313 | } | |
314 | else | |
315 | num_indirections = 0; | |
0823efed DN |
316 | str = concat (str, id, (char *) 0); |
317 | } | |
0823efed DN |
318 | return str; |
319 | } | |
320 | ||
321 | ||
9771b263 DN |
322 | /* typedef_name: either an ID, or a template type |
323 | specification of the form ID<t1,t2,...,tn>. */ | |
0823efed | 324 | |
703d89ab ZW |
325 | static const char * |
326 | typedef_name (void) | |
327 | { | |
0823efed DN |
328 | const char *id = require (ID); |
329 | if (token () == '<') | |
330 | return require_template_declaration (id); | |
703d89ab | 331 | else |
0823efed | 332 | return id; |
703d89ab ZW |
333 | } |
334 | ||
335 | /* Absorb a sequence of tokens delimited by balanced ()[]{}. */ | |
336 | static void | |
337 | consume_balanced (int opener, int closer) | |
338 | { | |
339 | require (opener); | |
340 | for (;;) | |
341 | switch (token ()) | |
342 | { | |
e1b793e7 BS |
343 | default: |
344 | advance (); | |
345 | break; | |
346 | case '(': | |
347 | consume_balanced ('(', ')'); | |
348 | break; | |
349 | case '[': | |
350 | consume_balanced ('[', ']'); | |
351 | break; | |
352 | case '{': | |
353 | consume_balanced ('{', '}'); | |
354 | break; | |
703d89ab ZW |
355 | |
356 | case '}': | |
357 | case ']': | |
358 | case ')': | |
359 | if (token () != closer) | |
360 | parse_error ("unbalanced delimiters - expected '%c', have '%c'", | |
361 | closer, token ()); | |
e1b793e7 BS |
362 | advance (); |
363 | return; | |
703d89ab ZW |
364 | |
365 | case EOF_TOKEN: | |
366 | parse_error ("unexpected end of file within %c%c-delimited construct", | |
367 | opener, closer); | |
368 | return; | |
369 | } | |
370 | } | |
371 | ||
372 | /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
313465bb DN |
373 | expressions, until we encounter an end-of-statement marker (a ';' or |
374 | a '}') outside any such delimiters; absorb that too. */ | |
375 | ||
703d89ab | 376 | static void |
313465bb | 377 | consume_until_eos (void) |
703d89ab | 378 | { |
703d89ab ZW |
379 | for (;;) |
380 | switch (token ()) | |
381 | { | |
e1b793e7 BS |
382 | case ';': |
383 | advance (); | |
384 | return; | |
313465bb DN |
385 | |
386 | case '{': | |
387 | consume_balanced ('{', '}'); | |
388 | return; | |
703d89ab | 389 | |
e1b793e7 BS |
390 | case '(': |
391 | consume_balanced ('(', ')'); | |
392 | break; | |
313465bb | 393 | |
e1b793e7 BS |
394 | case '[': |
395 | consume_balanced ('[', ']'); | |
396 | break; | |
703d89ab ZW |
397 | |
398 | case '}': | |
399 | case ']': | |
400 | case ')': | |
401 | parse_error ("unmatched '%c' while scanning for ';'", token ()); | |
313465bb | 402 | return; |
703d89ab ZW |
403 | |
404 | case EOF_TOKEN: | |
405 | parse_error ("unexpected end of file while scanning for ';'"); | |
406 | return; | |
313465bb DN |
407 | |
408 | default: | |
409 | advance (); | |
410 | break; | |
703d89ab ZW |
411 | } |
412 | } | |
413 | ||
414 | /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
415 | expressions, until we encounter a comma or semicolon outside any | |
313465bb DN |
416 | such delimiters; absorb that too. Returns true if the loop ended |
417 | with a comma. */ | |
418 | ||
703d89ab | 419 | static bool |
313465bb | 420 | consume_until_comma_or_eos () |
703d89ab | 421 | { |
703d89ab ZW |
422 | for (;;) |
423 | switch (token ()) | |
424 | { | |
e1b793e7 BS |
425 | case ',': |
426 | advance (); | |
427 | return true; | |
313465bb | 428 | |
e1b793e7 BS |
429 | case ';': |
430 | advance (); | |
431 | return false; | |
313465bb DN |
432 | |
433 | case '{': | |
434 | consume_balanced ('{', '}'); | |
435 | return false; | |
703d89ab | 436 | |
e1b793e7 BS |
437 | case '(': |
438 | consume_balanced ('(', ')'); | |
439 | break; | |
313465bb | 440 | |
e1b793e7 BS |
441 | case '[': |
442 | consume_balanced ('[', ']'); | |
443 | break; | |
703d89ab ZW |
444 | |
445 | case '}': | |
446 | case ']': | |
447 | case ')': | |
448 | parse_error ("unmatched '%s' while scanning for ',' or ';'", | |
449 | print_cur_token ()); | |
e1b793e7 | 450 | return false; |
703d89ab ZW |
451 | |
452 | case EOF_TOKEN: | |
453 | parse_error ("unexpected end of file while scanning for ',' or ';'"); | |
454 | return false; | |
313465bb DN |
455 | |
456 | default: | |
457 | advance (); | |
458 | break; | |
703d89ab ZW |
459 | } |
460 | } | |
703d89ab | 461 | \f |
e1b793e7 | 462 | |
703d89ab ZW |
463 | /* GTY(()) option handling. */ |
464 | static type_p type (options_p *optsp, bool nested); | |
465 | ||
466 | /* Optional parenthesized string: ('(' string_seq ')')? */ | |
467 | static options_p | |
468 | str_optvalue_opt (options_p prev) | |
469 | { | |
470 | const char *name = advance (); | |
471 | const char *value = ""; | |
472 | if (token () == '(') | |
473 | { | |
474 | advance (); | |
475 | value = string_seq (); | |
476 | require (')'); | |
477 | } | |
412dc29d | 478 | return create_string_option (prev, name, value); |
703d89ab ZW |
479 | } |
480 | ||
481 | /* absdecl: type '*'* | |
482 | -- a vague approximation to what the C standard calls an abstract | |
483 | declarator. The only kinds that are actually used are those that | |
484 | are just a bare type and those that have trailing pointer-stars. | |
485 | Further kinds should be implemented if and when they become | |
486 | necessary. Used only within GTY(()) option values, therefore | |
487 | further GTY(()) tags within the type are invalid. Note that the | |
488 | return value has already been run through adjust_field_type. */ | |
489 | static type_p | |
490 | absdecl (void) | |
491 | { | |
492 | type_p ty; | |
493 | options_p opts; | |
494 | ||
495 | ty = type (&opts, true); | |
496 | while (token () == '*') | |
497 | { | |
498 | ty = create_pointer (ty); | |
499 | advance (); | |
500 | } | |
501 | ||
502 | if (opts) | |
503 | parse_error ("nested GTY(()) options are invalid"); | |
504 | ||
505 | return adjust_field_type (ty, 0); | |
506 | } | |
507 | ||
508 | /* Type-option: '(' absdecl ')' */ | |
509 | static options_p | |
510 | type_optvalue (options_p prev, const char *name) | |
511 | { | |
512 | type_p ty; | |
513 | require ('('); | |
514 | ty = absdecl (); | |
515 | require (')'); | |
412dc29d | 516 | return create_type_option (prev, name, ty); |
703d89ab ZW |
517 | } |
518 | ||
519 | /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */ | |
520 | static options_p | |
521 | nestedptr_optvalue (options_p prev) | |
522 | { | |
523 | type_p ty; | |
524 | const char *from, *to; | |
525 | ||
526 | require ('('); | |
527 | ty = absdecl (); | |
528 | require (','); | |
529 | to = string_seq (); | |
530 | require (','); | |
531 | from = string_seq (); | |
532 | require (')'); | |
533 | ||
534 | return create_nested_ptr_option (prev, ty, to, from); | |
535 | } | |
536 | ||
537 | /* One GTY(()) option: | |
e1b793e7 BS |
538 | ID str_optvalue_opt |
539 | | PTR_ALIAS type_optvalue | |
540 | | PARAM_IS type_optvalue | |
541 | | NESTED_PTR nestedptr_optvalue | |
542 | */ | |
703d89ab ZW |
543 | static options_p |
544 | option (options_p prev) | |
545 | { | |
546 | switch (token ()) | |
547 | { | |
548 | case ID: | |
549 | return str_optvalue_opt (prev); | |
550 | ||
551 | case PTR_ALIAS: | |
552 | advance (); | |
553 | return type_optvalue (prev, "ptr_alias"); | |
554 | ||
555 | case PARAM_IS: | |
556 | return type_optvalue (prev, advance ()); | |
557 | ||
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 ZW |
613 | \f |
614 | /* Declarators. The logic here is largely lifted from c-parser.c. | |
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. */ | |
958 | if (0 == strcmp (basename, "public") | |
959 | || 0 == strcmp (basename, "protected") | |
960 | || 0 == strcmp (basename, "private")) | |
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 | } |