Commit | Line | Data |
---|---|---|
25223506 C |
1 | /* YACC parser for C++ syntax. |
2 | Copyright (C) 1988, 1989 Free Software Foundation, Inc. | |
3 | Hacked by Michael Tiemann (tiemann@cygnus.com) | |
4 | ||
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | ||
22 | /* This grammar is based on the GNU CC grammar. */ | |
23 | ||
24 | /* Note: Bison automatically applies a default action of "$$ = $1" for | |
25 | all derivations; this is applied before the explicit action, if one | |
26 | is given. Keep this in mind when reading the actions. */ | |
27 | ||
28 | /* Also note: this version contains experimental exception | |
29 | handling features. They could break, change, disappear, | |
30 | or otherwise exhibit volatile behavior. Don't depend on | |
31 | me (Michael Tiemann) to protect you from any negative impact | |
32 | this may have on your professional, personal, or spiritual life. | |
33 | ||
34 | NEWS FLASH: This version now supports the exception handling | |
35 | syntax of Stroustrup's 2nd edition, if -fansi-exceptions is given. | |
36 | THIS IS WORK IN PROGRESS!!! The type of the 'throw' and the | |
37 | 'catch' much match EXACTLY (no inheritance support or coercions). | |
38 | Also, throw-specifications of functions don't work. | |
39 | Destructors aren't called correctly. Etc, etc. --Per Bothner. | |
40 | */ | |
41 | ||
42 | %{ | |
43 | #if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG) | |
44 | #undef YYDEBUG | |
45 | #define YYDEBUG 1 | |
46 | #endif | |
47 | ||
48 | #include "config.h" | |
49 | ||
50 | #include <stdio.h> | |
51 | #include <errno.h> | |
52 | ||
53 | #include "tree.h" | |
54 | #include "input.h" | |
55 | #include "flags.h" | |
56 | #include "cp-lex.h" | |
57 | #include "cp-tree.h" | |
58 | ||
59 | extern tree void_list_node; | |
60 | extern struct obstack permanent_obstack; | |
61 | ||
62 | #ifndef errno | |
63 | extern int errno; | |
64 | #endif | |
65 | ||
66 | extern int end_of_file; | |
67 | ||
68 | void yyerror (); | |
69 | ||
70 | /* Like YYERROR but do call yyerror. */ | |
71 | #define YYERROR1 { yyerror ("syntax error"); YYERROR; } | |
72 | ||
73 | static void position_after_white_space (); | |
74 | ||
75 | /* Contains error message to give if user tries to declare | |
76 | a variable where one does not belong. */ | |
77 | static char *stmt_decl_msg = 0; | |
78 | ||
79 | /* Nonzero if we have an `extern "C"' acting as an extern specifier. */ | |
80 | int have_extern_spec; | |
81 | int used_extern_spec; | |
82 | ||
83 | void yyhook (); | |
84 | ||
85 | /* Cons up an empty parameter list. */ | |
86 | #ifdef __GNUC__ | |
87 | __inline | |
88 | #endif | |
89 | static tree | |
90 | empty_parms () | |
91 | { | |
92 | tree parms; | |
93 | ||
94 | if (strict_prototype) | |
95 | parms = void_list_node; | |
96 | else | |
97 | parms = NULL_TREE; | |
98 | return parms; | |
99 | } | |
100 | %} | |
101 | ||
102 | %start program | |
103 | ||
104 | %union {long itype; tree ttype; char *strtype; enum tree_code code; } | |
105 | ||
106 | /* All identifiers that are not reserved words | |
107 | and are not declared typedefs in the current block */ | |
108 | %token IDENTIFIER | |
109 | ||
110 | /* All identifiers that are declared typedefs in the current block. | |
111 | In some contexts, they are treated just like IDENTIFIER, | |
112 | but they can also serve as typespecs in declarations. */ | |
113 | %token TYPENAME | |
114 | ||
115 | /* Qualified identifiers that end in a TYPENAME. */ | |
116 | %token SCOPED_TYPENAME | |
117 | ||
118 | /* Reserved words that specify storage class. | |
119 | yylval contains an IDENTIFIER_NODE which indicates which one. */ | |
120 | %token SCSPEC | |
121 | ||
122 | /* Reserved words that specify type. | |
123 | yylval contains an IDENTIFIER_NODE which indicates which one. */ | |
124 | %token TYPESPEC | |
125 | ||
126 | /* Reserved words that qualify type: "const" or "volatile". | |
127 | yylval contains an IDENTIFIER_NODE which indicates which one. */ | |
128 | %token TYPE_QUAL | |
129 | ||
130 | /* Character or numeric constants. | |
131 | yylval is the node for the constant. */ | |
132 | %token CONSTANT | |
133 | ||
134 | /* String constants in raw form. | |
135 | yylval is a STRING_CST node. */ | |
136 | %token STRING | |
137 | ||
138 | /* "...", used for functions with variable arglists. */ | |
139 | %token ELLIPSIS | |
140 | ||
141 | /* the reserved words */ | |
142 | /* SCO include files test "ASM", so use something else. */ | |
143 | %token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT | |
144 | %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF HEADOF CLASSOF | |
145 | %token ATTRIBUTE EXTENSION LABEL | |
146 | ||
147 | /* the reserved words... C++ extensions */ | |
148 | %token <ttype> AGGR | |
149 | %token <itype> VISSPEC | |
150 | %token DELETE NEW OVERLOAD THIS OPERATOR | |
151 | %token DYNAMIC POINTSAT_LEFT_RIGHT LEFT_RIGHT TEMPLATE | |
152 | %token <itype> SCOPE | |
153 | ||
154 | /* Special token created by the lexer to separate TYPENAME | |
155 | from an ABSDCL. This allows us to parse `foo (*pf)()'. */ | |
156 | ||
157 | %token START_DECLARATOR | |
158 | ||
159 | /* Define the operator tokens and their precedences. | |
160 | The value is an integer because, if used, it is the tree code | |
161 | to use in the expression made from the operator. */ | |
162 | ||
163 | %left EMPTY /* used to resolve s/r with epsilon */ | |
164 | ||
165 | /* Add precedence rules to solve dangling else s/r conflict */ | |
166 | %nonassoc IF | |
167 | %nonassoc ELSE | |
168 | ||
169 | %left IDENTIFIER TYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR | |
170 | ||
171 | %left '{' ',' | |
172 | ||
173 | %right <code> ASSIGN '=' | |
174 | %right <code> '?' ':' RANGE | |
175 | %left <code> OROR | |
176 | %left <code> ANDAND | |
177 | %left <code> '|' | |
178 | %left <code> '^' | |
179 | %left <code> '&' | |
180 | %left <code> MIN_MAX | |
181 | %left <code> EQCOMPARE | |
182 | %left <code> ARITHCOMPARE '<' '>' | |
183 | %left <code> LSHIFT RSHIFT | |
184 | %left <code> '+' '-' | |
185 | %left <code> '*' '/' '%' | |
186 | %right <code> UNARY PLUSPLUS MINUSMINUS | |
187 | %left HYPERUNARY | |
188 | %left <ttype> PAREN_STAR_PAREN LEFT_RIGHT | |
189 | %left <code> POINTSAT POINTSAT_STAR '.' DOT_STAR '(' '[' | |
190 | ||
191 | %right SCOPE /* C++ extension */ | |
192 | %nonassoc NEW DELETE RAISE RAISES RERAISE TRY EXCEPT CATCH THROW | |
193 | %nonassoc ANSI_TRY ANSI_THROW | |
194 | %right DYNAMIC | |
195 | ||
196 | %type <code> unop | |
197 | ||
198 | %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist | |
199 | %type <ttype> optional_identifier | |
200 | %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING | |
201 | %type <ttype> typed_declspecs reserved_declspecs | |
202 | %type <ttype> typed_typespecs reserved_typespecquals | |
203 | %type <ttype> declmods typespec typespecqual_reserved | |
204 | %type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual | |
205 | %type <itype> initdecls notype_initdecls initdcl /* C++ modification */ | |
206 | %type <ttype> init initlist maybeasm | |
207 | %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers | |
208 | %type <ttype> maybe_attribute attribute_list attrib | |
209 | %type <ttype> abs_member_declarator after_type_member_declarator | |
210 | ||
211 | %type <ttype> compstmt except_stmts ansi_except_stmts | |
212 | ||
213 | %type <ttype> declarator notype_declarator after_type_declarator | |
214 | ||
215 | %type <ttype> structsp opt.component_decl_list component_decl_list component_decl components component_declarator | |
216 | %type <ttype> enumlist enumerator | |
217 | %type <ttype> typename absdcl absdcl1 type_quals abs_or_notype_decl | |
218 | %type <ttype> xexpr see_typename parmlist parms parm bad_parm | |
219 | %type <ttype> identifiers_or_typenames | |
220 | ||
221 | /* C++ extensions */ | |
222 | %type <ttype> typename_scope | |
223 | %token <ttype> TYPENAME_COLON TYPENAME_ELLIPSIS | |
224 | %token <ttype> PTYPENAME SCOPED_TYPENAME | |
225 | %token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL | |
226 | %token <ttype> PRE_PARSED_CLASS_DECL | |
227 | %type <ttype> fn.def1 /* Not really! */ | |
228 | %type <ttype> fn.def2 return_id | |
229 | %type <ttype> named_class_head named_class_head_sans_basetype | |
230 | %type <ttype> unnamed_class_head | |
231 | %type <ttype> class_head base_class_list | |
232 | %type <itype> base_class_visibility_list | |
233 | %type <ttype> base_class maybe_base_class_list base_class.1 | |
234 | %type <ttype> after_type_declarator_no_typename | |
235 | %type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers | |
236 | %type <ttype> component_declarator0 scoped_id scoped_typename scoped_base_class | |
237 | %type <ttype> forhead.1 identifier_or_opname operator_name | |
238 | %type <ttype> new delete object object_star aggr | |
239 | /* %type <ttype> primary_no_id */ | |
240 | %type <ttype> nonmomentary_expr | |
241 | %type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list | |
242 | %type <itype> .scope try ansi_try | |
243 | %type <ttype> template_header template_parm_list template_parm | |
244 | %type <ttype> template_type template_arg_list template_arg | |
245 | %type <ttype> template_instantiation template_type_name tmpl.1 tmpl.2 | |
246 | %type <ttype> template_instantiate_once template_instantiate_some | |
247 | %type <itype> fn_tmpl_end | |
248 | /* %type <itype> try_for_typename */ | |
249 | ||
250 | /* in order to recognize aggr tags as defining and thus shadowing. */ | |
251 | %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN | |
252 | %type <ttype> named_class_head_sans_basetype_defn | |
253 | %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN | |
254 | ||
255 | %type <strtype> .pushlevel | |
256 | ||
257 | /* cp-spew.c depends on this being the last token. Define | |
258 | any new tokens before this one! */ | |
259 | %token END_OF_SAVED_INPUT | |
260 | \f | |
261 | %{ | |
262 | /* List of types and structure classes of the current declaration. */ | |
263 | static tree current_declspecs; | |
264 | ||
265 | /* When defining an aggregate, this is the most recent one being defined. */ | |
266 | static tree current_aggr; | |
267 | ||
268 | /* 1 if we explained undeclared var errors. */ | |
269 | int undeclared_variable_notice; | |
270 | ||
271 | /* Tell yyparse how to print a token's value, if yydebug is set. */ | |
272 | ||
273 | #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) | |
274 | extern void yyprint (); | |
275 | %} | |
276 | \f | |
277 | %% | |
278 | program: /* empty */ | |
279 | | extdefs | |
280 | { finish_file (); } | |
281 | ; | |
282 | ||
283 | /* the reason for the strange actions in this rule | |
284 | is so that notype_initdecls when reached via datadef | |
285 | can find a valid list of type and sc specs in $0. */ | |
286 | ||
287 | extdefs: | |
288 | { $<ttype>$ = NULL_TREE; } extdef | |
289 | {$<ttype>$ = NULL_TREE; } | |
290 | | extdefs extdef | |
291 | {$<ttype>$ = NULL_TREE; } | |
292 | ; | |
293 | ||
294 | .hush_warning: | |
295 | { have_extern_spec = 1; | |
296 | used_extern_spec = 0; | |
297 | $<ttype>$ = NULL_TREE; } | |
298 | ; | |
299 | .warning_ok: | |
300 | { have_extern_spec = 0; } | |
301 | ; | |
302 | ||
303 | extdef: | |
304 | fndef | |
305 | { if (pending_inlines) do_pending_inlines (); } | |
306 | | datadef | |
307 | { if (pending_inlines) do_pending_inlines (); } | |
308 | | template_def | |
309 | { if (pending_inlines) do_pending_inlines (); } | |
310 | | overloaddef | |
311 | | ASM_KEYWORD '(' string ')' ';' | |
312 | { if (pedantic) | |
313 | pedwarn ("ANSI C++ forbids use of `asm' keyword"); | |
314 | if (TREE_CHAIN ($3)) $3 = combine_strings ($3); | |
315 | assemble_asm ($3); } | |
316 | | extern_lang_string '{' extdefs '}' | |
317 | { pop_lang_context (); } | |
318 | | extern_lang_string '{' '}' | |
319 | { pop_lang_context (); } | |
320 | | extern_lang_string .hush_warning fndef .warning_ok | |
321 | { if (pending_inlines) do_pending_inlines (); | |
322 | pop_lang_context (); } | |
323 | | extern_lang_string .hush_warning datadef .warning_ok | |
324 | { if (pending_inlines) do_pending_inlines (); | |
325 | pop_lang_context (); } | |
326 | ; | |
327 | ||
328 | extern_lang_string: | |
329 | EXTERN_LANG_STRING | |
330 | { push_lang_context ($1); } | |
331 | ; | |
332 | ||
333 | template_header: | |
334 | TEMPLATE '<' | |
335 | { begin_template_parm_list (); } | |
336 | template_parm_list '>' | |
337 | { $$ = end_template_parm_list ($4); } | |
338 | ; | |
339 | ||
340 | template_parm_list: | |
341 | template_parm | |
342 | { $$ = process_template_parm (0, $1); } | |
343 | | template_parm_list ',' template_parm | |
344 | { $$ = process_template_parm ($1, $3); } | |
345 | ; | |
346 | ||
347 | template_parm: | |
348 | /* The following rules introduce a new reduce/reduce | |
349 | conflict: they are valid prefixes for a `structsp', | |
350 | which means they could match a nameless parameter. | |
351 | By putting them before the `parm' rule, we get | |
352 | their match before considering them nameless parameter | |
353 | declarations. */ | |
354 | aggr identifier | |
355 | { | |
356 | if ($1 != class_type_node) | |
357 | error ("template type parameter must use keyword `class'"); | |
358 | $$ = build_tree_list ($2, NULL_TREE); | |
359 | } | |
360 | | aggr identifier_defn ':' base_class.1 | |
361 | { | |
362 | if ($1 != class_type_node) | |
363 | error ("template type parameter must use keyword `class'"); | |
364 | warning ("restricted template type parameters not yet implemented"); | |
365 | $$ = build_tree_list ($2, $4); | |
366 | } | |
367 | | aggr TYPENAME_COLON base_class.1 | |
368 | { | |
369 | if ($1 != class_type_node) | |
370 | error ("template type parameter must use keyword `class'"); | |
371 | warning ("restricted template type parameters not yet implemented"); | |
372 | $$ = build_tree_list ($2, $3); | |
373 | } | |
374 | | parm | |
375 | ; | |
376 | ||
377 | overloaddef: | |
378 | OVERLOAD ov_identifiers ';' | |
379 | ||
380 | ov_identifiers: IDENTIFIER | |
381 | { declare_overloaded ($1); } | |
382 | | ov_identifiers ',' IDENTIFIER | |
383 | { declare_overloaded ($3); } | |
384 | ; | |
385 | ||
386 | template_def: | |
387 | /* Class template declarations go here; they aren't normal class | |
388 | declarations, because we can't process the bodies yet. */ | |
389 | template_header named_class_head_sans_basetype '{' | |
390 | { yychar = '{'; goto template1; } | |
391 | ';' | |
392 | | template_header named_class_head_sans_basetype_defn '{' | |
393 | { yychar = '{'; goto template1; } | |
394 | ';' | |
395 | | template_header named_class_head_sans_basetype ':' | |
396 | { yychar = ':'; goto template1; } | |
397 | ';' | |
398 | | template_header named_class_head_sans_basetype_defn ':' | |
399 | { | |
400 | yychar = ':'; | |
401 | template1: | |
402 | if (current_aggr == exception_type_node) | |
403 | error ("template type must define an aggregate or union"); | |
404 | /* Maybe pedantic warning for union? | |
405 | How about an enum? :-) */ | |
406 | end_template_decl ($1, $2, current_aggr); | |
407 | reinit_parse_for_template (yychar, $1, $2); | |
408 | yychar = YYEMPTY; | |
409 | } | |
410 | ';' | |
411 | | template_header named_class_head_sans_basetype ';' | |
412 | { | |
413 | end_template_decl ($1, $2, current_aggr); | |
414 | /* declare $2 as template name with $1 parm list */ | |
415 | } | |
416 | | template_header named_class_head_sans_basetype_defn ';' | |
417 | { | |
418 | end_template_decl ($1, $2, current_aggr); | |
419 | /* declare $2 as template name with $1 parm list */ | |
420 | } | |
421 | | template_header /* notype_initdcl0 ';' */ | |
422 | notype_declarator maybe_raises maybeasm maybe_attribute | |
423 | fn_tmpl_end | |
424 | { | |
425 | tree d; | |
426 | int momentary; | |
427 | momentary = suspend_momentary (); | |
428 | d = start_decl ($2, /*current_declspecs*/0, 0, $3); | |
429 | cplus_decl_attributes (d, $5); | |
430 | finish_decl (d, NULL_TREE, $4, 0); | |
431 | end_template_decl ($1, d, 0); | |
432 | if ($6 != ';') | |
433 | reinit_parse_for_template ($6, $1, d); | |
434 | resume_momentary (momentary); | |
435 | } | |
436 | | template_header typed_declspecs /*initdcl0*/ | |
437 | declarator maybe_raises maybeasm maybe_attribute | |
438 | fn_tmpl_end | |
439 | { | |
440 | tree d; | |
441 | int momentary; | |
442 | ||
443 | current_declspecs = $2; | |
444 | momentary = suspend_momentary (); | |
445 | d = start_decl ($3, current_declspecs, 0, $4); | |
446 | cplus_decl_attributes (d, $6); | |
447 | finish_decl (d, NULL_TREE, $5, 0); | |
448 | end_exception_decls (); | |
449 | end_template_decl ($1, d, 0); | |
450 | if ($7 != ';') | |
451 | { | |
452 | reinit_parse_for_template ($7, $1, d); | |
453 | yychar = YYEMPTY; | |
454 | } | |
455 | note_list_got_semicolon ($<ttype>2); | |
456 | resume_momentary (momentary); | |
457 | } | |
458 | | template_header declmods declarator fn_tmpl_end | |
459 | { | |
460 | tree d = start_decl ($3, $<ttype>2, 0, NULL_TREE); | |
461 | finish_decl (d, NULL_TREE, NULL_TREE, 0); | |
462 | end_template_decl ($1, d, 0); | |
463 | if ($4 != ';') | |
464 | reinit_parse_for_template ($4, $1, d); | |
465 | } | |
466 | /* Try to recover from syntax errors in templates. */ | |
467 | | template_header error '}' { end_template_decl ($1, 0, 0); } | |
468 | | template_header error ';' { end_template_decl ($1, 0, 0); } | |
469 | ; | |
470 | ||
471 | fn_tmpl_end: '{' { $$ = '{'; } | |
472 | | ':' { $$ = ':'; } | |
473 | | ';' { $$ = ';'; } | |
474 | | '=' { $$ = '='; } | |
475 | | RETURN { $$ = RETURN; } | |
476 | ; | |
477 | ||
478 | datadef: | |
479 | notype_initdecls ';' | |
480 | { if (pedantic) | |
481 | pedwarn ("ANSI C++ forbids data definition with no type or storage class"); | |
482 | else if (! flag_traditional && ! have_extern_spec) | |
483 | warning ("data definition has no type or storage class"); } | |
484 | | declmods notype_initdecls ';' | |
485 | {} | |
486 | /* Normal case to make fast: "int i;". */ | |
487 | | declmods declarator ';' | |
488 | { tree d; | |
489 | d = start_decl ($2, $<ttype>$, 0, NULL_TREE); | |
490 | finish_decl (d, NULL_TREE, NULL_TREE, 0); | |
491 | } | |
492 | | typed_declspecs initdecls ';' | |
493 | { | |
494 | end_exception_decls (); | |
495 | note_list_got_semicolon ($<ttype>$); | |
496 | } | |
497 | /* Normal case: make this fast. */ | |
498 | | typed_declspecs declarator ';' | |
499 | { tree d; | |
500 | d = start_decl ($2, $<ttype>$, 0, NULL_TREE); | |
501 | finish_decl (d, NULL_TREE, NULL_TREE, 0); | |
502 | end_exception_decls (); | |
503 | note_list_got_semicolon ($<ttype>$); | |
504 | } | |
505 | | declmods ';' | |
506 | { pedwarn ("empty declaration"); } | |
507 | | typed_declspecs ';' | |
508 | { | |
509 | tree t = $<ttype>$; | |
510 | shadow_tag (t); | |
511 | if (TREE_CODE (t) == TREE_LIST | |
512 | && TREE_PURPOSE (t) == NULL_TREE) | |
513 | { | |
514 | t = TREE_VALUE (t); | |
515 | if (TREE_CODE (t) == RECORD_TYPE) | |
516 | { | |
517 | if (CLASSTYPE_USE_TEMPLATE (t) == 0) | |
518 | CLASSTYPE_USE_TEMPLATE (t) = 2; | |
519 | else if (CLASSTYPE_USE_TEMPLATE (t) == 1) | |
520 | error ("override declaration for already-expanded template"); | |
521 | } | |
522 | } | |
523 | note_list_got_semicolon ($<ttype>$); | |
524 | } | |
525 | | error ';' | |
526 | | error '}' | |
527 | | ';' | |
528 | ; | |
529 | ||
530 | fndef: | |
531 | fn.def1 base_init compstmt_or_error | |
532 | { | |
533 | finish_function (lineno, 1); | |
534 | /* finish_function performs these three statements: | |
535 | ||
536 | expand_end_bindings (getdecls (), 1, 0); | |
537 | poplevel (1, 1, 0); | |
538 | ||
539 | expand_end_bindings (0, 0, 0); | |
540 | poplevel (0, 0, 1); | |
541 | */ | |
542 | if ($<ttype>$) process_next_inline ($<ttype>$); | |
543 | } | |
544 | | fn.def1 return_init base_init compstmt_or_error | |
545 | { | |
546 | finish_function (lineno, 1); | |
547 | /* finish_function performs these three statements: | |
548 | ||
549 | expand_end_bindings (getdecls (), 1, 0); | |
550 | poplevel (1, 1, 0); | |
551 | ||
552 | expand_end_bindings (0, 0, 0); | |
553 | poplevel (0, 0, 1); | |
554 | */ | |
555 | if ($<ttype>$) process_next_inline ($<ttype>$); | |
556 | } | |
557 | | fn.def1 nodecls compstmt_or_error | |
558 | { finish_function (lineno, 0); | |
559 | if ($<ttype>$) process_next_inline ($<ttype>$); } | |
560 | | fn.def1 return_init ';' nodecls compstmt_or_error | |
561 | { finish_function (lineno, 0); | |
562 | if ($<ttype>$) process_next_inline ($<ttype>$); } | |
563 | | fn.def1 return_init nodecls compstmt_or_error | |
564 | { finish_function (lineno, 0); | |
565 | if ($<ttype>$) process_next_inline ($<ttype>$); } | |
566 | | typed_declspecs declarator error | |
567 | {} | |
568 | | declmods notype_declarator error | |
569 | {} | |
570 | | notype_declarator error | |
571 | {} | |
572 | ; | |
573 | ||
574 | fn.def1: | |
575 | typed_declspecs declarator maybe_raises | |
576 | { if (! start_function ($$, $2, $3, 0)) | |
577 | YYERROR1; | |
578 | reinit_parse_for_function (); | |
579 | $$ = NULL_TREE; } | |
580 | | declmods notype_declarator maybe_raises | |
581 | { if (! start_function ($$, $2, $3, 0)) | |
582 | YYERROR1; | |
583 | reinit_parse_for_function (); | |
584 | $$ = NULL_TREE; } | |
585 | | notype_declarator maybe_raises | |
586 | { if (! start_function (NULL_TREE, $$, $2, 0)) | |
587 | YYERROR1; | |
588 | reinit_parse_for_function (); | |
589 | $$ = NULL_TREE; } | |
590 | | TYPENAME '(' parmlist ')' type_quals maybe_raises | |
591 | { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) | |
592 | YYERROR1; | |
593 | reinit_parse_for_function (); | |
594 | $$ = NULL_TREE; } | |
595 | | scoped_typename '(' parmlist ')' type_quals maybe_raises | |
596 | { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) | |
597 | YYERROR1; | |
598 | reinit_parse_for_function (); | |
599 | $$ = NULL_TREE; } | |
600 | | TYPENAME LEFT_RIGHT type_quals maybe_raises | |
601 | { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) | |
602 | YYERROR1; | |
603 | reinit_parse_for_function (); | |
604 | $$ = NULL_TREE; } | |
605 | | scoped_typename LEFT_RIGHT type_quals maybe_raises | |
606 | { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) | |
607 | YYERROR1; | |
608 | reinit_parse_for_function (); | |
609 | $$ = NULL_TREE; } | |
610 | | PRE_PARSED_FUNCTION_DECL | |
611 | { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1); | |
612 | reinit_parse_for_function (); } | |
613 | ; | |
614 | ||
615 | /* more C++ complexity */ | |
616 | fn.def2: | |
617 | typed_declspecs '(' parmlist ')' type_quals maybe_raises | |
618 | { | |
619 | tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); | |
620 | $$ = start_method (TREE_CHAIN ($$), decl, $6); | |
621 | if (! $$) | |
622 | YYERROR1; | |
623 | if (yychar == YYEMPTY) | |
624 | yychar = YYLEX; | |
625 | reinit_parse_for_method (yychar, $$); } | |
626 | | typed_declspecs LEFT_RIGHT type_quals maybe_raises | |
627 | { | |
628 | tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); | |
629 | $$ = start_method (TREE_CHAIN ($$), decl, $4); | |
630 | if (! $$) | |
631 | YYERROR1; | |
632 | if (yychar == YYEMPTY) | |
633 | yychar = YYLEX; | |
634 | reinit_parse_for_method (yychar, $$); } | |
635 | | typed_declspecs declarator maybe_raises | |
636 | { $$ = start_method ($$, $2, $3); | |
637 | if (! $$) | |
638 | YYERROR1; | |
639 | if (yychar == YYEMPTY) | |
640 | yychar = YYLEX; | |
641 | reinit_parse_for_method (yychar, $$); } | |
642 | | declmods '(' parmlist ')' type_quals maybe_raises | |
643 | { | |
644 | tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); | |
645 | $$ = start_method (TREE_CHAIN ($$), decl, $6); | |
646 | if (! $$) | |
647 | YYERROR1; | |
648 | if (yychar == YYEMPTY) | |
649 | yychar = YYLEX; | |
650 | reinit_parse_for_method (yychar, $$); } | |
651 | | declmods LEFT_RIGHT type_quals maybe_raises | |
652 | { | |
653 | tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); | |
654 | $$ = start_method (TREE_CHAIN ($$), decl, $4); | |
655 | if (! $$) | |
656 | YYERROR1; | |
657 | if (yychar == YYEMPTY) | |
658 | yychar = YYLEX; | |
659 | reinit_parse_for_method (yychar, $$); } | |
660 | | declmods declarator maybe_raises | |
661 | { $$ = start_method ($$, $2, $3); | |
662 | if (! $$) | |
663 | YYERROR1; | |
664 | if (yychar == YYEMPTY) | |
665 | yychar = YYLEX; | |
666 | reinit_parse_for_method (yychar, $$); } | |
667 | | notype_declarator maybe_raises | |
668 | { $$ = start_method (NULL_TREE, $$, $2); | |
669 | if (! $$) | |
670 | YYERROR1; | |
671 | if (yychar == YYEMPTY) | |
672 | yychar = YYLEX; | |
673 | reinit_parse_for_method (yychar, $$); } | |
674 | ; | |
675 | ||
676 | return_id: RETURN IDENTIFIER | |
677 | { | |
678 | if (! current_function_parms_stored) | |
679 | store_parm_decls (); | |
680 | $$ = $2; | |
681 | } | |
682 | ; | |
683 | ||
684 | return_init: return_id | |
685 | { store_return_init ($<ttype>$, NULL_TREE); } | |
686 | | return_id '=' init | |
687 | { store_return_init ($<ttype>$, $3); } | |
688 | | return_id '(' nonnull_exprlist ')' | |
689 | { store_return_init ($<ttype>$, $3); } | |
690 | | return_id LEFT_RIGHT | |
691 | { store_return_init ($<ttype>$, NULL_TREE); } | |
692 | ; | |
693 | ||
694 | base_init: | |
695 | ':' .set_base_init member_init_list | |
696 | { | |
697 | if ($3 == 0) | |
698 | error ("no base initializers given following ':'"); | |
699 | setup_vtbl_ptr (); | |
700 | } | |
701 | ; | |
702 | ||
703 | .set_base_init: | |
704 | /* empty */ | |
705 | { | |
706 | if (! current_function_parms_stored) | |
707 | store_parm_decls (); | |
708 | ||
709 | /* Flag that we are processing base and member initializers. */ | |
710 | current_vtable_decl = error_mark_node; | |
711 | ||
712 | if (DECL_CONSTRUCTOR_P (current_function_decl)) | |
713 | { | |
714 | /* Make a contour for the initializer list. */ | |
715 | pushlevel (0); | |
716 | clear_last_expr (); | |
717 | expand_start_bindings (0); | |
718 | } | |
719 | else if (current_class_type == NULL_TREE) | |
720 | error ("base initializers not allowed for non-member functions"); | |
721 | else if (! DECL_CONSTRUCTOR_P (current_function_decl)) | |
722 | error ("only constructors take base initializers"); | |
723 | } | |
724 | ; | |
725 | ||
726 | member_init_list: | |
727 | /* empty */ | |
728 | { $$ = 0; } | |
729 | | member_init | |
730 | { $$ = 1; } | |
731 | | member_init_list ',' member_init | |
732 | | member_init_list error | |
733 | ; | |
734 | ||
735 | member_init: '(' nonnull_exprlist ')' | |
736 | { | |
737 | if (current_class_name && !flag_traditional) | |
738 | pedwarn ("ANSI C++ forbids old style base class initialization", | |
739 | IDENTIFIER_POINTER (current_class_name)); | |
740 | expand_member_init (C_C_D, NULL_TREE, $2); | |
741 | } | |
742 | | LEFT_RIGHT | |
743 | { | |
744 | if (current_class_name && !flag_traditional) | |
745 | pedwarn ("ANSI C++ forbids old style base class initialization", | |
746 | IDENTIFIER_POINTER (current_class_name)); | |
747 | expand_member_init (C_C_D, NULL_TREE, void_type_node); | |
748 | } | |
749 | | identifier '(' nonnull_exprlist ')' | |
750 | { | |
751 | expand_member_init (C_C_D, $<ttype>$, $3); | |
752 | } | |
753 | | identifier LEFT_RIGHT | |
754 | { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | |
755 | | template_type_name '(' nonnull_exprlist ')' | |
756 | { expand_member_init (C_C_D, $<ttype>$, $3); } | |
757 | | template_type_name LEFT_RIGHT | |
758 | { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | |
759 | | scoped_typename '(' nonnull_exprlist ')' | |
760 | { expand_member_init (C_C_D, $<ttype>$, $3); } | |
761 | | scoped_typename LEFT_RIGHT | |
762 | { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | |
763 | | scoped_id identifier '(' nonnull_exprlist ')' | |
764 | { | |
765 | do_member_init ($<ttype>$, $2, $4); | |
766 | } | |
767 | | scoped_id identifier LEFT_RIGHT | |
768 | { | |
769 | do_member_init ($<ttype>$, $2, void_type_node); | |
770 | } | |
771 | ; | |
772 | ||
773 | identifier: | |
774 | IDENTIFIER | |
775 | | TYPENAME | |
776 | | PTYPENAME | |
777 | ; | |
778 | ||
779 | identifier_defn: | |
780 | IDENTIFIER_DEFN | |
781 | | TYPENAME_DEFN | |
782 | | PTYPENAME_DEFN | |
783 | ; | |
784 | ||
785 | identifier_or_opname: | |
786 | IDENTIFIER | |
787 | | TYPENAME | |
788 | | PTYPENAME | |
789 | /* | '~' TYPENAME | |
790 | { $$ = build_parse_node (BIT_NOT_EXPR, $2); }*/ | |
791 | /* get rid of the next line, replace it with the above */ | |
792 | | '~' identifier { $$ = build_parse_node (BIT_NOT_EXPR,$2);} | |
793 | | operator_name | |
794 | ; | |
795 | ||
796 | template_type: | |
797 | template_type_name tmpl.1 template_instantiation | |
798 | { | |
799 | extern tree template_type_seen_before_scope; | |
800 | ||
801 | if ($3) | |
802 | $$ = $3; | |
803 | else if ($$ != error_mark_node) | |
804 | $$ = IDENTIFIER_TYPE_VALUE ($$); | |
805 | /* This is a kludge: In order to detect nested types inside | |
806 | * template classes, we have to tell the lexer that it should | |
807 | * try to replace a following SCOPE token with the correct | |
808 | * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME | |
809 | * token will be handled in the rule "scoped_typename". | |
810 | * - niklas@appli.se */ | |
811 | if (yychar == SCOPE) { | |
812 | template_type_seen_before_scope = TYPE_IDENTIFIER ($$); | |
813 | yychar = YYLEX; | |
814 | } | |
815 | } | |
816 | ; | |
817 | ||
818 | template_type_name: | |
819 | PTYPENAME '<' template_arg_list '>' | |
820 | { $$ = lookup_template_class ($$, $3); } | |
821 | | TYPENAME '<' template_arg_list '>' | |
822 | { $$ = lookup_template_class ($$, $3); } | |
823 | ; | |
824 | ||
825 | tmpl.1: | |
826 | /* Expansion of template may be required, unless we're followed by | |
827 | a class definition. */ | |
828 | '{' { yyungetc ('{', 1); $$ = 0; } | |
829 | | ':' { yyungetc (':', 1); $$ = 0; } | |
830 | | /* empty */ %prec EMPTY | |
831 | { $$ = instantiate_class_template ($<ttype>0, 1); } | |
832 | ; | |
833 | ||
834 | tmpl.2: | |
835 | /* Always do expansion if it hasn't been done already. */ | |
836 | { $$ = instantiate_class_template ($<ttype>0, 1); } | |
837 | ; | |
838 | ||
839 | template_arg_list: | |
840 | template_arg | |
841 | { $$ = build_tree_list (NULL_TREE, $$); } | |
842 | | template_arg_list ',' template_arg | |
843 | { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } | |
844 | ; | |
845 | ||
846 | template_arg: | |
847 | typename | |
848 | { $$ = groktypename ($$); } | |
849 | | expr_no_commas %prec UNARY | |
850 | ; | |
851 | ||
852 | template_instantiate_once: | |
853 | PRE_PARSED_CLASS_DECL maybe_base_class_list | |
854 | { | |
855 | tree t, decl, id, tmpl; | |
856 | ||
857 | id = TREE_VALUE ($1); | |
858 | tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)); | |
859 | t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, $2); | |
860 | set_current_level_tags_transparency (1); | |
861 | my_friendly_assert (TREE_CODE (t) == RECORD_TYPE, 257); | |
862 | $<ttype>$ = t; | |
863 | ||
864 | /* Now, put a copy of the decl in global scope, to avoid | |
865 | recursive expansion. */ | |
866 | decl = IDENTIFIER_LOCAL_VALUE (id); | |
867 | if (!decl) | |
868 | decl = IDENTIFIER_CLASS_VALUE (id); | |
869 | /* Now, put a copy of the decl in global scope, to avoid | |
870 | recursive expansion. */ | |
871 | if (decl) | |
872 | { | |
873 | /* Need to copy it to clear the chain pointer, | |
874 | and need to get it into permanent storage. */ | |
875 | my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258); | |
876 | push_obstacks (&permanent_obstack, &permanent_obstack); | |
877 | decl = copy_node (decl); | |
878 | if (DECL_LANG_SPECIFIC (decl)) | |
879 | copy_lang_decl (decl); | |
880 | pop_obstacks (); | |
881 | pushdecl_top_level (decl); | |
882 | } | |
883 | } | |
884 | left_curly opt.component_decl_list '}' | |
885 | { | |
886 | extern void end_template_instantiation (); | |
887 | int old_interface = interface_unknown; | |
888 | ||
889 | interface_unknown = 1; | |
890 | $$ = finish_struct ($<ttype>3, $5, 0, 0); | |
891 | ||
892 | pop_obstacks (); | |
893 | end_template_instantiation ($1, $<ttype>3); | |
894 | ||
895 | /* Now go after the methods & class data. */ | |
896 | old_interface = interface_unknown; | |
897 | interface_unknown = 1; | |
898 | instantiate_member_templates ($1); | |
899 | interface_unknown = old_interface; | |
900 | CLASSTYPE_GOT_SEMICOLON ($$) = 1; | |
901 | } | |
902 | ; | |
903 | ||
904 | template_instantiation: | |
905 | /* empty */ | |
906 | { $$ = NULL_TREE; } | |
907 | | template_instantiate_once | |
908 | { $$ = $1; } | |
909 | ; | |
910 | ||
911 | template_instantiate_some: | |
912 | /* empty */ | |
913 | { $$ = NULL_TREE; /* never used from here... */} | |
914 | | template_instantiate_once template_instantiate_some | |
915 | { $$ = $1; /*???*/ } | |
916 | ; | |
917 | ||
918 | unop: '-' | |
919 | { $$ = NEGATE_EXPR; } | |
920 | | '+' | |
921 | { $$ = CONVERT_EXPR; } | |
922 | | PLUSPLUS | |
923 | { $$ = PREINCREMENT_EXPR; } | |
924 | | MINUSMINUS | |
925 | { $$ = PREDECREMENT_EXPR; } | |
926 | | '!' | |
927 | { $$ = TRUTH_NOT_EXPR; } | |
928 | ; | |
929 | ||
930 | expr: nonnull_exprlist | |
931 | { $$ = build_x_compound_expr ($$); } | |
932 | /* Ugly, but faster. */ | |
933 | | expr_no_commas | |
934 | ; | |
935 | ||
936 | nonnull_exprlist: | |
937 | expr_no_commas | |
938 | { $$ = build_tree_list (NULL_TREE, $$); } | |
939 | | nonnull_exprlist ',' expr_no_commas | |
940 | { chainon ($$, build_tree_list (NULL_TREE, $3)); } | |
941 | | nonnull_exprlist ',' error | |
942 | { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); } | |
943 | ; | |
944 | ||
945 | unary_expr: | |
946 | primary %prec UNARY | |
947 | { | |
948 | if (TREE_CODE ($$) == TYPE_EXPR) | |
949 | $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1); | |
950 | } | |
951 | /* __extension__ turns off -pedantic for following primary. */ | |
952 | | EXTENSION | |
953 | { $<itype>1 = pedantic; | |
954 | pedantic = 0; } | |
955 | cast_expr %prec UNARY | |
956 | { $$ = $3; | |
957 | pedantic = $<itype>1; } | |
958 | | '*' cast_expr %prec UNARY | |
959 | { $$ = build_x_indirect_ref ($2, "unary *"); } | |
960 | | '&' cast_expr %prec UNARY | |
961 | { $$ = build_x_unary_op (ADDR_EXPR, $2); } | |
962 | | '~' cast_expr %prec UNARY | |
963 | { $$ = build_x_unary_op (BIT_NOT_EXPR, $2); } | |
964 | | unop cast_expr %prec UNARY | |
965 | { $$ = build_x_unary_op ($$, $2); | |
966 | if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST) | |
967 | TREE_NEGATED_INT ($$) = 1; | |
968 | } | |
969 | /* Refer to the address of a label as a pointer. */ | |
970 | | ANDAND identifier | |
971 | { tree label = lookup_label ($2); | |
972 | TREE_USED (label) = 1; | |
973 | $$ = build1 (ADDR_EXPR, ptr_type_node, label); | |
974 | TREE_CONSTANT ($$) = 1; } | |
975 | | SIZEOF unary_expr %prec UNARY | |
976 | { if (TREE_CODE ($2) == COMPONENT_REF | |
977 | && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) | |
978 | error ("sizeof applied to a bit-field"); | |
979 | /* ANSI says arrays and functions are converted inside comma. | |
980 | But we can't really convert them in build_compound_expr | |
981 | because that would break commas in lvalues. | |
982 | So do the conversion here if operand was a comma. */ | |
983 | if (TREE_CODE ($2) == COMPOUND_EXPR | |
984 | && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE | |
985 | || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) | |
986 | $2 = default_conversion ($2); | |
987 | $$ = c_sizeof (TREE_TYPE ($2)); } | |
988 | | SIZEOF '(' typename ')' %prec HYPERUNARY | |
989 | { $$ = c_sizeof (groktypename ($3)); } | |
990 | | ALIGNOF unary_expr %prec UNARY | |
991 | { if (TREE_CODE ($2) == COMPONENT_REF | |
992 | && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) | |
993 | error ("`__alignof' applied to a bit-field"); | |
994 | if (TREE_CODE ($2) == INDIRECT_REF) | |
995 | { | |
996 | tree t = TREE_OPERAND ($2, 0); | |
997 | tree best = t; | |
998 | int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); | |
999 | while (TREE_CODE (t) == NOP_EXPR | |
1000 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) | |
1001 | { | |
1002 | int thisalign; | |
1003 | t = TREE_OPERAND (t, 0); | |
1004 | thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); | |
1005 | if (thisalign > bestalign) | |
1006 | best = t, bestalign = thisalign; | |
1007 | } | |
1008 | $$ = c_alignof (TREE_TYPE (TREE_TYPE (best))); | |
1009 | } | |
1010 | else | |
1011 | { | |
1012 | /* ANSI says arrays and fns are converted inside comma. | |
1013 | But we can't convert them in build_compound_expr | |
1014 | because that would break commas in lvalues. | |
1015 | So do the conversion here if operand was a comma. */ | |
1016 | if (TREE_CODE ($2) == COMPOUND_EXPR | |
1017 | && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE | |
1018 | || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) | |
1019 | $2 = default_conversion ($2); | |
1020 | $$ = c_alignof (TREE_TYPE ($2)); | |
1021 | } | |
1022 | } | |
1023 | | ALIGNOF '(' typename ')' %prec HYPERUNARY | |
1024 | { $$ = c_alignof (groktypename ($3)); } | |
1025 | ||
1026 | | .scope new typename %prec '=' | |
1027 | { $$ = build_new ($2, $3, NULL_TREE, $$); } | |
1028 | | .scope new '(' nonnull_exprlist ')' typename %prec '=' | |
1029 | { $$ = build_new ($4, $6, NULL_TREE, $$); } | |
1030 | | .scope new typespec '(' nonnull_exprlist ')' | |
1031 | { $$ = build_new ($2, $3, $5, $$); } | |
1032 | | .scope new '(' nonnull_exprlist ')' typespec '(' nonnull_exprlist ')' | |
1033 | { $$ = build_new ($4, $6, $8, $$); } | |
1034 | | .scope new typespec LEFT_RIGHT | |
1035 | { $$ = build_new ($2, $3, NULL_TREE, $$); } | |
1036 | | .scope new '(' nonnull_exprlist ')' typespec LEFT_RIGHT | |
1037 | { $$ = build_new ($4, $6, NULL_TREE, $$); } | |
1038 | | .scope new typename '=' init %prec '=' | |
1039 | { $$ = build_new ($2, $3, $5, $$); } | |
1040 | | .scope new '(' nonnull_exprlist ')' typename '=' init %prec '=' | |
1041 | { $$ = build_new ($4, $6, $8, $$); } | |
1042 | ||
1043 | /* I am not going to add placement syntax to the below complex rules | |
1044 | because Ken says the syntax is illegal. (mrs) */ | |
1045 | /* I'm not sure why this is disallowed. But since it is, and it | |
1046 | doesn't seem difficult to catch it, let's give a message, so | |
1047 | the programmer can fix it. --Ken Raeburn */ | |
1048 | | .scope new '(' typed_typespecs absdcl ')' '[' nonmomentary_expr ']' | |
1049 | { | |
1050 | tree absdcl, typename; | |
1051 | ||
1052 | illegal_new_array: | |
1053 | absdcl = build_parse_node (ARRAY_REF, $5, $8); | |
1054 | typename = build_decl_list ($4, absdcl); | |
1055 | pedwarn ("ANSI C++ forbids array dimensions with parenthesized type"); | |
1056 | $$ = build_new ($2, typename, NULL_TREE, $$); | |
1057 | } | |
1058 | | .scope new '(' nonempty_type_quals absdcl ')' '[' nonmomentary_expr ']' | |
1059 | { goto illegal_new_array; } | |
1060 | ||
1061 | | .scope new '(' typed_typespecs absdcl ')' | |
1062 | { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } | |
1063 | | .scope new '(' nonnull_exprlist ')' '(' typed_typespecs absdcl ')' | |
1064 | { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } | |
1065 | | .scope new '(' nonempty_type_quals absdcl ')' | |
1066 | { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } | |
1067 | | .scope new '(' nonnull_exprlist ')' '(' nonempty_type_quals absdcl ')' | |
1068 | { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } | |
1069 | /* Unswallow a ':' which is probably meant for ?: expression. */ | |
1070 | | .scope new TYPENAME_COLON | |
1071 | { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$); } | |
1072 | | .scope new '(' nonnull_exprlist ')' TYPENAME_COLON | |
1073 | { yyungetc (':', 1); $$ = build_new ($4, $6, NULL_TREE, $$); } | |
1074 | ||
1075 | | delete cast_expr %prec UNARY | |
1076 | { tree expr = stabilize_reference (convert_from_reference ($2)); | |
1077 | tree type = TREE_TYPE (expr); | |
1078 | ||
1079 | if (TREE_CODE (type) != POINTER_TYPE) | |
1080 | { | |
1081 | error ("non-pointer type to `delete'"); | |
1082 | $$ = error_mark_node; | |
1083 | break; | |
1084 | } | |
1085 | else if (integer_zerop (expr)) | |
1086 | { | |
1087 | /* ANSI C++ June 5 1992 WP 5.3.4. Deleting a pointer | |
1088 | with the value zero is legal and has no effect. */ | |
1089 | $$ = build1 (NOP_EXPR, void_type_node, expr); | |
1090 | break; | |
1091 | } | |
1092 | else if (TREE_READONLY (TREE_TYPE (type))) | |
1093 | { | |
1094 | error ("`const *' cannot be deleted"); | |
1095 | $$ = error_mark_node; | |
1096 | break; | |
1097 | } | |
1098 | $$ = build_delete (type, expr, integer_three_node, | |
1099 | LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, | |
1100 | TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)), | |
1101 | 0); | |
1102 | } | |
1103 | | delete '[' ']' cast_expr %prec UNARY | |
1104 | { | |
1105 | tree exp = stabilize_reference (convert_from_reference ($4)); | |
1106 | tree type = TREE_TYPE (exp); | |
1107 | tree elt_size = c_sizeof (type); | |
1108 | ||
1109 | if (yychar == YYEMPTY) | |
1110 | yychar = YYLEX; | |
1111 | ||
1112 | if (TREE_CODE (type) == POINTER_TYPE | |
1113 | && TREE_READONLY (TREE_TYPE (type))) | |
1114 | { | |
1115 | error ("`const *' cannot be deleted"); | |
1116 | $$ = error_mark_node; | |
1117 | break; | |
1118 | } | |
1119 | $$ = build_vec_delete (exp, NULL_TREE, elt_size, NULL_TREE, | |
1120 | integer_one_node, integer_two_node); | |
1121 | } | |
1122 | | delete '[' expr ']' cast_expr %prec UNARY | |
1123 | { | |
1124 | tree maxindex = build_binary_op (MINUS_EXPR, $3, | |
1125 | integer_one_node); | |
1126 | tree exp = stabilize_reference (convert_from_reference ($5)); | |
1127 | tree type = TREE_TYPE (exp); | |
1128 | tree elt_size = c_sizeof (type); | |
1129 | ||
1130 | if (yychar == YYEMPTY) | |
1131 | yychar = YYLEX; | |
1132 | ||
1133 | if (! flag_traditional) | |
1134 | pedwarn ("ANSI C++ forbids array size in vector delete"); | |
1135 | if (TREE_CODE (type) == POINTER_TYPE | |
1136 | && TREE_READONLY (TREE_TYPE (type))) | |
1137 | { | |
1138 | error ("`const *' cannot be deleted"); | |
1139 | $$ = error_mark_node; | |
1140 | break; | |
1141 | } | |
1142 | $$ = build_vec_delete (exp, maxindex, elt_size, NULL_TREE, | |
1143 | integer_one_node, integer_two_node); | |
1144 | } | |
1145 | ; | |
1146 | ||
1147 | cast_expr: | |
1148 | unary_expr | |
1149 | | '(' typename ')' expr_no_commas %prec UNARY | |
1150 | { tree type = groktypename ($2); | |
1151 | $$ = build_c_cast (type, $4); } | |
1152 | | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY | |
1153 | { tree type = groktypename ($2); | |
1154 | tree init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)); | |
1155 | if (pedantic) | |
1156 | pedwarn ("ANSI C++ forbids constructor-expressions"); | |
1157 | /* Indicate that this was a GNU C constructor expression. */ | |
1158 | TREE_HAS_CONSTRUCTOR (init) = 1; | |
1159 | $$ = digest_init (type, init, 0); | |
1160 | if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) | |
1161 | { | |
1162 | int failure = complete_array_type (type, $$, 1); | |
1163 | if (failure) | |
1164 | my_friendly_abort (78); | |
1165 | } | |
1166 | } | |
1167 | | HEADOF '(' expr ')' | |
1168 | { $$ = build_headof ($3); } | |
1169 | | CLASSOF '(' expr ')' | |
1170 | { $$ = build_classof ($3); } | |
1171 | | CLASSOF '(' TYPENAME ')' | |
1172 | { if (is_aggr_typedef ($3, 1)) | |
1173 | { | |
1174 | tree type = IDENTIFIER_TYPE_VALUE ($3); | |
1175 | $$ = CLASSTYPE_DOSSIER (type); | |
1176 | } | |
1177 | else | |
1178 | $$ = error_mark_node; | |
1179 | } | |
1180 | ; | |
1181 | ||
1182 | expr_no_commas: | |
1183 | cast_expr | |
1184 | | expr_no_commas '+' expr_no_commas | |
1185 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1186 | | expr_no_commas '-' expr_no_commas | |
1187 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1188 | | expr_no_commas '*' expr_no_commas | |
1189 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1190 | | expr_no_commas '/' expr_no_commas | |
1191 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1192 | | expr_no_commas '%' expr_no_commas | |
1193 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1194 | | expr_no_commas LSHIFT expr_no_commas | |
1195 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1196 | | expr_no_commas RSHIFT expr_no_commas | |
1197 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1198 | | expr_no_commas ARITHCOMPARE expr_no_commas | |
1199 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1200 | | expr_no_commas '<' expr_no_commas | |
1201 | { $$ = build_x_binary_op (LT_EXPR, $$, $3); } | |
1202 | | expr_no_commas '>' expr_no_commas | |
1203 | { $$ = build_x_binary_op (GT_EXPR, $$, $3); } | |
1204 | | expr_no_commas EQCOMPARE expr_no_commas | |
1205 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1206 | | expr_no_commas MIN_MAX expr_no_commas | |
1207 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1208 | | expr_no_commas '&' expr_no_commas | |
1209 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1210 | | expr_no_commas '|' expr_no_commas | |
1211 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1212 | | expr_no_commas '^' expr_no_commas | |
1213 | { $$ = build_x_binary_op ($2, $$, $3); } | |
1214 | | expr_no_commas ANDAND expr_no_commas | |
1215 | { $$ = build_x_binary_op (TRUTH_ANDIF_EXPR, $$, $3); } | |
1216 | | expr_no_commas OROR expr_no_commas | |
1217 | { $$ = build_x_binary_op (TRUTH_ORIF_EXPR, $$, $3); } | |
1218 | | expr_no_commas '?' xexpr ':' expr_no_commas | |
1219 | { $$ = build_x_conditional_expr ($$, $3, $5); } | |
1220 | | expr_no_commas '=' expr_no_commas | |
1221 | { $$ = build_modify_expr ($$, NOP_EXPR, $3); } | |
1222 | | expr_no_commas ASSIGN expr_no_commas | |
1223 | { register tree rval; | |
1224 | if (rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3, | |
1225 | make_node ($2))) | |
1226 | $$ = rval; | |
1227 | else | |
1228 | $$ = build_modify_expr ($$, $2, $3); } | |
1229 | | primary DOT_STAR expr_no_commas %prec UNARY | |
1230 | { $$ = build_m_component_ref ($$, build_indirect_ref ($3, 0)); } | |
1231 | /* Handle general members. */ | |
1232 | | object_star expr_no_commas %prec UNARY | |
1233 | { $$ = build_x_binary_op (MEMBER_REF, $$, $2); } | |
1234 | /* These extensions are not defined. | |
1235 | | object '&' expr_no_commas %prec UNARY | |
1236 | { $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); } | |
1237 | | object unop expr_no_commas %prec UNARY | |
1238 | { $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); } | |
1239 | | object '(' typename ')' expr_no_commas %prec UNARY | |
1240 | { tree type = groktypename ($3); | |
1241 | $$ = build_m_component_ref ($$, build_c_cast (type, $5)); } | |
1242 | | object primary_no_id %prec UNARY | |
1243 | { $$ = build_m_component_ref ($$, $2); } | |
1244 | */ | |
1245 | ; | |
1246 | ||
1247 | primary: | |
1248 | IDENTIFIER | |
1249 | { $$ = do_identifier ($$); } | |
1250 | | operator_name | |
1251 | { | |
1252 | tree op = $$; | |
1253 | if (TREE_CODE (op) != IDENTIFIER_NODE) | |
1254 | $$ = op; | |
1255 | else | |
1256 | { | |
1257 | $$ = lookup_name (op, 0); | |
1258 | if ($$ == NULL_TREE) | |
1259 | { | |
1260 | error ("operator %s not defined", operator_name_string (op)); | |
1261 | $$ = error_mark_node; | |
1262 | } | |
1263 | } | |
1264 | } | |
1265 | | CONSTANT | |
1266 | | string | |
1267 | { $$ = combine_strings ($$); } | |
1268 | | '(' expr ')' | |
1269 | { $$ = $2; } | |
1270 | | '(' error ')' | |
1271 | { $$ = error_mark_node; } | |
1272 | | '(' | |
1273 | { if (current_function_decl == 0) | |
1274 | { | |
1275 | error ("braced-group within expression allowed only inside a function"); | |
1276 | YYERROR; | |
1277 | } | |
1278 | keep_next_level (); | |
1279 | $<ttype>$ = expand_start_stmt_expr (); } | |
1280 | compstmt ')' | |
1281 | { tree rtl_exp; | |
1282 | if (pedantic) | |
1283 | pedwarn ("ANSI C++ forbids braced-groups within expressions"); | |
1284 | rtl_exp = expand_end_stmt_expr ($<ttype>2); | |
1285 | /* The statements have side effects, so the group does. */ | |
1286 | TREE_SIDE_EFFECTS (rtl_exp) = 1; | |
1287 | /* Make a BIND_EXPR for the BLOCK already made. */ | |
1288 | $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), | |
1289 | NULL_TREE, rtl_exp, $3); | |
1290 | /* Remove the block from the tree at this point. | |
1291 | It gets put back at the proper place | |
1292 | when the BIND_EXPR is expanded. */ | |
1293 | delete_block ($3); | |
1294 | } | |
1295 | | primary '(' nonnull_exprlist ')' | |
1296 | { /* [eichin:19911016.1902EST] */ | |
1297 | $<ttype>$ = build_x_function_call ($1, $3, current_class_decl); | |
1298 | /* here we instantiate_class_template as needed... */ | |
1299 | do_pending_templates (); | |
1300 | } template_instantiate_some { | |
1301 | if (TREE_CODE ($<ttype>5) == CALL_EXPR | |
1302 | && TREE_TYPE ($<ttype>5) != void_type_node) | |
1303 | $$ = require_complete_type ($<ttype>5); | |
1304 | else | |
1305 | $$ = $<ttype>5; | |
1306 | } | |
1307 | | primary LEFT_RIGHT | |
1308 | { | |
1309 | if ($$ != error_mark_node) | |
1310 | { | |
1311 | $$ = build_x_function_call ($$, NULL_TREE, | |
1312 | current_class_decl); | |
1313 | if (TREE_CODE ($$) == CALL_EXPR | |
1314 | && TREE_TYPE ($$) != void_type_node) | |
1315 | $$ = require_complete_type ($$); | |
1316 | } | |
1317 | } | |
1318 | | primary '[' expr ']' | |
1319 | { | |
1320 | do_array: | |
1321 | { | |
1322 | tree array_expr = $$; | |
1323 | tree index_exp = $3; | |
1324 | tree type = TREE_TYPE (array_expr); | |
1325 | if (type == error_mark_node || index_exp == error_mark_node) | |
1326 | $$ = error_mark_node; | |
1327 | else if (type == NULL_TREE) | |
1328 | { | |
1329 | /* Something has gone very wrong. Assume we | |
1330 | are mistakenly reducing an expression | |
1331 | instead of a declaration. */ | |
1332 | error ("parser may be lost: is there a '{' missing somewhere?"); | |
1333 | $$ = NULL_TREE; | |
1334 | } | |
1335 | else | |
1336 | { | |
1337 | if (TREE_CODE (type) == OFFSET_TYPE) | |
1338 | type = TREE_TYPE (type); | |
1339 | if (TREE_CODE (type) == REFERENCE_TYPE) | |
1340 | type = TREE_TYPE (type); | |
1341 | ||
1342 | if (TYPE_LANG_SPECIFIC (type) | |
1343 | && TYPE_OVERLOADS_ARRAY_REF (type)) | |
1344 | $$ = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp); | |
1345 | else if (TREE_CODE (type) == POINTER_TYPE | |
1346 | || TREE_CODE (type) == ARRAY_TYPE) | |
1347 | $$ = build_array_ref (array_expr, index_exp); | |
1348 | else | |
1349 | { | |
1350 | type = TREE_TYPE (index_exp); | |
1351 | if (TREE_CODE (type) == OFFSET_TYPE) | |
1352 | type = TREE_TYPE (type); | |
1353 | if (TREE_CODE (type) == REFERENCE_TYPE) | |
1354 | type = TREE_TYPE (type); | |
1355 | ||
1356 | if (TYPE_LANG_SPECIFIC (type) | |
1357 | && TYPE_OVERLOADS_ARRAY_REF (type)) | |
1358 | error ("array expression backwards"); | |
1359 | else if (TREE_CODE (type) == POINTER_TYPE | |
1360 | || TREE_CODE (type) == ARRAY_TYPE) | |
1361 | $$ = build_array_ref (index_exp, array_expr); | |
1362 | else | |
1363 | error("[] applied to non-pointer type"); | |
1364 | } | |
1365 | } | |
1366 | } | |
1367 | } | |
1368 | | object identifier_or_opname %prec UNARY | |
1369 | { $$ = build_component_ref ($$, $2, NULL_TREE, 1); } | |
1370 | | object scoped_id identifier_or_opname %prec UNARY | |
1371 | { | |
1372 | tree basetype = $2; | |
1373 | if (is_aggr_typedef (basetype, 1)) | |
1374 | { | |
1375 | basetype = IDENTIFIER_TYPE_VALUE (basetype); | |
1376 | ||
1377 | if ($$ == error_mark_node) | |
1378 | ; | |
1379 | else if (binfo_or_else (basetype, TREE_TYPE ($$))) | |
1380 | $$ = build_component_ref (build_scoped_ref ($$, $2), $3, NULL_TREE, 1); | |
1381 | else | |
1382 | $$ = error_mark_node; | |
1383 | } | |
1384 | else $$ = error_mark_node; | |
1385 | } | |
1386 | | primary PLUSPLUS | |
1387 | { $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | |
1388 | | primary MINUSMINUS | |
1389 | { $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } | |
1390 | ||
1391 | /* C++ extensions */ | |
1392 | | THIS | |
1393 | { if (current_class_decl) | |
1394 | { | |
1395 | #ifdef WARNING_ABOUT_CCD | |
1396 | TREE_USED (current_class_decl) = 1; | |
1397 | #endif | |
1398 | $$ = current_class_decl; | |
1399 | } | |
1400 | else if (current_function_decl | |
1401 | && DECL_STATIC_FUNCTION_P (current_function_decl)) | |
1402 | { | |
1403 | error ("`this' is unavailable for static member functions"); | |
1404 | $$ = error_mark_node; | |
1405 | } | |
1406 | else | |
1407 | { | |
1408 | if (current_function_decl) | |
1409 | error ("invalid use of `this' in non-member function"); | |
1410 | else | |
1411 | error ("invalid use of `this' at top level"); | |
1412 | $$ = error_mark_node; | |
1413 | } | |
1414 | } | |
1415 | | TYPE_QUAL '(' nonnull_exprlist ')' | |
1416 | { | |
1417 | tree type; | |
1418 | tree id = $$; | |
1419 | ||
1420 | /* This is a C cast in C++'s `functional' notation. */ | |
1421 | if ($3 == error_mark_node) | |
1422 | { | |
1423 | $$ = error_mark_node; | |
1424 | break; | |
1425 | } | |
1426 | #if 0 | |
1427 | if ($3 == NULL_TREE) | |
1428 | { | |
1429 | error ("cannot cast null list to type `%s'", | |
1430 | IDENTIFIER_POINTER (TYPE_NAME (id))); | |
1431 | $$ = error_mark_node; | |
1432 | break; | |
1433 | } | |
1434 | #endif | |
1435 | #if 0 | |
1436 | /* type is not set! (mrs) */ | |
1437 | if (type == error_mark_node) | |
1438 | $$ = error_mark_node; | |
1439 | else | |
1440 | #endif | |
1441 | { | |
1442 | if (id == ridpointers[(int) RID_CONST]) | |
1443 | type = build_type_variant (integer_type_node, 1, 0); | |
1444 | else if (id == ridpointers[(int) RID_VOLATILE]) | |
1445 | type = build_type_variant (integer_type_node, 0, 1); | |
1446 | #if 0 | |
1447 | /* should not be able to get here (mrs) */ | |
1448 | else if (id == ridpointers[(int) RID_FRIEND]) | |
1449 | { | |
1450 | error ("cannot cast expression to `friend' type"); | |
1451 | $$ = error_mark_node; | |
1452 | break; | |
1453 | } | |
1454 | #endif | |
1455 | else my_friendly_abort (79); | |
1456 | $$ = build_c_cast (type, build_compound_expr ($3)); | |
1457 | } | |
1458 | } | |
1459 | | typespec '(' nonnull_exprlist ')' | |
1460 | { $$ = build_functional_cast ($$, $3); } | |
1461 | | typespec LEFT_RIGHT | |
1462 | { $$ = build_functional_cast ($$, NULL_TREE); } | |
1463 | | SCOPE typespec '(' nonnull_exprlist ')' | |
1464 | { $$ = build_functional_cast ($2, $4); } | |
1465 | | SCOPE typespec LEFT_RIGHT | |
1466 | { $$ = build_functional_cast ($2, NULL_TREE); } | |
1467 | | SCOPE IDENTIFIER | |
1468 | { | |
1469 | do_scoped_id: | |
1470 | $$ = IDENTIFIER_GLOBAL_VALUE ($2); | |
1471 | if (yychar == YYEMPTY) | |
1472 | yychar = YYLEX; | |
1473 | if (! $$) | |
1474 | { | |
1475 | if (yychar == '(' || yychar == LEFT_RIGHT) | |
1476 | $$ = implicitly_declare ($2); | |
1477 | else | |
1478 | { | |
1479 | if (IDENTIFIER_GLOBAL_VALUE ($2) != error_mark_node) | |
1480 | error ("undeclared variable `%s' (first use here)", | |
1481 | IDENTIFIER_POINTER ($2)); | |
1482 | $$ = error_mark_node; | |
1483 | /* Prevent repeated error messages. */ | |
1484 | IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node; | |
1485 | } | |
1486 | } | |
1487 | else | |
1488 | { | |
1489 | assemble_external ($$); | |
1490 | TREE_USED ($$) = 1; | |
1491 | } | |
1492 | if (TREE_CODE ($$) == CONST_DECL) | |
1493 | { | |
1494 | /* XXX CHS - should we set TREE_USED of the constant? */ | |
1495 | $$ = DECL_INITIAL ($$); | |
1496 | /* This is to prevent an enum whose value is 0 | |
1497 | from being considered a null pointer constant. */ | |
1498 | $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$); | |
1499 | TREE_CONSTANT ($$) = 1; | |
1500 | } | |
1501 | ||
1502 | } | |
1503 | | SCOPE operator_name | |
1504 | { | |
1505 | if (TREE_CODE ($2) == IDENTIFIER_NODE) | |
1506 | goto do_scoped_id; | |
1507 | do_scoped_operator: | |
1508 | $$ = $2; | |
1509 | } | |
1510 | | scoped_id identifier_or_opname %prec HYPERUNARY | |
1511 | { $$ = build_offset_ref ($$, $2); } | |
1512 | | scoped_id identifier_or_opname '(' nonnull_exprlist ')' | |
1513 | { $$ = build_member_call ($$, $2, $4); } | |
1514 | | scoped_id identifier_or_opname LEFT_RIGHT | |
1515 | { $$ = build_member_call ($$, $2, NULL_TREE); } | |
1516 | | object identifier_or_opname '(' nonnull_exprlist ')' | |
1517 | { $$ = build_method_call ($$, $2, $4, NULL_TREE, | |
1518 | (LOOKUP_NORMAL|LOOKUP_AGGR)); } | |
1519 | | object identifier_or_opname LEFT_RIGHT | |
1520 | { $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE, | |
1521 | (LOOKUP_NORMAL|LOOKUP_AGGR)); } | |
1522 | | object scoped_id identifier_or_opname '(' nonnull_exprlist ')' | |
1523 | { $$ = build_scoped_method_call ($$, $2, $3, $5); } | |
1524 | | object scoped_id identifier_or_opname LEFT_RIGHT | |
1525 | { $$ = build_scoped_method_call ($$, $2, $3, NULL_TREE); } | |
1526 | ; | |
1527 | ||
1528 | /* Not needed for now. | |
1529 | ||
1530 | primary_no_id: | |
1531 | '(' expr ')' | |
1532 | { $$ = $2; } | |
1533 | | '(' error ')' | |
1534 | { $$ = error_mark_node; } | |
1535 | | '(' | |
1536 | { if (current_function_decl == 0) | |
1537 | { | |
1538 | error ("braced-group within expression allowed only inside a function"); | |
1539 | YYERROR; | |
1540 | } | |
1541 | $<ttype>$ = expand_start_stmt_expr (); } | |
1542 | compstmt ')' | |
1543 | { if (pedantic) | |
1544 | pedwarn ("ANSI C++ forbids braced-groups within expressions"); | |
1545 | $$ = expand_end_stmt_expr ($<ttype>2); } | |
1546 | | primary_no_id '(' nonnull_exprlist ')' | |
1547 | { $$ = build_x_function_call ($$, $3, current_class_decl); } | |
1548 | | primary_no_id LEFT_RIGHT | |
1549 | { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); } | |
1550 | | primary_no_id '[' expr ']' | |
1551 | { goto do_array; } | |
1552 | | primary_no_id PLUSPLUS | |
1553 | { $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | |
1554 | | primary_no_id MINUSMINUS | |
1555 | { $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } | |
1556 | | SCOPE IDENTIFIER | |
1557 | { goto do_scoped_id; } | |
1558 | | SCOPE operator_name | |
1559 | { if (TREE_CODE ($2) == IDENTIFIER_NODE) | |
1560 | goto do_scoped_id; | |
1561 | goto do_scoped_operator; | |
1562 | } | |
1563 | ; | |
1564 | */ | |
1565 | ||
1566 | new: NEW | |
1567 | { $$ = NULL_TREE; } | |
1568 | | NEW '{' nonnull_exprlist '}' | |
1569 | { | |
1570 | $$ = $3; | |
1571 | pedwarn ("old style placement syntax, use () instead"); | |
1572 | } | |
1573 | | NEW DYNAMIC %prec EMPTY | |
1574 | { $$ = void_type_node; } | |
1575 | | NEW DYNAMIC '(' string ')' | |
1576 | { $$ = combine_strings ($4); } | |
1577 | ; | |
1578 | ||
1579 | .scope: | |
1580 | /* empty */ | |
1581 | { $$ = 0; } | |
1582 | | SCOPE | |
1583 | { $$ = 1; } | |
1584 | ; | |
1585 | ||
1586 | delete: DELETE | |
1587 | { $$ = NULL_TREE; } | |
1588 | | SCOPE delete | |
1589 | { if ($2) | |
1590 | error ("extra `::' before `delete' ignored"); | |
1591 | $$ = error_mark_node; | |
1592 | } | |
1593 | ; | |
1594 | ||
1595 | /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ | |
1596 | string: | |
1597 | STRING | |
1598 | | string STRING | |
1599 | { $$ = chainon ($$, $2); } | |
1600 | ; | |
1601 | ||
1602 | nodecls: | |
1603 | /* empty */ | |
1604 | { | |
1605 | if (! current_function_parms_stored) | |
1606 | store_parm_decls (); | |
1607 | setup_vtbl_ptr (); | |
1608 | } | |
1609 | ; | |
1610 | ||
1611 | object: primary '.' | |
1612 | { | |
1613 | if ($$ == error_mark_node) | |
1614 | ; | |
1615 | else | |
1616 | { | |
1617 | tree type = TREE_TYPE ($$); | |
1618 | ||
1619 | if (! PROMOTES_TO_AGGR_TYPE (type, REFERENCE_TYPE)) | |
1620 | { | |
1621 | error ("object in '.' expression is not of aggregate type"); | |
1622 | $$ = error_mark_node; | |
1623 | } | |
1624 | } | |
1625 | } | |
1626 | | primary POINTSAT | |
1627 | { | |
1628 | $$ = build_x_arrow ($$); | |
1629 | } | |
1630 | ; | |
1631 | ||
1632 | object_star: primary POINTSAT_STAR | |
1633 | ; | |
1634 | ||
1635 | decl: | |
1636 | typed_declspecs initdecls ';' | |
1637 | { | |
1638 | resume_momentary ($2); | |
1639 | note_list_got_semicolon ($<ttype>$); | |
1640 | } | |
1641 | /* Normal case: make this fast. */ | |
1642 | | typed_declspecs declarator ';' | |
1643 | { tree d; | |
1644 | int yes = suspend_momentary (); | |
1645 | d = start_decl ($2, $<ttype>$, 0, NULL_TREE); | |
1646 | finish_decl (d, NULL_TREE, NULL_TREE, 0); | |
1647 | resume_momentary (yes); | |
1648 | note_list_got_semicolon ($<ttype>$); | |
1649 | } | |
1650 | | declmods notype_initdecls ';' | |
1651 | { resume_momentary ($2); } | |
1652 | /* Normal case: make this fast. */ | |
1653 | | declmods declarator ';' | |
1654 | { tree d; | |
1655 | int yes = suspend_momentary (); | |
1656 | d = start_decl ($2, $<ttype>$, 0, NULL_TREE); | |
1657 | finish_decl (d, NULL_TREE, NULL_TREE, 0); | |
1658 | resume_momentary (yes); | |
1659 | } | |
1660 | | typed_declspecs ';' | |
1661 | { | |
1662 | shadow_tag ($<ttype>$); | |
1663 | note_list_got_semicolon ($<ttype>$); | |
1664 | } | |
1665 | | declmods ';' | |
1666 | { warning ("empty declaration"); } | |
1667 | ; | |
1668 | ||
1669 | /* Any kind of declarator (thus, all declarators allowed | |
1670 | after an explicit typespec). */ | |
1671 | ||
1672 | declarator: | |
1673 | after_type_declarator | |
1674 | | notype_declarator | |
1675 | | START_DECLARATOR after_type_declarator | |
1676 | { $$ = $2; } | |
1677 | | START_DECLARATOR notype_declarator | |
1678 | { $$ = $2; } | |
1679 | ; | |
1680 | ||
1681 | /* Declspecs which contain at least one type specifier or typedef name. | |
1682 | (Just `const' or `volatile' is not enough.) | |
1683 | A typedef'd name following these is taken as a name to be declared. */ | |
1684 | ||
1685 | typed_declspecs: | |
1686 | typespec %prec HYPERUNARY | |
1687 | { $$ = list_hash_lookup_or_cons ($$); } | |
1688 | | declmods typespec | |
1689 | { $$ = hash_tree_chain ($2, $$); } | |
1690 | | typespec reserved_declspecs %prec HYPERUNARY | |
1691 | { $$ = hash_tree_chain ($$, $2); } | |
1692 | | declmods typespec reserved_declspecs | |
1693 | { $$ = hash_tree_chain ($2, hash_chainon ($3, $$)); } | |
1694 | ; | |
1695 | ||
1696 | reserved_declspecs: /* empty | |
1697 | { $$ = NULL_TREE; } */ | |
1698 | typespecqual_reserved | |
1699 | { $$ = build_decl_list (NULL_TREE, $$); } | |
1700 | | SCSPEC | |
1701 | { if (extra_warnings) | |
1702 | warning ("`%s' is not at beginning of declaration", | |
1703 | IDENTIFIER_POINTER ($$)); | |
1704 | $$ = build_decl_list (NULL_TREE, $$); } | |
1705 | | reserved_declspecs typespecqual_reserved | |
1706 | { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
1707 | | reserved_declspecs SCSPEC | |
1708 | { if (extra_warnings) | |
1709 | warning ("`%s' is not at beginning of declaration", | |
1710 | IDENTIFIER_POINTER ($2)); | |
1711 | $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
1712 | ; | |
1713 | ||
1714 | /* List of just storage classes and type modifiers. | |
1715 | A declaration can start with just this, but then it cannot be used | |
1716 | to redeclare a typedef-name. */ | |
1717 | ||
1718 | declmods: | |
1719 | TYPE_QUAL | |
1720 | { $$ = IDENTIFIER_AS_LIST ($$); | |
1721 | TREE_STATIC ($$) = 1; } | |
1722 | | SCSPEC | |
1723 | { $$ = IDENTIFIER_AS_LIST ($$); } | |
1724 | | declmods TYPE_QUAL | |
1725 | { $$ = hash_tree_chain ($2, $$); | |
1726 | TREE_STATIC ($$) = 1; } | |
1727 | | declmods SCSPEC | |
1728 | { if (extra_warnings && TREE_STATIC ($$)) | |
1729 | warning ("`%s' is not at beginning of declaration", | |
1730 | IDENTIFIER_POINTER ($2)); | |
1731 | $$ = hash_tree_chain ($2, $$); | |
1732 | TREE_STATIC ($$) = TREE_STATIC ($1); } | |
1733 | ; | |
1734 | ||
1735 | ||
1736 | /* Used instead of declspecs where storage classes are not allowed | |
1737 | (that is, for typenames and structure components). | |
1738 | ||
1739 | C++ can takes storage classes for structure components. | |
1740 | Don't accept a typedef-name if anything but a modifier precedes it. */ | |
1741 | ||
1742 | typed_typespecs: | |
1743 | typespec %prec EMPTY | |
1744 | { $$ = get_decl_list ($$); } | |
1745 | | nonempty_type_quals typespec | |
1746 | { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
1747 | | typespec reserved_typespecquals | |
1748 | { $$ = decl_tree_cons (NULL_TREE, $$, $2); } | |
1749 | | nonempty_type_quals typespec reserved_typespecquals | |
1750 | { $$ = decl_tree_cons (NULL_TREE, $2, hash_chainon ($3, $$)); } | |
1751 | ; | |
1752 | ||
1753 | reserved_typespecquals: | |
1754 | typespecqual_reserved | |
1755 | { $$ = get_decl_list ($$); } | |
1756 | | reserved_typespecquals typespecqual_reserved | |
1757 | { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
1758 | ; | |
1759 | ||
1760 | /* A typespec (but not a type qualifier). | |
1761 | Once we have seen one of these in a declaration, | |
1762 | if a typedef name appears then it is being redeclared. */ | |
1763 | ||
1764 | typespec: structsp | |
1765 | | TYPESPEC %prec EMPTY | |
1766 | | TYPENAME %prec EMPTY | |
1767 | | scoped_typename | |
1768 | | TYPEOF '(' expr ')' | |
1769 | { $$ = TREE_TYPE ($3); | |
1770 | if (pedantic) | |
1771 | pedwarn ("ANSI C++ forbids `typeof'"); } | |
1772 | | TYPEOF '(' typename ')' | |
1773 | { $$ = groktypename ($3); | |
1774 | if (pedantic) | |
1775 | pedwarn ("ANSI C++ forbids `typeof'"); } | |
1776 | | template_type | |
1777 | ; | |
1778 | ||
1779 | /* A typespec that is a reserved word, or a type qualifier. */ | |
1780 | ||
1781 | typespecqual_reserved: TYPESPEC | |
1782 | | TYPE_QUAL | |
1783 | | structsp | |
1784 | ; | |
1785 | ||
1786 | initdecls: | |
1787 | initdcl0 | |
1788 | | initdecls ',' initdcl | |
1789 | ; | |
1790 | ||
1791 | notype_initdecls: | |
1792 | notype_initdcl0 | |
1793 | | notype_initdecls ',' initdcl | |
1794 | ; | |
1795 | ||
1796 | maybeasm: | |
1797 | /* empty */ | |
1798 | { $$ = NULL_TREE; } | |
1799 | | ASM_KEYWORD '(' string ')' | |
1800 | { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); | |
1801 | $$ = $3; | |
1802 | if (pedantic) | |
1803 | pedwarn ("ANSI C++ forbids use of `asm' keyword"); | |
1804 | } | |
1805 | ; | |
1806 | ||
1807 | initdcl0: | |
1808 | declarator maybe_raises maybeasm maybe_attribute '=' | |
1809 | { current_declspecs = $<ttype>0; | |
1810 | $<itype>5 = suspend_momentary (); | |
1811 | $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); | |
1812 | cplus_decl_attributes ($<ttype>$, $4); } | |
1813 | init | |
1814 | /* Note how the declaration of the variable is in effect while its init is parsed! */ | |
1815 | { finish_decl ($<ttype>6, $7, $3, 0); | |
1816 | $$ = $<itype>5; } | |
1817 | | declarator maybe_raises maybeasm maybe_attribute | |
1818 | { tree d; | |
1819 | current_declspecs = $<ttype>0; | |
1820 | $$ = suspend_momentary (); | |
1821 | d = start_decl ($1, current_declspecs, 0, $2); | |
1822 | cplus_decl_attributes (d, $4); | |
1823 | finish_decl (d, NULL_TREE, $3, 0); } | |
1824 | ; | |
1825 | ||
1826 | initdcl: | |
1827 | declarator maybe_raises maybeasm maybe_attribute '=' | |
1828 | { $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); | |
1829 | cplus_decl_attributes ($<ttype>$, $4); } | |
1830 | init | |
1831 | /* Note how the declaration of the variable is in effect while its init is parsed! */ | |
1832 | { finish_decl ($<ttype>6, $7, $3, 0); } | |
1833 | | declarator maybe_raises maybeasm maybe_attribute | |
1834 | { tree d = start_decl ($$, current_declspecs, 0, $2); | |
1835 | cplus_decl_attributes ($<ttype>$, $4); | |
1836 | finish_decl (d, NULL_TREE, $3, 0); } | |
1837 | ; | |
1838 | ||
1839 | notype_initdcl0: | |
1840 | notype_declarator maybe_raises maybeasm maybe_attribute '=' | |
1841 | { current_declspecs = $<ttype>0; | |
1842 | $<itype>5 = suspend_momentary (); | |
1843 | $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); | |
1844 | cplus_decl_attributes ($<ttype>$, $4); } | |
1845 | init | |
1846 | /* Note how the declaration of the variable is in effect while its init is parsed! */ | |
1847 | { finish_decl ($<ttype>6, $7, $3, 0); | |
1848 | $$ = $<itype>5; } | |
1849 | | notype_declarator maybe_raises maybeasm maybe_attribute | |
1850 | { tree d; | |
1851 | current_declspecs = $<ttype>0; | |
1852 | $$ = suspend_momentary (); | |
1853 | d = start_decl ($1, current_declspecs, 0, $2); | |
1854 | cplus_decl_attributes (d, $4); | |
1855 | finish_decl (d, NULL_TREE, $3, 0); } | |
1856 | ; | |
1857 | ||
1858 | /* the * rules are dummies to accept the Apollo extended syntax | |
1859 | so that the header files compile. */ | |
1860 | maybe_attribute: | |
1861 | /* empty */ | |
1862 | { $$ = NULL_TREE; } | |
1863 | | ATTRIBUTE '(' '(' attribute_list ')' ')' | |
1864 | { $$ = $4; } | |
1865 | ; | |
1866 | ||
1867 | attribute_list | |
1868 | : attrib | |
1869 | { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | |
1870 | | attribute_list ',' attrib | |
1871 | { $$ = tree_cons (NULL_TREE, $3, $1); } | |
1872 | ; | |
1873 | ||
1874 | attrib | |
1875 | : IDENTIFIER | |
1876 | { if (strcmp (IDENTIFIER_POINTER ($1), "packed")) | |
1877 | warning ("`%s' attribute directive ignored", | |
1878 | IDENTIFIER_POINTER ($1)); | |
1879 | $$ = $1; } | |
1880 | | IDENTIFIER '(' CONSTANT ')' | |
1881 | { /* if not "aligned(n)", then issue warning */ | |
1882 | if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0 | |
1883 | || TREE_CODE ($3) != INTEGER_CST) | |
1884 | { | |
1885 | warning ("`%s' attribute directive ignored", | |
1886 | IDENTIFIER_POINTER ($1)); | |
1887 | $$ = $1; | |
1888 | } | |
1889 | else | |
1890 | $$ = tree_cons ($1, $3, NULL_TREE); } | |
1891 | | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' | |
1892 | { /* if not "format(...)", then issue warning */ | |
1893 | if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0 | |
1894 | || TREE_CODE ($5) != INTEGER_CST | |
1895 | || TREE_CODE ($7) != INTEGER_CST) | |
1896 | { | |
1897 | warning ("`%s' attribute directive ignored", | |
1898 | IDENTIFIER_POINTER ($1)); | |
1899 | $$ = $1; | |
1900 | } | |
1901 | else | |
1902 | $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7, NULL_TREE), NULL_TREE), NULL_TREE); } | |
1903 | ; | |
1904 | ||
1905 | /* A nonempty list of identifiers, including typenames. */ | |
1906 | identifiers_or_typenames: | |
1907 | identifier | |
1908 | { $$ = build_tree_list (NULL_TREE, $1); } | |
1909 | | identifiers_or_typenames ',' identifier | |
1910 | { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } | |
1911 | ; | |
1912 | ||
1913 | init: | |
1914 | expr_no_commas %prec '=' | |
1915 | | '{' '}' | |
1916 | { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); | |
1917 | TREE_HAS_CONSTRUCTOR ($$) = 1; | |
1918 | if (pedantic) | |
1919 | pedwarn ("ANSI C++ forbids empty initializer braces"); } | |
1920 | | '{' initlist '}' | |
1921 | { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); | |
1922 | TREE_HAS_CONSTRUCTOR ($$) = 1; } | |
1923 | | '{' initlist ',' '}' | |
1924 | { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); | |
1925 | TREE_HAS_CONSTRUCTOR ($$) = 1; } | |
1926 | | error | |
1927 | { $$ = NULL_TREE; } | |
1928 | ; | |
1929 | ||
1930 | /* This chain is built in reverse order, | |
1931 | and put in forward order where initlist is used. */ | |
1932 | initlist: | |
1933 | init | |
1934 | { $$ = build_tree_list (NULL_TREE, $$); } | |
1935 | | initlist ',' init | |
1936 | { $$ = tree_cons (NULL_TREE, $3, $$); } | |
1937 | /* These are for labeled elements. */ | |
1938 | | '[' expr_no_commas ']' init | |
1939 | { $$ = build_tree_list ($2, $4); } | |
1940 | | initlist ',' CASE expr_no_commas ':' init | |
1941 | { $$ = tree_cons ($4, $6, $$); } | |
1942 | | identifier ':' init | |
1943 | { $$ = build_tree_list ($$, $3); } | |
1944 | | initlist ',' identifier ':' init | |
1945 | { $$ = tree_cons ($3, $5, $$); } | |
1946 | ; | |
1947 | ||
1948 | structsp: | |
1949 | ENUM identifier '{' | |
1950 | { $<itype>3 = suspend_momentary (); | |
1951 | $$ = start_enum ($2); } | |
1952 | enumlist maybecomma_warn '}' | |
1953 | { $$ = finish_enum ($<ttype>4, $5); | |
1954 | resume_momentary ($<itype>3); | |
1955 | check_for_missing_semicolon ($<ttype>4); } | |
1956 | | ENUM identifier '{' '}' | |
1957 | { $$ = finish_enum (start_enum ($2), NULL_TREE); | |
1958 | check_for_missing_semicolon ($$); } | |
1959 | | ENUM '{' | |
1960 | { $<itype>2 = suspend_momentary (); | |
1961 | $$ = start_enum (make_anon_name ()); } | |
1962 | enumlist maybecomma_warn '}' | |
1963 | { $$ = finish_enum ($<ttype>3, $4); | |
1964 | resume_momentary ($<itype>1); | |
1965 | check_for_missing_semicolon ($<ttype>3); } | |
1966 | | ENUM '{' '}' | |
1967 | { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE); | |
1968 | check_for_missing_semicolon ($$); } | |
1969 | | ENUM identifier | |
1970 | { $$ = xref_tag (enum_type_node, $2, NULL_TREE); } | |
1971 | ||
1972 | /* C++ extensions, merged with C to avoid shift/reduce conflicts */ | |
1973 | | class_head left_curly opt.component_decl_list '}' | |
1974 | { | |
1975 | int semi; | |
1976 | tree id; | |
1977 | ||
1978 | #if 0 | |
1979 | /* Need to rework class nesting in the | |
1980 | presence of nested classes, etc. */ | |
1981 | shadow_tag (CLASSTYPE_AS_LIST ($$)); */ | |
1982 | #endif | |
1983 | if (yychar == YYEMPTY) | |
1984 | yychar = YYLEX; | |
1985 | semi = yychar == ';'; | |
1986 | /* finish_struct nukes this anyway; if | |
1987 | finish_exception does too, then it can go. */ | |
1988 | if (semi) | |
1989 | note_got_semicolon ($$); | |
1990 | ||
1991 | if (TREE_CODE ($$) == ENUMERAL_TYPE) | |
1992 | /* $$ = $1 from default rule. */; | |
1993 | else if (CLASSTYPE_DECLARED_EXCEPTION ($$)) | |
1994 | { | |
1995 | if (! semi) | |
1996 | $$ = finish_exception ($$, $3); | |
1997 | else | |
1998 | warning ("empty exception declaration\n"); | |
1999 | } | |
2000 | else | |
2001 | { | |
2002 | $$ = finish_struct ($$, $3, semi, semi); | |
2003 | if (semi) note_got_semicolon ($$); | |
2004 | } | |
2005 | ||
2006 | pop_obstacks (); | |
2007 | ||
2008 | id = TYPE_IDENTIFIER ($$); | |
2009 | if (IDENTIFIER_TEMPLATE (id)) | |
2010 | { | |
2011 | tree decl; | |
2012 | ||
2013 | /* I don't know if the copying of this TYPE_DECL is | |
2014 | * really needed. However, it's such a small per- | |
2015 | * formance penalty that the extra safety is a bargain. | |
2016 | * - niklas@appli.se | |
2017 | */ | |
2018 | push_obstacks (&permanent_obstack, &permanent_obstack); | |
2019 | decl = copy_node (lookup_name (id)); | |
2020 | if (DECL_LANG_SPECIFIC (decl)) | |
2021 | copy_lang_decl (decl); | |
2022 | pop_obstacks (); | |
2023 | undo_template_name_overload (id, 0); | |
2024 | pushdecl_top_level (decl); | |
2025 | } | |
2026 | if (! semi) | |
2027 | check_for_missing_semicolon ($$); } | |
2028 | | class_head %prec EMPTY | |
2029 | { | |
2030 | #if 0 | |
2031 | /* It's no longer clear what the following error is supposed to | |
2032 | accomplish. If it turns out to be needed, add a comment why. */ | |
2033 | if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)) | |
2034 | { | |
2035 | error ("incomplete definition of type `%s'", | |
2036 | TYPE_NAME_STRING ($$)); | |
2037 | $$ = error_mark_node; | |
2038 | } | |
2039 | #endif | |
2040 | } | |
2041 | ; | |
2042 | ||
2043 | maybecomma: | |
2044 | /* empty */ | |
2045 | | ',' | |
2046 | ; | |
2047 | ||
2048 | maybecomma_warn: | |
2049 | /* empty */ | |
2050 | | ',' | |
2051 | { if (pedantic) | |
2052 | pedwarn ("ANSI C++ forbids comma at end of enumerator list"); } | |
2053 | ; | |
2054 | ||
2055 | aggr: AGGR | |
2056 | | DYNAMIC AGGR | |
2057 | { $$ = build_tree_list (NULL_TREE, $2); } | |
2058 | | DYNAMIC '(' string ')' AGGR | |
2059 | { $$ = build_tree_list ($3, $5); } | |
2060 | | aggr SCSPEC | |
2061 | { error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); | |
2062 | } | |
2063 | | aggr TYPESPEC | |
2064 | { error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); | |
2065 | } | |
2066 | | aggr TYPE_QUAL | |
2067 | { error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); | |
2068 | } | |
2069 | | aggr AGGR | |
2070 | { error ("no body nor ';' separates two class, struct or union declarations"); | |
2071 | } | |
2072 | ; | |
2073 | ||
2074 | named_class_head_sans_basetype: | |
2075 | aggr identifier | |
2076 | { aggr1: current_aggr = $$; $$ = $2; } | |
2077 | | aggr template_type_name %prec EMPTY | |
2078 | { current_aggr = $$; $$ = $2; } | |
2079 | | aggr TYPENAME_COLON | |
2080 | { yyungetc (':', 1); goto aggr1; } | |
2081 | | aggr template_type_name '{' | |
2082 | { yyungetc ('{', 1); | |
2083 | aggr2: | |
2084 | current_aggr = $$; | |
2085 | $$ = $2; | |
2086 | overload_template_name ($$, 0); } | |
2087 | | aggr template_type_name ':' | |
2088 | { yyungetc (':', 1); goto aggr2; } | |
2089 | ; | |
2090 | ||
2091 | named_class_head_sans_basetype_defn: | |
2092 | aggr identifier_defn | |
2093 | { current_aggr = $$; $$ = $2; } | |
2094 | ; | |
2095 | ||
2096 | named_class_head: | |
2097 | named_class_head_sans_basetype | |
2098 | { | |
2099 | $<ttype>$ = xref_tag (current_aggr, $1, NULL_TREE); | |
2100 | } | |
2101 | maybe_base_class_list %prec EMPTY | |
2102 | { | |
2103 | if ($3) | |
2104 | $$ = xref_tag (current_aggr, $1, $3); | |
2105 | else | |
2106 | $$ = $<ttype>2; | |
2107 | } | |
2108 | | | |
2109 | named_class_head_sans_basetype_defn | |
2110 | { | |
2111 | $<ttype>$ = xref_defn_tag (current_aggr, $1, NULL_TREE); | |
2112 | } | |
2113 | maybe_base_class_list %prec EMPTY | |
2114 | { | |
2115 | if ($3) | |
2116 | $$ = xref_defn_tag (current_aggr, $1, $3); | |
2117 | else | |
2118 | $$ = $<ttype>2; | |
2119 | } | |
2120 | ; | |
2121 | ||
2122 | unnamed_class_head: aggr '{' | |
2123 | { $$ = xref_tag ($$, make_anon_name (), NULL_TREE); | |
2124 | yyungetc ('{', 1); } | |
2125 | ; | |
2126 | ||
2127 | class_head: unnamed_class_head | named_class_head ; | |
2128 | ||
2129 | maybe_base_class_list: | |
2130 | /* empty */ | |
2131 | { $$ = NULL_TREE; } | |
2132 | | ':' %prec EMPTY | |
2133 | { yyungetc(':', 1); $$ = NULL_TREE; } | |
2134 | | ':' base_class_list %prec EMPTY | |
2135 | { $$ = $2; } | |
2136 | ; | |
2137 | ||
2138 | base_class_list: | |
2139 | base_class | |
2140 | | base_class_list ',' base_class | |
2141 | { $$ = chainon ($$, $3); } | |
2142 | ; | |
2143 | ||
2144 | base_class: | |
2145 | base_class.1 | |
2146 | { if (! is_aggr_typedef ($$, 1)) | |
2147 | $$ = NULL_TREE; | |
2148 | else $$ = build_tree_list ((tree)visibility_default, $$); } | |
2149 | | scoped_base_class | |
2150 | { if (! is_aggr_typedef ($$, 1)) | |
2151 | $$ = NULL_TREE; | |
2152 | else $$ = build_tree_list ((tree)visibility_default, $$); } | |
2153 | | base_class_visibility_list base_class.1 | |
2154 | { if (! is_aggr_typedef ($2, 1)) | |
2155 | $$ = NULL_TREE; | |
2156 | else $$ = build_tree_list ((tree) $$, $2); } | |
2157 | | base_class_visibility_list scoped_base_class | |
2158 | { if (! is_aggr_typedef ($2, 1)) | |
2159 | $$ = NULL_TREE; | |
2160 | else $$ = build_tree_list ((tree) $$, $2); } | |
2161 | ; | |
2162 | ||
2163 | scoped_base_class: | |
2164 | base_class.1 SCOPED_TYPENAME | |
2165 | { | |
2166 | /* Kludge!!! See rule "template_type" and the code | |
2167 | * dealing with "template_type_seen_before_scope" in | |
2168 | * yylex(). */ | |
2169 | $$ = $2; | |
2170 | } | |
2171 | ; | |
2172 | base_class.1: | |
2173 | template_type_name tmpl.2 template_instantiation | |
2174 | { | |
2175 | extern tree template_type_seen_before_scope; | |
2176 | tree id = $3 ? TYPE_IDENTIFIER ($3) : $1; | |
2177 | ||
2178 | /* Check the rule template_type to get this... */ | |
2179 | if (yychar == YYEMPTY) | |
2180 | yychar = YYLEX; | |
2181 | if (yychar == SCOPE) { | |
2182 | template_type_seen_before_scope = id; | |
2183 | yychar = YYLEX; | |
2184 | } | |
2185 | } | |
2186 | | identifier | |
2187 | ; | |
2188 | ||
2189 | base_class_visibility_list: | |
2190 | VISSPEC | |
2191 | | SCSPEC | |
2192 | { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL]) | |
2193 | sorry ("non-virtual visibility"); | |
2194 | $$ = visibility_default_virtual; } | |
2195 | | base_class_visibility_list VISSPEC | |
2196 | { int err = 0; | |
2197 | if ($2 == visibility_protected) | |
2198 | { | |
2199 | warning ("`protected' visibility not implemented"); | |
2200 | $2 = visibility_public; | |
2201 | err++; | |
2202 | } | |
2203 | else if ($2 == visibility_public) | |
2204 | { | |
2205 | if ($1 == visibility_private) | |
2206 | { | |
2207 | mixed: | |
2208 | error ("base class cannot be public and private"); | |
2209 | } | |
2210 | else if ($1 == visibility_default_virtual) | |
2211 | $$ = visibility_public_virtual; | |
2212 | } | |
2213 | else /* $2 == visibility_private */ | |
2214 | { | |
2215 | if ($1 == visibility_public) | |
2216 | goto mixed; | |
2217 | else if ($1 == visibility_default_virtual) | |
2218 | $$ = visibility_private_virtual; | |
2219 | } | |
2220 | } | |
2221 | | base_class_visibility_list SCSPEC | |
2222 | { if ($2 != ridpointers[(int)RID_VIRTUAL]) | |
2223 | sorry ("non-virtual visibility"); | |
2224 | if ($$ == visibility_public) | |
2225 | $$ = visibility_public_virtual; | |
2226 | else if ($$ == visibility_private) | |
2227 | $$ = visibility_private_virtual; } | |
2228 | ; | |
2229 | ||
2230 | left_curly: '{' | |
2231 | { tree t; | |
2232 | push_obstacks_nochange (); | |
2233 | end_temporary_allocation (); | |
2234 | ||
2235 | if (! IS_AGGR_TYPE ($<ttype>0)) | |
2236 | { | |
2237 | $<ttype>0 = make_lang_type (RECORD_TYPE); | |
2238 | TYPE_NAME ($<ttype>0) = get_identifier ("erroneous type"); | |
2239 | } | |
2240 | if (TYPE_SIZE ($<ttype>0)) | |
2241 | duplicate_tag_error ($<ttype>0); | |
2242 | if (TYPE_SIZE ($<ttype>0) || TYPE_BEING_DEFINED ($<ttype>0)) | |
2243 | { | |
2244 | t = make_lang_type (TREE_CODE ($<ttype>0)); | |
2245 | pushtag (TYPE_IDENTIFIER ($<ttype>0), t); | |
2246 | $<ttype>0 = t; | |
2247 | } | |
2248 | pushclass ($<ttype>0, 0); | |
2249 | TYPE_BEING_DEFINED ($<ttype>0) = 1; | |
2250 | t = TYPE_IDENTIFIER ($<ttype>0); | |
2251 | if (IDENTIFIER_TEMPLATE (t)) | |
2252 | overload_template_name (t, 1); | |
2253 | } | |
2254 | ; | |
2255 | ||
2256 | opt.component_decl_list: | |
2257 | /* empty */ | |
2258 | { $$ = NULL_TREE; } | |
2259 | | component_decl_list | |
2260 | { $$ = build_tree_list ((tree)visibility_default, $$); } | |
2261 | | opt.component_decl_list VISSPEC ':' component_decl_list | |
2262 | { $$ = chainon ($$, build_tree_list ((tree) $2, $4)); } | |
2263 | | opt.component_decl_list VISSPEC ':' | |
2264 | ; | |
2265 | ||
2266 | component_decl_list: | |
2267 | component_decl | |
2268 | { if ($$ == void_type_node) $$ = NULL_TREE; } | |
2269 | | component_decl_list component_decl | |
2270 | { if ($2 != NULL_TREE && $2 != void_type_node) | |
2271 | $$ = chainon ($$, $2); } | |
2272 | | component_decl_list ';' | |
2273 | { if (pedantic) | |
2274 | pedwarn ("ANSI C++ forbids extra semicolons here"); } | |
2275 | ; | |
2276 | ||
2277 | component_decl: | |
2278 | typed_declspecs components ';' | |
2279 | { | |
2280 | do_components: | |
2281 | if ($2 == void_type_node) | |
2282 | /* We just got some friends. | |
2283 | They have been recorded elsewhere. */ | |
2284 | $$ = NULL_TREE; | |
2285 | else if ($2 == NULL_TREE) | |
2286 | { | |
2287 | tree t = groktypename (build_decl_list ($$, NULL_TREE)); | |
2288 | if (t == NULL_TREE) | |
2289 | { | |
2290 | error ("error in component specification"); | |
2291 | $$ = NULL_TREE; | |
2292 | } | |
2293 | else if (TREE_CODE (t) == UNION_TYPE) | |
2294 | { | |
2295 | /* handle anonymous unions */ | |
2296 | if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) | |
2297 | $$ = build_lang_field_decl (FIELD_DECL, | |
2298 | NULL_TREE, t); | |
2299 | else | |
2300 | { | |
2301 | /* This is a local union decl with a name, but | |
2302 | no components, I think this is the right thing | |
2303 | to do. (mrs) */ | |
2304 | #if 0 | |
2305 | /* I copied this from below, it is probably | |
2306 | needed, but I cannot prove that to myself | |
2307 | right now, but if you find it is needed | |
2308 | please turn it on. (mrs) */ | |
2309 | if (TYPE_LANG_SPECIFIC (t) | |
2310 | && CLASSTYPE_DECLARED_EXCEPTION (t)) | |
2311 | shadow_tag ($$); | |
2312 | #endif | |
2313 | $$ = NULL_TREE; | |
2314 | } | |
2315 | } | |
2316 | else if (TREE_CODE (t) == ENUMERAL_TYPE) | |
2317 | $$ = grok_enum_decls (t, NULL_TREE); | |
2318 | else if (TREE_CODE (t) == RECORD_TYPE) | |
2319 | { | |
2320 | if (TYPE_LANG_SPECIFIC (t) | |
2321 | && CLASSTYPE_DECLARED_EXCEPTION (t)) | |
2322 | shadow_tag ($$); | |
2323 | $$ = NULL_TREE; | |
2324 | } | |
2325 | else if (t != void_type_node) | |
2326 | { | |
2327 | error ("empty component declaration"); | |
2328 | $$ = NULL_TREE; | |
2329 | } | |
2330 | else $$ = NULL_TREE; | |
2331 | } | |
2332 | else | |
2333 | { | |
2334 | tree t = TREE_TYPE ($2); | |
2335 | if (TREE_CODE (t) == ENUMERAL_TYPE && TREE_NONLOCAL_FLAG (t)) | |
2336 | $$ = grok_enum_decls (t, $2); | |
2337 | else | |
2338 | $$ = $2; | |
2339 | } | |
2340 | end_exception_decls (); | |
2341 | } | |
2342 | | typed_declspecs '(' parmlist ')' ';' | |
2343 | { $$ = groktypefield ($$, $3); } | |
2344 | | typed_declspecs '(' parmlist ')' '}' | |
2345 | { error ("missing ';' before right brace"); | |
2346 | yyungetc ('}', 0); | |
2347 | $$ = groktypefield ($$, $3); } | |
2348 | | typed_declspecs LEFT_RIGHT ';' | |
2349 | { $$ = groktypefield ($$, empty_parms ()); } | |
2350 | | typed_declspecs LEFT_RIGHT '}' | |
2351 | { error ("missing ';' before right brace"); | |
2352 | yyungetc ('}', 0); | |
2353 | $$ = groktypefield ($$, empty_parms ()); } | |
2354 | | declmods components ';' | |
2355 | { goto do_components; } | |
2356 | /* Normal case: make this fast. */ | |
2357 | | declmods declarator ';' | |
2358 | { $$ = grokfield ($2, $$, 0, 0, 0, 0); } | |
2359 | | declmods components '}' | |
2360 | { error ("missing ';' before right brace"); | |
2361 | yyungetc ('}', 0); | |
2362 | goto do_components; } | |
2363 | | declmods '(' parmlist ')' ';' | |
2364 | { $$ = groktypefield ($$, $3); } | |
2365 | | declmods '(' parmlist ')' '}' | |
2366 | { error ("missing ';' before right brace"); | |
2367 | yyungetc ('}', 0); | |
2368 | $$ = groktypefield ($$, $3); } | |
2369 | | declmods LEFT_RIGHT ';' | |
2370 | { $$ = groktypefield ($$, empty_parms ()); } | |
2371 | | declmods LEFT_RIGHT '}' | |
2372 | { error ("missing ';' before right brace"); | |
2373 | yyungetc ('}', 0); | |
2374 | $$ = groktypefield ($$, empty_parms ()); } | |
2375 | | ':' expr_no_commas ';' | |
2376 | { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | |
2377 | | ':' expr_no_commas '}' | |
2378 | { error ("missing ';' before right brace"); | |
2379 | yyungetc ('}', 0); | |
2380 | $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | |
2381 | | error | |
2382 | { $$ = NULL_TREE; } | |
2383 | ||
2384 | /* C++: handle constructors, destructors and inline functions */ | |
2385 | /* note that INLINE is like a TYPESPEC */ | |
2386 | | fn.def2 ':' /* base_init compstmt */ | |
2387 | { $$ = finish_method ($$); } | |
2388 | | fn.def2 '{' /* nodecls compstmt */ | |
2389 | { $$ = finish_method ($$); } | |
2390 | | notype_declarator maybe_raises ';' | |
2391 | { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } | |
2392 | | notype_declarator maybe_raises '}' | |
2393 | { error ("missing ';' before right brace"); | |
2394 | yyungetc ('}', 0); | |
2395 | $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } | |
2396 | ; | |
2397 | ||
2398 | components: | |
2399 | /* empty: possibly anonymous */ | |
2400 | { $$ = NULL_TREE; } | |
2401 | | component_declarator0 | |
2402 | | components ',' component_declarator | |
2403 | { | |
2404 | /* In this context, void_type_node encodes | |
2405 | friends. They have been recorded elsewhere. */ | |
2406 | if ($$ == void_type_node) | |
2407 | $$ = $3; | |
2408 | else | |
2409 | $$ = chainon ($$, $3); | |
2410 | } | |
2411 | ; | |
2412 | ||
2413 | component_declarator0: | |
2414 | declarator maybe_raises maybeasm maybe_attribute | |
2415 | { current_declspecs = $<ttype>0; | |
2416 | $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3); | |
2417 | cplus_decl_attributes ($$, $4); } | |
2418 | | declarator maybe_raises maybeasm maybe_attribute '=' init | |
2419 | { current_declspecs = $<ttype>0; | |
2420 | $$ = grokfield ($$, current_declspecs, $2, $6, $3); | |
2421 | cplus_decl_attributes ($$, $4); } | |
2422 | | IDENTIFIER ':' expr_no_commas maybe_attribute | |
2423 | { current_declspecs = $<ttype>0; | |
2424 | $$ = grokbitfield ($$, current_declspecs, $3); | |
2425 | cplus_decl_attributes ($$, $4); } | |
2426 | | TYPENAME_COLON expr_no_commas maybe_attribute | |
2427 | { current_declspecs = $<ttype>0; | |
2428 | $$ = grokbitfield ($$, current_declspecs, $2); | |
2429 | cplus_decl_attributes ($$, $3); } | |
2430 | | ':' expr_no_commas | |
2431 | { current_declspecs = $<ttype>0; | |
2432 | $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | |
2433 | ; | |
2434 | ||
2435 | component_declarator: | |
2436 | declarator maybe_raises maybeasm maybe_attribute | |
2437 | { $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3); | |
2438 | cplus_decl_attributes ($$, $4); } | |
2439 | | declarator maybe_raises maybeasm maybe_attribute '=' init | |
2440 | { $$ = grokfield ($$, current_declspecs, $2, $6, $3); | |
2441 | cplus_decl_attributes ($$, $4); } | |
2442 | | IDENTIFIER ':' expr_no_commas maybe_attribute | |
2443 | { $$ = grokbitfield ($$, current_declspecs, $3); | |
2444 | cplus_decl_attributes ($$, $4); } | |
2445 | | TYPENAME_COLON expr_no_commas maybe_attribute | |
2446 | { $$ = grokbitfield ($$, current_declspecs, $2); | |
2447 | cplus_decl_attributes ($$, $3); } | |
2448 | | ':' expr_no_commas | |
2449 | { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | |
2450 | ; | |
2451 | ||
2452 | /* We chain the enumerators in reverse order. | |
2453 | Because of the way enums are built, the order is | |
2454 | insignificant. Take advantage of this fact. */ | |
2455 | ||
2456 | enumlist: | |
2457 | enumerator | |
2458 | | enumlist ',' enumerator | |
2459 | { TREE_CHAIN ($3) = $$; $$ = $3; } | |
2460 | ; | |
2461 | ||
2462 | enumerator: | |
2463 | identifier | |
2464 | { $$ = build_enumerator ($$, NULL_TREE); } | |
2465 | | identifier '=' expr_no_commas | |
2466 | { $$ = build_enumerator ($$, $3); } | |
2467 | ; | |
2468 | ||
2469 | typename: | |
2470 | typed_typespecs absdcl | |
2471 | { $$ = build_decl_list ($$, $2); } | |
2472 | | nonempty_type_quals absdcl | |
2473 | { $$ = build_decl_list ($$, $2); } | |
2474 | ; | |
2475 | ||
2476 | absdcl: /* an abstract declarator */ | |
2477 | /* empty */ %prec EMPTY | |
2478 | { $$ = NULL_TREE; } | |
2479 | | absdcl1 %prec EMPTY | |
2480 | | START_DECLARATOR absdcl1 %prec EMPTY | |
2481 | { $$ = $2; } | |
2482 | ; | |
2483 | ||
2484 | nonempty_type_quals: | |
2485 | TYPE_QUAL | |
2486 | { $$ = IDENTIFIER_AS_LIST ($$); } | |
2487 | | nonempty_type_quals TYPE_QUAL | |
2488 | { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
2489 | ; | |
2490 | ||
2491 | type_quals: | |
2492 | /* empty */ | |
2493 | { $$ = NULL_TREE; } | |
2494 | | type_quals TYPE_QUAL | |
2495 | { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | |
2496 | ; | |
2497 | ||
2498 | /* These rules must follow the rules for function declarations | |
2499 | and component declarations. That way, longer rules are preferred. */ | |
2500 | ||
2501 | /* An expression which will not live on the momentary obstack. */ | |
2502 | nonmomentary_expr: | |
2503 | { $<itype>$ = suspend_momentary (); } expr | |
2504 | { resume_momentary ($<itype>1); $$ = $2; } | |
2505 | ||
2506 | /* A declarator that is allowed only after an explicit typespec. */ | |
2507 | /* may all be followed by prec '.' */ | |
2508 | after_type_declarator: | |
2509 | after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.' | |
2510 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2511 | | after_type_declarator '(' parmlist ')' type_quals %prec '.' | |
2512 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2513 | | after_type_declarator LEFT_RIGHT type_quals %prec '.' | |
2514 | { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); } | |
2515 | | after_type_declarator '(' error ')' type_quals %prec '.' | |
2516 | { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); } | |
2517 | | after_type_declarator '[' nonmomentary_expr ']' | |
2518 | { $$ = build_parse_node (ARRAY_REF, $$, $3); } | |
2519 | | after_type_declarator '[' ']' | |
2520 | { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | |
2521 | | '(' after_type_declarator_no_typename ')' | |
2522 | { $$ = $2; } | |
2523 | | '(' '*' type_quals after_type_declarator ')' | |
2524 | { $$ = make_pointer_declarator ($3, $4); } | |
2525 | | PAREN_STAR_PAREN | |
2526 | { see_typename (); } | |
2527 | | after_type_member_declarator | |
2528 | | '(' '&' type_quals after_type_declarator ')' | |
2529 | { $$ = make_reference_declarator ($3, $4); } | |
2530 | | '*' type_quals after_type_declarator %prec UNARY | |
2531 | { $$ = make_pointer_declarator ($2, $3); } | |
2532 | | '&' type_quals after_type_declarator %prec UNARY | |
2533 | { $$ = make_reference_declarator ($2, $3); } | |
2534 | | TYPENAME | |
2535 | ; | |
2536 | ||
2537 | after_type_declarator_no_typename: | |
2538 | after_type_declarator_no_typename '(' nonnull_exprlist ')' type_quals %prec '.' | |
2539 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2540 | | after_type_declarator_no_typename '(' parmlist ')' type_quals %prec '.' | |
2541 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2542 | | after_type_declarator_no_typename LEFT_RIGHT type_quals %prec '.' | |
2543 | { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); } | |
2544 | | after_type_declarator_no_typename '(' error ')' type_quals %prec '.' | |
2545 | { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); } | |
2546 | | after_type_declarator_no_typename '[' nonmomentary_expr ']' | |
2547 | { $$ = build_parse_node (ARRAY_REF, $$, $3); } | |
2548 | | after_type_declarator_no_typename '[' ']' | |
2549 | { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | |
2550 | | '(' after_type_declarator_no_typename ')' | |
2551 | { $$ = $2; } | |
2552 | | PAREN_STAR_PAREN | |
2553 | { see_typename (); } | |
2554 | | after_type_member_declarator | |
2555 | | '*' type_quals after_type_declarator %prec UNARY | |
2556 | { $$ = make_pointer_declarator ($2, $3); } | |
2557 | | '&' type_quals after_type_declarator %prec UNARY | |
2558 | { $$ = make_reference_declarator ($2, $3); } | |
2559 | ; | |
2560 | ||
2561 | /* A declarator allowed whether or not there has been | |
2562 | an explicit typespec. These cannot redeclare a typedef-name. */ | |
2563 | ||
2564 | notype_declarator: | |
2565 | notype_declarator '(' nonnull_exprlist ')' type_quals %prec '.' | |
2566 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2567 | | notype_declarator '(' parmlist ')' type_quals %prec '.' | |
2568 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2569 | | notype_declarator LEFT_RIGHT type_quals %prec '.' | |
2570 | { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); } | |
2571 | | notype_declarator '(' error ')' type_quals %prec '.' | |
2572 | { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); } | |
2573 | | '(' notype_declarator ')' | |
2574 | { $$ = $2; } | |
2575 | | '*' type_quals notype_declarator %prec UNARY | |
2576 | { $$ = make_pointer_declarator ($2, $3); } | |
2577 | | '&' type_quals notype_declarator %prec UNARY | |
2578 | { $$ = make_reference_declarator ($2, $3); } | |
2579 | | notype_declarator '[' nonmomentary_expr ']' | |
2580 | { $$ = build_parse_node (ARRAY_REF, $$, $3); } | |
2581 | | notype_declarator '[' ']' | |
2582 | { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | |
2583 | | IDENTIFIER | |
2584 | { see_typename (); } | |
2585 | ||
2586 | /* C++ extensions. */ | |
2587 | | operator_name | |
2588 | { see_typename (); } | |
2589 | ||
2590 | | '~' TYPENAME | |
2591 | { | |
2592 | destructor_name: | |
2593 | see_typename (); | |
2594 | $$ = build_parse_node (BIT_NOT_EXPR, $2); | |
2595 | } | |
2596 | | '~' IDENTIFIER | |
2597 | { goto destructor_name; } | |
2598 | | '~' PTYPENAME | |
2599 | { goto destructor_name; } | |
2600 | | scoped_id see_typename notype_declarator %prec '(' | |
2601 | { see_typename (); | |
2602 | if (TREE_CODE ($$) != SCOPE_REF) | |
2603 | $$ = build_push_scope ($$, $3); | |
2604 | else if (TREE_OPERAND ($$, 1) == NULL_TREE) | |
2605 | TREE_OPERAND ($$, 1) = $3; | |
2606 | else | |
2607 | $$ = build_parse_node (SCOPE_REF, $$, $3); | |
2608 | } | |
2609 | | scoped_id see_typename TYPENAME %prec '(' | |
2610 | { $$ = build_push_scope ($$, $3); } | |
2611 | | scoped_id see_typename TYPENAME '(' nonnull_exprlist ')' type_quals %prec '.' | |
2612 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); } | |
2613 | | scoped_id see_typename TYPENAME '(' parmlist ')' type_quals %prec '.' | |
2614 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); } | |
2615 | | scoped_id see_typename TYPENAME LEFT_RIGHT type_quals %prec '.' | |
2616 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, empty_parms (), $5)); } | |
2617 | | scoped_id see_typename TYPENAME '(' error ')' type_quals %prec '.' | |
2618 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, NULL_TREE, NULL_TREE)); } | |
2619 | /* For constructor templates. */ | |
2620 | | scoped_id see_typename PTYPENAME %prec '(' | |
2621 | { $$ = build_push_scope ($$, $3); } | |
2622 | | scoped_id see_typename PTYPENAME '(' nonnull_exprlist ')' type_quals %prec '.' | |
2623 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); } | |
2624 | | scoped_id see_typename PTYPENAME '(' parmlist ')' type_quals %prec '.' | |
2625 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); } | |
2626 | | scoped_id see_typename PTYPENAME LEFT_RIGHT type_quals %prec '.' | |
2627 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, empty_parms (), $5)); } | |
2628 | | scoped_id see_typename PTYPENAME '(' error ')' type_quals %prec '.' | |
2629 | { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, NULL_TREE, NULL_TREE)); } | |
2630 | | SCOPE see_typename notype_declarator | |
2631 | { $$ = build_parse_node (SCOPE_REF, NULL_TREE, $3); } | |
2632 | ; | |
2633 | ||
2634 | scoped_id: typename_scope | |
2635 | { $$ = resolve_scope_to_name (NULL_TREE, $$); | |
2636 | if ($$ == NULL_TREE) | |
2637 | { | |
2638 | error ("undefined explicitly scoped type"); | |
2639 | $$ = error_mark_node; | |
2640 | } | |
2641 | } | |
2642 | | template_type SCOPE /* try_for_typename %prec EMPTY */ | |
2643 | { | |
2644 | if ($$ == error_mark_node) | |
2645 | /* leave it alone */; | |
2646 | else | |
2647 | { | |
2648 | $$ = resolve_scope_to_name (NULL_TREE, TYPE_IDENTIFIER ($$)); | |
2649 | if ($$ == NULL_TREE) | |
2650 | { | |
2651 | error ("undefined explicitly scoped type"); | |
2652 | $$ = error_mark_node; | |
2653 | } | |
2654 | } | |
2655 | /* if ($3) popclass (1); */ | |
2656 | } | |
2657 | ; | |
2658 | ||
2659 | typename_scope: | |
2660 | TYPENAME SCOPE; | |
2661 | ||
2662 | scoped_typename: SCOPED_TYPENAME | |
2663 | | template_type SCOPED_TYPENAME | |
2664 | { | |
2665 | /* Kludge!!! See rule "template_type" and the code | |
2666 | * dealing with "template_type_seen_before_scope" in | |
2667 | * yylex(). */ | |
2668 | $$ = $2; | |
2669 | } | |
2670 | /* | template_type SCOPE try_for_typename TYPENAME | |
2671 | { | |
2672 | if ($$ == error_mark_node) | |
2673 | ; | |
2674 | else | |
2675 | { | |
2676 | $$ = build_parse_node (SCOPE_REF, | |
2677 | TYPE_IDENTIFIER ($$), | |
2678 | $4); | |
2679 | } | |
2680 | if ($3) popclass (1); | |
2681 | } */ | |
2682 | ; | |
2683 | ||
2684 | absdcl1: /* a nonempty abstract declarator */ | |
2685 | '(' absdcl1 ')' | |
2686 | { see_typename (); | |
2687 | $$ = $2; } | |
2688 | /* `(typedef)1' is `int'. */ | |
2689 | | '*' type_quals absdcl1 %prec EMPTY | |
2690 | { $$ = make_pointer_declarator ($2, $3); } | |
2691 | | '*' type_quals %prec EMPTY | |
2692 | { $$ = make_pointer_declarator ($2, NULL_TREE); } | |
2693 | | PAREN_STAR_PAREN | |
2694 | { see_typename (); } | |
2695 | | '(' abs_member_declarator ')' | |
2696 | { $$ = $2; } | |
2697 | | '&' type_quals absdcl1 %prec EMPTY | |
2698 | { $$ = make_reference_declarator ($2, $3); } | |
2699 | | '&' type_quals %prec EMPTY | |
2700 | { $$ = make_reference_declarator ($2, NULL_TREE); } | |
2701 | | absdcl1 '(' parmlist ')' type_quals %prec '.' | |
2702 | { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | |
2703 | | absdcl1 LEFT_RIGHT type_quals %prec '.' | |
2704 | { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); } | |
2705 | | absdcl1 '[' nonmomentary_expr ']' %prec '.' | |
2706 | { $$ = build_parse_node (ARRAY_REF, $$, $3); } | |
2707 | | absdcl1 '[' ']' %prec '.' | |
2708 | { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | |
2709 | | '(' parmlist ')' type_quals %prec '.' | |
2710 | { $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, $4); } | |
2711 | | LEFT_RIGHT type_quals %prec '.' | |
2712 | { $$ = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (), $2); } | |
2713 | | '[' nonmomentary_expr ']' %prec '.' | |
2714 | { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); } | |
2715 | | '[' ']' %prec '.' | |
2716 | { $$ = build_parse_node (ARRAY_REF, NULL_TREE, NULL_TREE); } | |
2717 | ; | |
2718 | ||
2719 | abs_member_declarator: | |
2720 | scoped_id '*' type_quals | |
2721 | { tree t; | |
2722 | t = $$; | |
2723 | while (TREE_OPERAND (t, 1)) | |
2724 | t = TREE_OPERAND (t, 1); | |
2725 | TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, 0); | |
2726 | } | |
2727 | | scoped_id '*' type_quals absdcl1 | |
2728 | { tree t; | |
2729 | t = $$; | |
2730 | while (TREE_OPERAND (t, 1)) | |
2731 | t = TREE_OPERAND (t, 1); | |
2732 | TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, $4); | |
2733 | } | |
2734 | | scoped_id '&' type_quals | |
2735 | { tree t; | |
2736 | t = $$; | |
2737 | while (TREE_OPERAND (t, 1)) | |
2738 | t = TREE_OPERAND (t, 1); | |
2739 | TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, 0); | |
2740 | } | |
2741 | | scoped_id '&' type_quals absdcl1 | |
2742 | { tree t; | |
2743 | t = $$; | |
2744 | while (TREE_OPERAND (t, 1)) | |
2745 | t = TREE_OPERAND (t, 1); | |
2746 | TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, $4); | |
2747 | } | |
2748 | ; | |
2749 | ||
2750 | after_type_member_declarator: | |
2751 | scoped_id see_typename '*' type_quals after_type_declarator | |
2752 | { tree t; | |
2753 | t = $$; | |
2754 | while (TREE_OPERAND (t, 1)) | |
2755 | t = TREE_OPERAND (t, 1); | |
2756 | TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, $5); | |
2757 | } | |
2758 | | scoped_id see_typename '&' type_quals after_type_declarator | |
2759 | { tree t; | |
2760 | t = $$; | |
2761 | while (TREE_OPERAND (t, 1)) | |
2762 | t = TREE_OPERAND (t, 1); | |
2763 | TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, $5); | |
2764 | } | |
2765 | ; | |
2766 | ||
2767 | /* For C++, decls and stmts can be intermixed, so we don't need to | |
2768 | have a special rule that won't start parsing the stmt section | |
2769 | until we have a stmt that parses without errors. */ | |
2770 | ||
2771 | stmts: | |
2772 | stmt | |
2773 | | errstmt | |
2774 | | stmts stmt | |
2775 | | stmts errstmt | |
2776 | ; | |
2777 | ||
2778 | errstmt: error ';' | |
2779 | ; | |
2780 | ||
2781 | /* build the LET_STMT node before parsing its contents, | |
2782 | so that any LET_STMTs within the context can have their display pointers | |
2783 | set up to point at this one. */ | |
2784 | ||
2785 | .pushlevel: /* empty */ | |
2786 | { emit_line_note (input_filename, lineno); | |
2787 | pushlevel (0); | |
2788 | clear_last_expr (); | |
2789 | push_momentary (); | |
2790 | expand_start_bindings (0); | |
2791 | $$ = stmt_decl_msg; | |
2792 | stmt_decl_msg = 0; } | |
2793 | ; | |
2794 | ||
2795 | /* Read zero or more forward-declarations for labels | |
2796 | that nested functions can jump to. */ | |
2797 | maybe_label_decls: | |
2798 | /* empty */ | |
2799 | | label_decls | |
2800 | { if (pedantic) | |
2801 | pedwarn ("ANSI C++ forbids label declarations"); } | |
2802 | ; | |
2803 | ||
2804 | label_decls: | |
2805 | label_decl | |
2806 | | label_decls label_decl | |
2807 | ; | |
2808 | ||
2809 | label_decl: | |
2810 | LABEL identifiers_or_typenames ';' | |
2811 | { tree link; | |
2812 | for (link = $2; link; link = TREE_CHAIN (link)) | |
2813 | { | |
2814 | tree label = shadow_label (TREE_VALUE (link)); | |
2815 | C_DECLARED_LABEL_FLAG (label) = 1; | |
2816 | declare_nonlocal_label (label); | |
2817 | } | |
2818 | } | |
2819 | ; | |
2820 | ||
2821 | /* This is the body of a function definition. | |
2822 | It causes syntax errors to ignore to the next openbrace. */ | |
2823 | compstmt_or_error: | |
2824 | compstmt | |
2825 | {} | |
2826 | | error compstmt | |
2827 | ; | |
2828 | ||
2829 | compstmt: '{' '}' | |
2830 | { $$ = convert (void_type_node, integer_zero_node); } | |
2831 | | '{' .pushlevel maybe_label_decls stmts '}' | |
2832 | { pop_implicit_try_blocks (NULL_TREE); | |
2833 | stmt_decl_msg = $2; | |
2834 | expand_end_bindings (getdecls (), kept_level_p (), 1); | |
2835 | $$ = poplevel (kept_level_p (), 1, 0); | |
2836 | pop_momentary (); } | |
2837 | | '{' .pushlevel maybe_label_decls error '}' | |
2838 | { pop_implicit_try_blocks (NULL_TREE); | |
2839 | stmt_decl_msg = $2; | |
2840 | expand_end_bindings (getdecls (), kept_level_p (), 1); | |
2841 | $$ = poplevel (kept_level_p (), 0, 0); | |
2842 | pop_momentary (); } | |
2843 | ; | |
2844 | ||
2845 | simple_if: | |
2846 | IF '(' expr ')' | |
2847 | { emit_line_note (input_filename, lineno); | |
2848 | expand_start_cond (truthvalue_conversion ($3), 0); | |
2849 | stmt_decl_msg = "if"; } | |
2850 | stmt | |
2851 | { stmt_decl_msg = 0; } | |
2852 | ; | |
2853 | ||
2854 | stmt: | |
2855 | compstmt | |
2856 | { finish_stmt (); } | |
2857 | | decl | |
2858 | { if (stmt_decl_msg) | |
2859 | error ("declaration after %s invalid", stmt_decl_msg); | |
2860 | stmt_decl_msg = 0; | |
2861 | finish_stmt (); } | |
2862 | | expr ';' | |
2863 | { | |
2864 | tree expr = $1; | |
2865 | emit_line_note (input_filename, lineno); | |
2866 | /* Do default conversion if safe and possibly important, | |
2867 | in case within ({...}). */ | |
2868 | if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE | |
2869 | && lvalue_p (expr)) | |
2870 | || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE) | |
2871 | expr = default_conversion (expr); | |
2872 | cplus_expand_expr_stmt (expr); | |
2873 | clear_momentary (); | |
2874 | finish_stmt (); } | |
2875 | | simple_if ELSE | |
2876 | { expand_start_else (); | |
2877 | stmt_decl_msg = "else"; } | |
2878 | stmt | |
2879 | { expand_end_cond (); | |
2880 | stmt_decl_msg = 0; | |
2881 | finish_stmt (); } | |
2882 | | simple_if %prec IF | |
2883 | { expand_end_cond (); | |
2884 | stmt_decl_msg = 0; | |
2885 | finish_stmt (); } | |
2886 | | WHILE | |
2887 | { emit_nop (); | |
2888 | emit_line_note (input_filename, lineno); | |
2889 | expand_start_loop (1); } | |
2890 | '(' expr ')' | |
2891 | { expand_exit_loop_if_false (0, truthvalue_conversion ($4)); | |
2892 | stmt_decl_msg = "while"; } | |
2893 | stmt | |
2894 | { | |
2895 | expand_end_loop (); | |
2896 | stmt_decl_msg = 0; | |
2897 | finish_stmt (); } | |
2898 | | DO | |
2899 | { emit_nop (); | |
2900 | emit_line_note (input_filename, lineno); | |
2901 | expand_start_loop_continue_elsewhere (1); | |
2902 | stmt_decl_msg = "do"; } | |
2903 | stmt WHILE | |
2904 | { stmt_decl_msg = 0; | |
2905 | expand_loop_continue_here (); } | |
2906 | '(' expr ')' ';' | |
2907 | { emit_line_note (input_filename, lineno); | |
2908 | expand_exit_loop_if_false (0, truthvalue_conversion ($7)); | |
2909 | expand_end_loop (); | |
2910 | clear_momentary (); | |
2911 | finish_stmt (); } | |
2912 | | forhead.1 | |
2913 | { emit_nop (); | |
2914 | emit_line_note (input_filename, lineno); | |
2915 | if ($1) cplus_expand_expr_stmt ($1); | |
2916 | expand_start_loop_continue_elsewhere (1); } | |
2917 | xexpr ';' | |
2918 | { emit_line_note (input_filename, lineno); | |
2919 | if ($3) expand_exit_loop_if_false (0, truthvalue_conversion ($3)); } | |
2920 | xexpr ')' | |
2921 | /* Don't let the tree nodes for $6 be discarded | |
2922 | by clear_momentary during the parsing of the next stmt. */ | |
2923 | { push_momentary (); | |
2924 | stmt_decl_msg = "for"; } | |
2925 | stmt | |
2926 | { emit_line_note (input_filename, lineno); | |
2927 | expand_loop_continue_here (); | |
2928 | if ($6) cplus_expand_expr_stmt ($6); | |
2929 | pop_momentary (); | |
2930 | expand_end_loop (); | |
2931 | stmt_decl_msg = 0; | |
2932 | finish_stmt (); } | |
2933 | | forhead.2 | |
2934 | { emit_nop (); | |
2935 | emit_line_note (input_filename, lineno); | |
2936 | expand_start_loop_continue_elsewhere (1); } | |
2937 | xexpr ';' | |
2938 | { emit_line_note (input_filename, lineno); | |
2939 | if ($3) expand_exit_loop_if_false (0, truthvalue_conversion ($3)); } | |
2940 | xexpr ')' | |
2941 | /* Don't let the tree nodes for $6 be discarded | |
2942 | by clear_momentary during the parsing of the next stmt. */ | |
2943 | { push_momentary (); | |
2944 | stmt_decl_msg = "for"; | |
2945 | $<itype>7 = lineno; } | |
2946 | stmt | |
2947 | { emit_line_note (input_filename, $<itype>7); | |
2948 | expand_loop_continue_here (); | |
2949 | if ($6) cplus_expand_expr_stmt ($6); | |
2950 | pop_momentary (); | |
2951 | expand_end_loop (); | |
2952 | pop_implicit_try_blocks (NULL_TREE); | |
2953 | if ($1) | |
2954 | { | |
2955 | register int keep = $1 > 0; | |
2956 | if (keep) expand_end_bindings (0, keep, 1); | |
2957 | poplevel (keep, 1, 0); | |
2958 | pop_momentary (); | |
2959 | } | |
2960 | stmt_decl_msg = 0; | |
2961 | finish_stmt (); | |
2962 | } | |
2963 | | SWITCH '(' expr ')' | |
2964 | { emit_line_note (input_filename, lineno); | |
2965 | c_expand_start_case ($3); | |
2966 | /* Don't let the tree nodes for $3 be discarded by | |
2967 | clear_momentary during the parsing of the next stmt. */ | |
2968 | push_momentary (); | |
2969 | stmt_decl_msg = "switch"; } | |
2970 | stmt | |
2971 | { expand_end_case ($3); | |
2972 | pop_momentary (); | |
2973 | stmt_decl_msg = 0; | |
2974 | finish_stmt (); } | |
2975 | | CASE expr ':' | |
2976 | { register tree value = $2; | |
2977 | register tree label | |
2978 | = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); | |
2979 | ||
2980 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
2981 | Strip such NOP_EXPRs. */ | |
2982 | if (TREE_CODE (value) == NOP_EXPR | |
2983 | && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) | |
2984 | value = TREE_OPERAND (value, 0); | |
2985 | ||
2986 | if (TREE_READONLY_DECL_P (value)) | |
2987 | { | |
2988 | value = decl_constant_value (value); | |
2989 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
2990 | Strip such NOP_EXPRs. */ | |
2991 | if (TREE_CODE (value) == NOP_EXPR | |
2992 | && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) | |
2993 | value = TREE_OPERAND (value, 0); | |
2994 | } | |
2995 | value = fold (value); | |
2996 | ||
2997 | if (TREE_CODE (value) != INTEGER_CST | |
2998 | && value != error_mark_node) | |
2999 | { | |
3000 | error ("case label does not reduce to an integer constant"); | |
3001 | value = error_mark_node; | |
3002 | } | |
3003 | else | |
3004 | /* Promote char or short to int. */ | |
3005 | value = default_conversion (value); | |
3006 | if (value != error_mark_node) | |
3007 | { | |
3008 | tree duplicate; | |
3009 | int success = pushcase (value, label, &duplicate); | |
3010 | if (success == 1) | |
3011 | error ("case label not within a switch statement"); | |
3012 | else if (success == 2) | |
3013 | { | |
3014 | error ("duplicate case value"); | |
3015 | error_with_decl (duplicate, "this is the first entry for that value"); | |
3016 | } | |
3017 | else if (success == 3) | |
3018 | warning ("case value out of range"); | |
3019 | else if (success == 5) | |
3020 | error ("case label within scope of cleanup or variable array"); | |
3021 | } | |
3022 | define_case_label (label); | |
3023 | } | |
3024 | stmt | |
3025 | | CASE expr RANGE expr ':' | |
3026 | { register tree value1 = $2; | |
3027 | register tree value2 = $4; | |
3028 | register tree label | |
3029 | = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); | |
3030 | ||
3031 | if (pedantic) | |
3032 | pedwarn ("ANSI C++ forbids range expressions in switch statement"); | |
3033 | ||
3034 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
3035 | Strip such NOP_EXPRs. */ | |
3036 | if (TREE_CODE (value1) == NOP_EXPR | |
3037 | && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0))) | |
3038 | value1 = TREE_OPERAND (value1, 0); | |
3039 | ||
3040 | if (TREE_READONLY_DECL_P (value1)) | |
3041 | { | |
3042 | value1 = decl_constant_value (value1); | |
3043 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
3044 | Strip such NOP_EXPRs. */ | |
3045 | if (TREE_CODE (value1) == NOP_EXPR | |
3046 | && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0))) | |
3047 | value1 = TREE_OPERAND (value1, 0); | |
3048 | } | |
3049 | value1 = fold (value1); | |
3050 | ||
3051 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
3052 | Strip such NOP_EXPRs. */ | |
3053 | if (TREE_CODE (value2) == NOP_EXPR | |
3054 | && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0))) | |
3055 | value2 = TREE_OPERAND (value2, 0); | |
3056 | ||
3057 | if (TREE_READONLY_DECL_P (value2)) | |
3058 | { | |
3059 | value2 = decl_constant_value (value2); | |
3060 | /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. | |
3061 | Strip such NOP_EXPRs. */ | |
3062 | if (TREE_CODE (value2) == NOP_EXPR | |
3063 | && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0))) | |
3064 | value2 = TREE_OPERAND (value2, 0); | |
3065 | } | |
3066 | value2 = fold (value2); | |
3067 | ||
3068 | ||
3069 | if (TREE_CODE (value1) != INTEGER_CST | |
3070 | && value1 != error_mark_node) | |
3071 | { | |
3072 | error ("case label does not reduce to an integer constant"); | |
3073 | value1 = error_mark_node; | |
3074 | } | |
3075 | if (TREE_CODE (value2) != INTEGER_CST | |
3076 | && value2 != error_mark_node) | |
3077 | { | |
3078 | error ("case label does not reduce to an integer constant"); | |
3079 | value2 = error_mark_node; | |
3080 | } | |
3081 | if (value1 != error_mark_node | |
3082 | && value2 != error_mark_node) | |
3083 | { | |
3084 | tree duplicate; | |
3085 | int success = pushcase_range (value1, value2, label, | |
3086 | &duplicate); | |
3087 | if (success == 1) | |
3088 | error ("case label not within a switch statement"); | |
3089 | else if (success == 2) | |
3090 | { | |
3091 | error ("duplicate (or overlapping) case value"); | |
3092 | error_with_decl (duplicate, "this is the first entry overlapping that value"); | |
3093 | } | |
3094 | else if (success == 3) | |
3095 | warning ("case value out of range"); | |
3096 | else if (success == 4) | |
3097 | warning ("empty range specified"); | |
3098 | else if (success == 5) | |
3099 | error ("case label within scope of cleanup or variable array"); | |
3100 | } | |
3101 | define_case_label (label); | |
3102 | } | |
3103 | stmt | |
3104 | | DEFAULT ':' | |
3105 | { | |
3106 | tree duplicate; | |
3107 | register tree label | |
3108 | = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); | |
3109 | int success = pushcase (NULL_TREE, label, &duplicate); | |
3110 | if (success == 1) | |
3111 | error ("default label not within a switch statement"); | |
3112 | else if (success == 2) | |
3113 | { | |
3114 | error ("multiple default labels in one switch"); | |
3115 | error_with_decl (duplicate, "this is the first default label"); | |
3116 | } | |
3117 | define_case_label (NULL_TREE); | |
3118 | } | |
3119 | stmt | |
3120 | | BREAK ';' | |
3121 | { emit_line_note (input_filename, lineno); | |
3122 | if ( ! expand_exit_something ()) | |
3123 | error ("break statement not within loop or switch"); } | |
3124 | | CONTINUE ';' | |
3125 | { emit_line_note (input_filename, lineno); | |
3126 | if (! expand_continue_loop (0)) | |
3127 | error ("continue statement not within a loop"); } | |
3128 | | RETURN ';' | |
3129 | { emit_line_note (input_filename, lineno); | |
3130 | c_expand_return (NULL_TREE); } | |
3131 | | RETURN expr ';' | |
3132 | { emit_line_note (input_filename, lineno); | |
3133 | c_expand_return ($2); | |
3134 | finish_stmt (); | |
3135 | } | |
3136 | | ASM_KEYWORD maybe_type_qual '(' string ')' ';' | |
3137 | { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); | |
3138 | emit_line_note (input_filename, lineno); | |
3139 | expand_asm ($4); | |
3140 | finish_stmt (); | |
3141 | } | |
3142 | /* This is the case with just output operands. */ | |
3143 | | ASM_KEYWORD maybe_type_qual '(' string ':' asm_operands ')' ';' | |
3144 | { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); | |
3145 | emit_line_note (input_filename, lineno); | |
3146 | c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE, | |
3147 | $2 == ridpointers[(int)RID_VOLATILE], | |
3148 | input_filename, lineno); | |
3149 | finish_stmt (); | |
3150 | } | |
3151 | /* This is the case with input operands as well. */ | |
3152 | | ASM_KEYWORD maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';' | |
3153 | { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); | |
3154 | emit_line_note (input_filename, lineno); | |
3155 | c_expand_asm_operands ($4, $6, $8, NULL_TREE, | |
3156 | $2 == ridpointers[(int)RID_VOLATILE], | |
3157 | input_filename, lineno); | |
3158 | finish_stmt (); | |
3159 | } | |
3160 | /* This is the case with clobbered registers as well. */ | |
3161 | | ASM_KEYWORD maybe_type_qual '(' string ':' asm_operands ':' | |
3162 | asm_operands ':' asm_clobbers ')' ';' | |
3163 | { if (TREE_CHAIN ($4)) $4 = combine_strings ($4); | |
3164 | emit_line_note (input_filename, lineno); | |
3165 | c_expand_asm_operands ($4, $6, $8, $10, | |
3166 | $2 == ridpointers[(int)RID_VOLATILE], | |
3167 | input_filename, lineno); | |
3168 | finish_stmt (); | |
3169 | } | |
3170 | | GOTO '*' expr ';' | |
3171 | { emit_line_note (input_filename, lineno); | |
3172 | expand_computed_goto ($3); } | |
3173 | | GOTO identifier ';' | |
3174 | { tree decl; | |
3175 | emit_line_note (input_filename, lineno); | |
3176 | decl = lookup_label ($2); | |
3177 | TREE_USED (decl) = 1; | |
3178 | expand_goto (decl); } | |
3179 | | label_colon stmt | |
3180 | { finish_stmt (); } | |
3181 | | label_colon '}' | |
3182 | { error ("label must be followed by statement"); | |
3183 | yyungetc ('}', 0); | |
3184 | finish_stmt (); } | |
3185 | | ';' | |
3186 | { finish_stmt (); } | |
3187 | ||
3188 | /* Exception handling extensions. */ | |
3189 | | ANSI_THROW ';' { cplus_expand_throw (NULL_TREE); } | |
3190 | | ANSI_THROW expr ';' { cplus_expand_throw ($2); } | |
3191 | | THROW raise_identifier '(' nonnull_exprlist ')' ';' | |
3192 | { cplus_expand_raise ($2, $4, NULL_TREE, 0); | |
3193 | finish_stmt (); } | |
3194 | | THROW raise_identifier LEFT_RIGHT ';' | |
3195 | { cplus_expand_raise ($2, NULL_TREE, NULL_TREE, 0); | |
3196 | finish_stmt (); } | |
3197 | | RAISE raise_identifier '(' nonnull_exprlist ')' ';' | |
3198 | { cplus_expand_raise ($2, $4, NULL_TREE, 0); | |
3199 | finish_stmt (); } | |
3200 | | RAISE raise_identifier LEFT_RIGHT ';' | |
3201 | { cplus_expand_raise ($2, NULL_TREE, NULL_TREE, 0); | |
3202 | finish_stmt (); } | |
3203 | | RAISE identifier ';' | |
3204 | { cplus_expand_reraise ($2); | |
3205 | finish_stmt (); } | |
3206 | | try EXCEPT identifier '{' | |
3207 | { | |
3208 | tree decl = cplus_expand_end_try ($1); | |
3209 | $<ttype>2 = current_exception_type; | |
3210 | $<ttype>4 = current_exception_decl; | |
3211 | $<ttype>$ = current_exception_object; | |
3212 | cplus_expand_start_except ($3, decl); | |
3213 | pushlevel (0); | |
3214 | clear_last_expr (); | |
3215 | push_momentary (); | |
3216 | expand_start_bindings (0); | |
3217 | stmt_decl_msg = 0; | |
3218 | } | |
3219 | except_stmts '}' | |
3220 | { | |
3221 | tree decls = getdecls (); | |
3222 | /* If there is a default exception to handle, | |
3223 | handle it here. */ | |
3224 | if ($6) | |
3225 | { | |
3226 | tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0); | |
3227 | tree block; | |
3228 | ||
3229 | pushlevel (1); | |
3230 | expand_start_bindings (0); | |
3231 | expand_expr ($6, 0, 0, 0); | |
3232 | expand_end_bindings (0, 1, 0); | |
3233 | block = poplevel (1, 0, 0); | |
3234 | ||
3235 | /* This is a catch block. */ | |
3236 | TREE_LANG_FLAG_2 (block) = 1; | |
3237 | BLOCK_VARS (block) = decl; | |
3238 | } | |
3239 | ||
3240 | expand_end_bindings (decls, decls != 0, 1); | |
3241 | poplevel (decls != 0, 1, 0); | |
3242 | pop_momentary (); | |
3243 | current_exception_type = $<ttype>2; | |
3244 | current_exception_decl = $<ttype>4; | |
3245 | current_exception_object = $<ttype>5; | |
3246 | cplus_expand_end_except ($6); | |
3247 | } | |
3248 | | try error | |
3249 | { | |
3250 | cplus_expand_end_try ($1); | |
3251 | /* These are the important actions of | |
3252 | `cplus_expand_end_except' which we must emulate. */ | |
3253 | if (expand_escape_except ()) | |
3254 | expand_end_except (); | |
3255 | expand_end_bindings (0, 0, 1); | |
3256 | poplevel (0, 0, 0); | |
3257 | } | |
3258 | | ansi_try ansi_dummy ansi_dummy | |
3259 | { | |
3260 | tree decl = cplus_expand_end_try ($1); | |
3261 | $<ttype>2 = current_exception_type; | |
3262 | $<ttype>3 = current_exception_decl; | |
3263 | $<ttype>$ = current_exception_object; | |
3264 | cplus_expand_start_except (NULL, decl); | |
3265 | pushlevel (0); | |
3266 | clear_last_expr (); | |
3267 | push_momentary (); | |
3268 | expand_start_bindings (0); | |
3269 | stmt_decl_msg = 0; | |
3270 | } | |
3271 | ansi_except_stmts | |
3272 | { | |
3273 | tree decls = getdecls (); | |
3274 | /* If there is a default exception to handle, | |
3275 | handle it here. */ | |
3276 | if ($5) | |
3277 | { | |
3278 | tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0); | |
3279 | tree block; | |
3280 | ||
3281 | pushlevel (1); | |
3282 | expand_start_bindings (0); | |
3283 | expand_expr ($5, 0, 0, 0); | |
3284 | expand_end_bindings (0, 1, 0); | |
3285 | block = poplevel (1, 0, 0); | |
3286 | ||
3287 | /* This is a catch block. */ | |
3288 | TREE_LANG_FLAG_2 (block) = 1; | |
3289 | BLOCK_VARS (block) = decl; | |
3290 | } | |
3291 | ||
3292 | expand_end_bindings (decls, decls != 0, 1); | |
3293 | poplevel (decls != 0, 1, 0); | |
3294 | pop_momentary (); | |
3295 | current_exception_type = $<ttype>2; | |
3296 | current_exception_decl = $<ttype>3; | |
3297 | current_exception_object = $<ttype>4; | |
3298 | cplus_expand_end_except ($5); | |
3299 | } | |
3300 | | try RERAISE raise_identifiers /* ';' checked for at bottom. */ | |
3301 | { tree name = get_identifier ("(compiler error)"); | |
3302 | tree orig_ex_type = current_exception_type; | |
3303 | tree orig_ex_decl = current_exception_decl; | |
3304 | tree orig_ex_obj = current_exception_object; | |
3305 | tree decl = cplus_expand_end_try ($1), decls; | |
3306 | ||
3307 | /* Start hidden EXCEPT. */ | |
3308 | cplus_expand_start_except (name, decl); | |
3309 | pushlevel (0); | |
3310 | clear_last_expr (); | |
3311 | push_momentary (); | |
3312 | expand_start_bindings (0); | |
3313 | stmt_decl_msg = 0; | |
3314 | ||
3315 | /* This sets up the reraise. */ | |
3316 | cplus_expand_reraise ($3); | |
3317 | ||
3318 | decls = getdecls (); | |
3319 | expand_end_bindings (decls, decls != 0, 1); | |
3320 | poplevel (decls != 0, 1, 0); | |
3321 | pop_momentary (); | |
3322 | current_exception_type = orig_ex_type; | |
3323 | current_exception_decl = orig_ex_decl; | |
3324 | current_exception_object = orig_ex_obj; | |
3325 | /* This will reraise for us. */ | |
3326 | cplus_expand_end_except (error_mark_node); | |
3327 | if (yychar == YYEMPTY) | |
3328 | yychar = YYLEX; | |
3329 | if (yychar != ';') | |
3330 | error ("missing ';' after reraise statement"); | |
3331 | } | |
3332 | | try %prec EMPTY | |
3333 | { yyerror ("`except' missing after `try' statement"); | |
3334 | /* Terminate the binding contour started by special | |
3335 | code in `.pushlevel'. Automagically pops off | |
3336 | the conditional we started for `try' stmt. */ | |
3337 | cplus_expand_end_try ($1); | |
3338 | expand_end_bindings (0, 0, 1); | |
3339 | poplevel (0, 0, 0); | |
3340 | pop_momentary (); | |
3341 | YYERROR; } | |
3342 | ; | |
3343 | ||
3344 | try: try_head '}' | |
3345 | /* An empty try block is degenerate, but it's better to | |
3346 | do extra work here than to do all the special-case work | |
3347 | everywhere else. */ | |
3348 | { | |
3349 | $$ = 1; | |
3350 | pop_implicit_try_blocks (NULL_TREE); | |
3351 | } | |
3352 | | try_head stmts '}' | |
3353 | { | |
3354 | $$ = 1; | |
3355 | pop_implicit_try_blocks (NULL_TREE); | |
3356 | } | |
3357 | | try_head error '}' | |
3358 | { | |
3359 | $$ = 0; | |
3360 | pop_implicit_try_blocks (NULL_TREE); | |
3361 | } | |
3362 | ; | |
3363 | ||
3364 | label_colon: | |
3365 | IDENTIFIER ':' | |
3366 | { tree label; | |
3367 | do_label: | |
3368 | label = define_label (input_filename, lineno, $1); | |
3369 | if (label) | |
3370 | expand_label (label); | |
3371 | } | |
3372 | | PTYPENAME ':' | |
3373 | { goto do_label; } | |
3374 | | TYPENAME_COLON | |
3375 | { tree label = define_label (input_filename, lineno, $1); | |
3376 | if (label) | |
3377 | expand_label (label); | |
3378 | } | |
3379 | ; | |
3380 | ||
3381 | try_head: TRY '{' { cplus_expand_start_try (0); } .pushlevel | |
3382 | ||
3383 | ansi_try: ansi_try_head '}' | |
3384 | /* An empty try block is degenerate, but it's better to | |
3385 | do extra work here than to do all the special-case work | |
3386 | everywhere else. */ | |
3387 | { | |
3388 | $$ = 1; | |
3389 | pop_implicit_try_blocks (NULL_TREE); | |
3390 | } | |
3391 | | ansi_try_head stmts '}' | |
3392 | { | |
3393 | $$ = 1; | |
3394 | pop_implicit_try_blocks (NULL_TREE); | |
3395 | } | |
3396 | | ansi_try_head error '}' | |
3397 | { | |
3398 | $$ = 0; | |
3399 | pop_implicit_try_blocks (NULL_TREE); | |
3400 | } | |
3401 | ; | |
3402 | ||
3403 | ansi_dummy: ; /* Temporary place-holder. */ | |
3404 | ansi_try_head: ANSI_TRY '{' { cplus_expand_start_try (0); } .pushlevel | |
3405 | ||
3406 | except_stmts: | |
3407 | /* empty */ | |
3408 | { $$ = NULL_TREE; } | |
3409 | | except_stmts raise_identifier | |
3410 | { | |
3411 | tree type = lookup_exception_type (current_class_type, current_class_name, $2); | |
3412 | if (type == NULL_TREE) | |
3413 | { | |
3414 | error ("`%s' is not an exception type", | |
3415 | IDENTIFIER_POINTER (TREE_VALUE ($2))); | |
3416 | current_exception_type = NULL_TREE; | |
3417 | TREE_TYPE (current_exception_object) = error_mark_node; | |
3418 | } | |
3419 | else | |
3420 | { | |
3421 | current_exception_type = type; | |
3422 | /* In-place union. */ | |
3423 | TREE_TYPE (current_exception_object) = type; | |
3424 | } | |
3425 | $2 = cplus_expand_start_catch ($2); | |
3426 | pushlevel (1); | |
3427 | expand_start_bindings (0); | |
3428 | } | |
3429 | compstmt | |
3430 | { | |
3431 | expand_end_bindings (0, 1, 0); | |
3432 | $4 = poplevel (1, 0, 0); | |
3433 | ||
3434 | cplus_expand_end_catch (0); | |
3435 | ||
3436 | /* Mark this as a catch block. */ | |
3437 | TREE_LANG_FLAG_2 ($4) = 1; | |
3438 | if ($2 != error_mark_node) | |
3439 | { | |
3440 | tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME ($2), 0); | |
3441 | DECL_RTL (decl) = DECL_RTL ($2); | |
3442 | TREE_CHAIN (decl) = BLOCK_VARS ($4); | |
3443 | BLOCK_VARS ($4) = decl; | |
3444 | } | |
3445 | } | |
3446 | | except_stmts DEFAULT | |
3447 | { | |
3448 | if ($1) | |
3449 | error ("duplicate default in exception handler"); | |
3450 | current_exception_type = NULL_TREE; | |
3451 | /* Takes it right out of scope. */ | |
3452 | TREE_TYPE (current_exception_object) = error_mark_node; | |
3453 | ||
3454 | if (! expand_catch_default ()) | |
3455 | compiler_error ("default catch botch"); | |
3456 | ||
3457 | /* The default exception is handled as the | |
3458 | last in the chain of exceptions handled. */ | |
3459 | do_pending_stack_adjust (); | |
3460 | start_sequence (); | |
3461 | $1 = make_node (RTL_EXPR); | |
3462 | TREE_TYPE ($1) = void_type_node; | |
3463 | } | |
3464 | compstmt | |
3465 | { | |
3466 | extern struct rtx_def *get_insns (); | |
3467 | do_pending_stack_adjust (); | |
3468 | if (! expand_catch (NULL_TREE)) | |
3469 | compiler_error ("except nesting botch"); | |
3470 | if (! expand_end_catch ()) | |
3471 | compiler_error ("except nesting botch"); | |
3472 | RTL_EXPR_SEQUENCE ($1) = get_insns (); | |
3473 | if ($4) | |
3474 | { | |
3475 | /* Mark this block as the default catch block. */ | |
3476 | TREE_LANG_FLAG_1 ($4) = 1; | |
3477 | TREE_LANG_FLAG_2 ($4) = 1; | |
3478 | } | |
3479 | end_sequence (); | |
3480 | } | |
3481 | ; | |
3482 | ||
3483 | optional_identifier: | |
3484 | /* empty */ | |
3485 | { $$ = NULL_TREE; } | |
3486 | | identifier ; | |
3487 | ||
3488 | ansi_except_stmts: | |
3489 | /* empty */ | |
3490 | { $$ = NULL_TREE; } | |
3491 | | ansi_except_stmts CATCH '(' typename optional_identifier ')' | |
3492 | { | |
3493 | extern tree ansi_expand_start_catch (); | |
3494 | extern tree cplus_exception_name (); | |
3495 | tree type = groktypename ($4); | |
3496 | current_exception_type = type; | |
3497 | /* In-place union. */ | |
3498 | if ($5) | |
3499 | { | |
3500 | tree tmp; | |
3501 | tmp = pushdecl (build_decl (VAR_DECL, $5, type)); | |
3502 | current_exception_object = | |
3503 | build1 (INDIRECT_REF, type, tmp); | |
3504 | } | |
3505 | $4 = ansi_expand_start_catch(type); | |
3506 | pushlevel (1); | |
3507 | expand_start_bindings (0); | |
3508 | } | |
3509 | compstmt | |
3510 | { | |
3511 | expand_end_bindings (0, 1, 0); | |
3512 | $8 = poplevel (1, 0, 0); | |
3513 | ||
3514 | cplus_expand_end_catch (0); | |
3515 | ||
3516 | /* Mark this as a catch block. */ | |
3517 | TREE_LANG_FLAG_2 ($8) = 1; | |
3518 | if ($4 != error_mark_node) | |
3519 | { | |
3520 | tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME ($4), 0); | |
3521 | DECL_RTL (decl) = DECL_RTL ($4); | |
3522 | TREE_CHAIN (decl) = BLOCK_VARS ($8); | |
3523 | BLOCK_VARS ($8) = decl; | |
3524 | } | |
3525 | } | |
3526 | ; | |
3527 | ||
3528 | forhead.1: | |
3529 | FOR '(' ';' | |
3530 | { $$ = NULL_TREE; } | |
3531 | | FOR '(' expr ';' | |
3532 | { $$ = $3; } | |
3533 | | FOR '(' '{' '}' | |
3534 | { $$ = NULL_TREE; } | |
3535 | ; | |
3536 | ||
3537 | forhead.2: | |
3538 | FOR '(' decl | |
3539 | { $$ = 0; } | |
3540 | | FOR '(' error ';' | |
3541 | { $$ = 0; } | |
3542 | | FOR '(' '{' .pushlevel stmts '}' | |
3543 | { $$ = 1; } | |
3544 | | FOR '(' '{' .pushlevel error '}' | |
3545 | { $$ = -1; } | |
3546 | ; | |
3547 | ||
3548 | /* Either a type-qualifier or nothing. First thing in an `asm' statement. */ | |
3549 | ||
3550 | maybe_type_qual: | |
3551 | /* empty */ | |
3552 | { if (pedantic) | |
3553 | pedwarn ("ANSI C++ forbids use of `asm' keyword"); | |
3554 | emit_line_note (input_filename, lineno); } | |
3555 | | TYPE_QUAL | |
3556 | { if (pedantic) | |
3557 | pedwarn ("ANSI C++ forbids use of `asm' keyword"); | |
3558 | emit_line_note (input_filename, lineno); } | |
3559 | ; | |
3560 | ||
3561 | xexpr: | |
3562 | /* empty */ | |
3563 | { $$ = NULL_TREE; } | |
3564 | | expr | |
3565 | | error | |
3566 | { $$ = NULL_TREE; } | |
3567 | ; | |
3568 | ||
3569 | /* These are the operands other than the first string and colon | |
3570 | in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */ | |
3571 | asm_operands: /* empty */ | |
3572 | { $$ = NULL_TREE; } | |
3573 | | nonnull_asm_operands | |
3574 | ; | |
3575 | ||
3576 | nonnull_asm_operands: | |
3577 | asm_operand | |
3578 | | nonnull_asm_operands ',' asm_operand | |
3579 | { $$ = chainon ($$, $3); } | |
3580 | ; | |
3581 | ||
3582 | asm_operand: | |
3583 | STRING '(' expr ')' | |
3584 | { $$ = build_tree_list ($$, $3); } | |
3585 | ; | |
3586 | ||
3587 | asm_clobbers: | |
3588 | STRING | |
3589 | { $$ = tree_cons (NULL_TREE, $$, NULL_TREE); } | |
3590 | | asm_clobbers ',' STRING | |
3591 | { $$ = tree_cons (NULL_TREE, $3, $$); } | |
3592 | ; | |
3593 | ||
3594 | /* This is what appears inside the parens in a function declarator. | |
3595 | Its value is represented in the format that grokdeclarator expects. | |
3596 | ||
3597 | In C++, declaring a function with no parameters | |
3598 | means that that function takes *no* parameters. */ | |
3599 | parmlist: /* empty */ | |
3600 | { | |
3601 | if (strict_prototype) | |
3602 | $$ = void_list_node; | |
3603 | else | |
3604 | $$ = NULL_TREE; | |
3605 | } | |
3606 | | parms | |
3607 | { | |
3608 | $$ = chainon ($$, void_list_node); | |
3609 | TREE_PARMLIST ($$) = 1; | |
3610 | } | |
3611 | | parms ',' ELLIPSIS | |
3612 | { | |
3613 | TREE_PARMLIST ($$) = 1; | |
3614 | } | |
3615 | /* C++ allows an ellipsis without a separating ',' */ | |
3616 | | parms ELLIPSIS | |
3617 | { | |
3618 | TREE_PARMLIST ($$) = 1; | |
3619 | } | |
3620 | | ELLIPSIS | |
3621 | { | |
3622 | /* ARM $8.2.5 has this as a boxed-off comment. */ | |
3623 | if (pedantic) | |
3624 | warning ("use of `...' without a first argument is non-portable"); | |
3625 | $$ = NULL_TREE; | |
3626 | } | |
3627 | | TYPENAME_ELLIPSIS | |
3628 | { | |
3629 | TREE_PARMLIST ($$) = 1; | |
3630 | } | |
3631 | | parms TYPENAME_ELLIPSIS | |
3632 | { | |
3633 | TREE_PARMLIST ($$) = 1; | |
3634 | } | |
3635 | | parms ':' | |
3636 | { | |
3637 | /* This helps us recover from really nasty | |
3638 | parse errors, for example, a missing right | |
3639 | parenthesis. */ | |
3640 | yyerror ("possibly missing ')'"); | |
3641 | $$ = chainon ($$, void_list_node); | |
3642 | TREE_PARMLIST ($$) = 1; | |
3643 | yyungetc (':', 0); | |
3644 | yychar = ')'; | |
3645 | } | |
3646 | ; | |
3647 | ||
3648 | /* A nonempty list of parameter declarations or type names. */ | |
3649 | parms: | |
3650 | parm | |
3651 | { $$ = build_tree_list (NULL_TREE, $$); } | |
3652 | | parm '=' init | |
3653 | { $$ = build_tree_list ($3, $$); } | |
3654 | | parms ',' parm | |
3655 | { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } | |
3656 | | parms ',' parm '=' init | |
3657 | { $$ = chainon ($$, build_tree_list ($5, $3)); } | |
3658 | | parms ',' bad_parm | |
3659 | { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } | |
3660 | | parms ',' bad_parm '=' init | |
3661 | { $$ = chainon ($$, build_tree_list ($5, $3)); } | |
3662 | ; | |
3663 | ||
3664 | /* A single parameter declaration or parameter type name, | |
3665 | as found in a parmlist. The first four cases make up for 10% | |
3666 | of the time spent parsing C++. We cannot use them because | |
3667 | of `int id[]' which won't get parsed properly. */ | |
3668 | parm: | |
3669 | /* | |
3670 | typed_declspecs dont_see_typename '*' IDENTIFIER | |
3671 | { $$ = build_tree_list ($$, build_parse_node (INDIRECT_REF, $4)); | |
3672 | see_typename (); } | |
3673 | | typed_declspecs dont_see_typename '&' IDENTIFIER | |
3674 | { $$ = build_tree_list ($$, build_parse_node (ADDR_EXPR, $4)); | |
3675 | see_typename (); } | |
3676 | | TYPENAME IDENTIFIER | |
3677 | { $$ = build_tree_list (list_hash_lookup_or_cons ($$), $2); } | |
3678 | | TYPESPEC IDENTIFIER | |
3679 | { $$ = build_tree_list (list_hash_lookup_or_cons ($$), $2); } | |
3680 | | */ | |
3681 | typed_declspecs dont_see_typename abs_or_notype_decl | |
3682 | { $$ = build_tree_list ($$, $3); | |
3683 | see_typename (); } | |
3684 | | declmods dont_see_typename abs_or_notype_decl | |
3685 | { $$ = build_tree_list ($$, $3); | |
3686 | see_typename (); } | |
3687 | ; | |
3688 | ||
3689 | abs_or_notype_decl: absdcl | |
3690 | | notype_declarator | |
3691 | | START_DECLARATOR notype_declarator | |
3692 | { $$ = $2; } | |
3693 | ; | |
3694 | ||
3695 | see_typename: type_quals | |
3696 | { see_typename (); } | |
3697 | ; | |
3698 | ||
3699 | dont_see_typename: /* empty */ | |
3700 | { dont_see_typename (); } | |
3701 | ; | |
3702 | ||
3703 | /* | |
3704 | try_for_typename: | |
3705 | { | |
3706 | if ($<ttype>-1 == error_mark_node) | |
3707 | $$ = 0; | |
3708 | else | |
3709 | { | |
3710 | $$ = 1; | |
3711 | pushclass ($<ttype>-1, 1); | |
3712 | } | |
3713 | } | |
3714 | ; | |
3715 | */ | |
3716 | ||
3717 | bad_parm: | |
3718 | abs_or_notype_decl | |
3719 | { | |
3720 | warning ("type specifier omitted for parameter"); | |
3721 | $$ = build_tree_list (TREE_PURPOSE (TREE_VALUE ($<ttype>-1)), $$); | |
3722 | } | |
3723 | ; | |
3724 | ||
3725 | maybe_raises: | |
3726 | /* empty */ | |
3727 | { $$ = NULL_TREE; } | |
3728 | | RAISES raise_identifiers %prec EMPTY | |
3729 | { $$ = $2; } | |
3730 | | ANSI_THROW '(' ansi_raise_identifiers ')' %prec EMPTY | |
3731 | { $$ = $3; } | |
3732 | ; | |
3733 | ||
3734 | raise_identifier: | |
3735 | ALL | |
3736 | { $$ = void_list_node; } | |
3737 | | IDENTIFIER | |
3738 | { $$ = build_decl_list (NULL_TREE, $$); } | |
3739 | | TYPENAME | |
3740 | { $$ = build_decl_list (NULL_TREE, $$); } | |
3741 | | SCOPE IDENTIFIER | |
3742 | { $$ = build_decl_list (void_type_node, $2); } | |
3743 | | SCOPE TYPENAME | |
3744 | { $$ = build_decl_list (void_type_node, $2); } | |
3745 | | scoped_id IDENTIFIER | |
3746 | { $$ = build_decl_list ($$, $2); } | |
3747 | | scoped_typename | |
3748 | ; | |
3749 | ||
3750 | ansi_raise_identifier: | |
3751 | typename | |
3752 | { $$ = build_decl_list (NULL_TREE, $$); } | |
3753 | ; | |
3754 | ||
3755 | raise_identifiers: | |
3756 | raise_identifier | |
3757 | | raise_identifiers ',' raise_identifier | |
3758 | { | |
3759 | TREE_CHAIN ($3) = $$; | |
3760 | $$ = $3; | |
3761 | } | |
3762 | ; | |
3763 | ||
3764 | ansi_raise_identifiers: | |
3765 | ansi_raise_identifier | |
3766 | | ansi_raise_identifiers ',' ansi_raise_identifier | |
3767 | { | |
3768 | TREE_CHAIN ($3) = $$; | |
3769 | $$ = $3; | |
3770 | } | |
3771 | ; | |
3772 | ||
3773 | operator_name: | |
3774 | OPERATOR '*' | |
3775 | { $$ = ansi_opname[MULT_EXPR]; } | |
3776 | | OPERATOR '/' | |
3777 | { $$ = ansi_opname[TRUNC_DIV_EXPR]; } | |
3778 | | OPERATOR '%' | |
3779 | { $$ = ansi_opname[TRUNC_MOD_EXPR]; } | |
3780 | | OPERATOR '+' | |
3781 | { $$ = ansi_opname[PLUS_EXPR]; } | |
3782 | | OPERATOR '-' | |
3783 | { $$ = ansi_opname[MINUS_EXPR]; } | |
3784 | | OPERATOR '&' | |
3785 | { $$ = ansi_opname[BIT_AND_EXPR]; } | |
3786 | | OPERATOR '|' | |
3787 | { $$ = ansi_opname[BIT_IOR_EXPR]; } | |
3788 | | OPERATOR '^' | |
3789 | { $$ = ansi_opname[BIT_XOR_EXPR]; } | |
3790 | | OPERATOR '~' | |
3791 | { $$ = ansi_opname[BIT_NOT_EXPR]; } | |
3792 | | OPERATOR ',' | |
3793 | { $$ = ansi_opname[COMPOUND_EXPR]; } | |
3794 | | OPERATOR ARITHCOMPARE | |
3795 | { $$ = ansi_opname[$2]; } | |
3796 | | OPERATOR '<' | |
3797 | { $$ = ansi_opname[LT_EXPR]; } | |
3798 | | OPERATOR '>' | |
3799 | { $$ = ansi_opname[GT_EXPR]; } | |
3800 | | OPERATOR EQCOMPARE | |
3801 | { $$ = ansi_opname[$2]; } | |
3802 | | OPERATOR ASSIGN | |
3803 | { $$ = ansi_assopname[$2]; } | |
3804 | | OPERATOR '=' | |
3805 | { | |
3806 | $$ = ansi_opname [MODIFY_EXPR]; | |
3807 | if (current_class_type) | |
3808 | { | |
3809 | TYPE_HAS_ASSIGNMENT (current_class_type) = 1; | |
3810 | TYPE_GETS_ASSIGNMENT (current_class_type) = 1; | |
3811 | } | |
3812 | } | |
3813 | | OPERATOR LSHIFT | |
3814 | { $$ = ansi_opname[$2]; } | |
3815 | | OPERATOR RSHIFT | |
3816 | { $$ = ansi_opname[$2]; } | |
3817 | | OPERATOR PLUSPLUS | |
3818 | { $$ = ansi_opname[POSTINCREMENT_EXPR]; } | |
3819 | | OPERATOR MINUSMINUS | |
3820 | { $$ = ansi_opname[PREDECREMENT_EXPR]; } | |
3821 | | OPERATOR ANDAND | |
3822 | { $$ = ansi_opname[TRUTH_ANDIF_EXPR]; } | |
3823 | | OPERATOR OROR | |
3824 | { $$ = ansi_opname[TRUTH_ORIF_EXPR]; } | |
3825 | | OPERATOR '!' | |
3826 | { $$ = ansi_opname[TRUTH_NOT_EXPR]; } | |
3827 | | OPERATOR '?' ':' | |
3828 | { $$ = ansi_opname[COND_EXPR]; } | |
3829 | | OPERATOR MIN_MAX | |
3830 | { $$ = ansi_opname[$2]; } | |
3831 | | OPERATOR POINTSAT %prec EMPTY | |
3832 | { $$ = ansi_opname[COMPONENT_REF]; | |
3833 | if (current_class_type) | |
3834 | { | |
3835 | tree t = current_class_type; | |
3836 | while (t) | |
3837 | { | |
3838 | TYPE_OVERLOADS_ARROW (t) = 1; | |
3839 | t = TYPE_NEXT_VARIANT (t); | |
3840 | } | |
3841 | } | |
3842 | } | |
3843 | | OPERATOR POINTSAT_STAR %prec EMPTY | |
3844 | { $$ = ansi_opname[MEMBER_REF]; | |
3845 | if (current_class_type) | |
3846 | { | |
3847 | tree t = current_class_type; | |
3848 | while (t) | |
3849 | { | |
3850 | TYPE_OVERLOADS_ARROW (t) = 1; | |
3851 | t = TYPE_NEXT_VARIANT (t); | |
3852 | } | |
3853 | } | |
3854 | } | |
3855 | | OPERATOR POINTSAT_LEFT_RIGHT type_quals %prec '.' | |
3856 | { | |
3857 | if (yychar == YYEMPTY) | |
3858 | yychar = YYLEX; | |
3859 | if (yychar == '(' || yychar == LEFT_RIGHT) | |
3860 | { | |
3861 | $$ = ansi_opname[METHOD_CALL_EXPR]; | |
3862 | if (current_class_type) | |
3863 | { | |
3864 | tree t = current_class_type; | |
3865 | while (t) | |
3866 | { | |
3867 | TYPE_OVERLOADS_METHOD_CALL_EXPR (t) = 1; | |
3868 | t = TYPE_NEXT_VARIANT (t); | |
3869 | } | |
3870 | } | |
3871 | } | |
3872 | else | |
3873 | { | |
3874 | $$ = build_parse_node (CALL_EXPR, ansi_opname[COMPONENT_REF], void_list_node, $3); | |
3875 | if (current_class_type) | |
3876 | { | |
3877 | tree t = current_class_type; | |
3878 | while (t) | |
3879 | { | |
3880 | TYPE_OVERLOADS_ARROW (t) = 1; | |
3881 | t = TYPE_NEXT_VARIANT (t); | |
3882 | } | |
3883 | } | |
3884 | } | |
3885 | } | |
3886 | | OPERATOR LEFT_RIGHT | |
3887 | { $$ = ansi_opname[CALL_EXPR]; | |
3888 | if (current_class_type) | |
3889 | { | |
3890 | tree t = current_class_type; | |
3891 | while (t) | |
3892 | { | |
3893 | TYPE_OVERLOADS_CALL_EXPR (t) = 1; | |
3894 | t = TYPE_NEXT_VARIANT (t); | |
3895 | } | |
3896 | } | |
3897 | } | |
3898 | | OPERATOR '[' ']' | |
3899 | { $$ = ansi_opname[ARRAY_REF]; | |
3900 | if (current_class_type) | |
3901 | { | |
3902 | tree t = current_class_type; | |
3903 | while (t) | |
3904 | { | |
3905 | TYPE_OVERLOADS_ARRAY_REF (t) = 1; | |
3906 | t = TYPE_NEXT_VARIANT (t); | |
3907 | } | |
3908 | } | |
3909 | } | |
3910 | | OPERATOR NEW | |
3911 | { | |
3912 | $$ = ansi_opname[NEW_EXPR]; | |
3913 | if (current_class_type) | |
3914 | { | |
3915 | tree t = current_class_type; | |
3916 | while (t) | |
3917 | { | |
3918 | TREE_GETS_NEW (t) = 1; | |
3919 | t = TYPE_NEXT_VARIANT (t); | |
3920 | } | |
3921 | } | |
3922 | } | |
3923 | | OPERATOR DELETE | |
3924 | { | |
3925 | $$ = ansi_opname[DELETE_EXPR]; | |
3926 | if (current_class_type) | |
3927 | { | |
3928 | tree t = current_class_type; | |
3929 | while (t) | |
3930 | { | |
3931 | TREE_GETS_DELETE (t) = 1; | |
3932 | t = TYPE_NEXT_VARIANT (t); | |
3933 | } | |
3934 | } | |
3935 | } | |
3936 | ||
3937 | /* These should do `groktypename' and set up TREE_HAS_X_CONVERSION | |
3938 | here, rather than doing it in class.c . */ | |
3939 | | OPERATOR typed_typespecs absdcl | |
3940 | { $$ = build1 (TYPE_EXPR, $2, $3); } | |
3941 | | OPERATOR error | |
3942 | { $$ = ansi_opname[ERROR_MARK]; } | |
3943 | ; | |
3944 | ||
3945 | %% | |
3946 | ||
3947 | tree | |
3948 | get_current_declspecs () | |
3949 | { | |
3950 | return current_declspecs; | |
3951 | } |