1 | /* -*- C++ -*- Parser. |
2 | Copyright (C) 2000-2024 Free Software Foundation, Inc. |
3 | Written by Mark Mitchell <mark@codesourcery.com>. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3, or (at your option) |
10 | any later version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include "config.h" |
22 | #define INCLUDE_MEMORY |
23 | #include "system.h" |
24 | #include "coretypes.h" |
25 | #include "cp-tree.h" |
26 | #include "c-family/c-common.h" |
27 | #include "timevar.h" |
28 | #include "stringpool.h" |
29 | #include "cgraph.h" |
30 | #include "print-tree.h" |
31 | #include "attribs.h" |
32 | #include "trans-mem.h" |
33 | #include "intl.h" |
34 | #include "decl.h" |
35 | #include "c-family/c-objc.h" |
36 | #include "plugin.h" |
37 | #include "tree-pretty-print.h" |
38 | #include "parser.h" |
39 | #include "gomp-constants.h" |
40 | #include "omp-general.h" |
41 | #include "omp-offload.h" |
42 | #include "c-family/c-indentation.h" |
43 | #include "context.h" |
44 | #include "gcc-rich-location.h" |
45 | #include "tree-iterator.h" |
46 | #include "cp-name-hint.h" |
47 | #include "memmodel.h" |
48 | #include "c-family/known-headers.h" |
49 | #include "contracts.h" |
50 | #include "bitmap.h" |
51 | #include "builtins.h" |
52 | |
53 | |
54 | /* The lexer. */ |
55 | |
56 | /* The cp_lexer_* routines mediate between the lexer proper (in libcpp |
57 | and c-lex.cc) and the C++ parser. */ |
58 | |
59 | /* The various kinds of non integral constant we encounter. */ |
60 | enum non_integral_constant { |
61 | NIC_NONE, |
62 | /* floating-point literal */ |
63 | NIC_FLOAT, |
64 | /* %<this%> */ |
65 | NIC_THIS, |
66 | /* %<__FUNCTION__%> */ |
67 | NIC_FUNC_NAME, |
68 | /* %<__PRETTY_FUNCTION__%> */ |
69 | NIC_PRETTY_FUNC, |
70 | /* %<__func__%> */ |
71 | NIC_C99_FUNC, |
72 | /* "%<va_arg%> */ |
73 | NIC_VA_ARG, |
74 | /* a cast */ |
75 | NIC_CAST, |
76 | /* %<typeid%> operator */ |
77 | NIC_TYPEID, |
78 | /* non-constant compound literals */ |
79 | NIC_NCC, |
80 | /* a function call */ |
81 | NIC_FUNC_CALL, |
82 | /* an increment */ |
83 | NIC_INC, |
84 | /* an decrement */ |
85 | NIC_DEC, |
86 | /* an array reference */ |
87 | NIC_ARRAY_REF, |
88 | /* %<->%> */ |
89 | NIC_ARROW, |
90 | /* %<.%> */ |
91 | NIC_POINT, |
92 | /* the address of a label */ |
93 | NIC_ADDR_LABEL, |
94 | /* %<*%> */ |
95 | NIC_STAR, |
96 | /* %<&%> */ |
97 | NIC_ADDR, |
98 | /* %<++%> */ |
99 | NIC_PREINCREMENT, |
100 | /* %<--%> */ |
101 | NIC_PREDECREMENT, |
102 | /* %<new%> */ |
103 | NIC_NEW, |
104 | /* %<delete%> */ |
105 | NIC_DEL, |
106 | /* calls to overloaded operators */ |
107 | NIC_OVERLOADED, |
108 | /* an assignment */ |
109 | NIC_ASSIGNMENT, |
110 | /* a comma operator */ |
111 | NIC_COMMA, |
112 | /* a call to a constructor */ |
113 | NIC_CONSTRUCTOR, |
114 | /* a transaction expression */ |
115 | NIC_TRANSACTION |
116 | }; |
117 | |
118 | /* The various kinds of errors about name-lookup failing. */ |
119 | enum name_lookup_error { |
120 | /* NULL */ |
121 | NLE_NULL, |
122 | /* is not a type */ |
123 | NLE_TYPE, |
124 | /* is not a class or namespace */ |
125 | NLE_CXX98, |
126 | /* is not a class, namespace, or enumeration */ |
127 | NLE_NOT_CXX98 |
128 | }; |
129 | |
130 | /* The various kinds of required token */ |
131 | enum required_token { |
132 | RT_NONE, |
133 | RT_SEMICOLON, /* ';' */ |
134 | RT_OPEN_PAREN, /* '(' */ |
135 | RT_CLOSE_BRACE, /* '}' */ |
136 | RT_OPEN_BRACE, /* '{' */ |
137 | RT_CLOSE_SQUARE, /* ']' */ |
138 | RT_OPEN_SQUARE, /* '[' */ |
139 | RT_COMMA, /* ',' */ |
140 | RT_SCOPE, /* '::' */ |
141 | RT_LESS, /* '<' */ |
142 | RT_GREATER, /* '>' */ |
143 | RT_EQ, /* '=' */ |
144 | RT_ELLIPSIS, /* '...' */ |
145 | RT_MULT, /* '*' */ |
146 | RT_COMPL, /* '~' */ |
147 | RT_COLON, /* ':' */ |
148 | RT_COLON_SCOPE, /* ':' or '::' */ |
149 | RT_CLOSE_PAREN, /* ')' */ |
150 | RT_COMMA_CLOSE_PAREN, /* ',' or ')' */ |
151 | RT_PRAGMA_EOL, /* end of line */ |
152 | RT_NAME, /* identifier */ |
153 | |
154 | /* The type is CPP_KEYWORD */ |
155 | RT_NEW, /* new */ |
156 | RT_DELETE, /* delete */ |
157 | RT_RETURN, /* return */ |
158 | RT_WHILE, /* while */ |
159 | RT_EXTERN, /* extern */ |
160 | RT_STATIC_ASSERT, /* static_assert */ |
161 | RT_DECLTYPE, /* decltype */ |
162 | RT_OPERATOR, /* operator */ |
163 | RT_CLASS, /* class */ |
164 | RT_TEMPLATE, /* template */ |
165 | RT_NAMESPACE, /* namespace */ |
166 | RT_USING, /* using */ |
167 | RT_ASM, /* asm */ |
168 | RT_TRY, /* try */ |
169 | RT_CATCH, /* catch */ |
170 | RT_THROW, /* throw */ |
171 | RT_AUTO, /* auto */ |
172 | RT_LABEL, /* __label__ */ |
173 | RT_AT_TRY, /* @try */ |
174 | RT_AT_SYNCHRONIZED, /* @synchronized */ |
175 | RT_AT_THROW, /* @throw */ |
176 | |
177 | RT_SELECT, /* selection-statement */ |
178 | RT_ITERATION, /* iteration-statement */ |
179 | RT_JUMP, /* jump-statement */ |
180 | RT_CLASS_KEY, /* class-key */ |
181 | RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */ |
182 | RT_TRANSACTION_ATOMIC, /* __transaction_atomic */ |
183 | RT_TRANSACTION_RELAXED, /* __transaction_relaxed */ |
184 | RT_TRANSACTION_CANCEL, /* __transaction_cancel */ |
185 | |
186 | RT_CO_YIELD /* co_yield */ |
187 | }; |
188 | |
189 | /* RAII wrapper for parser->in_type_id_in_expr_p, setting it on creation and |
190 | reverting it on destruction. */ |
191 | |
192 | class type_id_in_expr_sentinel |
193 | { |
194 | cp_parser *parser; |
195 | bool saved; |
196 | public: |
197 | type_id_in_expr_sentinel (cp_parser *parser, bool set = true) |
198 | : parser (parser), |
199 | saved (parser->in_type_id_in_expr_p) |
200 | { parser->in_type_id_in_expr_p = set; } |
201 | ~type_id_in_expr_sentinel () |
202 | { parser->in_type_id_in_expr_p = saved; } |
203 | }; |
204 | |
205 | /* Prototypes. */ |
206 | |
207 | static cp_lexer *cp_lexer_new_main |
208 | (void); |
209 | static cp_lexer *cp_lexer_new_from_tokens |
210 | (cp_token_cache *tokens); |
211 | static void cp_lexer_destroy |
212 | (cp_lexer *); |
213 | static int cp_lexer_saving_tokens |
214 | (const cp_lexer *); |
215 | static cp_token *cp_lexer_token_at |
216 | (cp_lexer *, cp_token_position); |
217 | static void cp_lexer_get_preprocessor_token |
218 | (unsigned, cp_token *); |
219 | static inline cp_token *cp_lexer_peek_token |
220 | (cp_lexer *); |
221 | static cp_token *cp_lexer_peek_nth_token |
222 | (cp_lexer *, size_t); |
223 | static inline bool cp_lexer_next_token_is |
224 | (cp_lexer *, enum cpp_ttype); |
225 | static bool cp_lexer_next_token_is_not |
226 | (cp_lexer *, enum cpp_ttype); |
227 | static bool cp_lexer_next_token_is_keyword |
228 | (cp_lexer *, enum rid); |
229 | static cp_token *cp_lexer_consume_token |
230 | (cp_lexer *); |
231 | static void cp_lexer_purge_token |
232 | (cp_lexer *); |
233 | static void cp_lexer_purge_tokens_after |
234 | (cp_lexer *, cp_token_position); |
235 | static void cp_lexer_save_tokens |
236 | (cp_lexer *); |
237 | static void cp_lexer_commit_tokens |
238 | (cp_lexer *); |
239 | static void cp_lexer_rollback_tokens |
240 | (cp_lexer *); |
241 | static void cp_lexer_print_token |
242 | (FILE *, cp_token *); |
243 | static inline bool cp_lexer_debugging_p |
244 | (cp_lexer *); |
245 | static void cp_lexer_start_debugging |
246 | (cp_lexer *) ATTRIBUTE_UNUSED; |
247 | static void cp_lexer_stop_debugging |
248 | (cp_lexer *) ATTRIBUTE_UNUSED; |
249 | static const cp_trait *cp_lexer_peek_trait |
250 | (cp_lexer *); |
251 | static const cp_trait *cp_lexer_peek_trait_expr |
252 | (cp_lexer *); |
253 | static const cp_trait *cp_lexer_peek_trait_type |
254 | (cp_lexer *); |
255 | |
256 | static cp_token_cache *cp_token_cache_new |
257 | (cp_token *, cp_token *); |
258 | static tree cp_parser_late_noexcept_specifier |
259 | (cp_parser *, tree); |
260 | static void noexcept_override_late_checks |
261 | (tree); |
262 | |
263 | static void cp_parser_initial_pragma |
264 | (cp_token *); |
265 | |
266 | static bool cp_parser_omp_declare_reduction_exprs |
267 | (tree, cp_parser *); |
268 | static void cp_finalize_oacc_routine |
269 | (cp_parser *, tree, bool); |
270 | |
271 | static void check_omp_intervening_code |
272 | (cp_parser *); |
273 | |
274 | |
275 | /* Manifest constants. */ |
276 | #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) |
277 | #define CP_SAVED_TOKEN_STACK 5 |
278 | |
279 | /* Variables. */ |
280 | |
281 | /* The stream to which debugging output should be written. */ |
282 | static FILE *cp_lexer_debug_stream; |
283 | |
284 | /* Nonzero if we are parsing an unevaluated operand: an operand to |
285 | sizeof, typeof, or alignof. */ |
286 | int cp_unevaluated_operand; |
287 | |
288 | /* Dump up to NUM tokens in BUFFER to FILE starting with token |
289 | START_TOKEN. If START_TOKEN is NULL, the dump starts with the |
290 | first token in BUFFER. If NUM is 0, dump all the tokens. If |
291 | CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be |
292 | highlighted by surrounding it in [[ ]]. */ |
293 | |
294 | static void |
295 | cp_lexer_dump_tokens (FILE *file, vec<cp_token, va_gc> *buffer, |
296 | cp_token *start_token, unsigned num, |
297 | cp_token *curr_token) |
298 | { |
299 | unsigned i, nprinted; |
300 | cp_token *token; |
301 | bool do_print; |
302 | |
303 | fprintf (stream: file, format: "%u tokens\n" , vec_safe_length (v: buffer)); |
304 | |
305 | if (buffer == NULL) |
306 | return; |
307 | |
308 | if (num == 0) |
309 | num = buffer->length (); |
310 | |
311 | if (start_token == NULL) |
312 | start_token = buffer->address (); |
313 | |
314 | if (start_token > buffer->address ()) |
315 | { |
316 | cp_lexer_print_token (file, &(*buffer)[0]); |
317 | fprintf (stream: file, format: " ... " ); |
318 | } |
319 | |
320 | do_print = false; |
321 | nprinted = 0; |
322 | for (i = 0; buffer->iterate (ix: i, ptr: &token) && nprinted < num; i++) |
323 | { |
324 | if (token == start_token) |
325 | do_print = true; |
326 | |
327 | if (!do_print) |
328 | continue; |
329 | |
330 | nprinted++; |
331 | if (token == curr_token) |
332 | fprintf (stream: file, format: "[[" ); |
333 | |
334 | cp_lexer_print_token (file, token); |
335 | |
336 | if (token == curr_token) |
337 | fprintf (stream: file, format: "]]" ); |
338 | |
339 | switch (token->type) |
340 | { |
341 | case CPP_SEMICOLON: |
342 | case CPP_OPEN_BRACE: |
343 | case CPP_CLOSE_BRACE: |
344 | case CPP_EOF: |
345 | fputc (c: '\n', stream: file); |
346 | break; |
347 | |
348 | default: |
349 | fputc (c: ' ', stream: file); |
350 | } |
351 | } |
352 | |
353 | if (i == num && i < buffer->length ()) |
354 | { |
355 | fprintf (stream: file, format: " ... " ); |
356 | cp_lexer_print_token (file, &buffer->last ()); |
357 | } |
358 | |
359 | fprintf (stream: file, format: "\n" ); |
360 | } |
361 | |
362 | |
363 | /* Dump all tokens in BUFFER to stderr. */ |
364 | |
365 | void |
366 | cp_lexer_debug_tokens (vec<cp_token, va_gc> *buffer) |
367 | { |
368 | cp_lexer_dump_tokens (stderr, buffer, NULL, num: 0, NULL); |
369 | } |
370 | |
371 | DEBUG_FUNCTION void |
372 | debug (vec<cp_token, va_gc> &ref) |
373 | { |
374 | cp_lexer_dump_tokens (stderr, buffer: &ref, NULL, num: 0, NULL); |
375 | } |
376 | |
377 | DEBUG_FUNCTION void |
378 | debug (vec<cp_token, va_gc> *ptr) |
379 | { |
380 | if (ptr) |
381 | debug (ref&: *ptr); |
382 | else |
383 | fprintf (stderr, format: "<nil>\n" ); |
384 | } |
385 | |
386 | |
387 | /* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the |
388 | description for T. */ |
389 | |
390 | static void |
391 | cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t) |
392 | { |
393 | if (t) |
394 | { |
395 | fprintf (stream: file, format: "%s: " , desc); |
396 | print_node_brief (file, "" , t, 0); |
397 | } |
398 | } |
399 | |
400 | |
401 | /* Dump parser context C to FILE. */ |
402 | |
403 | static void |
404 | cp_debug_print_context (FILE *file, cp_parser_context *c) |
405 | { |
406 | const char *status_s[] = { "OK" , "ERROR" , "COMMITTED" }; |
407 | fprintf (stream: file, format: "{ status = %s, scope = " , status_s[c->status]); |
408 | print_node_brief (file, "" , c->object_type, 0); |
409 | fprintf (stream: file, format: "}\n" ); |
410 | } |
411 | |
412 | |
413 | /* Print the stack of parsing contexts to FILE starting with FIRST. */ |
414 | |
415 | static void |
416 | cp_debug_print_context_stack (FILE *file, cp_parser_context *first) |
417 | { |
418 | unsigned i; |
419 | cp_parser_context *c; |
420 | |
421 | fprintf (stream: file, format: "Parsing context stack:\n" ); |
422 | for (i = 0, c = first; c; c = c->next, i++) |
423 | { |
424 | fprintf (stream: file, format: "\t#%u: " , i); |
425 | cp_debug_print_context (file, c); |
426 | } |
427 | } |
428 | |
429 | |
430 | /* Print the value of FLAG to FILE. DESC is a string describing the flag. */ |
431 | |
432 | static void |
433 | cp_debug_print_flag (FILE *file, const char *desc, bool flag) |
434 | { |
435 | if (flag) |
436 | fprintf (stream: file, format: "%s: true\n" , desc); |
437 | } |
438 | |
439 | |
440 | /* Print an unparsed function entry UF to FILE. */ |
441 | |
442 | static void |
443 | cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf) |
444 | { |
445 | unsigned i; |
446 | cp_default_arg_entry *default_arg_fn; |
447 | tree fn; |
448 | |
449 | fprintf (stream: file, format: "\tFunctions with default args:\n" ); |
450 | for (i = 0; |
451 | vec_safe_iterate (v: uf->funs_with_default_args, ix: i, ptr: &default_arg_fn); |
452 | i++) |
453 | { |
454 | fprintf (stream: file, format: "\t\tClass type: " ); |
455 | print_node_brief (file, "" , default_arg_fn->class_type, 0); |
456 | fprintf (stream: file, format: "\t\tDeclaration: " ); |
457 | print_node_brief (file, "" , default_arg_fn->decl, 0); |
458 | fprintf (stream: file, format: "\n" ); |
459 | } |
460 | |
461 | fprintf (stream: file, format: "\n\tFunctions with definitions that require " |
462 | "post-processing\n\t\t" ); |
463 | for (i = 0; vec_safe_iterate (v: uf->funs_with_definitions, ix: i, ptr: &fn); i++) |
464 | { |
465 | print_node_brief (file, "" , fn, 0); |
466 | fprintf (stream: file, format: " " ); |
467 | } |
468 | fprintf (stream: file, format: "\n" ); |
469 | |
470 | fprintf (stream: file, format: "\n\tNon-static data members with initializers that require " |
471 | "post-processing\n\t\t" ); |
472 | for (i = 0; vec_safe_iterate (v: uf->nsdmis, ix: i, ptr: &fn); i++) |
473 | { |
474 | print_node_brief (file, "" , fn, 0); |
475 | fprintf (stream: file, format: " " ); |
476 | } |
477 | fprintf (stream: file, format: "\n" ); |
478 | } |
479 | |
480 | |
481 | /* Print the stack of unparsed member functions S to FILE. */ |
482 | |
483 | static void |
484 | cp_debug_print_unparsed_queues (FILE *file, |
485 | vec<cp_unparsed_functions_entry, va_gc> *s) |
486 | { |
487 | unsigned i; |
488 | cp_unparsed_functions_entry *uf; |
489 | |
490 | fprintf (stream: file, format: "Unparsed functions\n" ); |
491 | for (i = 0; vec_safe_iterate (v: s, ix: i, ptr: &uf); i++) |
492 | { |
493 | fprintf (stream: file, format: "#%u:\n" , i); |
494 | cp_debug_print_unparsed_function (file, uf); |
495 | } |
496 | } |
497 | |
498 | |
499 | /* Dump the tokens in a window of size WINDOW_SIZE around the next_token for |
500 | the given PARSER. If FILE is NULL, the output is printed on stderr. */ |
501 | |
502 | static void |
503 | cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size) |
504 | { |
505 | cp_token *next_token, *first_token, *start_token; |
506 | |
507 | if (file == NULL) |
508 | file = stderr; |
509 | |
510 | next_token = parser->lexer->next_token; |
511 | first_token = parser->lexer->buffer->address (); |
512 | start_token = (next_token > first_token + window_size / 2) |
513 | ? next_token - window_size / 2 |
514 | : first_token; |
515 | cp_lexer_dump_tokens (file, buffer: parser->lexer->buffer, start_token, num: window_size, |
516 | curr_token: next_token); |
517 | } |
518 | |
519 | |
520 | /* Dump debugging information for the given PARSER. If FILE is NULL, |
521 | the output is printed on stderr. */ |
522 | |
523 | void |
524 | cp_debug_parser (FILE *file, cp_parser *parser) |
525 | { |
526 | const size_t window_size = 20; |
527 | cp_token *token; |
528 | expanded_location eloc; |
529 | |
530 | if (file == NULL) |
531 | file = stderr; |
532 | |
533 | fprintf (stream: file, format: "Parser state\n\n" ); |
534 | fprintf (stream: file, format: "Number of tokens: %u\n" , |
535 | vec_safe_length (v: parser->lexer->buffer)); |
536 | cp_debug_print_tree_if_set (file, desc: "Lookup scope" , t: parser->scope); |
537 | cp_debug_print_tree_if_set (file, desc: "Object scope" , |
538 | t: parser->object_scope); |
539 | cp_debug_print_tree_if_set (file, desc: "Qualifying scope" , |
540 | t: parser->qualifying_scope); |
541 | cp_debug_print_context_stack (file, first: parser->context); |
542 | cp_debug_print_flag (file, desc: "Allow GNU extensions" , |
543 | flag: parser->allow_gnu_extensions_p); |
544 | cp_debug_print_flag (file, desc: "'>' token is greater-than" , |
545 | flag: parser->greater_than_is_operator_p); |
546 | cp_debug_print_flag (file, desc: "Default args allowed in current " |
547 | "parameter list" , flag: parser->default_arg_ok_p); |
548 | cp_debug_print_flag (file, desc: "Parsing integral constant-expression" , |
549 | flag: parser->integral_constant_expression_p); |
550 | cp_debug_print_flag (file, desc: "Allow non-constant expression in current " |
551 | "constant-expression" , |
552 | flag: parser->allow_non_integral_constant_expression_p); |
553 | cp_debug_print_flag (file, desc: "Seen non-constant expression" , |
554 | flag: parser->non_integral_constant_expression_p); |
555 | cp_debug_print_flag (file, desc: "Local names forbidden in current context" , |
556 | flag: (parser->local_variables_forbidden_p |
557 | & LOCAL_VARS_FORBIDDEN)); |
558 | cp_debug_print_flag (file, desc: "'this' forbidden in current context" , |
559 | flag: (parser->local_variables_forbidden_p |
560 | & THIS_FORBIDDEN)); |
561 | cp_debug_print_flag (file, desc: "In unbraced linkage specification" , |
562 | flag: parser->in_unbraced_linkage_specification_p); |
563 | cp_debug_print_flag (file, desc: "Parsing a declarator" , |
564 | flag: parser->in_declarator_p); |
565 | cp_debug_print_flag (file, desc: "In template argument list" , |
566 | flag: parser->in_template_argument_list_p); |
567 | cp_debug_print_flag (file, desc: "Parsing an iteration statement" , |
568 | flag: parser->in_statement & IN_ITERATION_STMT); |
569 | cp_debug_print_flag (file, desc: "Parsing a switch statement" , |
570 | flag: parser->in_statement & IN_SWITCH_STMT); |
571 | cp_debug_print_flag (file, desc: "Parsing a structured OpenMP block" , |
572 | flag: parser->in_statement & IN_OMP_BLOCK); |
573 | cp_debug_print_flag (file, desc: "Parsing an OpenMP loop" , |
574 | flag: parser->in_statement & IN_OMP_FOR); |
575 | cp_debug_print_flag (file, desc: "Parsing an if statement" , |
576 | flag: parser->in_statement & IN_IF_STMT); |
577 | cp_debug_print_flag (file, desc: "Parsing a type-id in an expression " |
578 | "context" , flag: parser->in_type_id_in_expr_p); |
579 | cp_debug_print_flag (file, desc: "String expressions should be translated " |
580 | "to execution character set" , |
581 | flag: parser->translate_strings_p); |
582 | cp_debug_print_flag (file, desc: "Parsing function body outside of a " |
583 | "local class" , flag: parser->in_function_body); |
584 | cp_debug_print_flag (file, desc: "Auto correct a colon to a scope operator" , |
585 | flag: parser->colon_corrects_to_scope_p); |
586 | cp_debug_print_flag (file, desc: "Colon doesn't start a class definition" , |
587 | flag: parser->colon_doesnt_start_class_def_p); |
588 | cp_debug_print_flag (file, desc: "Parsing an Objective-C++ message context" , |
589 | flag: parser->objective_c_message_context_p); |
590 | if (parser->type_definition_forbidden_message) |
591 | fprintf (stream: file, format: "Error message for forbidden type definitions: %s %s\n" , |
592 | parser->type_definition_forbidden_message, |
593 | parser->type_definition_forbidden_message_arg |
594 | ? parser->type_definition_forbidden_message_arg : "<none>" ); |
595 | cp_debug_print_unparsed_queues (file, s: parser->unparsed_queues); |
596 | fprintf (stream: file, format: "Number of class definitions in progress: %u\n" , |
597 | parser->num_classes_being_defined); |
598 | fprintf (stream: file, format: "Number of template parameter lists for the current " |
599 | "declaration: %u\n" , parser->num_template_parameter_lists); |
600 | cp_debug_parser_tokens (file, parser, window_size); |
601 | token = parser->lexer->next_token; |
602 | fprintf (stream: file, format: "Next token to parse:\n" ); |
603 | fprintf (stream: file, format: "\tToken: " ); |
604 | cp_lexer_print_token (file, token); |
605 | eloc = expand_location (token->location); |
606 | fprintf (stream: file, format: "\n\tFile: %s\n" , eloc.file); |
607 | fprintf (stream: file, format: "\tLine: %d\n" , eloc.line); |
608 | fprintf (stream: file, format: "\tColumn: %d\n" , eloc.column); |
609 | } |
610 | |
611 | DEBUG_FUNCTION void |
612 | debug (cp_parser &ref) |
613 | { |
614 | cp_debug_parser (stderr, parser: &ref); |
615 | } |
616 | |
617 | DEBUG_FUNCTION void |
618 | debug (cp_parser *ptr) |
619 | { |
620 | if (ptr) |
621 | debug (ref&: *ptr); |
622 | else |
623 | fprintf (stderr, format: "<nil>\n" ); |
624 | } |
625 | |
626 | /* Allocate memory for a new lexer object and return it. */ |
627 | |
628 | static cp_lexer * |
629 | cp_lexer_alloc (void) |
630 | { |
631 | /* Allocate the memory. */ |
632 | cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> (); |
633 | |
634 | /* Initially we are not debugging. */ |
635 | lexer->debugging_p = false; |
636 | |
637 | lexer->saved_tokens.create (CP_SAVED_TOKEN_STACK); |
638 | |
639 | /* Create the buffer. */ |
640 | vec_alloc (v&: lexer->buffer, CP_LEXER_BUFFER_SIZE); |
641 | |
642 | return lexer; |
643 | } |
644 | |
645 | /* Return TRUE if token is the start of a module declaration that will be |
646 | terminated by a CPP_PRAGMA_EOL token. */ |
647 | static inline bool |
648 | cp_token_is_module_directive (cp_token *token) |
649 | { |
650 | return token->keyword == RID__EXPORT |
651 | || token->keyword == RID__MODULE |
652 | || token->keyword == RID__IMPORT; |
653 | } |
654 | |
655 | /* Return TOKEN's pragma_kind if it is CPP_PRAGMA, otherwise |
656 | PRAGMA_NONE. */ |
657 | |
658 | static enum pragma_kind |
659 | cp_parser_pragma_kind (cp_token *token) |
660 | { |
661 | if (token->type != CPP_PRAGMA) |
662 | return PRAGMA_NONE; |
663 | /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ |
664 | return (enum pragma_kind) TREE_INT_CST_LOW (token->u.value); |
665 | } |
666 | |
667 | /* Handle early pragmas such as #pragma GCC diagnostic, which needs to be done |
668 | during preprocessing for the case of preprocessing-related diagnostics. This |
669 | is called immediately after pushing the CPP_PRAGMA_EOL token onto |
670 | lexer->buffer. */ |
671 | |
672 | static void |
673 | cp_lexer_handle_early_pragma (cp_lexer *lexer) |
674 | { |
675 | const auto first_token = lexer->buffer->address (); |
676 | const auto last_token = first_token + lexer->buffer->length () - 1; |
677 | |
678 | /* Back up to the start of the pragma so pragma_lex () can parse it when |
679 | c-pragma lib asks it to. */ |
680 | auto begin = last_token; |
681 | gcc_assert (begin->type == CPP_PRAGMA_EOL); |
682 | while (begin->type != CPP_PRAGMA) |
683 | { |
684 | if (cp_token_is_module_directive (token: begin)) |
685 | return; |
686 | gcc_assert (begin != first_token); |
687 | --begin; |
688 | } |
689 | gcc_assert (!lexer->next_token); |
690 | gcc_assert (!lexer->last_token); |
691 | lexer->next_token = begin; |
692 | lexer->last_token = last_token; |
693 | |
694 | /* Dispatch it. */ |
695 | const unsigned int id |
696 | = cp_parser_pragma_kind (token: cp_lexer_consume_token (lexer)); |
697 | if (id >= PRAGMA_FIRST_EXTERNAL) |
698 | c_invoke_early_pragma_handler (id); |
699 | |
700 | /* Reset to normal state. */ |
701 | lexer->next_token = lexer->last_token = nullptr; |
702 | } |
703 | |
704 | /* The parser. */ |
705 | static cp_parser *cp_parser_new (cp_lexer *); |
706 | static GTY (()) cp_parser *the_parser; |
707 | |
708 | /* Create a new main C++ lexer, the lexer that gets tokens from the |
709 | preprocessor, and also create the main parser. */ |
710 | |
711 | static cp_lexer * |
712 | cp_lexer_new_main (void) |
713 | { |
714 | cp_token token; |
715 | |
716 | /* It's possible that parsing the first pragma will load a PCH file, |
717 | which is a GC collection point. So we have to do that before |
718 | allocating any memory. */ |
719 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, &token); |
720 | cp_parser_initial_pragma (&token); |
721 | c_common_no_more_pch (); |
722 | |
723 | cp_lexer *lexer = cp_lexer_alloc (); |
724 | /* Put the first token in the buffer. */ |
725 | cp_token *tok = lexer->buffer->quick_push (obj: token); |
726 | |
727 | uintptr_t filter = 0; |
728 | if (modules_p ()) |
729 | filter = module_token_cdtor (parse_in, filter); |
730 | |
731 | /* Create the parser now, so we can use it to handle early pragmas. */ |
732 | gcc_assert (!the_parser); |
733 | the_parser = cp_parser_new (lexer); |
734 | |
735 | /* Get the remaining tokens from the preprocessor. */ |
736 | while (tok->type != CPP_EOF) |
737 | { |
738 | if (filter) |
739 | /* Process the previous token. */ |
740 | module_token_lang (type: tok->type, keyword: tok->keyword, value: tok->u.value, |
741 | tok->location, filter); |
742 | |
743 | /* Check for early pragmas that need to be handled now. */ |
744 | if (tok->type == CPP_PRAGMA_EOL) |
745 | cp_lexer_handle_early_pragma (lexer); |
746 | |
747 | tok = vec_safe_push (v&: lexer->buffer, obj: cp_token ()); |
748 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, tok); |
749 | } |
750 | |
751 | lexer->next_token = lexer->buffer->address (); |
752 | lexer->last_token = lexer->next_token |
753 | + lexer->buffer->length () |
754 | - 1; |
755 | |
756 | if (lexer->buffer->length () != 1) |
757 | { |
758 | /* Set the EOF token's location to be the just after the previous |
759 | token's range. That way 'at-eof' diagnostics point at something |
760 | meaninful. */ |
761 | auto range = get_range_from_loc (set: line_table, loc: tok[-1].location); |
762 | tok[0].location |
763 | = linemap_position_for_loc_and_offset (set: line_table, loc: range.m_finish, offset: 1); |
764 | } |
765 | |
766 | if (filter) |
767 | module_token_cdtor (parse_in, filter); |
768 | |
769 | /* Subsequent preprocessor diagnostics should use compiler |
770 | diagnostic functions to get the compiler source location. */ |
771 | override_libcpp_locations = true; |
772 | |
773 | maybe_check_all_macros (parse_in); |
774 | |
775 | /* If we processed any #pragma GCC target directives, we handled them early so |
776 | any macros they defined would be effective during preprocessing. Now, we |
777 | need to reset to the default state to begin compilation, and we will |
778 | process them again at the correct time as needed. */ |
779 | c_reset_target_pragmas (); |
780 | |
781 | gcc_assert (!lexer->next_token->purged_p); |
782 | return lexer; |
783 | } |
784 | |
785 | /* Create a lexer and parser to be used during preprocess-only mode. |
786 | This will be filled with tokens to parse when needed by pragma_lex (). */ |
787 | void |
788 | c_init_preprocess () |
789 | { |
790 | gcc_assert (!the_parser); |
791 | the_parser = cp_parser_new (cp_lexer_alloc ()); |
792 | } |
793 | |
794 | /* Create a new lexer whose token stream is primed with the tokens in |
795 | CACHE. When these tokens are exhausted, no new tokens will be read. */ |
796 | |
797 | static cp_lexer * |
798 | cp_lexer_new_from_tokens (cp_token_cache *cache) |
799 | { |
800 | cp_token *first = cache->first; |
801 | cp_token *last = cache->last; |
802 | cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> (); |
803 | |
804 | /* We do not own the buffer. */ |
805 | lexer->buffer = NULL; |
806 | |
807 | /* Insert an EOF token. */ |
808 | lexer->saved_type = last->type; |
809 | lexer->saved_keyword = last->keyword; |
810 | last->type = CPP_EOF; |
811 | last->keyword = RID_MAX; |
812 | |
813 | lexer->next_token = first; |
814 | lexer->last_token = last; |
815 | |
816 | lexer->saved_tokens.create (CP_SAVED_TOKEN_STACK); |
817 | |
818 | /* Initially we are not debugging. */ |
819 | lexer->debugging_p = false; |
820 | |
821 | gcc_assert (!lexer->next_token->purged_p |
822 | && !lexer->last_token->purged_p); |
823 | return lexer; |
824 | } |
825 | |
826 | /* Frees all resources associated with LEXER. */ |
827 | |
828 | static void |
829 | cp_lexer_destroy (cp_lexer *lexer) |
830 | { |
831 | if (lexer->buffer) |
832 | vec_free (v&: lexer->buffer); |
833 | else |
834 | { |
835 | /* Restore the token we overwrite with EOF. */ |
836 | lexer->last_token->type = lexer->saved_type; |
837 | lexer->last_token->keyword = lexer->saved_keyword; |
838 | } |
839 | lexer->saved_tokens.release (); |
840 | ggc_free (lexer); |
841 | } |
842 | |
843 | /* This needs to be set to TRUE before the lexer-debugging infrastructure can |
844 | be used. The point of this flag is to help the compiler to fold away calls |
845 | to cp_lexer_debugging_p within this source file at compile time, when the |
846 | lexer is not being debugged. */ |
847 | |
848 | #define LEXER_DEBUGGING_ENABLED_P false |
849 | |
850 | /* Returns nonzero if debugging information should be output. */ |
851 | |
852 | static inline bool |
853 | cp_lexer_debugging_p (cp_lexer *lexer) |
854 | { |
855 | if (!LEXER_DEBUGGING_ENABLED_P) |
856 | return false; |
857 | |
858 | return lexer->debugging_p; |
859 | } |
860 | |
861 | |
862 | static inline cp_token_position |
863 | cp_lexer_token_position (cp_lexer *lexer, bool previous_p) |
864 | { |
865 | return lexer->next_token - previous_p; |
866 | } |
867 | |
868 | static inline cp_token * |
869 | cp_lexer_token_at (cp_lexer * /*lexer*/, cp_token_position pos) |
870 | { |
871 | return pos; |
872 | } |
873 | |
874 | static inline void |
875 | cp_lexer_set_token_position (cp_lexer *lexer, cp_token_position pos) |
876 | { |
877 | lexer->next_token = cp_lexer_token_at (lexer, pos); |
878 | } |
879 | |
880 | static inline cp_token_position |
881 | cp_lexer_previous_token_position (cp_lexer *lexer) |
882 | { |
883 | return cp_lexer_token_position (lexer, previous_p: true); |
884 | } |
885 | |
886 | static inline cp_token * |
887 | cp_lexer_previous_token (cp_lexer *lexer) |
888 | { |
889 | cp_token_position tp = cp_lexer_previous_token_position (lexer); |
890 | |
891 | /* Skip past purged tokens. */ |
892 | while (tp->purged_p) |
893 | { |
894 | gcc_assert (tp != vec_safe_address (lexer->buffer)); |
895 | tp--; |
896 | } |
897 | |
898 | return cp_lexer_token_at (lexer, pos: tp); |
899 | } |
900 | |
901 | /* Same as above, but return NULL when the lexer doesn't own the token |
902 | buffer or if the next_token is at the start of the token |
903 | vector or if all previous tokens are purged. */ |
904 | |
905 | static cp_token * |
906 | cp_lexer_safe_previous_token (cp_lexer *lexer) |
907 | { |
908 | if (lexer->buffer |
909 | && lexer->next_token != lexer->buffer->address ()) |
910 | { |
911 | cp_token_position tp = cp_lexer_previous_token_position (lexer); |
912 | |
913 | /* Skip past purged tokens. */ |
914 | while (tp->purged_p) |
915 | { |
916 | if (tp == lexer->buffer->address ()) |
917 | return NULL; |
918 | tp--; |
919 | } |
920 | return cp_lexer_token_at (lexer, pos: tp); |
921 | } |
922 | |
923 | return NULL; |
924 | } |
925 | |
926 | /* Overload for make_location, taking the lexer to mean the location of the |
927 | previous token. */ |
928 | |
929 | static inline location_t |
930 | make_location (location_t caret, location_t start, cp_lexer *lexer) |
931 | { |
932 | cp_token *t = cp_lexer_previous_token (lexer); |
933 | return make_location (caret, start, finish: t->location); |
934 | } |
935 | |
936 | /* Overload for make_location taking tokens instead of locations. */ |
937 | |
938 | static inline location_t |
939 | make_location (cp_token *caret, cp_token *start, cp_token *end) |
940 | { |
941 | return make_location (caret: caret->location, start: start->location, finish: end->location); |
942 | } |
943 | |
944 | /* nonzero if we are presently saving tokens. */ |
945 | |
946 | static inline int |
947 | cp_lexer_saving_tokens (const cp_lexer* lexer) |
948 | { |
949 | return lexer->saved_tokens.length () != 0; |
950 | } |
951 | |
952 | /* Store the next token from the preprocessor in *TOKEN. Return true |
953 | if we reach EOF. If LEXER is NULL, assume we are handling an |
954 | initial #pragma pch_preprocess, and thus want the lexer to return |
955 | processed strings. |
956 | |
957 | Diagnostics issued from this function must have their controlling option (if |
958 | any) in c.opt annotated as a libcpp option via the CppReason property. */ |
959 | |
960 | static void |
961 | cp_lexer_get_preprocessor_token (unsigned flags, cp_token *token) |
962 | { |
963 | static int is_extern_c = 0; |
964 | |
965 | /* Get a new token from the preprocessor. */ |
966 | token->type |
967 | = c_lex_with_flags (&token->u.value, &token->location, &token->flags, |
968 | flags); |
969 | token->keyword = RID_MAX; |
970 | token->purged_p = false; |
971 | token->error_reported = false; |
972 | token->tree_check_p = false; |
973 | /* Usually never see a zero, but just in case ... */ |
974 | token->main_source_p = line_table->depth <= 1; |
975 | |
976 | /* On some systems, some header files are surrounded by an |
977 | implicit extern "C" block. Set a flag in the token if it |
978 | comes from such a header. */ |
979 | is_extern_c += pending_lang_change; |
980 | pending_lang_change = 0; |
981 | token->implicit_extern_c = is_extern_c > 0; |
982 | |
983 | /* Check to see if this token is a keyword. */ |
984 | if (token->type == CPP_NAME) |
985 | { |
986 | if (IDENTIFIER_KEYWORD_P (token->u.value)) |
987 | { |
988 | /* Mark this token as a keyword. */ |
989 | token->type = CPP_KEYWORD; |
990 | /* Record which keyword. */ |
991 | token->keyword = C_RID_CODE (token->u.value); |
992 | } |
993 | else |
994 | { |
995 | if (warn_cxx11_compat |
996 | && ((C_RID_CODE (token->u.value) >= RID_FIRST_CXX11 |
997 | && C_RID_CODE (token->u.value) <= RID_LAST_CXX11) |
998 | /* These are outside the CXX11 range. */ |
999 | || C_RID_CODE (token->u.value) == RID_ALIGNOF |
1000 | || C_RID_CODE (token->u.value) == RID_ALIGNAS |
1001 | || C_RID_CODE (token->u.value)== RID_THREAD)) |
1002 | { |
1003 | /* Warn about the C++11 keyword (but still treat it as |
1004 | an identifier). */ |
1005 | warning_at (token->location, OPT_Wc__11_compat, |
1006 | "identifier %qE is a keyword in C++11" , |
1007 | token->u.value); |
1008 | |
1009 | /* Clear out the C_RID_CODE so we don't warn about this |
1010 | particular identifier-turned-keyword again. */ |
1011 | C_SET_RID_CODE (token->u.value, RID_MAX); |
1012 | } |
1013 | if (warn_cxx20_compat |
1014 | && C_RID_CODE (token->u.value) >= RID_FIRST_CXX20 |
1015 | && C_RID_CODE (token->u.value) <= RID_LAST_CXX20) |
1016 | { |
1017 | /* Warn about the C++20 keyword (but still treat it as |
1018 | an identifier). */ |
1019 | warning_at (token->location, OPT_Wc__20_compat, |
1020 | "identifier %qE is a keyword in C++20" , |
1021 | token->u.value); |
1022 | |
1023 | /* Clear out the C_RID_CODE so we don't warn about this |
1024 | particular identifier-turned-keyword again. */ |
1025 | C_SET_RID_CODE (token->u.value, RID_MAX); |
1026 | } |
1027 | |
1028 | token->keyword = RID_MAX; |
1029 | } |
1030 | } |
1031 | else if (token->type == CPP_AT_NAME) |
1032 | { |
1033 | /* This only happens in Objective-C++; it must be a keyword. */ |
1034 | token->type = CPP_KEYWORD; |
1035 | switch (C_RID_CODE (token->u.value)) |
1036 | { |
1037 | /* Replace 'class' with '@class', 'private' with '@private', |
1038 | etc. This prevents confusion with the C++ keyword |
1039 | 'class', and makes the tokens consistent with other |
1040 | Objective-C 'AT' keywords. For example '@class' is |
1041 | reported as RID_AT_CLASS which is consistent with |
1042 | '@synchronized', which is reported as |
1043 | RID_AT_SYNCHRONIZED. |
1044 | */ |
1045 | case RID_CLASS: token->keyword = RID_AT_CLASS; break; |
1046 | case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break; |
1047 | case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break; |
1048 | case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break; |
1049 | case RID_THROW: token->keyword = RID_AT_THROW; break; |
1050 | case RID_TRY: token->keyword = RID_AT_TRY; break; |
1051 | case RID_CATCH: token->keyword = RID_AT_CATCH; break; |
1052 | case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break; |
1053 | default: token->keyword = C_RID_CODE (token->u.value); |
1054 | } |
1055 | } |
1056 | } |
1057 | |
1058 | /* Update the globals input_location and the input file stack from TOKEN. */ |
1059 | static inline void |
1060 | cp_lexer_set_source_position_from_token (cp_token *token) |
1061 | { |
1062 | input_location = token->location; |
1063 | } |
1064 | |
1065 | /* Update the globals input_location and the input file stack from LEXER. */ |
1066 | static inline void |
1067 | cp_lexer_set_source_position (cp_lexer *lexer) |
1068 | { |
1069 | cp_token *token = cp_lexer_peek_token (lexer); |
1070 | cp_lexer_set_source_position_from_token (token); |
1071 | } |
1072 | |
1073 | /* Return a pointer to the next token in the token stream, but do not |
1074 | consume it. */ |
1075 | |
1076 | static inline cp_token * |
1077 | cp_lexer_peek_token (cp_lexer *lexer) |
1078 | { |
1079 | if (cp_lexer_debugging_p (lexer)) |
1080 | { |
1081 | fputs (s: "cp_lexer: peeking at token: " , stream: cp_lexer_debug_stream); |
1082 | cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token); |
1083 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1084 | } |
1085 | return lexer->next_token; |
1086 | } |
1087 | |
1088 | /* Return true if the next token has the indicated TYPE. */ |
1089 | |
1090 | static inline bool |
1091 | cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type) |
1092 | { |
1093 | return cp_lexer_peek_token (lexer)->type == type; |
1094 | } |
1095 | |
1096 | /* Return true if the next token does not have the indicated TYPE. */ |
1097 | |
1098 | static inline bool |
1099 | cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type) |
1100 | { |
1101 | return !cp_lexer_next_token_is (lexer, type); |
1102 | } |
1103 | |
1104 | /* Return true if the next token is the indicated KEYWORD. */ |
1105 | |
1106 | static inline bool |
1107 | cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) |
1108 | { |
1109 | return cp_lexer_peek_token (lexer)->keyword == keyword; |
1110 | } |
1111 | |
1112 | static inline bool |
1113 | cp_lexer_nth_token_is (cp_lexer* lexer, size_t n, enum cpp_ttype type) |
1114 | { |
1115 | return cp_lexer_peek_nth_token (lexer, n)->type == type; |
1116 | } |
1117 | |
1118 | static inline bool |
1119 | cp_lexer_nth_token_is_keyword (cp_lexer* lexer, size_t n, enum rid keyword) |
1120 | { |
1121 | return cp_lexer_peek_nth_token (lexer, n)->keyword == keyword; |
1122 | } |
1123 | |
1124 | /* Return true if KEYWORD can start a decl-specifier. */ |
1125 | |
1126 | bool |
1127 | cp_keyword_starts_decl_specifier_p (enum rid keyword) |
1128 | { |
1129 | switch (keyword) |
1130 | { |
1131 | /* auto specifier: storage-class-specifier in C++, |
1132 | simple-type-specifier in C++0x. */ |
1133 | case RID_AUTO: |
1134 | /* Storage classes. */ |
1135 | case RID_REGISTER: |
1136 | case RID_STATIC: |
1137 | case RID_EXTERN: |
1138 | case RID_MUTABLE: |
1139 | case RID_THREAD: |
1140 | /* Elaborated type specifiers. */ |
1141 | case RID_ENUM: |
1142 | case RID_CLASS: |
1143 | case RID_STRUCT: |
1144 | case RID_UNION: |
1145 | case RID_TYPENAME: |
1146 | /* Simple type specifiers. */ |
1147 | case RID_CHAR: |
1148 | case RID_CHAR8: |
1149 | case RID_CHAR16: |
1150 | case RID_CHAR32: |
1151 | case RID_WCHAR: |
1152 | case RID_BOOL: |
1153 | case RID_SHORT: |
1154 | case RID_INT: |
1155 | case RID_LONG: |
1156 | case RID_SIGNED: |
1157 | case RID_UNSIGNED: |
1158 | case RID_FLOAT: |
1159 | case RID_DOUBLE: |
1160 | CASE_RID_FLOATN_NX: |
1161 | case RID_VOID: |
1162 | /* CV qualifiers. */ |
1163 | case RID_CONST: |
1164 | case RID_VOLATILE: |
1165 | /* Function specifiers. */ |
1166 | case RID_EXPLICIT: |
1167 | case RID_VIRTUAL: |
1168 | /* friend/typdef/inline specifiers. */ |
1169 | case RID_FRIEND: |
1170 | case RID_TYPEDEF: |
1171 | case RID_INLINE: |
1172 | /* GNU extensions. */ |
1173 | case RID_TYPEOF: |
1174 | /* C++11 extensions. */ |
1175 | case RID_DECLTYPE: |
1176 | case RID_CONSTEXPR: |
1177 | /* C++20 extensions. */ |
1178 | case RID_CONSTINIT: |
1179 | case RID_CONSTEVAL: |
1180 | return true; |
1181 | |
1182 | default: |
1183 | if (keyword >= RID_FIRST_INT_N |
1184 | && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS |
1185 | && int_n_enabled_p[keyword - RID_FIRST_INT_N]) |
1186 | return true; |
1187 | return false; |
1188 | } |
1189 | } |
1190 | |
1191 | /* Peeks the corresponding built-in trait if the first token is |
1192 | a built-in trait and the second token is either `(' or `<' depending |
1193 | on the trait. Otherwise, returns nullptr. */ |
1194 | |
1195 | static const cp_trait * |
1196 | cp_lexer_peek_trait (cp_lexer *lexer) |
1197 | { |
1198 | const cp_token *token1 = cp_lexer_peek_token (lexer); |
1199 | if (token1->type == CPP_NAME && IDENTIFIER_TRAIT_P (token1->u.value)) |
1200 | { |
1201 | const cp_trait &trait = cp_traits[IDENTIFIER_CP_INDEX (token1->u.value)]; |
1202 | const bool is_pack_element = (trait.kind == CPTK_TYPE_PACK_ELEMENT); |
1203 | |
1204 | /* Check if the subsequent token is a `<' token to |
1205 | __type_pack_element or is a `(' token to everything else. */ |
1206 | const cp_token *token2 = cp_lexer_peek_nth_token (lexer, 2); |
1207 | if (is_pack_element && token2->type != CPP_LESS) |
1208 | return nullptr; |
1209 | if (!is_pack_element && token2->type != CPP_OPEN_PAREN) |
1210 | return nullptr; |
1211 | |
1212 | return &trait; |
1213 | } |
1214 | return nullptr; |
1215 | } |
1216 | |
1217 | /* Similarly, but only if the token is an expression-yielding |
1218 | built-in trait. */ |
1219 | |
1220 | static const cp_trait * |
1221 | cp_lexer_peek_trait_expr (cp_lexer *lexer) |
1222 | { |
1223 | const cp_trait *trait = cp_lexer_peek_trait (lexer); |
1224 | if (trait && !trait->type) |
1225 | return trait; |
1226 | |
1227 | return nullptr; |
1228 | } |
1229 | |
1230 | /* Similarly, but only if the token is a type-yielding |
1231 | built-in trait. */ |
1232 | |
1233 | static const cp_trait * |
1234 | cp_lexer_peek_trait_type (cp_lexer *lexer) |
1235 | { |
1236 | const cp_trait *trait = cp_lexer_peek_trait (lexer); |
1237 | if (trait && trait->type) |
1238 | return trait; |
1239 | |
1240 | return nullptr; |
1241 | } |
1242 | |
1243 | /* Return true if the next token is a keyword for a decl-specifier. */ |
1244 | |
1245 | static bool |
1246 | cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) |
1247 | { |
1248 | cp_token *token; |
1249 | |
1250 | if (cp_lexer_peek_trait_type (lexer)) |
1251 | return true; |
1252 | |
1253 | token = cp_lexer_peek_token (lexer); |
1254 | return cp_keyword_starts_decl_specifier_p (keyword: token->keyword); |
1255 | } |
1256 | |
1257 | /* Returns TRUE iff the token T begins a decltype type. */ |
1258 | |
1259 | static bool |
1260 | token_is_decltype (cp_token *t) |
1261 | { |
1262 | return (t->keyword == RID_DECLTYPE |
1263 | || t->type == CPP_DECLTYPE); |
1264 | } |
1265 | |
1266 | /* Returns TRUE iff the next token begins a decltype type. */ |
1267 | |
1268 | static bool |
1269 | cp_lexer_next_token_is_decltype (cp_lexer *lexer) |
1270 | { |
1271 | cp_token *t = cp_lexer_peek_token (lexer); |
1272 | return token_is_decltype (t); |
1273 | } |
1274 | |
1275 | /* Called when processing a token with tree_check_value; perform or defer the |
1276 | associated checks and return the value. */ |
1277 | |
1278 | static tree |
1279 | saved_checks_value (struct tree_check *check_value) |
1280 | { |
1281 | /* Perform any access checks that were deferred. */ |
1282 | vec<deferred_access_check, va_gc> *checks; |
1283 | deferred_access_check *chk; |
1284 | checks = check_value->checks; |
1285 | if (checks) |
1286 | { |
1287 | int i; |
1288 | FOR_EACH_VEC_SAFE_ELT (checks, i, chk) |
1289 | perform_or_defer_access_check (chk->binfo, |
1290 | chk->decl, |
1291 | chk->diag_decl, tf_warning_or_error); |
1292 | } |
1293 | /* Return the stored value. */ |
1294 | return check_value->value; |
1295 | } |
1296 | |
1297 | /* Return a pointer to the Nth token in the token stream. If N is 1, |
1298 | then this is precisely equivalent to cp_lexer_peek_token (except |
1299 | that it is not inline). One would like to disallow that case, but |
1300 | there is one case (cp_parser_nth_token_starts_template_id) where |
1301 | the caller passes a variable for N and it might be 1. */ |
1302 | |
1303 | static cp_token * |
1304 | cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) |
1305 | { |
1306 | cp_token *token; |
1307 | |
1308 | /* N is 1-based, not zero-based. */ |
1309 | gcc_assert (n > 0); |
1310 | |
1311 | if (cp_lexer_debugging_p (lexer)) |
1312 | fprintf (stream: cp_lexer_debug_stream, |
1313 | format: "cp_lexer: peeking ahead " HOST_SIZE_T_PRINT_DEC " at token: " , |
1314 | (fmt_size_t) n); |
1315 | |
1316 | --n; |
1317 | token = lexer->next_token; |
1318 | while (n && token->type != CPP_EOF) |
1319 | { |
1320 | ++token; |
1321 | if (!token->purged_p) |
1322 | --n; |
1323 | } |
1324 | |
1325 | if (cp_lexer_debugging_p (lexer)) |
1326 | { |
1327 | cp_lexer_print_token (cp_lexer_debug_stream, token); |
1328 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1329 | } |
1330 | |
1331 | return token; |
1332 | } |
1333 | |
1334 | /* Return the next token, and advance the lexer's next_token pointer |
1335 | to point to the next non-purged token. */ |
1336 | |
1337 | static cp_token * |
1338 | cp_lexer_consume_token (cp_lexer* lexer) |
1339 | { |
1340 | cp_token *token = lexer->next_token; |
1341 | |
1342 | do |
1343 | { |
1344 | gcc_assert (token->type != CPP_EOF); |
1345 | lexer->next_token++; |
1346 | } |
1347 | while (lexer->next_token->purged_p); |
1348 | |
1349 | cp_lexer_set_source_position_from_token (token); |
1350 | |
1351 | /* Provide debugging output. */ |
1352 | if (cp_lexer_debugging_p (lexer)) |
1353 | { |
1354 | fputs (s: "cp_lexer: consuming token: " , stream: cp_lexer_debug_stream); |
1355 | cp_lexer_print_token (cp_lexer_debug_stream, token); |
1356 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1357 | } |
1358 | |
1359 | return token; |
1360 | } |
1361 | |
1362 | /* Permanently remove the next token from the token stream, and |
1363 | advance the next_token pointer to refer to the next non-purged |
1364 | token. */ |
1365 | |
1366 | static void |
1367 | cp_lexer_purge_token (cp_lexer *lexer) |
1368 | { |
1369 | cp_token *tok = lexer->next_token; |
1370 | |
1371 | gcc_assert (tok->type != CPP_EOF); |
1372 | tok->purged_p = true; |
1373 | tok->location = UNKNOWN_LOCATION; |
1374 | tok->u.value = NULL_TREE; |
1375 | tok->keyword = RID_MAX; |
1376 | |
1377 | do |
1378 | tok++; |
1379 | while (tok->purged_p); |
1380 | lexer->next_token = tok; |
1381 | } |
1382 | |
1383 | /* Permanently remove all tokens after TOK, up to, but not |
1384 | including, the token that will be returned next by |
1385 | cp_lexer_peek_token. */ |
1386 | |
1387 | static void |
1388 | cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok) |
1389 | { |
1390 | cp_token *peek = lexer->next_token; |
1391 | |
1392 | gcc_assert (tok < peek); |
1393 | |
1394 | for (tok++; tok != peek; tok++) |
1395 | { |
1396 | tok->purged_p = true; |
1397 | tok->location = UNKNOWN_LOCATION; |
1398 | tok->u.value = NULL_TREE; |
1399 | tok->keyword = RID_MAX; |
1400 | } |
1401 | } |
1402 | |
1403 | /* Begin saving tokens. All tokens consumed after this point will be |
1404 | preserved. */ |
1405 | |
1406 | static void |
1407 | cp_lexer_save_tokens (cp_lexer* lexer) |
1408 | { |
1409 | /* Provide debugging output. */ |
1410 | if (cp_lexer_debugging_p (lexer)) |
1411 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: saving tokens\n" ); |
1412 | |
1413 | lexer->saved_tokens.safe_push (obj: lexer->next_token); |
1414 | } |
1415 | |
1416 | /* Commit to the portion of the token stream most recently saved. */ |
1417 | |
1418 | static void |
1419 | cp_lexer_commit_tokens (cp_lexer* lexer) |
1420 | { |
1421 | /* Provide debugging output. */ |
1422 | if (cp_lexer_debugging_p (lexer)) |
1423 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: committing tokens\n" ); |
1424 | |
1425 | lexer->saved_tokens.pop (); |
1426 | } |
1427 | |
1428 | /* Return all tokens saved since the last call to cp_lexer_save_tokens |
1429 | to the token stream. Stop saving tokens. */ |
1430 | |
1431 | static void |
1432 | cp_lexer_rollback_tokens (cp_lexer* lexer) |
1433 | { |
1434 | /* Provide debugging output. */ |
1435 | if (cp_lexer_debugging_p (lexer)) |
1436 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: restoring tokens\n" ); |
1437 | |
1438 | lexer->next_token = lexer->saved_tokens.pop (); |
1439 | } |
1440 | |
1441 | /* Determines what saved_token_sentinel does when going out of scope. */ |
1442 | |
1443 | enum saved_token_sentinel_mode { |
1444 | STS_COMMIT, |
1445 | STS_ROLLBACK, |
1446 | STS_DONOTHING |
1447 | }; |
1448 | |
1449 | /* RAII wrapper around the above functions, with sanity checking (the token |
1450 | stream should be the same at the point of instantiation as it is at the |
1451 | point of destruction). |
1452 | |
1453 | Creating a variable saves tokens. MODE determines what happens when the |
1454 | object is destroyed. STS_COMMIT commits tokens (default), |
1455 | STS_ROLLBACK rolls-back and STS_DONOTHING does nothing. Calling |
1456 | rollback() will immediately roll-back tokens and set MODE to |
1457 | STS_DONOTHING. */ |
1458 | |
1459 | struct saved_token_sentinel |
1460 | { |
1461 | cp_lexer *lexer; |
1462 | unsigned len; |
1463 | saved_token_sentinel_mode mode; |
1464 | saved_token_sentinel (cp_lexer *_lexer, |
1465 | saved_token_sentinel_mode _mode = STS_COMMIT) |
1466 | : lexer (_lexer), mode (_mode) |
1467 | { |
1468 | len = lexer->saved_tokens.length (); |
1469 | cp_lexer_save_tokens (lexer); |
1470 | } |
1471 | void rollback () |
1472 | { |
1473 | cp_lexer_rollback_tokens (lexer); |
1474 | cp_lexer_set_source_position_from_token |
1475 | (token: cp_lexer_previous_token (lexer)); |
1476 | mode = STS_DONOTHING; |
1477 | } |
1478 | ~saved_token_sentinel () |
1479 | { |
1480 | if (mode == STS_COMMIT) |
1481 | cp_lexer_commit_tokens (lexer); |
1482 | else if (mode == STS_ROLLBACK) |
1483 | rollback (); |
1484 | |
1485 | gcc_assert (lexer->saved_tokens.length () == len); |
1486 | } |
1487 | }; |
1488 | |
1489 | /* Print a representation of the TOKEN on the STREAM. */ |
1490 | |
1491 | static void |
1492 | cp_lexer_print_token (FILE * stream, cp_token *token) |
1493 | { |
1494 | /* We don't use cpp_type2name here because the parser defines |
1495 | a few tokens of its own. */ |
1496 | static const char *const token_names[] = { |
1497 | /* cpplib-defined token types */ |
1498 | #define OP(e, s) #e, |
1499 | #define TK(e, s) #e, |
1500 | TTYPE_TABLE |
1501 | #undef OP |
1502 | #undef TK |
1503 | /* C++ parser token types - see "Manifest constants", above. */ |
1504 | "KEYWORD" , |
1505 | "TEMPLATE_ID" , |
1506 | "NESTED_NAME_SPECIFIER" , |
1507 | }; |
1508 | |
1509 | /* For some tokens, print the associated data. */ |
1510 | switch (token->type) |
1511 | { |
1512 | case CPP_KEYWORD: |
1513 | /* Some keywords have a value that is not an IDENTIFIER_NODE. |
1514 | For example, `struct' is mapped to an INTEGER_CST. */ |
1515 | if (!identifier_p (t: token->u.value)) |
1516 | break; |
1517 | /* fall through */ |
1518 | case CPP_NAME: |
1519 | fputs (IDENTIFIER_POINTER (token->u.value), stream: stream); |
1520 | break; |
1521 | |
1522 | case CPP_STRING: |
1523 | case CPP_STRING16: |
1524 | case CPP_STRING32: |
1525 | case CPP_WSTRING: |
1526 | case CPP_UTF8STRING: |
1527 | fprintf (stream: stream, format: " \"%s\"" , TREE_STRING_POINTER (token->u.value)); |
1528 | break; |
1529 | |
1530 | case CPP_NUMBER: |
1531 | print_generic_expr (stream, token->u.value); |
1532 | break; |
1533 | |
1534 | default: |
1535 | /* If we have a name for the token, print it out. Otherwise, we |
1536 | simply give the numeric code. */ |
1537 | if (token->type < ARRAY_SIZE(token_names)) |
1538 | fputs (s: token_names[token->type], stream: stream); |
1539 | else |
1540 | fprintf (stream: stream, format: "[%d]" , token->type); |
1541 | break; |
1542 | } |
1543 | } |
1544 | |
1545 | DEBUG_FUNCTION void |
1546 | debug (cp_token &ref) |
1547 | { |
1548 | cp_lexer_print_token (stderr, token: &ref); |
1549 | fprintf (stderr, format: "\n" ); |
1550 | } |
1551 | |
1552 | DEBUG_FUNCTION void |
1553 | debug (cp_token *ptr) |
1554 | { |
1555 | if (ptr) |
1556 | debug (ref&: *ptr); |
1557 | else |
1558 | fprintf (stderr, format: "<nil>\n" ); |
1559 | } |
1560 | |
1561 | |
1562 | /* Start emitting debugging information. */ |
1563 | |
1564 | static void |
1565 | cp_lexer_start_debugging (cp_lexer* lexer) |
1566 | { |
1567 | if (!LEXER_DEBUGGING_ENABLED_P) |
1568 | fatal_error (input_location, |
1569 | "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true" ); |
1570 | |
1571 | lexer->debugging_p = true; |
1572 | cp_lexer_debug_stream = stderr; |
1573 | } |
1574 | |
1575 | /* Stop emitting debugging information. */ |
1576 | |
1577 | static void |
1578 | cp_lexer_stop_debugging (cp_lexer* lexer) |
1579 | { |
1580 | if (!LEXER_DEBUGGING_ENABLED_P) |
1581 | fatal_error (input_location, |
1582 | "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true" ); |
1583 | |
1584 | lexer->debugging_p = false; |
1585 | cp_lexer_debug_stream = NULL; |
1586 | } |
1587 | |
1588 | /* Create a new cp_token_cache, representing a range of tokens. */ |
1589 | |
1590 | static cp_token_cache * |
1591 | cp_token_cache_new (cp_token *first, cp_token *last) |
1592 | { |
1593 | cp_token_cache *cache = ggc_alloc<cp_token_cache> (); |
1594 | cache->first = first; |
1595 | cache->last = last; |
1596 | return cache; |
1597 | } |
1598 | |
1599 | /* Diagnose if #pragma omp declare simd isn't followed immediately |
1600 | by function declaration or definition. */ |
1601 | |
1602 | static inline void |
1603 | cp_ensure_no_omp_declare_simd (cp_parser *parser) |
1604 | { |
1605 | if (parser->omp_declare_simd && !parser->omp_declare_simd->error_seen) |
1606 | { |
1607 | error ("%<#pragma omp declare %s%> not immediately followed by " |
1608 | "function declaration or definition" , |
1609 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
1610 | parser->omp_declare_simd = NULL; |
1611 | } |
1612 | } |
1613 | |
1614 | /* Finalize #pragma omp declare simd clauses after FNDECL has been parsed, |
1615 | and put that into "omp declare simd" attribute. */ |
1616 | |
1617 | static inline void |
1618 | cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl) |
1619 | { |
1620 | if (UNLIKELY (parser->omp_declare_simd != NULL)) |
1621 | { |
1622 | if (fndecl == error_mark_node) |
1623 | { |
1624 | parser->omp_declare_simd = NULL; |
1625 | return; |
1626 | } |
1627 | if (TREE_CODE (fndecl) != FUNCTION_DECL) |
1628 | { |
1629 | cp_ensure_no_omp_declare_simd (parser); |
1630 | return; |
1631 | } |
1632 | } |
1633 | } |
1634 | |
1635 | /* Similarly, but for use in declaration parsing functions |
1636 | which call cp_parser_handle_directive_omp_attributes. */ |
1637 | |
1638 | static inline void |
1639 | cp_finalize_omp_declare_simd (cp_parser *parser, cp_omp_declare_simd_data *data) |
1640 | { |
1641 | if (parser->omp_declare_simd != data) |
1642 | return; |
1643 | |
1644 | if (!parser->omp_declare_simd->error_seen |
1645 | && !parser->omp_declare_simd->fndecl_seen) |
1646 | error_at (parser->omp_declare_simd->loc, |
1647 | "%<declare %s%> directive not immediately followed by " |
1648 | "function declaration or definition" , |
1649 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
1650 | parser->omp_declare_simd = NULL; |
1651 | } |
1652 | |
1653 | /* Diagnose if #pragma acc routine isn't followed immediately by function |
1654 | declaration or definition. */ |
1655 | |
1656 | static inline void |
1657 | cp_ensure_no_oacc_routine (cp_parser *parser) |
1658 | { |
1659 | if (parser->oacc_routine && !parser->oacc_routine->error_seen) |
1660 | { |
1661 | error_at (parser->oacc_routine->loc, |
1662 | "%<#pragma acc routine%> not immediately followed by " |
1663 | "function declaration or definition" ); |
1664 | parser->oacc_routine = NULL; |
1665 | } |
1666 | } |
1667 | |
1668 | /* Decl-specifiers. */ |
1669 | |
1670 | /* Set *DECL_SPECS to represent an empty decl-specifier-seq. */ |
1671 | |
1672 | static void |
1673 | clear_decl_specs (cp_decl_specifier_seq *decl_specs) |
1674 | { |
1675 | memset (s: decl_specs, c: 0, n: sizeof (cp_decl_specifier_seq)); |
1676 | } |
1677 | |
1678 | /* Declarators. */ |
1679 | |
1680 | /* Nothing other than the parser should be creating declarators; |
1681 | declarators are a semi-syntactic representation of C++ entities. |
1682 | Other parts of the front end that need to create entities (like |
1683 | VAR_DECLs or FUNCTION_DECLs) should do that directly. */ |
1684 | |
1685 | static cp_declarator *make_call_declarator |
1686 | (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, |
1687 | tree, tree, tree, tree, tree, location_t); |
1688 | static cp_declarator *make_array_declarator |
1689 | (cp_declarator *, tree); |
1690 | static cp_declarator *make_pointer_declarator |
1691 | (cp_cv_quals, cp_declarator *, tree); |
1692 | static cp_declarator *make_reference_declarator |
1693 | (cp_cv_quals, cp_declarator *, bool, tree); |
1694 | static cp_declarator *make_ptrmem_declarator |
1695 | (cp_cv_quals, tree, cp_declarator *, tree); |
1696 | |
1697 | /* An erroneous declarator. */ |
1698 | static cp_declarator *cp_error_declarator; |
1699 | |
1700 | /* The obstack on which declarators and related data structures are |
1701 | allocated. */ |
1702 | static struct obstack declarator_obstack; |
1703 | |
1704 | /* Alloc BYTES from the declarator memory pool. */ |
1705 | |
1706 | static inline void * |
1707 | alloc_declarator (size_t bytes) |
1708 | { |
1709 | return obstack_alloc (&declarator_obstack, bytes); |
1710 | } |
1711 | |
1712 | /* Allocate a declarator of the indicated KIND. Clear fields that are |
1713 | common to all declarators. */ |
1714 | |
1715 | static cp_declarator * |
1716 | make_declarator (cp_declarator_kind kind) |
1717 | { |
1718 | cp_declarator *declarator; |
1719 | |
1720 | declarator = (cp_declarator *) alloc_declarator (bytes: sizeof (cp_declarator)); |
1721 | declarator->kind = kind; |
1722 | declarator->parenthesized = UNKNOWN_LOCATION; |
1723 | declarator->attributes = NULL_TREE; |
1724 | declarator->std_attributes = NULL_TREE; |
1725 | declarator->declarator = NULL; |
1726 | declarator->parameter_pack_p = false; |
1727 | declarator->id_loc = UNKNOWN_LOCATION; |
1728 | declarator->init_loc = UNKNOWN_LOCATION; |
1729 | |
1730 | return declarator; |
1731 | } |
1732 | |
1733 | /* Make a declarator for a generalized identifier. If |
1734 | QUALIFYING_SCOPE is non-NULL, the identifier is |
1735 | QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is just |
1736 | UNQUALIFIED_NAME. SFK indicates the kind of special function this |
1737 | is, if any. */ |
1738 | |
1739 | static cp_declarator * |
1740 | make_id_declarator (tree qualifying_scope, tree unqualified_name, |
1741 | special_function_kind sfk, location_t id_location) |
1742 | { |
1743 | cp_declarator *declarator; |
1744 | |
1745 | /* It is valid to write: |
1746 | |
1747 | class C { void f(); }; |
1748 | typedef C D; |
1749 | void D::f(); |
1750 | |
1751 | The standard is not clear about whether `typedef const C D' is |
1752 | legal; as of 2002-09-15 the committee is considering that |
1753 | question. EDG 3.0 allows that syntax. Therefore, we do as |
1754 | well. */ |
1755 | if (qualifying_scope && TYPE_P (qualifying_scope)) |
1756 | qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope); |
1757 | |
1758 | gcc_assert (identifier_p (unqualified_name) |
1759 | || TREE_CODE (unqualified_name) == BIT_NOT_EXPR |
1760 | || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR); |
1761 | |
1762 | declarator = make_declarator (kind: cdk_id); |
1763 | declarator->u.id.qualifying_scope = qualifying_scope; |
1764 | declarator->u.id.unqualified_name = unqualified_name; |
1765 | declarator->u.id.sfk = sfk; |
1766 | declarator->id_loc = id_location; |
1767 | |
1768 | return declarator; |
1769 | } |
1770 | |
1771 | /* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list |
1772 | of modifiers such as const or volatile to apply to the pointer |
1773 | type, represented as identifiers. ATTRIBUTES represent the attributes that |
1774 | appertain to the pointer or reference. */ |
1775 | |
1776 | cp_declarator * |
1777 | make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, |
1778 | tree attributes) |
1779 | { |
1780 | cp_declarator *declarator; |
1781 | |
1782 | declarator = make_declarator (kind: cdk_pointer); |
1783 | declarator->declarator = target; |
1784 | declarator->u.pointer.qualifiers = cv_qualifiers; |
1785 | declarator->u.pointer.class_type = NULL_TREE; |
1786 | if (target) |
1787 | { |
1788 | declarator->id_loc = target->id_loc; |
1789 | declarator->parameter_pack_p = target->parameter_pack_p; |
1790 | target->parameter_pack_p = false; |
1791 | } |
1792 | else |
1793 | declarator->parameter_pack_p = false; |
1794 | |
1795 | declarator->std_attributes = attributes; |
1796 | |
1797 | return declarator; |
1798 | } |
1799 | |
1800 | /* Like make_pointer_declarator -- but for references. ATTRIBUTES |
1801 | represent the attributes that appertain to the pointer or |
1802 | reference. */ |
1803 | |
1804 | cp_declarator * |
1805 | make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, |
1806 | bool rvalue_ref, tree attributes) |
1807 | { |
1808 | cp_declarator *declarator; |
1809 | |
1810 | declarator = make_declarator (kind: cdk_reference); |
1811 | declarator->declarator = target; |
1812 | declarator->u.reference.qualifiers = cv_qualifiers; |
1813 | declarator->u.reference.rvalue_ref = rvalue_ref; |
1814 | if (target) |
1815 | { |
1816 | declarator->id_loc = target->id_loc; |
1817 | declarator->parameter_pack_p = target->parameter_pack_p; |
1818 | target->parameter_pack_p = false; |
1819 | } |
1820 | else |
1821 | declarator->parameter_pack_p = false; |
1822 | |
1823 | declarator->std_attributes = attributes; |
1824 | |
1825 | return declarator; |
1826 | } |
1827 | |
1828 | /* Like make_pointer_declarator -- but for a pointer to a non-static |
1829 | member of CLASS_TYPE. ATTRIBUTES represent the attributes that |
1830 | appertain to the pointer or reference. */ |
1831 | |
1832 | cp_declarator * |
1833 | make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, |
1834 | cp_declarator *pointee, |
1835 | tree attributes) |
1836 | { |
1837 | cp_declarator *declarator; |
1838 | |
1839 | declarator = make_declarator (kind: cdk_ptrmem); |
1840 | declarator->declarator = pointee; |
1841 | declarator->u.pointer.qualifiers = cv_qualifiers; |
1842 | declarator->u.pointer.class_type = class_type; |
1843 | |
1844 | if (pointee) |
1845 | { |
1846 | declarator->parameter_pack_p = pointee->parameter_pack_p; |
1847 | pointee->parameter_pack_p = false; |
1848 | } |
1849 | else |
1850 | declarator->parameter_pack_p = false; |
1851 | |
1852 | declarator->std_attributes = attributes; |
1853 | |
1854 | return declarator; |
1855 | } |
1856 | |
1857 | /* Make a declarator for the function given by TARGET, with the |
1858 | indicated PARMS. The CV_QUALIFIERS apply to the function, as in |
1859 | "const"-qualified member function. The EXCEPTION_SPECIFICATION |
1860 | indicates what exceptions can be thrown. STD_ATTRS contains |
1861 | attributes that appertain to the function type. */ |
1862 | |
1863 | cp_declarator * |
1864 | make_call_declarator (cp_declarator *target, |
1865 | tree parms, |
1866 | cp_cv_quals cv_qualifiers, |
1867 | cp_virt_specifiers virt_specifiers, |
1868 | cp_ref_qualifier ref_qualifier, |
1869 | tree tx_qualifier, |
1870 | tree exception_specification, |
1871 | tree late_return_type, |
1872 | tree requires_clause, |
1873 | tree std_attrs, |
1874 | location_t parens_loc) |
1875 | { |
1876 | cp_declarator *declarator; |
1877 | |
1878 | declarator = make_declarator (kind: cdk_function); |
1879 | declarator->declarator = target; |
1880 | declarator->u.function.parameters = parms; |
1881 | declarator->u.function.qualifiers = cv_qualifiers; |
1882 | declarator->u.function.virt_specifiers = virt_specifiers; |
1883 | declarator->u.function.ref_qualifier = ref_qualifier; |
1884 | declarator->u.function.tx_qualifier = tx_qualifier; |
1885 | declarator->u.function.exception_specification = exception_specification; |
1886 | declarator->u.function.late_return_type = late_return_type; |
1887 | declarator->u.function.requires_clause = requires_clause; |
1888 | declarator->u.function.parens_loc = parens_loc; |
1889 | if (target) |
1890 | { |
1891 | declarator->id_loc = target->id_loc; |
1892 | declarator->parameter_pack_p = target->parameter_pack_p; |
1893 | target->parameter_pack_p = false; |
1894 | } |
1895 | else |
1896 | declarator->parameter_pack_p = false; |
1897 | |
1898 | declarator->std_attributes = std_attrs; |
1899 | |
1900 | return declarator; |
1901 | } |
1902 | |
1903 | /* Make a declarator for an array of BOUNDS elements, each of which is |
1904 | defined by ELEMENT. */ |
1905 | |
1906 | cp_declarator * |
1907 | make_array_declarator (cp_declarator *element, tree bounds) |
1908 | { |
1909 | cp_declarator *declarator; |
1910 | |
1911 | declarator = make_declarator (kind: cdk_array); |
1912 | declarator->declarator = element; |
1913 | declarator->u.array.bounds = bounds; |
1914 | if (element) |
1915 | { |
1916 | declarator->id_loc = element->id_loc; |
1917 | declarator->parameter_pack_p = element->parameter_pack_p; |
1918 | element->parameter_pack_p = false; |
1919 | } |
1920 | else |
1921 | declarator->parameter_pack_p = false; |
1922 | |
1923 | return declarator; |
1924 | } |
1925 | |
1926 | /* Determine whether the declarator we've seen so far can be a |
1927 | parameter pack, when followed by an ellipsis. */ |
1928 | static bool |
1929 | declarator_can_be_parameter_pack (cp_declarator *declarator) |
1930 | { |
1931 | if (declarator && declarator->parameter_pack_p) |
1932 | /* We already saw an ellipsis. */ |
1933 | return false; |
1934 | |
1935 | /* Search for a declarator name, or any other declarator that goes |
1936 | after the point where the ellipsis could appear in a parameter |
1937 | pack. If we find any of these, then this declarator cannot be |
1938 | made into a parameter pack. */ |
1939 | bool found = false; |
1940 | while (declarator && !found) |
1941 | { |
1942 | switch ((int)declarator->kind) |
1943 | { |
1944 | case cdk_id: |
1945 | case cdk_array: |
1946 | case cdk_decomp: |
1947 | found = true; |
1948 | break; |
1949 | |
1950 | case cdk_error: |
1951 | return true; |
1952 | |
1953 | default: |
1954 | declarator = declarator->declarator; |
1955 | break; |
1956 | } |
1957 | } |
1958 | |
1959 | return !found; |
1960 | } |
1961 | |
1962 | cp_parameter_declarator *no_parameters; |
1963 | |
1964 | /* Create a parameter declarator with the indicated DECL_SPECIFIERS, |
1965 | DECLARATOR and DEFAULT_ARGUMENT. */ |
1966 | |
1967 | cp_parameter_declarator * |
1968 | make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, |
1969 | cp_declarator *declarator, |
1970 | tree default_argument, |
1971 | location_t loc, |
1972 | bool template_parameter_pack_p = false) |
1973 | { |
1974 | cp_parameter_declarator *parameter; |
1975 | |
1976 | parameter = ((cp_parameter_declarator *) |
1977 | alloc_declarator (bytes: sizeof (cp_parameter_declarator))); |
1978 | parameter->next = NULL; |
1979 | if (decl_specifiers) |
1980 | parameter->decl_specifiers = *decl_specifiers; |
1981 | else |
1982 | clear_decl_specs (decl_specs: ¶meter->decl_specifiers); |
1983 | parameter->declarator = declarator; |
1984 | parameter->default_argument = default_argument; |
1985 | parameter->template_parameter_pack_p = template_parameter_pack_p; |
1986 | parameter->loc = loc; |
1987 | |
1988 | return parameter; |
1989 | } |
1990 | |
1991 | /* Returns true iff DECLARATOR is a declaration for a function. */ |
1992 | |
1993 | static bool |
1994 | function_declarator_p (const cp_declarator *declarator) |
1995 | { |
1996 | while (declarator) |
1997 | { |
1998 | if (declarator->kind == cdk_function |
1999 | && declarator->declarator->kind == cdk_id) |
2000 | return true; |
2001 | if (declarator->kind == cdk_id |
2002 | || declarator->kind == cdk_decomp |
2003 | || declarator->kind == cdk_error) |
2004 | return false; |
2005 | declarator = declarator->declarator; |
2006 | } |
2007 | return false; |
2008 | } |
2009 | |
2010 | /* The parser. */ |
2011 | |
2012 | /* Overview |
2013 | -------- |
2014 | |
2015 | A cp_parser parses the token stream as specified by the C++ |
2016 | grammar. Its job is purely parsing, not semantic analysis. For |
2017 | example, the parser breaks the token stream into declarators, |
2018 | expressions, statements, and other similar syntactic constructs. |
2019 | It does not check that the types of the expressions on either side |
2020 | of an assignment-statement are compatible, or that a function is |
2021 | not declared with a parameter of type `void'. |
2022 | |
2023 | The parser invokes routines elsewhere in the compiler to perform |
2024 | semantic analysis and to build up the abstract syntax tree for the |
2025 | code processed. |
2026 | |
2027 | The parser (and the template instantiation code, which is, in a |
2028 | way, a close relative of parsing) are the only parts of the |
2029 | compiler that should be calling push_scope and pop_scope, or |
2030 | related functions. The parser (and template instantiation code) |
2031 | keeps track of what scope is presently active; everything else |
2032 | should simply honor that. (The code that generates static |
2033 | initializers may also need to set the scope, in order to check |
2034 | access control correctly when emitting the initializers.) |
2035 | |
2036 | Methodology |
2037 | ----------- |
2038 | |
2039 | The parser is of the standard recursive-descent variety. Upcoming |
2040 | tokens in the token stream are examined in order to determine which |
2041 | production to use when parsing a non-terminal. Some C++ constructs |
2042 | require arbitrary look ahead to disambiguate. For example, it is |
2043 | impossible, in the general case, to tell whether a statement is an |
2044 | expression or declaration without scanning the entire statement. |
2045 | Therefore, the parser is capable of "parsing tentatively." When the |
2046 | parser is not sure what construct comes next, it enters this mode. |
2047 | Then, while we attempt to parse the construct, the parser queues up |
2048 | error messages, rather than issuing them immediately, and saves the |
2049 | tokens it consumes. If the construct is parsed successfully, the |
2050 | parser "commits", i.e., it issues any queued error messages and |
2051 | the tokens that were being preserved are permanently discarded. |
2052 | If, however, the construct is not parsed successfully, the parser |
2053 | rolls back its state completely so that it can resume parsing using |
2054 | a different alternative. |
2055 | |
2056 | Future Improvements |
2057 | ------------------- |
2058 | |
2059 | The performance of the parser could probably be improved substantially. |
2060 | We could often eliminate the need to parse tentatively by looking ahead |
2061 | a little bit. In some places, this approach might not entirely eliminate |
2062 | the need to parse tentatively, but it might still speed up the average |
2063 | case. */ |
2064 | |
2065 | /* Flags that are passed to some parsing functions. These values can |
2066 | be bitwise-ored together. */ |
2067 | |
2068 | enum |
2069 | { |
2070 | /* No flags. */ |
2071 | CP_PARSER_FLAGS_NONE = 0x0, |
2072 | /* The construct is optional. If it is not present, then no error |
2073 | should be issued. */ |
2074 | CP_PARSER_FLAGS_OPTIONAL = 0x1, |
2075 | /* When parsing a type-specifier, treat user-defined type-names |
2076 | as non-type identifiers. */ |
2077 | CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2, |
2078 | /* When parsing a type-specifier, do not try to parse a class-specifier |
2079 | or enum-specifier. */ |
2080 | CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4, |
2081 | /* When parsing a decl-specifier-seq, only allow type-specifier or |
2082 | constexpr. */ |
2083 | CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8, |
2084 | /* When parsing a decl-specifier-seq, only allow mutable, constexpr or |
2085 | for C++20 consteval or for C++23 static. */ |
2086 | CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10, |
2087 | /* When parsing a decl-specifier-seq, allow missing typename. */ |
2088 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20, |
2089 | /* When parsing of the noexcept-specifier should be delayed. */ |
2090 | CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40, |
2091 | /* When parsing a consteval declarator. */ |
2092 | CP_PARSER_FLAGS_CONSTEVAL = 0x80, |
2093 | /* When parsing a parameter declaration. */ |
2094 | CP_PARSER_FLAGS_PARAMETER = 0x100 |
2095 | }; |
2096 | |
2097 | /* This type is used for parameters and variables which hold |
2098 | combinations of the above flags. */ |
2099 | typedef int cp_parser_flags; |
2100 | |
2101 | /* The different kinds of declarators we want to parse. */ |
2102 | |
2103 | enum cp_parser_declarator_kind |
2104 | { |
2105 | /* We want an abstract declarator. */ |
2106 | CP_PARSER_DECLARATOR_ABSTRACT, |
2107 | /* We want a named declarator. */ |
2108 | CP_PARSER_DECLARATOR_NAMED, |
2109 | /* We don't mind, but the name must be an unqualified-id. */ |
2110 | CP_PARSER_DECLARATOR_EITHER |
2111 | }; |
2112 | |
2113 | /* The precedence values used to parse binary expressions. The minimum value |
2114 | of PREC must be 1, because zero is reserved to quickly discriminate |
2115 | binary operators from other tokens. */ |
2116 | |
2117 | enum cp_parser_prec |
2118 | { |
2119 | PREC_NOT_OPERATOR, |
2120 | PREC_LOGICAL_OR_EXPRESSION, |
2121 | PREC_LOGICAL_AND_EXPRESSION, |
2122 | PREC_INCLUSIVE_OR_EXPRESSION, |
2123 | PREC_EXCLUSIVE_OR_EXPRESSION, |
2124 | PREC_AND_EXPRESSION, |
2125 | PREC_EQUALITY_EXPRESSION, |
2126 | PREC_RELATIONAL_EXPRESSION, |
2127 | PREC_SPACESHIP_EXPRESSION, |
2128 | PREC_SHIFT_EXPRESSION, |
2129 | PREC_ADDITIVE_EXPRESSION, |
2130 | PREC_MULTIPLICATIVE_EXPRESSION, |
2131 | PREC_PM_EXPRESSION, |
2132 | NUM_PREC_VALUES = PREC_PM_EXPRESSION |
2133 | }; |
2134 | |
2135 | /* A mapping from a token type to a corresponding tree node type, with a |
2136 | precedence value. */ |
2137 | |
2138 | struct cp_parser_binary_operations_map_node |
2139 | { |
2140 | /* The token type. */ |
2141 | enum cpp_ttype token_type; |
2142 | /* The corresponding tree code. */ |
2143 | enum tree_code tree_type; |
2144 | /* The precedence of this operator. */ |
2145 | enum cp_parser_prec prec; |
2146 | }; |
2147 | |
2148 | struct cp_parser_expression_stack_entry |
2149 | { |
2150 | /* Left hand side of the binary operation we are currently |
2151 | parsing. */ |
2152 | cp_expr lhs; |
2153 | /* Original tree code for left hand side, if it was a binary |
2154 | expression itself (used for -Wparentheses). */ |
2155 | enum tree_code lhs_type; |
2156 | /* Tree code for the binary operation we are parsing. */ |
2157 | enum tree_code tree_type; |
2158 | /* Precedence of the binary operation we are parsing. */ |
2159 | enum cp_parser_prec prec; |
2160 | /* Location of the binary operation we are parsing. */ |
2161 | location_t loc; |
2162 | /* Flags from the operator token. */ |
2163 | unsigned char flags; |
2164 | }; |
2165 | |
2166 | /* The stack for storing partial expressions. We only need NUM_PREC_VALUES |
2167 | entries because precedence levels on the stack are monotonically |
2168 | increasing. */ |
2169 | typedef struct cp_parser_expression_stack_entry |
2170 | cp_parser_expression_stack[NUM_PREC_VALUES]; |
2171 | |
2172 | /* Used for parsing OMP for loops. |
2173 | |
2174 | Some notes on flags used for context: |
2175 | parser->omp_for_parse_state is non-null anywhere inside the OMP FOR |
2176 | construct, except for the final-loop-body. |
2177 | The want_nested_loop flag is true if inside a {} sequence where |
2178 | a loop-nest (or another {} sequence containing a loop-nest) is expected, |
2179 | but has not yet been seen. It's false when parsing intervening code |
2180 | statements or their substatements that cannot contain a loop-nest. |
2181 | The in_intervening_code flag is true when parsing any intervening code, |
2182 | including substatements, and whether or not want_nested_loop is true. |
2183 | |
2184 | And, about error handling: |
2185 | The saw_intervening_code flag is set if the loop is not perfectly |
2186 | nested, even in the usual case where this is not an error. |
2187 | perfect_nesting_fail is set if an error has been diagnosed because an |
2188 | imperfectly-nested loop was found where a perfectly-nested one is |
2189 | required (we diagnose this only once). |
2190 | fail is set if any kind of structural error in the loop nest |
2191 | has been found and diagnosed. |
2192 | */ |
2193 | struct omp_for_parse_data { |
2194 | enum tree_code code; |
2195 | tree declv, condv, incrv, initv; |
2196 | tree pre_body; |
2197 | tree orig_declv; |
2198 | auto_vec<tree, 4> orig_inits; |
2199 | int count; /* Expected nesting depth. */ |
2200 | int depth; /* Current nesting depth. */ |
2201 | location_t for_loc; |
2202 | releasing_vec init_blockv; |
2203 | releasing_vec body_blockv; |
2204 | releasing_vec init_placeholderv; |
2205 | releasing_vec body_placeholderv; |
2206 | bool ordered : 1; |
2207 | bool inscan : 1; |
2208 | bool want_nested_loop : 1; |
2209 | bool in_intervening_code : 1; |
2210 | bool saw_intervening_code : 1; |
2211 | bool perfect_nesting_fail : 1; |
2212 | bool fail : 1; |
2213 | tree clauses; |
2214 | tree *cclauses; |
2215 | tree ordered_cl; |
2216 | }; |
2217 | |
2218 | /* Prototypes. */ |
2219 | |
2220 | /* Constructors and destructors. */ |
2221 | |
2222 | static cp_parser_context *cp_parser_context_new |
2223 | (cp_parser_context *); |
2224 | |
2225 | /* Class variables. */ |
2226 | |
2227 | static GTY((deletable)) cp_parser_context* cp_parser_context_free_list; |
2228 | |
2229 | /* The operator-precedence table used by cp_parser_binary_expression. |
2230 | Transformed into an associative array (binops_by_token) by |
2231 | cp_parser_new. */ |
2232 | |
2233 | static const cp_parser_binary_operations_map_node binops[] = { |
2234 | { .token_type: CPP_DEREF_STAR, .tree_type: MEMBER_REF, .prec: PREC_PM_EXPRESSION }, |
2235 | { .token_type: CPP_DOT_STAR, .tree_type: DOTSTAR_EXPR, .prec: PREC_PM_EXPRESSION }, |
2236 | |
2237 | { .token_type: CPP_MULT, .tree_type: MULT_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2238 | { .token_type: CPP_DIV, .tree_type: TRUNC_DIV_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2239 | { .token_type: CPP_MOD, .tree_type: TRUNC_MOD_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2240 | |
2241 | { .token_type: CPP_PLUS, .tree_type: PLUS_EXPR, .prec: PREC_ADDITIVE_EXPRESSION }, |
2242 | { .token_type: CPP_MINUS, .tree_type: MINUS_EXPR, .prec: PREC_ADDITIVE_EXPRESSION }, |
2243 | |
2244 | { .token_type: CPP_LSHIFT, .tree_type: LSHIFT_EXPR, .prec: PREC_SHIFT_EXPRESSION }, |
2245 | { .token_type: CPP_RSHIFT, .tree_type: RSHIFT_EXPR, .prec: PREC_SHIFT_EXPRESSION }, |
2246 | |
2247 | { .token_type: CPP_SPACESHIP, .tree_type: SPACESHIP_EXPR, .prec: PREC_SPACESHIP_EXPRESSION }, |
2248 | |
2249 | { .token_type: CPP_LESS, .tree_type: LT_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2250 | { .token_type: CPP_GREATER, .tree_type: GT_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2251 | { .token_type: CPP_LESS_EQ, .tree_type: LE_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2252 | { .token_type: CPP_GREATER_EQ, .tree_type: GE_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2253 | |
2254 | { .token_type: CPP_EQ_EQ, .tree_type: EQ_EXPR, .prec: PREC_EQUALITY_EXPRESSION }, |
2255 | { .token_type: CPP_NOT_EQ, .tree_type: NE_EXPR, .prec: PREC_EQUALITY_EXPRESSION }, |
2256 | |
2257 | { .token_type: CPP_AND, .tree_type: BIT_AND_EXPR, .prec: PREC_AND_EXPRESSION }, |
2258 | |
2259 | { .token_type: CPP_XOR, .tree_type: BIT_XOR_EXPR, .prec: PREC_EXCLUSIVE_OR_EXPRESSION }, |
2260 | |
2261 | { .token_type: CPP_OR, .tree_type: BIT_IOR_EXPR, .prec: PREC_INCLUSIVE_OR_EXPRESSION }, |
2262 | |
2263 | { .token_type: CPP_AND_AND, .tree_type: TRUTH_ANDIF_EXPR, .prec: PREC_LOGICAL_AND_EXPRESSION }, |
2264 | |
2265 | { .token_type: CPP_OR_OR, .tree_type: TRUTH_ORIF_EXPR, .prec: PREC_LOGICAL_OR_EXPRESSION } |
2266 | }; |
2267 | |
2268 | /* The same as binops, but initialized by cp_parser_new so that |
2269 | binops_by_token[N].token_type == N. Used in cp_parser_binary_expression |
2270 | for speed. */ |
2271 | static cp_parser_binary_operations_map_node binops_by_token[N_CP_TTYPES]; |
2272 | |
2273 | /* Constructors and destructors. */ |
2274 | |
2275 | /* Construct a new context. The context below this one on the stack |
2276 | is given by NEXT. */ |
2277 | |
2278 | static cp_parser_context * |
2279 | cp_parser_context_new (cp_parser_context* next) |
2280 | { |
2281 | cp_parser_context *context; |
2282 | |
2283 | /* Allocate the storage. */ |
2284 | if (cp_parser_context_free_list != NULL) |
2285 | { |
2286 | /* Pull the first entry from the free list. */ |
2287 | context = cp_parser_context_free_list; |
2288 | cp_parser_context_free_list = context->next; |
2289 | memset (s: context, c: 0, n: sizeof (*context)); |
2290 | } |
2291 | else |
2292 | context = ggc_cleared_alloc<cp_parser_context> (); |
2293 | |
2294 | /* No errors have occurred yet in this context. */ |
2295 | context->status = CP_PARSER_STATUS_KIND_NO_ERROR; |
2296 | /* If this is not the bottommost context, copy information that we |
2297 | need from the previous context. */ |
2298 | if (next) |
2299 | { |
2300 | /* If, in the NEXT context, we are parsing an `x->' or `x.' |
2301 | expression, then we are parsing one in this context, too. */ |
2302 | context->object_type = next->object_type; |
2303 | /* Thread the stack. */ |
2304 | context->next = next; |
2305 | } |
2306 | |
2307 | return context; |
2308 | } |
2309 | |
2310 | /* Managing the unparsed function queues. */ |
2311 | |
2312 | #define unparsed_funs_with_default_args \ |
2313 | parser->unparsed_queues->last ().funs_with_default_args |
2314 | #define unparsed_funs_with_definitions \ |
2315 | parser->unparsed_queues->last ().funs_with_definitions |
2316 | #define unparsed_nsdmis \ |
2317 | parser->unparsed_queues->last ().nsdmis |
2318 | #define unparsed_noexcepts \ |
2319 | parser->unparsed_queues->last ().noexcepts |
2320 | #define unparsed_contracts \ |
2321 | parser->unparsed_queues->last ().contracts |
2322 | |
2323 | static void |
2324 | push_unparsed_function_queues (cp_parser *parser) |
2325 | { |
2326 | cp_unparsed_functions_entry e |
2327 | = { NULL, .funs_with_definitions: make_tree_vector (), NULL, NULL, NULL }; |
2328 | vec_safe_push (v&: parser->unparsed_queues, obj: e); |
2329 | } |
2330 | |
2331 | static void |
2332 | pop_unparsed_function_queues (cp_parser *parser) |
2333 | { |
2334 | release_tree_vector (unparsed_funs_with_definitions); |
2335 | parser->unparsed_queues->pop (); |
2336 | } |
2337 | |
2338 | /* Prototypes. */ |
2339 | |
2340 | /* Routines to parse various constructs. |
2341 | |
2342 | Those that return `tree' will return the error_mark_node (rather |
2343 | than NULL_TREE) if a parse error occurs, unless otherwise noted. |
2344 | Sometimes, they will return an ordinary node if error-recovery was |
2345 | attempted, even though a parse error occurred. So, to check |
2346 | whether or not a parse error occurred, you should always use |
2347 | cp_parser_error_occurred. If the construct is optional (indicated |
2348 | either by an `_opt' in the name of the function that does the |
2349 | parsing or via a FLAGS parameter), then NULL_TREE is returned if |
2350 | the construct is not present. */ |
2351 | |
2352 | /* Lexical conventions [gram.lex] */ |
2353 | |
2354 | static tree finish_userdef_string_literal |
2355 | (tree); |
2356 | |
2357 | /* Basic concepts [gram.basic] */ |
2358 | |
2359 | static void cp_parser_translation_unit (cp_parser *); |
2360 | |
2361 | /* Expressions [gram.expr] */ |
2362 | |
2363 | static cp_expr cp_parser_primary_expression |
2364 | (cp_parser *, bool, bool, bool, cp_id_kind *); |
2365 | static cp_expr cp_parser_id_expression |
2366 | (cp_parser *, bool, bool, bool *, bool, bool); |
2367 | static cp_expr cp_parser_unqualified_id |
2368 | (cp_parser *, bool, bool, bool, bool); |
2369 | static tree cp_parser_nested_name_specifier_opt |
2370 | (cp_parser *, bool, bool, bool, bool, bool = false); |
2371 | static tree cp_parser_nested_name_specifier |
2372 | (cp_parser *, bool, bool, bool, bool); |
2373 | static tree cp_parser_qualifying_entity |
2374 | (cp_parser *, bool, bool, bool, bool, bool); |
2375 | static cp_expr cp_parser_postfix_expression |
2376 | (cp_parser *, bool, bool, bool, bool, cp_id_kind *); |
2377 | static tree cp_parser_postfix_open_square_expression |
2378 | (cp_parser *, tree, bool, bool); |
2379 | static tree cp_parser_postfix_dot_deref_expression |
2380 | (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t); |
2381 | static vec<tree, va_gc> *cp_parser_parenthesized_expression_list |
2382 | (cp_parser *, int, bool, bool, bool *, location_t * = NULL, |
2383 | bool = false); |
2384 | /* Values for the second parameter of cp_parser_parenthesized_expression_list. */ |
2385 | enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3, |
2386 | uneval_string_attr = 4 }; |
2387 | static void cp_parser_pseudo_destructor_name |
2388 | (cp_parser *, tree, tree *, tree *); |
2389 | static cp_expr cp_parser_unary_expression |
2390 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false); |
2391 | static enum tree_code cp_parser_unary_operator |
2392 | (cp_token *); |
2393 | static tree cp_parser_has_attribute_expression |
2394 | (cp_parser *); |
2395 | static tree cp_parser_new_expression |
2396 | (cp_parser *); |
2397 | static vec<tree, va_gc> *cp_parser_new_placement |
2398 | (cp_parser *); |
2399 | static tree cp_parser_new_type_id |
2400 | (cp_parser *, tree *); |
2401 | static cp_declarator *cp_parser_new_declarator_opt |
2402 | (cp_parser *); |
2403 | static cp_declarator *cp_parser_direct_new_declarator |
2404 | (cp_parser *); |
2405 | static vec<tree, va_gc> *cp_parser_new_initializer |
2406 | (cp_parser *); |
2407 | static tree cp_parser_delete_expression |
2408 | (cp_parser *); |
2409 | static cp_expr cp_parser_cast_expression |
2410 | (cp_parser *, bool, bool, bool, cp_id_kind *); |
2411 | static cp_expr cp_parser_binary_expression |
2412 | (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *); |
2413 | static tree cp_parser_question_colon_clause |
2414 | (cp_parser *, cp_expr); |
2415 | static cp_expr cp_parser_conditional_expression (cp_parser *); |
2416 | static cp_expr cp_parser_assignment_expression |
2417 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false); |
2418 | static enum tree_code cp_parser_assignment_operator_opt |
2419 | (cp_parser *); |
2420 | static cp_expr cp_parser_expression |
2421 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false); |
2422 | static cp_expr cp_parser_constant_expression |
2423 | (cp_parser *, int = 0, bool * = NULL, bool = false); |
2424 | static cp_expr cp_parser_builtin_offsetof |
2425 | (cp_parser *); |
2426 | static cp_expr cp_parser_lambda_expression |
2427 | (cp_parser *); |
2428 | static void cp_parser_lambda_introducer |
2429 | (cp_parser *, tree); |
2430 | static bool cp_parser_lambda_declarator_opt |
2431 | (cp_parser *, tree); |
2432 | static void cp_parser_lambda_body |
2433 | (cp_parser *, tree); |
2434 | |
2435 | /* Statements [gram.stmt.stmt] */ |
2436 | |
2437 | static void cp_parser_statement |
2438 | (cp_parser *, tree, bool, bool *, vec<tree> * = NULL, location_t * = NULL); |
2439 | static void cp_parser_label_for_labeled_statement |
2440 | (cp_parser *, tree); |
2441 | static tree cp_parser_expression_statement |
2442 | (cp_parser *, tree); |
2443 | static tree cp_parser_compound_statement |
2444 | (cp_parser *, tree, int, bool); |
2445 | static void cp_parser_statement_seq_opt |
2446 | (cp_parser *, tree); |
2447 | static tree cp_parser_selection_statement |
2448 | (cp_parser *, bool *, vec<tree> *); |
2449 | static tree cp_parser_condition |
2450 | (cp_parser *); |
2451 | static tree cp_parser_iteration_statement |
2452 | (cp_parser *, bool *, bool, tree, bool); |
2453 | static bool cp_parser_init_statement |
2454 | (cp_parser *, tree *decl); |
2455 | static tree cp_parser_for |
2456 | (cp_parser *, bool, tree, bool); |
2457 | static tree cp_parser_c_for |
2458 | (cp_parser *, tree, tree, bool, tree, bool); |
2459 | static tree cp_parser_range_for |
2460 | (cp_parser *, tree, tree, tree, bool, tree, bool, bool); |
2461 | static void do_range_for_auto_deduction |
2462 | (tree, tree, cp_decomp *); |
2463 | static tree cp_parser_perform_range_for_lookup |
2464 | (tree, tree *, tree *); |
2465 | static tree cp_parser_range_for_member_function |
2466 | (tree, tree); |
2467 | static tree cp_parser_jump_statement |
2468 | (cp_parser *); |
2469 | static void cp_parser_declaration_statement |
2470 | (cp_parser *); |
2471 | |
2472 | static tree cp_parser_implicitly_scoped_statement |
2473 | (cp_parser *, bool *, const token_indent_info &, vec<tree> * = NULL); |
2474 | static void cp_parser_already_scoped_statement |
2475 | (cp_parser *, bool *, const token_indent_info &); |
2476 | |
2477 | /* State of module-declaration parsing. */ |
2478 | enum module_parse |
2479 | { |
2480 | MP_NOT_MODULE, /* Not a module. */ |
2481 | |
2482 | _MP_UNUSED, |
2483 | |
2484 | MP_FIRST, /* First declaration of TU. */ |
2485 | MP_GLOBAL, /* Global Module Fragment. */ |
2486 | |
2487 | MP_PURVIEW_IMPORTS, /* Imports of a module. */ |
2488 | MP_PURVIEW, /* Purview of a named module. */ |
2489 | |
2490 | MP_PRIVATE_IMPORTS, /* Imports of a Private Module Fragment. */ |
2491 | MP_PRIVATE, /* Private Module Fragment. */ |
2492 | }; |
2493 | |
2494 | static module_parse cp_parser_module_declaration |
2495 | (cp_parser *parser, module_parse, bool exporting); |
2496 | static void cp_parser_import_declaration |
2497 | (cp_parser *parser, module_parse, bool exporting); |
2498 | |
2499 | /* Declarations [gram.dcl.dcl] */ |
2500 | |
2501 | static void cp_parser_declaration_seq_opt |
2502 | (cp_parser *); |
2503 | static void cp_parser_declaration |
2504 | (cp_parser *, tree); |
2505 | static void cp_parser_toplevel_declaration |
2506 | (cp_parser *); |
2507 | static void cp_parser_block_declaration |
2508 | (cp_parser *, bool); |
2509 | static void cp_parser_simple_declaration |
2510 | (cp_parser *, bool, tree *); |
2511 | static void cp_parser_decl_specifier_seq |
2512 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *); |
2513 | static tree cp_parser_storage_class_specifier_opt |
2514 | (cp_parser *); |
2515 | static tree cp_parser_function_specifier_opt |
2516 | (cp_parser *, cp_decl_specifier_seq *); |
2517 | static tree cp_parser_type_specifier |
2518 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool, |
2519 | int *, bool *); |
2520 | static tree cp_parser_simple_type_specifier |
2521 | (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags); |
2522 | static tree cp_parser_placeholder_type_specifier |
2523 | (cp_parser *, location_t, tree, bool); |
2524 | static tree cp_parser_type_name |
2525 | (cp_parser *, bool); |
2526 | static tree cp_parser_nonclass_name |
2527 | (cp_parser* parser); |
2528 | static tree cp_parser_elaborated_type_specifier |
2529 | (cp_parser *, bool, bool); |
2530 | static tree cp_parser_enum_specifier |
2531 | (cp_parser *); |
2532 | static void cp_parser_enumerator_list |
2533 | (cp_parser *, tree); |
2534 | static void cp_parser_enumerator_definition |
2535 | (cp_parser *, tree); |
2536 | static tree cp_parser_namespace_name |
2537 | (cp_parser *); |
2538 | static void cp_parser_namespace_definition |
2539 | (cp_parser *); |
2540 | static void cp_parser_namespace_body |
2541 | (cp_parser *); |
2542 | static tree cp_parser_qualified_namespace_specifier |
2543 | (cp_parser *); |
2544 | static void cp_parser_namespace_alias_definition |
2545 | (cp_parser *); |
2546 | static bool cp_parser_using_declaration |
2547 | (cp_parser *, bool); |
2548 | static void cp_parser_using_directive |
2549 | (cp_parser *); |
2550 | static void cp_parser_using_enum |
2551 | (cp_parser *); |
2552 | static tree cp_parser_alias_declaration |
2553 | (cp_parser *); |
2554 | static void cp_parser_asm_definition |
2555 | (cp_parser *); |
2556 | static void cp_parser_linkage_specification |
2557 | (cp_parser *, tree); |
2558 | static void cp_parser_static_assert |
2559 | (cp_parser *, bool); |
2560 | static tree cp_parser_decltype |
2561 | (cp_parser *); |
2562 | static tree cp_parser_decomposition_declaration |
2563 | (cp_parser *, cp_decl_specifier_seq *, tree *, location_t *); |
2564 | |
2565 | /* Declarators [gram.dcl.decl] */ |
2566 | |
2567 | static tree cp_parser_init_declarator |
2568 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, |
2569 | vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *, |
2570 | location_t *, tree *); |
2571 | static cp_declarator *cp_parser_declarator |
2572 | (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *, |
2573 | bool, bool, bool); |
2574 | static cp_declarator *cp_parser_direct_declarator |
2575 | (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool, |
2576 | bool); |
2577 | static enum tree_code cp_parser_ptr_operator |
2578 | (cp_parser *, tree *, cp_cv_quals *, tree *); |
2579 | static cp_cv_quals cp_parser_cv_qualifier_seq_opt |
2580 | (cp_parser *); |
2581 | static cp_virt_specifiers cp_parser_virt_specifier_seq_opt |
2582 | (cp_parser *); |
2583 | static cp_ref_qualifier cp_parser_ref_qualifier_opt |
2584 | (cp_parser *); |
2585 | static tree cp_parser_tx_qualifier_opt |
2586 | (cp_parser *); |
2587 | static tree cp_parser_late_return_type_opt |
2588 | (cp_parser *, cp_declarator *, tree &); |
2589 | static tree cp_parser_declarator_id |
2590 | (cp_parser *, bool); |
2591 | static tree cp_parser_type_id |
2592 | (cp_parser *, cp_parser_flags = CP_PARSER_FLAGS_NONE, location_t * = NULL); |
2593 | static tree cp_parser_template_type_arg |
2594 | (cp_parser *); |
2595 | static tree cp_parser_trailing_type_id (cp_parser *); |
2596 | static tree cp_parser_type_id_1 |
2597 | (cp_parser *, cp_parser_flags, bool, bool, location_t *); |
2598 | static void cp_parser_type_specifier_seq |
2599 | (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *); |
2600 | static tree cp_parser_parameter_declaration_clause |
2601 | (cp_parser *, cp_parser_flags); |
2602 | static tree cp_parser_parameter_declaration_list |
2603 | (cp_parser *, cp_parser_flags, auto_vec<tree> *); |
2604 | static cp_parameter_declarator *cp_parser_parameter_declaration |
2605 | (cp_parser *, cp_parser_flags, bool, bool *); |
2606 | static tree cp_parser_default_argument |
2607 | (cp_parser *, bool); |
2608 | static void cp_parser_function_body |
2609 | (cp_parser *, bool); |
2610 | static tree cp_parser_initializer |
2611 | (cp_parser *, bool * = nullptr, bool * = nullptr, bool = false); |
2612 | static cp_expr cp_parser_initializer_clause |
2613 | (cp_parser *, bool * = nullptr); |
2614 | static cp_expr cp_parser_braced_list |
2615 | (cp_parser*, bool * = nullptr); |
2616 | static vec<constructor_elt, va_gc> *cp_parser_initializer_list |
2617 | (cp_parser *, bool *, bool *); |
2618 | |
2619 | static void cp_parser_ctor_initializer_opt_and_function_body |
2620 | (cp_parser *, bool); |
2621 | |
2622 | static tree cp_parser_late_parsing_omp_declare_simd |
2623 | (cp_parser *, tree); |
2624 | |
2625 | static tree cp_parser_late_parsing_oacc_routine |
2626 | (cp_parser *, tree); |
2627 | |
2628 | static tree synthesize_implicit_template_parm |
2629 | (cp_parser *, tree); |
2630 | static tree finish_fully_implicit_template |
2631 | (cp_parser *, tree); |
2632 | static void abort_fully_implicit_template |
2633 | (cp_parser *); |
2634 | |
2635 | /* Classes [gram.class] */ |
2636 | |
2637 | static tree cp_parser_class_name |
2638 | (cp_parser *, bool, bool, enum tag_types, bool, bool, bool, bool = false); |
2639 | static tree cp_parser_class_specifier |
2640 | (cp_parser *); |
2641 | static tree cp_parser_class_head |
2642 | (cp_parser *, bool *); |
2643 | static enum tag_types cp_parser_class_key |
2644 | (cp_parser *); |
2645 | static void cp_parser_type_parameter_key |
2646 | (cp_parser* parser); |
2647 | static void cp_parser_member_specification_opt |
2648 | (cp_parser *); |
2649 | static void cp_parser_member_declaration |
2650 | (cp_parser *); |
2651 | static tree cp_parser_pure_specifier |
2652 | (cp_parser *); |
2653 | static tree cp_parser_constant_initializer |
2654 | (cp_parser *); |
2655 | |
2656 | /* Derived classes [gram.class.derived] */ |
2657 | |
2658 | static tree cp_parser_base_clause |
2659 | (cp_parser *); |
2660 | static tree cp_parser_base_specifier |
2661 | (cp_parser *); |
2662 | |
2663 | /* Special member functions [gram.special] */ |
2664 | |
2665 | static tree cp_parser_conversion_function_id |
2666 | (cp_parser *); |
2667 | static tree cp_parser_conversion_type_id |
2668 | (cp_parser *); |
2669 | static cp_declarator *cp_parser_conversion_declarator_opt |
2670 | (cp_parser *); |
2671 | static void cp_parser_ctor_initializer_opt |
2672 | (cp_parser *); |
2673 | static void cp_parser_mem_initializer_list |
2674 | (cp_parser *); |
2675 | static tree cp_parser_mem_initializer |
2676 | (cp_parser *); |
2677 | static tree cp_parser_mem_initializer_id |
2678 | (cp_parser *); |
2679 | |
2680 | /* Overloading [gram.over] */ |
2681 | |
2682 | static cp_expr cp_parser_operator_function_id |
2683 | (cp_parser *); |
2684 | static cp_expr cp_parser_operator |
2685 | (cp_parser *, location_t); |
2686 | |
2687 | /* Templates [gram.temp] */ |
2688 | |
2689 | static void cp_parser_template_declaration |
2690 | (cp_parser *, bool); |
2691 | static tree cp_parser_template_parameter_list |
2692 | (cp_parser *); |
2693 | static tree cp_parser_template_parameter |
2694 | (cp_parser *, bool *, bool *); |
2695 | static tree cp_parser_type_parameter |
2696 | (cp_parser *, bool *); |
2697 | static tree cp_parser_template_id |
2698 | (cp_parser *, bool, bool, enum tag_types, bool); |
2699 | static tree cp_parser_template_id_expr |
2700 | (cp_parser *, bool, bool, bool); |
2701 | static tree cp_parser_template_name |
2702 | (cp_parser *, bool, bool, bool, enum tag_types, bool *); |
2703 | static tree cp_parser_template_argument_list |
2704 | (cp_parser *); |
2705 | static tree cp_parser_template_argument |
2706 | (cp_parser *); |
2707 | static void cp_parser_explicit_instantiation |
2708 | (cp_parser *); |
2709 | static void cp_parser_explicit_specialization |
2710 | (cp_parser *); |
2711 | |
2712 | /* Exception handling [gram.except] */ |
2713 | |
2714 | static tree cp_parser_try_block |
2715 | (cp_parser *); |
2716 | static void cp_parser_function_try_block |
2717 | (cp_parser *); |
2718 | static void cp_parser_handler_seq |
2719 | (cp_parser *); |
2720 | static void cp_parser_handler |
2721 | (cp_parser *); |
2722 | static tree cp_parser_exception_declaration |
2723 | (cp_parser *); |
2724 | static tree cp_parser_throw_expression |
2725 | (cp_parser *); |
2726 | static tree cp_parser_exception_specification_opt |
2727 | (cp_parser *, cp_parser_flags); |
2728 | static tree cp_parser_type_id_list |
2729 | (cp_parser *); |
2730 | static tree cp_parser_noexcept_specification_opt |
2731 | (cp_parser *, cp_parser_flags, bool, bool *, bool); |
2732 | |
2733 | /* GNU Extensions */ |
2734 | |
2735 | static tree cp_parser_asm_specification_opt |
2736 | (cp_parser *); |
2737 | static tree cp_parser_asm_operand_list |
2738 | (cp_parser *); |
2739 | static tree cp_parser_asm_clobber_list |
2740 | (cp_parser *); |
2741 | static tree cp_parser_asm_label_list |
2742 | (cp_parser *); |
2743 | static bool cp_next_tokens_can_be_attribute_p |
2744 | (cp_parser *); |
2745 | static bool cp_next_tokens_can_be_gnu_attribute_p |
2746 | (cp_parser *); |
2747 | static bool cp_next_tokens_can_be_std_attribute_p |
2748 | (cp_parser *); |
2749 | static bool cp_nth_tokens_can_be_std_attribute_p |
2750 | (cp_parser *, size_t); |
2751 | static bool cp_nth_tokens_can_be_gnu_attribute_p |
2752 | (cp_parser *, size_t); |
2753 | static bool cp_nth_tokens_can_be_attribute_p |
2754 | (cp_parser *, size_t); |
2755 | static tree cp_parser_attributes_opt |
2756 | (cp_parser *); |
2757 | static tree cp_parser_gnu_attributes_opt |
2758 | (cp_parser *); |
2759 | static tree cp_parser_gnu_attribute_list |
2760 | (cp_parser *, bool = false); |
2761 | static tree cp_parser_std_attribute |
2762 | (cp_parser *, tree); |
2763 | static tree cp_parser_std_attribute_spec |
2764 | (cp_parser *); |
2765 | static tree cp_parser_std_attribute_spec_seq |
2766 | (cp_parser *); |
2767 | static size_t cp_parser_skip_std_attribute_spec_seq |
2768 | (cp_parser *, size_t); |
2769 | static size_t cp_parser_skip_attributes_opt |
2770 | (cp_parser *, size_t); |
2771 | static bool cp_parser_extension_opt |
2772 | (cp_parser *, int *); |
2773 | static void cp_parser_label_declaration |
2774 | (cp_parser *); |
2775 | |
2776 | /* Concept Extensions */ |
2777 | |
2778 | static tree cp_parser_concept_definition |
2779 | (cp_parser *); |
2780 | static tree cp_parser_constraint_expression |
2781 | (cp_parser *); |
2782 | static tree cp_parser_requires_clause_opt |
2783 | (cp_parser *, bool); |
2784 | static tree cp_parser_requires_expression |
2785 | (cp_parser *); |
2786 | static tree cp_parser_requirement_parameter_list |
2787 | (cp_parser *); |
2788 | static tree cp_parser_requirement_body |
2789 | (cp_parser *); |
2790 | static tree cp_parser_requirement_seq |
2791 | (cp_parser *); |
2792 | static tree cp_parser_requirement |
2793 | (cp_parser *); |
2794 | static tree cp_parser_simple_requirement |
2795 | (cp_parser *); |
2796 | static tree cp_parser_compound_requirement |
2797 | (cp_parser *); |
2798 | static tree cp_parser_type_requirement |
2799 | (cp_parser *); |
2800 | static tree cp_parser_nested_requirement |
2801 | (cp_parser *); |
2802 | |
2803 | /* Transactional Memory Extensions */ |
2804 | |
2805 | static tree cp_parser_transaction |
2806 | (cp_parser *, cp_token *); |
2807 | static tree cp_parser_transaction_expression |
2808 | (cp_parser *, enum rid); |
2809 | static void cp_parser_function_transaction |
2810 | (cp_parser *, enum rid); |
2811 | static tree cp_parser_transaction_cancel |
2812 | (cp_parser *); |
2813 | |
2814 | /* Coroutine extensions. */ |
2815 | |
2816 | static tree cp_parser_yield_expression |
2817 | (cp_parser *); |
2818 | |
2819 | /* Contracts */ |
2820 | |
2821 | static void cp_parser_late_contract_condition |
2822 | (cp_parser *, tree, tree); |
2823 | |
2824 | enum pragma_context { |
2825 | pragma_external, |
2826 | pragma_member, |
2827 | pragma_objc_icode, |
2828 | pragma_stmt, |
2829 | pragma_compound |
2830 | }; |
2831 | static bool cp_parser_pragma |
2832 | (cp_parser *, enum pragma_context, bool *); |
2833 | |
2834 | /* Objective-C++ Productions */ |
2835 | |
2836 | static tree cp_parser_objc_message_receiver |
2837 | (cp_parser *); |
2838 | static tree cp_parser_objc_message_args |
2839 | (cp_parser *); |
2840 | static tree cp_parser_objc_message_expression |
2841 | (cp_parser *); |
2842 | static cp_expr cp_parser_objc_encode_expression |
2843 | (cp_parser *); |
2844 | static tree cp_parser_objc_defs_expression |
2845 | (cp_parser *); |
2846 | static tree cp_parser_objc_protocol_expression |
2847 | (cp_parser *); |
2848 | static tree cp_parser_objc_selector_expression |
2849 | (cp_parser *); |
2850 | static cp_expr cp_parser_objc_expression |
2851 | (cp_parser *); |
2852 | static bool cp_parser_objc_selector_p |
2853 | (enum cpp_ttype); |
2854 | static tree cp_parser_objc_selector |
2855 | (cp_parser *); |
2856 | static tree cp_parser_objc_protocol_refs_opt |
2857 | (cp_parser *); |
2858 | static void cp_parser_objc_declaration |
2859 | (cp_parser *, tree); |
2860 | static tree cp_parser_objc_statement |
2861 | (cp_parser *); |
2862 | static bool cp_parser_objc_valid_prefix_attributes |
2863 | (cp_parser *, tree *); |
2864 | static void cp_parser_objc_at_property_declaration |
2865 | (cp_parser *) ; |
2866 | static void cp_parser_objc_at_synthesize_declaration |
2867 | (cp_parser *) ; |
2868 | static void cp_parser_objc_at_dynamic_declaration |
2869 | (cp_parser *) ; |
2870 | static tree cp_parser_objc_struct_declaration |
2871 | (cp_parser *) ; |
2872 | |
2873 | /* Utility Routines */ |
2874 | |
2875 | static cp_expr cp_parser_lookup_name |
2876 | (cp_parser *, tree, enum tag_types, int, bool, bool, tree *, location_t); |
2877 | static tree cp_parser_lookup_name_simple |
2878 | (cp_parser *, tree, location_t); |
2879 | static tree cp_parser_maybe_treat_template_as_class |
2880 | (tree, bool); |
2881 | static bool cp_parser_check_declarator_template_parameters |
2882 | (cp_parser *, cp_declarator *, location_t); |
2883 | static bool cp_parser_check_template_parameters |
2884 | (cp_parser *, unsigned, bool, location_t, cp_declarator *); |
2885 | static cp_expr cp_parser_simple_cast_expression |
2886 | (cp_parser *); |
2887 | static tree cp_parser_global_scope_opt |
2888 | (cp_parser *, bool); |
2889 | static bool cp_parser_constructor_declarator_p |
2890 | (cp_parser *, cp_parser_flags, bool); |
2891 | static tree cp_parser_function_definition_from_specifiers_and_declarator |
2892 | (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *); |
2893 | static tree cp_parser_function_definition_after_declarator |
2894 | (cp_parser *, bool); |
2895 | static bool cp_parser_template_declaration_after_export |
2896 | (cp_parser *, bool); |
2897 | static void cp_parser_perform_template_parameter_access_checks |
2898 | (vec<deferred_access_check, va_gc> *); |
2899 | static tree cp_parser_single_declaration |
2900 | (cp_parser *, vec<deferred_access_check, va_gc> *, bool, bool, bool *); |
2901 | static cp_expr cp_parser_functional_cast |
2902 | (cp_parser *, tree); |
2903 | static tree cp_parser_save_member_function_body |
2904 | (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree); |
2905 | static tree cp_parser_save_nsdmi |
2906 | (cp_parser *); |
2907 | static tree cp_parser_enclosed_template_argument_list |
2908 | (cp_parser *); |
2909 | static void cp_parser_save_default_args |
2910 | (cp_parser *, tree); |
2911 | static void cp_parser_late_parsing_for_member |
2912 | (cp_parser *, tree); |
2913 | static tree cp_parser_late_parse_one_default_arg |
2914 | (cp_parser *, tree, tree, tree); |
2915 | static void cp_parser_late_parsing_nsdmi |
2916 | (cp_parser *, tree); |
2917 | static void cp_parser_late_parsing_default_args |
2918 | (cp_parser *, tree); |
2919 | static tree cp_parser_sizeof_operand |
2920 | (cp_parser *, enum rid); |
2921 | static cp_expr cp_parser_trait |
2922 | (cp_parser *, const cp_trait *); |
2923 | static bool cp_parser_declares_only_class_p |
2924 | (cp_parser *); |
2925 | static void cp_parser_set_storage_class |
2926 | (cp_parser *, cp_decl_specifier_seq *, enum rid, cp_token *); |
2927 | static void cp_parser_set_decl_spec_type |
2928 | (cp_decl_specifier_seq *, tree, cp_token *, bool); |
2929 | static void set_and_check_decl_spec_loc |
2930 | (cp_decl_specifier_seq *decl_specs, |
2931 | cp_decl_spec ds, cp_token *); |
2932 | static bool cp_parser_friend_p |
2933 | (const cp_decl_specifier_seq *); |
2934 | static void cp_parser_required_error |
2935 | (cp_parser *, required_token, bool, location_t); |
2936 | static cp_token *cp_parser_require |
2937 | (cp_parser *, enum cpp_ttype, required_token, location_t = UNKNOWN_LOCATION); |
2938 | static cp_token *cp_parser_require_keyword |
2939 | (cp_parser *, enum rid, required_token); |
2940 | static bool cp_parser_token_starts_function_definition_p |
2941 | (cp_token *); |
2942 | static bool cp_parser_next_token_starts_class_definition_p |
2943 | (cp_parser *); |
2944 | static bool cp_parser_next_token_ends_template_argument_p |
2945 | (cp_parser *); |
2946 | static bool cp_parser_nth_token_starts_template_argument_list_p |
2947 | (cp_parser *, size_t); |
2948 | static enum tag_types cp_parser_token_is_class_key |
2949 | (cp_token *); |
2950 | static enum tag_types cp_parser_token_is_type_parameter_key |
2951 | (cp_token *); |
2952 | static void cp_parser_maybe_warn_enum_key (cp_parser *, location_t, tree, rid); |
2953 | static void cp_parser_check_class_key |
2954 | (cp_parser *, location_t, enum tag_types, tree type, bool, bool); |
2955 | static void cp_parser_check_access_in_redeclaration |
2956 | (tree type, location_t location); |
2957 | static bool cp_parser_optional_template_keyword |
2958 | (cp_parser *); |
2959 | static void cp_parser_pre_parsed_nested_name_specifier |
2960 | (cp_parser *); |
2961 | static bool cp_parser_cache_group |
2962 | (cp_parser *, enum cpp_ttype, unsigned); |
2963 | static tree cp_parser_cache_defarg |
2964 | (cp_parser *parser, bool nsdmi); |
2965 | static void cp_parser_parse_tentatively |
2966 | (cp_parser *); |
2967 | static void cp_parser_commit_to_tentative_parse |
2968 | (cp_parser *); |
2969 | static void cp_parser_commit_to_topmost_tentative_parse |
2970 | (cp_parser *); |
2971 | static void cp_parser_abort_tentative_parse |
2972 | (cp_parser *); |
2973 | static bool cp_parser_parse_definitely |
2974 | (cp_parser *); |
2975 | static inline bool cp_parser_parsing_tentatively |
2976 | (cp_parser *); |
2977 | static bool cp_parser_uncommitted_to_tentative_parse_p |
2978 | (cp_parser *); |
2979 | static void cp_parser_error |
2980 | (cp_parser *, const char *); |
2981 | static void cp_parser_name_lookup_error |
2982 | (cp_parser *, tree, tree, name_lookup_error, location_t); |
2983 | static bool cp_parser_simulate_error |
2984 | (cp_parser *); |
2985 | static bool cp_parser_check_type_definition |
2986 | (cp_parser *); |
2987 | static void cp_parser_check_for_definition_in_return_type |
2988 | (cp_declarator *, tree, location_t type_location); |
2989 | static void cp_parser_check_for_invalid_template_id |
2990 | (cp_parser *, tree, enum tag_types, location_t location); |
2991 | static bool cp_parser_non_integral_constant_expression |
2992 | (cp_parser *, non_integral_constant); |
2993 | static void cp_parser_diagnose_invalid_type_name |
2994 | (cp_parser *, tree, location_t); |
2995 | static bool cp_parser_parse_and_diagnose_invalid_type_name |
2996 | (cp_parser *); |
2997 | static int cp_parser_skip_to_closing_parenthesis |
2998 | (cp_parser *, bool, bool, bool); |
2999 | static void cp_parser_skip_to_end_of_statement |
3000 | (cp_parser *); |
3001 | static void cp_parser_consume_semicolon_at_end_of_statement |
3002 | (cp_parser *); |
3003 | static void cp_parser_skip_to_end_of_block_or_statement |
3004 | (cp_parser *); |
3005 | static bool cp_parser_skip_to_closing_brace |
3006 | (cp_parser *); |
3007 | static bool cp_parser_skip_entire_template_parameter_list |
3008 | (cp_parser *); |
3009 | static void cp_parser_require_end_of_template_parameter_list |
3010 | (cp_parser *); |
3011 | static bool cp_parser_skip_to_end_of_template_parameter_list |
3012 | (cp_parser *); |
3013 | static void cp_parser_skip_to_pragma_eol |
3014 | (cp_parser*, cp_token *); |
3015 | static bool cp_parser_error_occurred |
3016 | (cp_parser *); |
3017 | static bool cp_parser_allow_gnu_extensions_p |
3018 | (cp_parser *); |
3019 | static bool cp_parser_is_pure_string_literal |
3020 | (cp_token *); |
3021 | static bool cp_parser_is_string_literal |
3022 | (cp_token *); |
3023 | static bool cp_parser_is_keyword |
3024 | (cp_token *, enum rid); |
3025 | static tree cp_parser_make_typename_type |
3026 | (cp_parser *, tree, location_t location); |
3027 | static cp_declarator * cp_parser_make_indirect_declarator |
3028 | (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree); |
3029 | static bool cp_parser_compound_literal_p |
3030 | (cp_parser *); |
3031 | static bool cp_parser_array_designator_p |
3032 | (cp_parser *); |
3033 | static bool cp_parser_init_statement_p |
3034 | (cp_parser *); |
3035 | static bool cp_parser_skip_up_to_closing_square_bracket |
3036 | (cp_parser *); |
3037 | static bool cp_parser_skip_to_closing_square_bracket |
3038 | (cp_parser *); |
3039 | static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t); |
3040 | static tree cp_parser_omp_loop_nest (cp_parser *, bool *); |
3041 | |
3042 | // -------------------------------------------------------------------------- // |
3043 | // Unevaluated Operand Guard |
3044 | // |
3045 | // Implementation of an RAII helper for unevaluated operand parsing. |
3046 | cp_unevaluated::cp_unevaluated () |
3047 | { |
3048 | ++cp_unevaluated_operand; |
3049 | ++c_inhibit_evaluation_warnings; |
3050 | } |
3051 | |
3052 | cp_unevaluated::~cp_unevaluated () |
3053 | { |
3054 | --c_inhibit_evaluation_warnings; |
3055 | --cp_unevaluated_operand; |
3056 | } |
3057 | |
3058 | // -------------------------------------------------------------------------- // |
3059 | // Tentative Parsing |
3060 | |
3061 | /* Returns nonzero if we are parsing tentatively. */ |
3062 | |
3063 | static inline bool |
3064 | cp_parser_parsing_tentatively (cp_parser* parser) |
3065 | { |
3066 | return parser->context->next != NULL; |
3067 | } |
3068 | |
3069 | /* Returns nonzero if TOKEN is a string literal. */ |
3070 | |
3071 | static bool |
3072 | cp_parser_is_pure_string_literal (cp_token* token) |
3073 | { |
3074 | return (token->type == CPP_STRING || |
3075 | token->type == CPP_STRING16 || |
3076 | token->type == CPP_STRING32 || |
3077 | token->type == CPP_WSTRING || |
3078 | token->type == CPP_UTF8STRING); |
3079 | } |
3080 | |
3081 | /* Returns nonzero if TOKEN is a string literal |
3082 | of a user-defined string literal. */ |
3083 | |
3084 | static bool |
3085 | cp_parser_is_string_literal (cp_token* token) |
3086 | { |
3087 | return (cp_parser_is_pure_string_literal (token) || |
3088 | token->type == CPP_STRING_USERDEF || |
3089 | token->type == CPP_STRING16_USERDEF || |
3090 | token->type == CPP_STRING32_USERDEF || |
3091 | token->type == CPP_WSTRING_USERDEF || |
3092 | token->type == CPP_UTF8STRING_USERDEF); |
3093 | } |
3094 | |
3095 | /* Returns nonzero if TOKEN is the indicated KEYWORD. */ |
3096 | |
3097 | static bool |
3098 | cp_parser_is_keyword (cp_token* token, enum rid keyword) |
3099 | { |
3100 | return token->keyword == keyword; |
3101 | } |
3102 | |
3103 | /* Helper function for cp_parser_error. |
3104 | Having peeked a token of kind TOK1_KIND that might signify |
3105 | a conflict marker, peek successor tokens to determine |
3106 | if we actually do have a conflict marker. |
3107 | Specifically, we consider a run of 7 '<', '=' or '>' characters |
3108 | at the start of a line as a conflict marker. |
3109 | These come through the lexer as three pairs and a single, |
3110 | e.g. three CPP_LSHIFT tokens ("<<") and a CPP_LESS token ('<'). |
3111 | If it returns true, *OUT_LOC is written to with the location/range |
3112 | of the marker. */ |
3113 | |
3114 | static bool |
3115 | cp_lexer_peek_conflict_marker (cp_lexer *lexer, enum cpp_ttype tok1_kind, |
3116 | location_t *out_loc) |
3117 | { |
3118 | cp_token *token2 = cp_lexer_peek_nth_token (lexer, n: 2); |
3119 | if (token2->type != tok1_kind) |
3120 | return false; |
3121 | cp_token *token3 = cp_lexer_peek_nth_token (lexer, n: 3); |
3122 | if (token3->type != tok1_kind) |
3123 | return false; |
3124 | cp_token *token4 = cp_lexer_peek_nth_token (lexer, n: 4); |
3125 | if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind)) |
3126 | return false; |
3127 | |
3128 | /* It must be at the start of the line. */ |
3129 | location_t start_loc = cp_lexer_peek_token (lexer)->location; |
3130 | if (LOCATION_COLUMN (start_loc) != 1) |
3131 | return false; |
3132 | |
3133 | /* We have a conflict marker. Construct a location of the form: |
3134 | <<<<<<< |
3135 | ^~~~~~~ |
3136 | with start == caret, finishing at the end of the marker. */ |
3137 | location_t finish_loc = get_finish (loc: token4->location); |
3138 | *out_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
3139 | |
3140 | return true; |
3141 | } |
3142 | |
3143 | /* Get a description of the matching symbol to TOKEN_DESC e.g. "(" for |
3144 | RT_CLOSE_PAREN. */ |
3145 | |
3146 | static const char * |
3147 | get_matching_symbol (required_token token_desc) |
3148 | { |
3149 | switch (token_desc) |
3150 | { |
3151 | default: |
3152 | gcc_unreachable (); |
3153 | return "" ; |
3154 | case RT_CLOSE_BRACE: |
3155 | return "{" ; |
3156 | case RT_CLOSE_PAREN: |
3157 | return "(" ; |
3158 | } |
3159 | } |
3160 | |
3161 | /* Attempt to convert TOKEN_DESC from a required_token to an |
3162 | enum cpp_ttype, returning CPP_EOF if there is no good conversion. */ |
3163 | |
3164 | static enum cpp_ttype |
3165 | get_required_cpp_ttype (required_token token_desc) |
3166 | { |
3167 | switch (token_desc) |
3168 | { |
3169 | case RT_SEMICOLON: |
3170 | return CPP_SEMICOLON; |
3171 | case RT_OPEN_PAREN: |
3172 | return CPP_OPEN_PAREN; |
3173 | case RT_CLOSE_BRACE: |
3174 | return CPP_CLOSE_BRACE; |
3175 | case RT_OPEN_BRACE: |
3176 | return CPP_OPEN_BRACE; |
3177 | case RT_CLOSE_SQUARE: |
3178 | return CPP_CLOSE_SQUARE; |
3179 | case RT_OPEN_SQUARE: |
3180 | return CPP_OPEN_SQUARE; |
3181 | case RT_COMMA: |
3182 | return CPP_COMMA; |
3183 | case RT_COLON: |
3184 | return CPP_COLON; |
3185 | case RT_CLOSE_PAREN: |
3186 | return CPP_CLOSE_PAREN; |
3187 | |
3188 | default: |
3189 | /* Use CPP_EOF as a "no completions possible" code. */ |
3190 | return CPP_EOF; |
3191 | } |
3192 | } |
3193 | |
3194 | |
3195 | /* Subroutine of cp_parser_error and cp_parser_required_error. |
3196 | |
3197 | Issue a diagnostic of the form |
3198 | FILE:LINE: MESSAGE before TOKEN |
3199 | where TOKEN is the next token in the input stream. MESSAGE |
3200 | (specified by the caller) is usually of the form "expected |
3201 | OTHER-TOKEN". |
3202 | |
3203 | This bypasses the check for tentative passing, and potentially |
3204 | adds material needed by cp_parser_required_error. |
3205 | |
3206 | If MISSING_TOKEN_DESC is not RT_NONE, then potentially add fix-it hints |
3207 | suggesting insertion of the missing token. |
3208 | |
3209 | Additionally, if MATCHING_LOCATION is not UNKNOWN_LOCATION, then we |
3210 | have an unmatched symbol at MATCHING_LOCATION; highlight this secondary |
3211 | location. */ |
3212 | |
3213 | static void |
3214 | cp_parser_error_1 (cp_parser* parser, const char* gmsgid, |
3215 | required_token missing_token_desc, |
3216 | location_t matching_location) |
3217 | { |
3218 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
3219 | /* This diagnostic makes more sense if it is tagged to the line |
3220 | of the token we just peeked at. */ |
3221 | cp_lexer_set_source_position_from_token (token); |
3222 | |
3223 | if (token->type == CPP_PRAGMA) |
3224 | { |
3225 | error_at (token->location, |
3226 | "%<#pragma%> is not allowed here" ); |
3227 | cp_parser_skip_to_pragma_eol (parser, token); |
3228 | return; |
3229 | } |
3230 | |
3231 | /* If this is actually a conflict marker, report it as such. */ |
3232 | if (token->type == CPP_LSHIFT |
3233 | || token->type == CPP_RSHIFT |
3234 | || token->type == CPP_EQ_EQ) |
3235 | { |
3236 | location_t loc; |
3237 | if (cp_lexer_peek_conflict_marker (lexer: parser->lexer, tok1_kind: token->type, out_loc: &loc)) |
3238 | { |
3239 | error_at (loc, "version control conflict marker in file" ); |
3240 | expanded_location token_exploc = expand_location (token->location); |
3241 | /* Consume tokens until the end of the source line. */ |
3242 | for (;;) |
3243 | { |
3244 | cp_lexer_consume_token (lexer: parser->lexer); |
3245 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
3246 | if (next->type == CPP_EOF) |
3247 | break; |
3248 | if (next->location == UNKNOWN_LOCATION |
3249 | || loc == UNKNOWN_LOCATION) |
3250 | break; |
3251 | |
3252 | expanded_location next_exploc = expand_location (next->location); |
3253 | if (next_exploc.file != token_exploc.file) |
3254 | break; |
3255 | if (next_exploc.line != token_exploc.line) |
3256 | break; |
3257 | } |
3258 | return; |
3259 | } |
3260 | } |
3261 | |
3262 | auto_diagnostic_group d; |
3263 | gcc_rich_location richloc (input_location); |
3264 | |
3265 | bool added_matching_location = false; |
3266 | |
3267 | if (missing_token_desc != RT_NONE) |
3268 | if (cp_token *prev_token = cp_lexer_safe_previous_token (lexer: parser->lexer)) |
3269 | { |
3270 | /* Potentially supply a fix-it hint, suggesting to add the |
3271 | missing token immediately after the *previous* token. |
3272 | This may move the primary location within richloc. */ |
3273 | enum cpp_ttype ttype = get_required_cpp_ttype (token_desc: missing_token_desc); |
3274 | location_t prev_token_loc = prev_token->location; |
3275 | maybe_suggest_missing_token_insertion (richloc: &richloc, token_type: ttype, |
3276 | prev_token_loc); |
3277 | |
3278 | /* If matching_location != UNKNOWN_LOCATION, highlight it. |
3279 | Attempt to consolidate diagnostics by printing it as a |
3280 | secondary range within the main diagnostic. */ |
3281 | if (matching_location != UNKNOWN_LOCATION) |
3282 | added_matching_location |
3283 | = richloc.add_location_if_nearby (loc: matching_location); |
3284 | } |
3285 | |
3286 | /* If we were parsing a string-literal and there is an unknown name |
3287 | token right after, then check to see if that could also have been |
3288 | a literal string by checking the name against a list of known |
3289 | standard string literal constants defined in header files. If |
3290 | there is one, then add that as an hint to the error message. */ |
3291 | name_hint h; |
3292 | if (token->type == CPP_NAME) |
3293 | if (cp_token *prev_token = cp_lexer_safe_previous_token (lexer: parser->lexer)) |
3294 | if (cp_parser_is_string_literal (token: prev_token)) |
3295 | { |
3296 | tree name = token->u.value; |
3297 | const char *token_name = IDENTIFIER_POINTER (name); |
3298 | const char * |
3299 | = get_cp_stdlib_header_for_string_macro_name (n: token_name); |
3300 | if (header_hint != NULL) |
3301 | h = name_hint (NULL, new suggest_missing_header (token->location, |
3302 | token_name, |
3303 | header_hint)); |
3304 | } |
3305 | |
3306 | /* Actually emit the error. */ |
3307 | c_parse_error (gmsgid, |
3308 | /* Because c_parser_error does not understand |
3309 | CPP_KEYWORD, keywords are treated like |
3310 | identifiers. */ |
3311 | (token->type == CPP_KEYWORD ? CPP_NAME : token->type), |
3312 | token->u.value, token->flags, richloc: &richloc); |
3313 | |
3314 | if (missing_token_desc != RT_NONE) |
3315 | { |
3316 | /* If we weren't able to consolidate matching_location, then |
3317 | print it as a secondary diagnostic. */ |
3318 | if (matching_location != UNKNOWN_LOCATION |
3319 | && !added_matching_location) |
3320 | inform (matching_location, "to match this %qs" , |
3321 | get_matching_symbol (token_desc: missing_token_desc)); |
3322 | } |
3323 | } |
3324 | |
3325 | /* If not parsing tentatively, issue a diagnostic of the form |
3326 | FILE:LINE: MESSAGE before TOKEN |
3327 | where TOKEN is the next token in the input stream. MESSAGE |
3328 | (specified by the caller) is usually of the form "expected |
3329 | OTHER-TOKEN". */ |
3330 | |
3331 | static void |
3332 | cp_parser_error (cp_parser* parser, const char* gmsgid) |
3333 | { |
3334 | if (!cp_parser_simulate_error (parser)) |
3335 | cp_parser_error_1 (parser, gmsgid, missing_token_desc: RT_NONE, UNKNOWN_LOCATION); |
3336 | } |
3337 | |
3338 | /* Issue an error about name-lookup failing. NAME is the |
3339 | IDENTIFIER_NODE DECL is the result of |
3340 | the lookup (as returned from cp_parser_lookup_name). DESIRED is |
3341 | the thing that we hoped to find. */ |
3342 | |
3343 | static void |
3344 | cp_parser_name_lookup_error (cp_parser* parser, |
3345 | tree name, |
3346 | tree decl, |
3347 | name_lookup_error desired, |
3348 | location_t location) |
3349 | { |
3350 | /* If name lookup completely failed, tell the user that NAME was not |
3351 | declared. */ |
3352 | if (decl == error_mark_node) |
3353 | { |
3354 | if (parser->scope && parser->scope != global_namespace) |
3355 | error_at (location, "%<%E::%E%> has not been declared" , |
3356 | parser->scope, name); |
3357 | else if (parser->scope == global_namespace) |
3358 | error_at (location, "%<::%E%> has not been declared" , name); |
3359 | else if (parser->object_scope |
3360 | && !CLASS_TYPE_P (parser->object_scope)) |
3361 | error_at (location, "request for member %qE in non-class type %qT" , |
3362 | name, parser->object_scope); |
3363 | else if (parser->object_scope) |
3364 | error_at (location, "%<%T::%E%> has not been declared" , |
3365 | parser->object_scope, name); |
3366 | else |
3367 | error_at (location, "%qE has not been declared" , name); |
3368 | } |
3369 | else if (parser->scope && parser->scope != global_namespace) |
3370 | { |
3371 | switch (desired) |
3372 | { |
3373 | case NLE_TYPE: |
3374 | error_at (location, "%<%E::%E%> is not a type" , |
3375 | parser->scope, name); |
3376 | break; |
3377 | case NLE_CXX98: |
3378 | error_at (location, "%<%E::%E%> is not a class or namespace" , |
3379 | parser->scope, name); |
3380 | break; |
3381 | case NLE_NOT_CXX98: |
3382 | error_at (location, |
3383 | "%<%E::%E%> is not a class, namespace, or enumeration" , |
3384 | parser->scope, name); |
3385 | break; |
3386 | default: |
3387 | gcc_unreachable (); |
3388 | |
3389 | } |
3390 | } |
3391 | else if (parser->scope == global_namespace) |
3392 | { |
3393 | switch (desired) |
3394 | { |
3395 | case NLE_TYPE: |
3396 | error_at (location, "%<::%E%> is not a type" , name); |
3397 | break; |
3398 | case NLE_CXX98: |
3399 | error_at (location, "%<::%E%> is not a class or namespace" , name); |
3400 | break; |
3401 | case NLE_NOT_CXX98: |
3402 | error_at (location, |
3403 | "%<::%E%> is not a class, namespace, or enumeration" , |
3404 | name); |
3405 | break; |
3406 | default: |
3407 | gcc_unreachable (); |
3408 | } |
3409 | } |
3410 | else |
3411 | { |
3412 | switch (desired) |
3413 | { |
3414 | case NLE_TYPE: |
3415 | error_at (location, "%qE is not a type" , name); |
3416 | break; |
3417 | case NLE_CXX98: |
3418 | error_at (location, "%qE is not a class or namespace" , name); |
3419 | break; |
3420 | case NLE_NOT_CXX98: |
3421 | error_at (location, |
3422 | "%qE is not a class, namespace, or enumeration" , name); |
3423 | break; |
3424 | default: |
3425 | gcc_unreachable (); |
3426 | } |
3427 | } |
3428 | } |
3429 | |
3430 | /* If we are parsing tentatively, remember that an error has occurred |
3431 | during this tentative parse. Returns true if the error was |
3432 | simulated; false if a message should be issued by the caller. */ |
3433 | |
3434 | static bool |
3435 | cp_parser_simulate_error (cp_parser* parser) |
3436 | { |
3437 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3438 | { |
3439 | parser->context->status = CP_PARSER_STATUS_KIND_ERROR; |
3440 | return true; |
3441 | } |
3442 | return false; |
3443 | } |
3444 | |
3445 | /* This function is called when a type is defined. If type |
3446 | definitions are forbidden at this point, an error message is |
3447 | issued. */ |
3448 | |
3449 | static bool |
3450 | cp_parser_check_type_definition (cp_parser* parser) |
3451 | { |
3452 | /* If types are forbidden here, issue a message. */ |
3453 | if (parser->type_definition_forbidden_message) |
3454 | { |
3455 | /* Don't use `%s' to print the string, because quotations (`%<', `%>') |
3456 | or %qs in the message need to be interpreted. */ |
3457 | error (parser->type_definition_forbidden_message, |
3458 | parser->type_definition_forbidden_message_arg); |
3459 | return false; |
3460 | } |
3461 | return true; |
3462 | } |
3463 | |
3464 | /* This function is called when the DECLARATOR is processed. The TYPE |
3465 | was a type defined in the decl-specifiers. If it is invalid to |
3466 | define a type in the decl-specifiers for DECLARATOR, an error is |
3467 | issued. TYPE_LOCATION is the location of TYPE and is used |
3468 | for error reporting. */ |
3469 | |
3470 | static void |
3471 | cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, |
3472 | tree type, location_t type_location) |
3473 | { |
3474 | /* [dcl.fct] forbids type definitions in return types. |
3475 | Unfortunately, it's not easy to know whether or not we are |
3476 | processing a return type until after the fact. */ |
3477 | while (declarator |
3478 | && (declarator->kind == cdk_pointer |
3479 | || declarator->kind == cdk_reference |
3480 | || declarator->kind == cdk_ptrmem)) |
3481 | declarator = declarator->declarator; |
3482 | if (declarator |
3483 | && declarator->kind == cdk_function) |
3484 | { |
3485 | error_at (type_location, |
3486 | "new types may not be defined in a return type" ); |
3487 | inform (type_location, |
3488 | "(perhaps a semicolon is missing after the definition of %qT)" , |
3489 | type); |
3490 | } |
3491 | } |
3492 | |
3493 | /* A type-specifier (TYPE) has been parsed which cannot be followed by |
3494 | "<" in any valid C++ program. If the next token is indeed "<", |
3495 | issue a message warning the user about what appears to be an |
3496 | invalid attempt to form a template-id. LOCATION is the location |
3497 | of the type-specifier (TYPE) */ |
3498 | |
3499 | static void |
3500 | cp_parser_check_for_invalid_template_id (cp_parser* parser, |
3501 | tree type, |
3502 | enum tag_types tag_type, |
3503 | location_t location) |
3504 | { |
3505 | cp_token_position start = 0; |
3506 | |
3507 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3508 | { |
3509 | if (TREE_CODE (type) == TYPE_DECL) |
3510 | type = TREE_TYPE (type); |
3511 | if (TYPE_P (type) && !template_placeholder_p (type)) |
3512 | error_at (location, "%qT is not a template" , type); |
3513 | else if (identifier_p (t: type)) |
3514 | { |
3515 | if (tag_type != none_type) |
3516 | error_at (location, "%qE is not a class template" , type); |
3517 | else |
3518 | error_at (location, "%qE is not a template" , type); |
3519 | } |
3520 | else |
3521 | error_at (location, "invalid template-id" ); |
3522 | /* Remember the location of the invalid "<". */ |
3523 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3524 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: true); |
3525 | /* Consume the "<". */ |
3526 | cp_lexer_consume_token (lexer: parser->lexer); |
3527 | /* Parse the template arguments. */ |
3528 | cp_parser_enclosed_template_argument_list (parser); |
3529 | /* Permanently remove the invalid template arguments so that |
3530 | this error message is not issued again. */ |
3531 | if (start) |
3532 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
3533 | } |
3534 | } |
3535 | |
3536 | /* If parsing an integral constant-expression, issue an error message |
3537 | about the fact that THING appeared and return true. Otherwise, |
3538 | return false. In either case, set |
3539 | PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P. */ |
3540 | |
3541 | static bool |
3542 | cp_parser_non_integral_constant_expression (cp_parser *parser, |
3543 | non_integral_constant thing) |
3544 | { |
3545 | parser->non_integral_constant_expression_p = true; |
3546 | if (parser->integral_constant_expression_p) |
3547 | { |
3548 | if (!parser->allow_non_integral_constant_expression_p) |
3549 | { |
3550 | const char *msg = NULL; |
3551 | switch (thing) |
3552 | { |
3553 | case NIC_FLOAT: |
3554 | pedwarn (input_location, OPT_Wpedantic, |
3555 | "ISO C++ forbids using a floating-point literal " |
3556 | "in a constant-expression" ); |
3557 | return true; |
3558 | case NIC_CAST: |
3559 | error ("a cast to a type other than an integral or " |
3560 | "enumeration type cannot appear in a " |
3561 | "constant-expression" ); |
3562 | return true; |
3563 | case NIC_TYPEID: |
3564 | error ("%<typeid%> operator " |
3565 | "cannot appear in a constant-expression" ); |
3566 | return true; |
3567 | case NIC_NCC: |
3568 | error ("non-constant compound literals " |
3569 | "cannot appear in a constant-expression" ); |
3570 | return true; |
3571 | case NIC_FUNC_CALL: |
3572 | error ("a function call " |
3573 | "cannot appear in a constant-expression" ); |
3574 | return true; |
3575 | case NIC_INC: |
3576 | error ("an increment " |
3577 | "cannot appear in a constant-expression" ); |
3578 | return true; |
3579 | case NIC_DEC: |
3580 | error ("an decrement " |
3581 | "cannot appear in a constant-expression" ); |
3582 | return true; |
3583 | case NIC_ARRAY_REF: |
3584 | error ("an array reference " |
3585 | "cannot appear in a constant-expression" ); |
3586 | return true; |
3587 | case NIC_ADDR_LABEL: |
3588 | error ("the address of a label " |
3589 | "cannot appear in a constant-expression" ); |
3590 | return true; |
3591 | case NIC_OVERLOADED: |
3592 | error ("calls to overloaded operators " |
3593 | "cannot appear in a constant-expression" ); |
3594 | return true; |
3595 | case NIC_ASSIGNMENT: |
3596 | error ("an assignment cannot appear in a constant-expression" ); |
3597 | return true; |
3598 | case NIC_COMMA: |
3599 | error ("a comma operator " |
3600 | "cannot appear in a constant-expression" ); |
3601 | return true; |
3602 | case NIC_CONSTRUCTOR: |
3603 | error ("a call to a constructor " |
3604 | "cannot appear in a constant-expression" ); |
3605 | return true; |
3606 | case NIC_TRANSACTION: |
3607 | error ("a transaction expression " |
3608 | "cannot appear in a constant-expression" ); |
3609 | return true; |
3610 | case NIC_THIS: |
3611 | msg = "this" ; |
3612 | break; |
3613 | case NIC_FUNC_NAME: |
3614 | msg = "__FUNCTION__" ; |
3615 | break; |
3616 | case NIC_PRETTY_FUNC: |
3617 | msg = "__PRETTY_FUNCTION__" ; |
3618 | break; |
3619 | case NIC_C99_FUNC: |
3620 | msg = "__func__" ; |
3621 | break; |
3622 | case NIC_VA_ARG: |
3623 | msg = "va_arg" ; |
3624 | break; |
3625 | case NIC_ARROW: |
3626 | msg = "->" ; |
3627 | break; |
3628 | case NIC_POINT: |
3629 | msg = "." ; |
3630 | break; |
3631 | case NIC_STAR: |
3632 | msg = "*" ; |
3633 | break; |
3634 | case NIC_ADDR: |
3635 | msg = "&" ; |
3636 | break; |
3637 | case NIC_PREINCREMENT: |
3638 | msg = "++" ; |
3639 | break; |
3640 | case NIC_PREDECREMENT: |
3641 | msg = "--" ; |
3642 | break; |
3643 | case NIC_NEW: |
3644 | msg = "new" ; |
3645 | break; |
3646 | case NIC_DEL: |
3647 | msg = "delete" ; |
3648 | break; |
3649 | default: |
3650 | gcc_unreachable (); |
3651 | } |
3652 | if (msg) |
3653 | error ("%qs cannot appear in a constant-expression" , msg); |
3654 | return true; |
3655 | } |
3656 | } |
3657 | return false; |
3658 | } |
3659 | |
3660 | /* Emit a diagnostic for an invalid type name. This function commits |
3661 | to the current active tentative parse, if any. (Otherwise, the |
3662 | problematic construct might be encountered again later, resulting |
3663 | in duplicate error messages.) LOCATION is the location of ID. */ |
3664 | |
3665 | static void |
3666 | cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, |
3667 | location_t location) |
3668 | { |
3669 | tree decl, ambiguous_decls; |
3670 | cp_parser_commit_to_tentative_parse (parser); |
3671 | /* Try to lookup the identifier. */ |
3672 | decl = cp_parser_lookup_name (parser, id, none_type, |
3673 | /*is_template=*/false, |
3674 | /*is_namespace=*/false, |
3675 | /*check_dependency=*/true, |
3676 | &ambiguous_decls, location); |
3677 | if (ambiguous_decls) |
3678 | /* If the lookup was ambiguous, an error will already have |
3679 | been issued. */ |
3680 | return; |
3681 | /* If the lookup found a template-name, it means that the user forgot |
3682 | to specify an argument list. Emit a useful error message. */ |
3683 | if (DECL_TYPE_TEMPLATE_P (decl)) |
3684 | { |
3685 | auto_diagnostic_group d; |
3686 | error_at (location, |
3687 | "invalid use of template-name %qE without an argument list" , |
3688 | decl); |
3689 | if (DECL_CLASS_TEMPLATE_P (decl) && cxx_dialect < cxx17) |
3690 | inform (location, "class template argument deduction is only available " |
3691 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
3692 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3693 | } |
3694 | else if (TREE_CODE (id) == BIT_NOT_EXPR) |
3695 | error_at (location, "invalid use of destructor %qD as a type" , id); |
3696 | else if (TREE_CODE (decl) == TYPE_DECL) |
3697 | /* Something like 'unsigned A a;' */ |
3698 | error_at (location, "invalid combination of multiple type-specifiers" ); |
3699 | else if (!parser->scope) |
3700 | { |
3701 | /* Issue an error message. */ |
3702 | auto_diagnostic_group d; |
3703 | name_hint hint; |
3704 | if (TREE_CODE (id) == IDENTIFIER_NODE) |
3705 | hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location); |
3706 | if (const char *suggestion = hint.suggestion ()) |
3707 | { |
3708 | gcc_rich_location richloc (location); |
3709 | richloc.add_fixit_replace (new_content: suggestion); |
3710 | error_at (&richloc, |
3711 | "%qE does not name a type; did you mean %qs?" , |
3712 | id, suggestion); |
3713 | } |
3714 | else |
3715 | error_at (location, "%qE does not name a type" , id); |
3716 | /* If we're in a template class, it's possible that the user was |
3717 | referring to a type from a base class. For example: |
3718 | |
3719 | template <typename T> struct A { typedef T X; }; |
3720 | template <typename T> struct B : public A<T> { X x; }; |
3721 | |
3722 | The user should have said "typename A<T>::X". */ |
3723 | if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_CONSTEXPR]) |
3724 | inform (location, "C++11 %<constexpr%> only available with " |
3725 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3726 | else if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_NOEXCEPT]) |
3727 | inform (location, "C++11 %<noexcept%> only available with " |
3728 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3729 | else if (TREE_CODE (id) == IDENTIFIER_NODE |
3730 | && (id_equal (id, str: "module" ) || id_equal (id, str: "import" ))) |
3731 | { |
3732 | if (modules_p ()) |
3733 | inform (location, "%qE is not recognized as a module control-line" , |
3734 | id); |
3735 | else if (cxx_dialect < cxx20) |
3736 | inform (location, "C++20 %qE only available with %<-fmodules-ts%>" , |
3737 | id); |
3738 | else |
3739 | inform (location, "C++20 %qE only available with %<-fmodules-ts%>" |
3740 | ", which is not yet enabled with %<-std=c++20%>" , id); |
3741 | } |
3742 | else if (cxx_dialect < cxx11 |
3743 | && TREE_CODE (id) == IDENTIFIER_NODE |
3744 | && id_equal (id, str: "thread_local" )) |
3745 | inform (location, "C++11 %<thread_local%> only available with " |
3746 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3747 | else if (cxx_dialect < cxx20 && id == ridpointers[(int)RID_CONSTINIT]) |
3748 | inform (location, "C++20 %<constinit%> only available with " |
3749 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
3750 | else if (!flag_concepts && id == ridpointers[(int)RID_CONCEPT]) |
3751 | inform (location, "%<concept%> only available with %<-std=c++20%> or " |
3752 | "%<-fconcepts%>" ); |
3753 | else if (!flag_concepts && id == ridpointers[(int)RID_REQUIRES]) |
3754 | inform (location, "%<requires%> only available with %<-std=c++20%> or " |
3755 | "%<-fconcepts%>" ); |
3756 | else if (processing_template_decl && current_class_type |
3757 | && TYPE_BINFO (current_class_type)) |
3758 | { |
3759 | for (tree b = TREE_CHAIN (TYPE_BINFO (current_class_type)); |
3760 | b; b = TREE_CHAIN (b)) |
3761 | { |
3762 | tree base_type = BINFO_TYPE (b); |
3763 | if (CLASS_TYPE_P (base_type) |
3764 | && dependent_type_p (base_type)) |
3765 | { |
3766 | /* Go from a particular instantiation of the |
3767 | template (which will have an empty TYPE_FIELDs), |
3768 | to the main version. */ |
3769 | base_type = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type); |
3770 | for (tree field = TYPE_FIELDS (base_type); |
3771 | field; field = DECL_CHAIN (field)) |
3772 | if (TREE_CODE (field) == TYPE_DECL |
3773 | && DECL_NAME (field) == id) |
3774 | { |
3775 | inform (location, |
3776 | "(perhaps %<typename %T::%E%> was intended)" , |
3777 | BINFO_TYPE (b), id); |
3778 | goto found; |
3779 | } |
3780 | } |
3781 | } |
3782 | found:; |
3783 | } |
3784 | } |
3785 | /* Here we diagnose qualified-ids where the scope is actually correct, |
3786 | but the identifier does not resolve to a valid type name. */ |
3787 | else if (parser->scope != error_mark_node) |
3788 | { |
3789 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
3790 | { |
3791 | auto_diagnostic_group d; |
3792 | name_hint hint; |
3793 | if (decl == error_mark_node) |
3794 | hint = suggest_alternative_in_explicit_scope (location, id, |
3795 | parser->scope); |
3796 | const char *suggestion = hint.suggestion (); |
3797 | gcc_rich_location richloc (location_of (id)); |
3798 | if (suggestion) |
3799 | richloc.add_fixit_replace (new_content: suggestion); |
3800 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3801 | { |
3802 | if (suggestion) |
3803 | error_at (&richloc, |
3804 | "%qE in namespace %qE does not name a template" |
3805 | " type; did you mean %qs?" , |
3806 | id, parser->scope, suggestion); |
3807 | else |
3808 | error_at (&richloc, |
3809 | "%qE in namespace %qE does not name a template type" , |
3810 | id, parser->scope); |
3811 | } |
3812 | else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) |
3813 | { |
3814 | if (suggestion) |
3815 | error_at (&richloc, |
3816 | "%qE in namespace %qE does not name a template" |
3817 | " type; did you mean %qs?" , |
3818 | TREE_OPERAND (id, 0), parser->scope, suggestion); |
3819 | else |
3820 | error_at (&richloc, |
3821 | "%qE in namespace %qE does not name a template" |
3822 | " type" , |
3823 | TREE_OPERAND (id, 0), parser->scope); |
3824 | } |
3825 | else |
3826 | { |
3827 | if (suggestion) |
3828 | error_at (&richloc, |
3829 | "%qE in namespace %qE does not name a type" |
3830 | "; did you mean %qs?" , |
3831 | id, parser->scope, suggestion); |
3832 | else |
3833 | error_at (&richloc, |
3834 | "%qE in namespace %qE does not name a type" , |
3835 | id, parser->scope); |
3836 | } |
3837 | if (DECL_P (decl)) |
3838 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3839 | } |
3840 | else if (CLASS_TYPE_P (parser->scope) |
3841 | && constructor_name_p (id, parser->scope)) |
3842 | { |
3843 | /* A<T>::A<T>() */ |
3844 | auto_diagnostic_group d; |
3845 | error_at (location, "%<%T::%E%> names the constructor, not" |
3846 | " the type" , parser->scope, id); |
3847 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3848 | error_at (location, "and %qT has no template constructors" , |
3849 | parser->scope); |
3850 | } |
3851 | else if (TYPE_P (parser->scope) |
3852 | && dependent_scope_p (parser->scope)) |
3853 | { |
3854 | gcc_rich_location richloc (location); |
3855 | richloc.add_fixit_insert_before (new_content: "typename " ); |
3856 | if (TREE_CODE (parser->scope) == TYPENAME_TYPE) |
3857 | error_at (&richloc, |
3858 | "need %<typename%> before %<%T::%D::%E%> because " |
3859 | "%<%T::%D%> is a dependent scope" , |
3860 | TYPE_CONTEXT (parser->scope), |
3861 | TYPENAME_TYPE_FULLNAME (parser->scope), |
3862 | id, |
3863 | TYPE_CONTEXT (parser->scope), |
3864 | TYPENAME_TYPE_FULLNAME (parser->scope)); |
3865 | else |
3866 | error_at (&richloc, "need %<typename%> before %<%T::%E%> because " |
3867 | "%qT is a dependent scope" , |
3868 | parser->scope, id, parser->scope); |
3869 | } |
3870 | else if (TYPE_P (parser->scope)) |
3871 | { |
3872 | auto_diagnostic_group d; |
3873 | if (!COMPLETE_TYPE_P (parser->scope)) |
3874 | cxx_incomplete_type_error (location_of (id), NULL_TREE, |
3875 | parser->scope); |
3876 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3877 | error_at (location_of (id), |
3878 | "%qE in %q#T does not name a template type" , |
3879 | id, parser->scope); |
3880 | else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) |
3881 | error_at (location_of (id), |
3882 | "%qE in %q#T does not name a template type" , |
3883 | TREE_OPERAND (id, 0), parser->scope); |
3884 | else |
3885 | error_at (location_of (id), |
3886 | "%qE in %q#T does not name a type" , |
3887 | id, parser->scope); |
3888 | if (DECL_P (decl)) |
3889 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3890 | } |
3891 | else |
3892 | gcc_unreachable (); |
3893 | } |
3894 | } |
3895 | |
3896 | /* Check for a common situation where a type-name should be present, |
3897 | but is not, and issue a sensible error message. Returns true if an |
3898 | invalid type-name was detected. |
3899 | |
3900 | The situation handled by this function are variable declarations of the |
3901 | form `ID a', where `ID' is an id-expression and `a' is a plain identifier. |
3902 | Usually, `ID' should name a type, but if we got here it means that it |
3903 | does not. We try to emit the best possible error message depending on |
3904 | how exactly the id-expression looks like. */ |
3905 | |
3906 | static bool |
3907 | cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) |
3908 | { |
3909 | tree id; |
3910 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
3911 | |
3912 | /* Avoid duplicate error about ambiguous lookup. */ |
3913 | if (token->type == CPP_NESTED_NAME_SPECIFIER) |
3914 | { |
3915 | cp_token *next = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
3916 | if (next->type == CPP_NAME && next->error_reported) |
3917 | goto out; |
3918 | } |
3919 | |
3920 | cp_parser_parse_tentatively (parser); |
3921 | id = cp_parser_id_expression (parser, |
3922 | /*template_keyword_p=*/false, |
3923 | /*check_dependency_p=*/true, |
3924 | /*template_p=*/NULL, |
3925 | /*declarator_p=*/true, |
3926 | /*optional_p=*/false); |
3927 | /* If the next token is a (, this is a function with no explicit return |
3928 | type, i.e. constructor, destructor or conversion op. */ |
3929 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
3930 | || TREE_CODE (id) == TYPE_DECL) |
3931 | { |
3932 | cp_parser_abort_tentative_parse (parser); |
3933 | return false; |
3934 | } |
3935 | if (!cp_parser_parse_definitely (parser)) |
3936 | return false; |
3937 | |
3938 | /* Emit a diagnostic for the invalid type. */ |
3939 | cp_parser_diagnose_invalid_type_name (parser, id, location: token->location); |
3940 | out: |
3941 | /* If we aren't in the middle of a declarator (i.e. in a |
3942 | parameter-declaration-clause), skip to the end of the declaration; |
3943 | there's no point in trying to process it. */ |
3944 | if (!parser->in_declarator_p) |
3945 | cp_parser_skip_to_end_of_block_or_statement (parser); |
3946 | return true; |
3947 | } |
3948 | |
3949 | /* Consume tokens up to, and including, the next non-nested closing `)'. |
3950 | Returns 1 iff we found a closing `)'. RECOVERING is true, if we |
3951 | are doing error recovery. Returns -1 if OR_TTYPE is not CPP_EOF and we |
3952 | found an unnested token of that type. */ |
3953 | |
3954 | static int |
3955 | cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser, |
3956 | bool recovering, |
3957 | cpp_ttype or_ttype, |
3958 | bool consume_paren) |
3959 | { |
3960 | unsigned paren_depth = 0; |
3961 | unsigned brace_depth = 0; |
3962 | unsigned square_depth = 0; |
3963 | unsigned condop_depth = 0; |
3964 | |
3965 | if (recovering && or_ttype == CPP_EOF |
3966 | && cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3967 | return 0; |
3968 | |
3969 | while (true) |
3970 | { |
3971 | cp_token * token = cp_lexer_peek_token (lexer: parser->lexer); |
3972 | |
3973 | /* Have we found what we're looking for before the closing paren? */ |
3974 | if (token->type == or_ttype && or_ttype != CPP_EOF |
3975 | && !brace_depth && !paren_depth && !square_depth && !condop_depth) |
3976 | return -1; |
3977 | |
3978 | switch (token->type) |
3979 | { |
3980 | case CPP_PRAGMA_EOL: |
3981 | if (!parser->lexer->in_pragma) |
3982 | break; |
3983 | /* FALLTHRU */ |
3984 | case CPP_EOF: |
3985 | /* If we've run out of tokens, then there is no closing `)'. */ |
3986 | return 0; |
3987 | |
3988 | /* This is good for lambda expression capture-lists. */ |
3989 | case CPP_OPEN_SQUARE: |
3990 | ++square_depth; |
3991 | break; |
3992 | case CPP_CLOSE_SQUARE: |
3993 | if (!square_depth--) |
3994 | return 0; |
3995 | break; |
3996 | |
3997 | case CPP_SEMICOLON: |
3998 | /* This matches the processing in skip_to_end_of_statement. */ |
3999 | if (!brace_depth) |
4000 | return 0; |
4001 | break; |
4002 | |
4003 | case CPP_OPEN_BRACE: |
4004 | ++brace_depth; |
4005 | break; |
4006 | case CPP_CLOSE_BRACE: |
4007 | if (!brace_depth--) |
4008 | return 0; |
4009 | break; |
4010 | |
4011 | case CPP_OPEN_PAREN: |
4012 | if (!brace_depth) |
4013 | ++paren_depth; |
4014 | break; |
4015 | |
4016 | case CPP_CLOSE_PAREN: |
4017 | if (!brace_depth && !paren_depth--) |
4018 | { |
4019 | if (consume_paren) |
4020 | cp_lexer_consume_token (lexer: parser->lexer); |
4021 | return 1; |
4022 | } |
4023 | break; |
4024 | |
4025 | case CPP_QUERY: |
4026 | if (!brace_depth && !paren_depth && !square_depth) |
4027 | ++condop_depth; |
4028 | break; |
4029 | |
4030 | case CPP_COLON: |
4031 | if (!brace_depth && !paren_depth && !square_depth && condop_depth > 0) |
4032 | condop_depth--; |
4033 | break; |
4034 | |
4035 | case CPP_KEYWORD: |
4036 | if (!cp_token_is_module_directive (token)) |
4037 | break; |
4038 | /* FALLTHROUGH */ |
4039 | |
4040 | case CPP_PRAGMA: |
4041 | /* We fell into a pragma. Skip it, and continue. */ |
4042 | cp_parser_skip_to_pragma_eol (parser, recovering ? token : nullptr); |
4043 | continue; |
4044 | |
4045 | default: |
4046 | break; |
4047 | } |
4048 | |
4049 | /* Consume the token. */ |
4050 | cp_lexer_consume_token (lexer: parser->lexer); |
4051 | } |
4052 | } |
4053 | |
4054 | /* Consume tokens up to, and including, the next non-nested closing `)'. |
4055 | Returns 1 iff we found a closing `)'. RECOVERING is true, if we |
4056 | are doing error recovery. Returns -1 if OR_COMMA is true and we |
4057 | found an unnested token of that type. */ |
4058 | |
4059 | static int |
4060 | cp_parser_skip_to_closing_parenthesis (cp_parser *parser, |
4061 | bool recovering, |
4062 | bool or_comma, |
4063 | bool consume_paren) |
4064 | { |
4065 | cpp_ttype ttype = or_comma ? CPP_COMMA : CPP_EOF; |
4066 | return cp_parser_skip_to_closing_parenthesis_1 (parser, recovering, |
4067 | or_ttype: ttype, consume_paren); |
4068 | } |
4069 | |
4070 | /* Consume tokens until we reach the end of the current statement. |
4071 | Normally, that will be just before consuming a `;'. However, if a |
4072 | non-nested `}' comes first, then we stop before consuming that. */ |
4073 | |
4074 | static void |
4075 | cp_parser_skip_to_end_of_statement (cp_parser* parser) |
4076 | { |
4077 | unsigned nesting_depth = 0; |
4078 | |
4079 | /* Unwind generic function template scope if necessary. */ |
4080 | if (parser->fully_implicit_function_template_p) |
4081 | abort_fully_implicit_template (parser); |
4082 | |
4083 | while (true) |
4084 | { |
4085 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4086 | |
4087 | switch (token->type) |
4088 | { |
4089 | case CPP_PRAGMA_EOL: |
4090 | if (!parser->lexer->in_pragma) |
4091 | break; |
4092 | /* FALLTHRU */ |
4093 | case CPP_EOF: |
4094 | /* If we've run out of tokens, stop. */ |
4095 | return; |
4096 | |
4097 | case CPP_SEMICOLON: |
4098 | /* If the next token is a `;', we have reached the end of the |
4099 | statement. */ |
4100 | if (!nesting_depth) |
4101 | return; |
4102 | break; |
4103 | |
4104 | case CPP_CLOSE_BRACE: |
4105 | /* If this is a non-nested '}', stop before consuming it. |
4106 | That way, when confronted with something like: |
4107 | |
4108 | { 3 + } |
4109 | |
4110 | we stop before consuming the closing '}', even though we |
4111 | have not yet reached a `;'. */ |
4112 | if (nesting_depth == 0) |
4113 | return; |
4114 | |
4115 | /* If it is the closing '}' for a block that we have |
4116 | scanned, stop -- but only after consuming the token. |
4117 | That way given: |
4118 | |
4119 | void f g () { ... } |
4120 | typedef int I; |
4121 | |
4122 | we will stop after the body of the erroneously declared |
4123 | function, but before consuming the following `typedef' |
4124 | declaration. */ |
4125 | if (--nesting_depth == 0) |
4126 | { |
4127 | cp_lexer_consume_token (lexer: parser->lexer); |
4128 | return; |
4129 | } |
4130 | break; |
4131 | |
4132 | case CPP_OPEN_BRACE: |
4133 | ++nesting_depth; |
4134 | break; |
4135 | |
4136 | case CPP_KEYWORD: |
4137 | if (!cp_token_is_module_directive (token)) |
4138 | break; |
4139 | /* FALLTHROUGH */ |
4140 | |
4141 | case CPP_PRAGMA: |
4142 | /* We fell into a pragma. Skip it, and continue or return. */ |
4143 | cp_parser_skip_to_pragma_eol (parser, token); |
4144 | if (!nesting_depth) |
4145 | return; |
4146 | continue; |
4147 | |
4148 | default: |
4149 | break; |
4150 | } |
4151 | |
4152 | /* Consume the token. */ |
4153 | cp_lexer_consume_token (lexer: parser->lexer); |
4154 | } |
4155 | } |
4156 | |
4157 | /* This function is called at the end of a statement or declaration. |
4158 | If the next token is a semicolon, it is consumed; otherwise, error |
4159 | recovery is attempted. */ |
4160 | |
4161 | static void |
4162 | cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser) |
4163 | { |
4164 | /* Look for the trailing `;'. */ |
4165 | if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
4166 | { |
4167 | /* If there is additional (erroneous) input, skip to the end of |
4168 | the statement. */ |
4169 | cp_parser_skip_to_end_of_statement (parser); |
4170 | /* If the next token is now a `;', consume it. */ |
4171 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
4172 | cp_lexer_consume_token (lexer: parser->lexer); |
4173 | } |
4174 | } |
4175 | |
4176 | /* Skip tokens until we have consumed an entire block, or until we |
4177 | have consumed a non-nested `;'. */ |
4178 | |
4179 | static void |
4180 | cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) |
4181 | { |
4182 | int nesting_depth = 0; |
4183 | |
4184 | /* Unwind generic function template scope if necessary. */ |
4185 | if (parser->fully_implicit_function_template_p) |
4186 | abort_fully_implicit_template (parser); |
4187 | |
4188 | while (nesting_depth >= 0) |
4189 | { |
4190 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4191 | |
4192 | switch (token->type) |
4193 | { |
4194 | case CPP_PRAGMA_EOL: |
4195 | if (!parser->lexer->in_pragma) |
4196 | break; |
4197 | /* FALLTHRU */ |
4198 | case CPP_EOF: |
4199 | /* If we've run out of tokens, stop. */ |
4200 | return; |
4201 | |
4202 | case CPP_SEMICOLON: |
4203 | /* Stop if this is an unnested ';'. */ |
4204 | if (!nesting_depth) |
4205 | nesting_depth = -1; |
4206 | break; |
4207 | |
4208 | case CPP_CLOSE_BRACE: |
4209 | /* Stop if this is an unnested '}', or closes the outermost |
4210 | nesting level. */ |
4211 | nesting_depth--; |
4212 | if (nesting_depth < 0) |
4213 | return; |
4214 | if (!nesting_depth) |
4215 | nesting_depth = -1; |
4216 | break; |
4217 | |
4218 | case CPP_OPEN_BRACE: |
4219 | /* Nest. */ |
4220 | nesting_depth++; |
4221 | break; |
4222 | |
4223 | case CPP_KEYWORD: |
4224 | if (!cp_token_is_module_directive (token)) |
4225 | break; |
4226 | /* FALLTHROUGH */ |
4227 | |
4228 | case CPP_PRAGMA: |
4229 | /* Skip it, and continue or return. */ |
4230 | cp_parser_skip_to_pragma_eol (parser, token); |
4231 | if (!nesting_depth) |
4232 | return; |
4233 | continue; |
4234 | |
4235 | default: |
4236 | break; |
4237 | } |
4238 | |
4239 | /* Consume the token. */ |
4240 | cp_lexer_consume_token (lexer: parser->lexer); |
4241 | } |
4242 | } |
4243 | |
4244 | /* Skip tokens until a non-nested closing curly brace is the next |
4245 | token, or there are no more tokens. Return true in the first case, |
4246 | false otherwise. */ |
4247 | |
4248 | static bool |
4249 | cp_parser_skip_to_closing_brace (cp_parser *parser) |
4250 | { |
4251 | unsigned nesting_depth = 0; |
4252 | |
4253 | while (true) |
4254 | { |
4255 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4256 | |
4257 | switch (token->type) |
4258 | { |
4259 | case CPP_PRAGMA_EOL: |
4260 | if (!parser->lexer->in_pragma) |
4261 | break; |
4262 | /* FALLTHRU */ |
4263 | case CPP_EOF: |
4264 | /* If we've run out of tokens, stop. */ |
4265 | return false; |
4266 | |
4267 | case CPP_CLOSE_BRACE: |
4268 | /* If the next token is a non-nested `}', then we have reached |
4269 | the end of the current block. */ |
4270 | if (nesting_depth-- == 0) |
4271 | return true; |
4272 | break; |
4273 | |
4274 | case CPP_OPEN_BRACE: |
4275 | /* If it the next token is a `{', then we are entering a new |
4276 | block. Consume the entire block. */ |
4277 | ++nesting_depth; |
4278 | break; |
4279 | |
4280 | default: |
4281 | break; |
4282 | } |
4283 | |
4284 | /* Consume the token. */ |
4285 | cp_lexer_consume_token (lexer: parser->lexer); |
4286 | } |
4287 | } |
4288 | |
4289 | /* Consume tokens until we reach the end of the pragma. The PRAGMA_TOK |
4290 | parameter is the PRAGMA token, allowing us to purge the entire pragma |
4291 | sequence. PRAGMA_TOK can be NULL, if we're speculatively scanning |
4292 | forwards (not error recovery). */ |
4293 | |
4294 | static void |
4295 | cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) |
4296 | { |
4297 | cp_token *token; |
4298 | |
4299 | do |
4300 | { |
4301 | /* The preprocessor makes sure that a PRAGMA_EOL token appears |
4302 | before an EOF token, even when the EOF is on the pragma line. |
4303 | We should never get here without being inside a deferred |
4304 | pragma. */ |
4305 | gcc_checking_assert (cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)); |
4306 | token = cp_lexer_consume_token (lexer: parser->lexer); |
4307 | } |
4308 | while (token->type != CPP_PRAGMA_EOL); |
4309 | |
4310 | if (pragma_tok) |
4311 | { |
4312 | parser->lexer->in_pragma = false; |
4313 | if (parser->lexer->in_omp_attribute_pragma |
4314 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
4315 | { |
4316 | parser->lexer = parser->lexer->next; |
4317 | /* Put the current source position back where it was before this |
4318 | lexer was pushed. */ |
4319 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4320 | } |
4321 | } |
4322 | } |
4323 | |
4324 | /* Require pragma end of line, resyncing with it as necessary. The |
4325 | arguments are as for cp_parser_skip_to_pragma_eol. */ |
4326 | |
4327 | static void |
4328 | cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) |
4329 | { |
4330 | parser->lexer->in_pragma = false; |
4331 | if (!cp_parser_require (parser, CPP_PRAGMA_EOL, RT_PRAGMA_EOL)) |
4332 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
4333 | else if (parser->lexer->in_omp_attribute_pragma |
4334 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
4335 | { |
4336 | parser->lexer = parser->lexer->next; |
4337 | /* Put the current source position back where it was before this |
4338 | lexer was pushed. */ |
4339 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4340 | } |
4341 | } |
4342 | |
4343 | /* This is a simple wrapper around make_typename_type. When the id is |
4344 | an unresolved identifier node, we can provide a superior diagnostic |
4345 | using cp_parser_diagnose_invalid_type_name. */ |
4346 | |
4347 | static tree |
4348 | cp_parser_make_typename_type (cp_parser *parser, tree id, |
4349 | location_t id_location) |
4350 | { |
4351 | tree result; |
4352 | if (identifier_p (t: id)) |
4353 | { |
4354 | result = make_typename_type (parser->scope, id, typename_type, |
4355 | /*complain=*/tf_none); |
4356 | if (result == error_mark_node) |
4357 | cp_parser_diagnose_invalid_type_name (parser, id, location: id_location); |
4358 | return result; |
4359 | } |
4360 | return make_typename_type (parser->scope, id, typename_type, tf_error); |
4361 | } |
4362 | |
4363 | /* This is a wrapper around the |
4364 | make_{pointer,ptrmem,reference}_declarator functions that decides |
4365 | which one to call based on the CODE and CLASS_TYPE arguments. The |
4366 | CODE argument should be one of the values returned by |
4367 | cp_parser_ptr_operator. ATTRIBUTES represent the attributes that |
4368 | appertain to the pointer or reference. */ |
4369 | |
4370 | static cp_declarator * |
4371 | cp_parser_make_indirect_declarator (enum tree_code code, tree class_type, |
4372 | cp_cv_quals cv_qualifiers, |
4373 | cp_declarator *target, |
4374 | tree attributes) |
4375 | { |
4376 | if (code == ERROR_MARK || target == cp_error_declarator) |
4377 | return cp_error_declarator; |
4378 | |
4379 | if (code == INDIRECT_REF) |
4380 | if (class_type == NULL_TREE) |
4381 | return make_pointer_declarator (cv_qualifiers, target, attributes); |
4382 | else |
4383 | return make_ptrmem_declarator (cv_qualifiers, class_type, |
4384 | pointee: target, attributes); |
4385 | else if (code == ADDR_EXPR && class_type == NULL_TREE) |
4386 | return make_reference_declarator (cv_qualifiers, target, |
4387 | rvalue_ref: false, attributes); |
4388 | else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE) |
4389 | return make_reference_declarator (cv_qualifiers, target, |
4390 | rvalue_ref: true, attributes); |
4391 | gcc_unreachable (); |
4392 | } |
4393 | |
4394 | /* Create a new C++ parser. */ |
4395 | |
4396 | static cp_parser * |
4397 | cp_parser_new (cp_lexer *lexer) |
4398 | { |
4399 | /* Initialize the binops_by_token so that we can get the tree |
4400 | directly from the token. */ |
4401 | for (unsigned i = 0; i < ARRAY_SIZE (binops); i++) |
4402 | binops_by_token[binops[i].token_type] = binops[i]; |
4403 | |
4404 | cp_parser *parser = ggc_cleared_alloc<cp_parser> (); |
4405 | parser->lexer = lexer; |
4406 | parser->context = cp_parser_context_new (NULL); |
4407 | |
4408 | /* For now, we always accept GNU extensions. */ |
4409 | parser->allow_gnu_extensions_p = 1; |
4410 | |
4411 | /* The `>' token is a greater-than operator, not the end of a |
4412 | template-id. */ |
4413 | parser->greater_than_is_operator_p = true; |
4414 | |
4415 | parser->default_arg_ok_p = true; |
4416 | |
4417 | /* We are not parsing a constant-expression. */ |
4418 | parser->integral_constant_expression_p = false; |
4419 | parser->allow_non_integral_constant_expression_p = false; |
4420 | parser->non_integral_constant_expression_p = false; |
4421 | |
4422 | /* Local variable names are not forbidden. */ |
4423 | parser->local_variables_forbidden_p = 0; |
4424 | |
4425 | /* We are not processing an `extern "C"' declaration. */ |
4426 | parser->in_unbraced_linkage_specification_p = false; |
4427 | |
4428 | /* We are not processing a declarator. */ |
4429 | parser->in_declarator_p = false; |
4430 | |
4431 | /* We are not processing a template-argument-list. */ |
4432 | parser->in_template_argument_list_p = false; |
4433 | |
4434 | /* We are not in an iteration statement. */ |
4435 | parser->in_statement = 0; |
4436 | |
4437 | /* We are not in a switch statement. */ |
4438 | parser->in_switch_statement_p = false; |
4439 | |
4440 | /* We are not parsing a type-id inside an expression. */ |
4441 | parser->in_type_id_in_expr_p = false; |
4442 | |
4443 | /* String literals should be translated to the execution character set. */ |
4444 | parser->translate_strings_p = true; |
4445 | |
4446 | /* We are not parsing a function body. */ |
4447 | parser->in_function_body = false; |
4448 | |
4449 | /* We can correct until told otherwise. */ |
4450 | parser->colon_corrects_to_scope_p = true; |
4451 | |
4452 | /* The unparsed function queue is empty. */ |
4453 | push_unparsed_function_queues (parser); |
4454 | |
4455 | /* There are no classes being defined. */ |
4456 | parser->num_classes_being_defined = 0; |
4457 | |
4458 | /* No template parameters apply. */ |
4459 | parser->num_template_parameter_lists = 0; |
4460 | |
4461 | /* Special parsing data structures. */ |
4462 | parser->omp_declare_simd = NULL; |
4463 | parser->oacc_routine = NULL; |
4464 | |
4465 | /* Disallow OpenMP array sections in expressions. */ |
4466 | parser->omp_array_section_p = false; |
4467 | |
4468 | /* Not declaring an implicit function template. */ |
4469 | parser->auto_is_implicit_function_template_parm_p = false; |
4470 | parser->fully_implicit_function_template_p = false; |
4471 | parser->implicit_template_parms = 0; |
4472 | parser->implicit_template_scope = 0; |
4473 | |
4474 | /* Allow constrained-type-specifiers. */ |
4475 | parser->prevent_constrained_type_specifiers = 0; |
4476 | |
4477 | /* We haven't yet seen an 'extern "C"'. */ |
4478 | parser->innermost_linkage_specification_location = UNKNOWN_LOCATION; |
4479 | |
4480 | return parser; |
4481 | } |
4482 | |
4483 | /* Create a cp_lexer structure which will emit the tokens in CACHE |
4484 | and push it onto the parser's lexer stack. This is used for delayed |
4485 | parsing of in-class method bodies and default arguments, and should |
4486 | not be confused with tentative parsing. */ |
4487 | static void |
4488 | cp_parser_push_lexer_for_tokens (cp_parser *parser, cp_token_cache *cache) |
4489 | { |
4490 | cp_lexer *lexer = cp_lexer_new_from_tokens (cache); |
4491 | lexer->next = parser->lexer; |
4492 | parser->lexer = lexer; |
4493 | |
4494 | /* Move the current source position to that of the first token in the |
4495 | new lexer. */ |
4496 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
4497 | } |
4498 | |
4499 | /* Pop the top lexer off the parser stack. This is never used for the |
4500 | "main" lexer, only for those pushed by cp_parser_push_lexer_for_tokens. */ |
4501 | static void |
4502 | cp_parser_pop_lexer (cp_parser *parser) |
4503 | { |
4504 | cp_lexer *lexer = parser->lexer; |
4505 | parser->lexer = lexer->next; |
4506 | cp_lexer_destroy (lexer); |
4507 | |
4508 | /* Put the current source position back where it was before this |
4509 | lexer was pushed. */ |
4510 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4511 | } |
4512 | |
4513 | /* Lexical conventions [gram.lex] */ |
4514 | |
4515 | /* Parse an identifier. Returns an IDENTIFIER_NODE representing the |
4516 | identifier. */ |
4517 | |
4518 | static cp_expr |
4519 | cp_parser_identifier (cp_parser* parser) |
4520 | { |
4521 | cp_token *token; |
4522 | |
4523 | /* Look for the identifier. */ |
4524 | token = cp_parser_require (parser, CPP_NAME, RT_NAME); |
4525 | /* Return the value. */ |
4526 | if (token) |
4527 | return cp_expr (token->u.value, token->location); |
4528 | else |
4529 | return error_mark_node; |
4530 | } |
4531 | |
4532 | /* Worker for cp_parser_string_literal, cp_parser_userdef_string_literal |
4533 | and cp_parser_unevaluated_string_literal. |
4534 | Do not call this directly; use either of the above. |
4535 | |
4536 | Parse a sequence of adjacent string constants. Return a |
4537 | TREE_STRING representing the combined, nul-terminated string |
4538 | constant. If TRANSLATE is true, translate the string to the |
4539 | execution character set. If WIDE_OK is true, a wide string is |
4540 | valid here. If UDL_OK is true, a string literal with user-defined |
4541 | suffix can be used in this context. If UNEVAL is true, diagnose |
4542 | numeric and conditional escape sequences in it if pedantic. |
4543 | |
4544 | C++98 [lex.string] says that if a narrow string literal token is |
4545 | adjacent to a wide string literal token, the behavior is undefined. |
4546 | However, C99 6.4.5p4 says that this results in a wide string literal. |
4547 | We follow C99 here, for consistency with the C front end. |
4548 | |
4549 | This code is largely lifted from lex_string() in c-lex.cc. |
4550 | |
4551 | FUTURE: ObjC++ will need to handle @-strings here. */ |
4552 | |
4553 | static cp_expr |
4554 | cp_parser_string_literal_common (cp_parser *parser, bool translate, |
4555 | bool wide_ok, bool udl_ok, |
4556 | bool lookup_udlit, bool uneval) |
4557 | { |
4558 | tree value; |
4559 | size_t count; |
4560 | struct obstack str_ob; |
4561 | struct obstack loc_ob; |
4562 | cpp_string str, istr, *strs; |
4563 | cp_token *tok; |
4564 | enum cpp_ttype type, curr_type; |
4565 | int have_suffix_p = 0; |
4566 | tree string_tree; |
4567 | tree suffix_id = NULL_TREE; |
4568 | bool curr_tok_is_userdef_p = false; |
4569 | |
4570 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
4571 | if (!cp_parser_is_string_literal (token: tok)) |
4572 | { |
4573 | cp_parser_error (parser, gmsgid: "expected string-literal" ); |
4574 | return error_mark_node; |
4575 | } |
4576 | |
4577 | location_t loc = tok->location; |
4578 | |
4579 | if (cpp_userdef_string_p (type: tok->type)) |
4580 | { |
4581 | if (!udl_ok) |
4582 | { |
4583 | error_at (loc, "string literal with user-defined suffix " |
4584 | "is invalid in this context" ); |
4585 | return error_mark_node; |
4586 | } |
4587 | string_tree = USERDEF_LITERAL_VALUE (tok->u.value); |
4588 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4589 | curr_tok_is_userdef_p = true; |
4590 | } |
4591 | else |
4592 | { |
4593 | string_tree = tok->u.value; |
4594 | curr_type = tok->type; |
4595 | } |
4596 | type = curr_type; |
4597 | |
4598 | /* Try to avoid the overhead of creating and destroying an obstack |
4599 | for the common case of just one string. */ |
4600 | if (!cp_parser_is_string_literal |
4601 | (token: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))) |
4602 | { |
4603 | cp_lexer_consume_token (lexer: parser->lexer); |
4604 | |
4605 | str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); |
4606 | str.len = TREE_STRING_LENGTH (string_tree); |
4607 | count = 1; |
4608 | |
4609 | if (curr_tok_is_userdef_p) |
4610 | { |
4611 | suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); |
4612 | have_suffix_p = 1; |
4613 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4614 | } |
4615 | else |
4616 | curr_type = tok->type; |
4617 | |
4618 | strs = &str; |
4619 | } |
4620 | else |
4621 | { |
4622 | location_t last_tok_loc = tok->location; |
4623 | gcc_obstack_init (&str_ob); |
4624 | gcc_obstack_init (&loc_ob); |
4625 | count = 0; |
4626 | |
4627 | do |
4628 | { |
4629 | cp_lexer_consume_token (lexer: parser->lexer); |
4630 | count++; |
4631 | str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); |
4632 | str.len = TREE_STRING_LENGTH (string_tree); |
4633 | |
4634 | if (curr_tok_is_userdef_p) |
4635 | { |
4636 | tree curr_suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); |
4637 | if (have_suffix_p == 0) |
4638 | { |
4639 | suffix_id = curr_suffix_id; |
4640 | have_suffix_p = 1; |
4641 | } |
4642 | else if (have_suffix_p == 1 |
4643 | && curr_suffix_id != suffix_id) |
4644 | { |
4645 | error ("inconsistent user-defined literal suffixes" |
4646 | " %qD and %qD in string literal" , |
4647 | suffix_id, curr_suffix_id); |
4648 | have_suffix_p = -1; |
4649 | } |
4650 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4651 | } |
4652 | else |
4653 | curr_type = tok->type; |
4654 | |
4655 | if (type != curr_type) |
4656 | { |
4657 | if (type == CPP_STRING) |
4658 | type = curr_type; |
4659 | else if (curr_type != CPP_STRING) |
4660 | { |
4661 | rich_location rich_loc (line_table, tok->location); |
4662 | rich_loc.add_range (loc: last_tok_loc); |
4663 | error_at (&rich_loc, |
4664 | "concatenation of string literals with " |
4665 | "conflicting encoding prefixes" ); |
4666 | } |
4667 | } |
4668 | |
4669 | obstack_grow (&str_ob, &str, sizeof (cpp_string)); |
4670 | obstack_grow (&loc_ob, &tok->location, sizeof (location_t)); |
4671 | |
4672 | last_tok_loc = tok->location; |
4673 | |
4674 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
4675 | if (cpp_userdef_string_p (type: tok->type)) |
4676 | { |
4677 | if (!udl_ok) |
4678 | { |
4679 | error_at (loc, "string literal with user-defined suffix " |
4680 | "is invalid in this context" ); |
4681 | return error_mark_node; |
4682 | } |
4683 | string_tree = USERDEF_LITERAL_VALUE (tok->u.value); |
4684 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4685 | curr_tok_is_userdef_p = true; |
4686 | } |
4687 | else |
4688 | { |
4689 | string_tree = tok->u.value; |
4690 | curr_type = tok->type; |
4691 | curr_tok_is_userdef_p = false; |
4692 | } |
4693 | } |
4694 | while (cp_parser_is_string_literal (token: tok)); |
4695 | |
4696 | /* A string literal built by concatenation has its caret=start at |
4697 | the start of the initial string, and its finish at the finish of |
4698 | the final string literal. */ |
4699 | loc = make_location (caret: loc, start: loc, finish: get_finish (loc: last_tok_loc)); |
4700 | |
4701 | strs = (cpp_string *) obstack_finish (&str_ob); |
4702 | } |
4703 | |
4704 | if (type != CPP_STRING && !wide_ok) |
4705 | { |
4706 | cp_parser_error (parser, gmsgid: "a wide string is invalid in this context" ); |
4707 | type = CPP_STRING; |
4708 | } |
4709 | if (uneval) |
4710 | type = CPP_UNEVAL_STRING; |
4711 | |
4712 | if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate) |
4713 | (parse_in, strs, count, &istr, type)) |
4714 | { |
4715 | value = build_string (istr.len, (const char *)istr.text); |
4716 | free (CONST_CAST (unsigned char *, istr.text)); |
4717 | if (count > 1) |
4718 | { |
4719 | location_t *locs = (location_t *)obstack_finish (&loc_ob); |
4720 | gcc_assert (g_string_concat_db); |
4721 | g_string_concat_db->record_string_concatenation (num: count, locs); |
4722 | } |
4723 | |
4724 | switch (type) |
4725 | { |
4726 | default: |
4727 | case CPP_STRING: |
4728 | TREE_TYPE (value) = char_array_type_node; |
4729 | break; |
4730 | case CPP_UTF8STRING: |
4731 | if (flag_char8_t) |
4732 | TREE_TYPE (value) = char8_array_type_node; |
4733 | else |
4734 | TREE_TYPE (value) = char_array_type_node; |
4735 | break; |
4736 | case CPP_STRING16: |
4737 | TREE_TYPE (value) = char16_array_type_node; |
4738 | break; |
4739 | case CPP_STRING32: |
4740 | TREE_TYPE (value) = char32_array_type_node; |
4741 | break; |
4742 | case CPP_WSTRING: |
4743 | TREE_TYPE (value) = wchar_array_type_node; |
4744 | break; |
4745 | } |
4746 | |
4747 | value = fix_string_type (value); |
4748 | |
4749 | if (have_suffix_p) |
4750 | { |
4751 | tree literal = build_userdef_literal (suffix_id, value, |
4752 | overflow: OT_NONE, NULL_TREE); |
4753 | if (lookup_udlit) |
4754 | value = finish_userdef_string_literal (literal); |
4755 | else |
4756 | value = literal; |
4757 | } |
4758 | } |
4759 | else |
4760 | /* cpp_interpret_string has issued an error. */ |
4761 | value = error_mark_node; |
4762 | |
4763 | if (count > 1) |
4764 | { |
4765 | obstack_free (&str_ob, 0); |
4766 | obstack_free (&loc_ob, 0); |
4767 | } |
4768 | |
4769 | return cp_expr (value, loc); |
4770 | } |
4771 | |
4772 | /* Parse a sequence of adjacent string constants. Return a TREE_STRING |
4773 | representing the combined, nul-terminated string constant. If |
4774 | TRANSLATE is true, translate the string to the execution character set. |
4775 | If WIDE_OK is true, a wide string is valid here. |
4776 | |
4777 | This function issues an error if a user defined string literal is |
4778 | encountered; use cp_parser_userdef_string_literal if UDLs are allowed. */ |
4779 | |
4780 | static inline cp_expr |
4781 | cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) |
4782 | { |
4783 | return cp_parser_string_literal_common (parser, translate, wide_ok, |
4784 | /*udl_ok=*/false, |
4785 | /*lookup_udlit=*/false, |
4786 | /*uneval=*/false); |
4787 | } |
4788 | |
4789 | /* Parse a string literal or user defined string literal. |
4790 | |
4791 | user-defined-string-literal : |
4792 | string-literal ud-suffix |
4793 | |
4794 | If LOOKUP_UDLIT, perform a lookup for a suitable template function. */ |
4795 | |
4796 | static inline cp_expr |
4797 | cp_parser_userdef_string_literal (cp_parser *parser, bool lookup_udlit) |
4798 | { |
4799 | return cp_parser_string_literal_common (parser, /*translate=*/true, |
4800 | /*wide_ok=*/true, /*udl_ok=*/true, |
4801 | lookup_udlit, /*uneval=*/false); |
4802 | } |
4803 | |
4804 | /* Parse an unevaluated string literal. |
4805 | |
4806 | unevaluated-string: |
4807 | string-literal */ |
4808 | |
4809 | static inline cp_expr |
4810 | cp_parser_unevaluated_string_literal (cp_parser *parser) |
4811 | { |
4812 | return cp_parser_string_literal_common (parser, /*translate=*/false, |
4813 | /*wide_ok=*/false, /*udl_ok=*/false, |
4814 | /*lookup_udlit=*/false, |
4815 | /*uneval=*/true); |
4816 | } |
4817 | |
4818 | /* Look up a literal operator with the name and the exact arguments. */ |
4819 | |
4820 | static tree |
4821 | lookup_literal_operator (tree name, vec<tree, va_gc> *args) |
4822 | { |
4823 | tree decl = lookup_name (name); |
4824 | if (!decl || !is_overloaded_fn (decl)) |
4825 | return error_mark_node; |
4826 | |
4827 | for (lkp_iterator iter (decl); iter; ++iter) |
4828 | { |
4829 | tree fn = *iter; |
4830 | |
4831 | if (tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn))) |
4832 | { |
4833 | unsigned int ix; |
4834 | bool found = true; |
4835 | |
4836 | for (ix = 0; |
4837 | found && ix < vec_safe_length (v: args) && parmtypes != NULL_TREE; |
4838 | ++ix, parmtypes = TREE_CHAIN (parmtypes)) |
4839 | { |
4840 | tree tparm = TREE_VALUE (parmtypes); |
4841 | tree targ = TREE_TYPE ((*args)[ix]); |
4842 | bool ptr = TYPE_PTR_P (tparm); |
4843 | bool arr = TREE_CODE (targ) == ARRAY_TYPE; |
4844 | if ((ptr || arr || !same_type_p (tparm, targ)) |
4845 | && (!ptr || !arr |
4846 | || !same_type_p (TREE_TYPE (tparm), |
4847 | TREE_TYPE (targ)))) |
4848 | found = false; |
4849 | } |
4850 | |
4851 | if (found |
4852 | && ix == vec_safe_length (v: args) |
4853 | /* May be this should be sufficient_parms_p instead, |
4854 | depending on how exactly should user-defined literals |
4855 | work in presence of default arguments on the literal |
4856 | operator parameters. */ |
4857 | && parmtypes == void_list_node) |
4858 | return decl; |
4859 | } |
4860 | } |
4861 | |
4862 | return error_mark_node; |
4863 | } |
4864 | |
4865 | /* Parse a user-defined char constant. Returns a call to a user-defined |
4866 | literal operator taking the character as an argument. */ |
4867 | |
4868 | static cp_expr |
4869 | cp_parser_userdef_char_literal (cp_parser *parser) |
4870 | { |
4871 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
4872 | tree literal = token->u.value; |
4873 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
4874 | tree value = USERDEF_LITERAL_VALUE (literal); |
4875 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
4876 | tree decl, result; |
4877 | |
4878 | /* Build up a call to the user-defined operator */ |
4879 | /* Lookup the name we got back from the id-expression. */ |
4880 | releasing_vec args; |
4881 | vec_safe_push (r&: args, t: value); |
4882 | decl = lookup_literal_operator (name, args); |
4883 | if (!decl || decl == error_mark_node) |
4884 | { |
4885 | error ("unable to find character literal operator %qD with %qT argument" , |
4886 | name, TREE_TYPE (value)); |
4887 | return error_mark_node; |
4888 | } |
4889 | result = finish_call_expr (decl, &args, false, true, tf_warning_or_error); |
4890 | return result; |
4891 | } |
4892 | |
4893 | /* A subroutine of cp_parser_userdef_numeric_literal to |
4894 | create a char... template parameter pack from a string node. */ |
4895 | |
4896 | static tree |
4897 | make_char_string_pack (tree value) |
4898 | { |
4899 | tree charvec; |
4900 | tree argpack = make_node (NONTYPE_ARGUMENT_PACK); |
4901 | const unsigned char *str |
4902 | = (const unsigned char *) TREE_STRING_POINTER (value); |
4903 | int i, len = TREE_STRING_LENGTH (value) - 1; |
4904 | tree argvec = make_tree_vec (1); |
4905 | |
4906 | /* Fill in CHARVEC with all of the parameters. */ |
4907 | charvec = make_tree_vec (len); |
4908 | for (i = 0; i < len; ++i) |
4909 | { |
4910 | unsigned char s[3] = { '\'', str[i], '\'' }; |
4911 | cpp_string in = { .len: 3, .text: s }; |
4912 | cpp_string out = { .len: 0, .text: 0 }; |
4913 | if (!cpp_interpret_string (parse_in, &in, 1, &out, CPP_STRING)) |
4914 | return NULL_TREE; |
4915 | gcc_assert (out.len == 2); |
4916 | TREE_VEC_ELT (charvec, i) = build_int_cst (char_type_node, |
4917 | out.text[0]); |
4918 | } |
4919 | |
4920 | /* Build the argument packs. */ |
4921 | ARGUMENT_PACK_ARGS (argpack) = charvec; |
4922 | |
4923 | TREE_VEC_ELT (argvec, 0) = argpack; |
4924 | |
4925 | return argvec; |
4926 | } |
4927 | |
4928 | /* A subroutine of cp_parser_userdef_numeric_literal to |
4929 | create a char... template parameter pack from a string node. */ |
4930 | |
4931 | static tree |
4932 | make_string_pack (tree value) |
4933 | { |
4934 | tree charvec; |
4935 | tree argpack = make_node (NONTYPE_ARGUMENT_PACK); |
4936 | const unsigned char *str |
4937 | = (const unsigned char *) TREE_STRING_POINTER (value); |
4938 | int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))); |
4939 | int len = TREE_STRING_LENGTH (value) / sz - 1; |
4940 | tree argvec = make_tree_vec (2); |
4941 | |
4942 | tree str_char_type_node = TREE_TYPE (TREE_TYPE (value)); |
4943 | str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node); |
4944 | |
4945 | /* First template parm is character type. */ |
4946 | TREE_VEC_ELT (argvec, 0) = str_char_type_node; |
4947 | |
4948 | /* Fill in CHARVEC with all of the parameters. */ |
4949 | charvec = make_tree_vec (len); |
4950 | for (int i = 0; i < len; ++i) |
4951 | TREE_VEC_ELT (charvec, i) |
4952 | = double_int_to_tree (str_char_type_node, |
4953 | double_int::from_buffer (buffer: str + i * sz, len: sz)); |
4954 | |
4955 | /* Build the argument packs. */ |
4956 | ARGUMENT_PACK_ARGS (argpack) = charvec; |
4957 | |
4958 | TREE_VEC_ELT (argvec, 1) = argpack; |
4959 | |
4960 | return argvec; |
4961 | } |
4962 | |
4963 | /* Parse a user-defined numeric constant. returns a call to a user-defined |
4964 | literal operator. */ |
4965 | |
4966 | static cp_expr |
4967 | cp_parser_userdef_numeric_literal (cp_parser *parser) |
4968 | { |
4969 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
4970 | tree literal = token->u.value; |
4971 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
4972 | tree value = USERDEF_LITERAL_VALUE (literal); |
4973 | int overflow = USERDEF_LITERAL_OVERFLOW (literal); |
4974 | tree num_string = USERDEF_LITERAL_NUM_STRING (literal); |
4975 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
4976 | tree decl, result; |
4977 | |
4978 | /* Look for a literal operator taking the exact type of numeric argument |
4979 | as the literal value. */ |
4980 | releasing_vec args; |
4981 | vec_safe_push (r&: args, t: value); |
4982 | decl = lookup_literal_operator (name, args); |
4983 | if (decl && decl != error_mark_node) |
4984 | { |
4985 | result = finish_call_expr (decl, &args, false, true, |
4986 | tf_warning_or_error); |
4987 | |
4988 | if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0) |
4989 | { |
4990 | warning_at (token->location, OPT_Woverflow, |
4991 | "integer literal exceeds range of %qT type" , |
4992 | long_long_unsigned_type_node); |
4993 | } |
4994 | else |
4995 | { |
4996 | if (overflow > 0) |
4997 | warning_at (token->location, OPT_Woverflow, |
4998 | "floating literal exceeds range of %qT type" , |
4999 | long_double_type_node); |
5000 | else if (overflow < 0) |
5001 | warning_at (token->location, OPT_Woverflow, |
5002 | "floating literal truncated to zero" ); |
5003 | } |
5004 | |
5005 | return result; |
5006 | } |
5007 | |
5008 | /* If the numeric argument didn't work, look for a raw literal |
5009 | operator taking a const char* argument consisting of the number |
5010 | in string format. */ |
5011 | args->truncate (size: 0); |
5012 | vec_safe_push (r&: args, t: num_string); |
5013 | decl = lookup_literal_operator (name, args); |
5014 | if (decl && decl != error_mark_node) |
5015 | { |
5016 | result = finish_call_expr (decl, &args, false, true, |
5017 | tf_warning_or_error); |
5018 | return result; |
5019 | } |
5020 | |
5021 | /* If the raw literal didn't work, look for a non-type template |
5022 | function with parameter pack char.... Call the function with |
5023 | template parameter characters representing the number. */ |
5024 | args->truncate (size: 0); |
5025 | decl = lookup_literal_operator (name, args); |
5026 | if (decl && decl != error_mark_node) |
5027 | { |
5028 | tree tmpl_args = make_char_string_pack (value: num_string); |
5029 | if (tmpl_args == NULL_TREE) |
5030 | { |
5031 | error ("failed to translate literal to execution character set %qT" , |
5032 | num_string); |
5033 | return error_mark_node; |
5034 | } |
5035 | decl = lookup_template_function (decl, tmpl_args); |
5036 | result = finish_call_expr (decl, &args, false, true, |
5037 | tf_warning_or_error); |
5038 | return result; |
5039 | } |
5040 | |
5041 | /* In C++14 the standard library defines complex number suffixes that |
5042 | conflict with GNU extensions. Prefer them if <complex> is #included. */ |
5043 | bool ext = cpp_get_options (parse_in)->ext_numeric_literals; |
5044 | bool i14 = (cxx_dialect > cxx11 |
5045 | && (id_equal (id: suffix_id, str: "i" ) |
5046 | || id_equal (id: suffix_id, str: "if" ) |
5047 | || id_equal (id: suffix_id, str: "il" ))); |
5048 | diagnostic_t kind = DK_ERROR; |
5049 | int opt = 0; |
5050 | |
5051 | if (i14 && ext) |
5052 | { |
5053 | tree cxlit = lookup_qualified_name (std_node, name: "complex_literals" , |
5054 | LOOK_want::NORMAL, false); |
5055 | if (cxlit == error_mark_node) |
5056 | { |
5057 | /* No <complex>, so pedwarn and use GNU semantics. */ |
5058 | kind = DK_PEDWARN; |
5059 | opt = OPT_Wpedantic; |
5060 | } |
5061 | } |
5062 | |
5063 | bool complained |
5064 | = emit_diagnostic (kind, input_location, opt, |
5065 | "unable to find numeric literal operator %qD" , name); |
5066 | |
5067 | if (!complained) |
5068 | /* Don't inform either. */; |
5069 | else if (i14) |
5070 | { |
5071 | inform (token->location, "add %<using namespace std::complex_literals%> " |
5072 | "(from %<<complex>%>) to enable the C++14 user-defined literal " |
5073 | "suffixes" ); |
5074 | if (ext) |
5075 | inform (token->location, "or use %<j%> instead of %<i%> for the " |
5076 | "GNU built-in suffix" ); |
5077 | } |
5078 | else if (!ext) |
5079 | inform (token->location, "use %<-fext-numeric-literals%> " |
5080 | "to enable more built-in suffixes" ); |
5081 | |
5082 | if (kind == DK_ERROR) |
5083 | value = error_mark_node; |
5084 | else |
5085 | { |
5086 | /* Use the built-in semantics. */ |
5087 | tree type; |
5088 | if (id_equal (id: suffix_id, str: "i" )) |
5089 | { |
5090 | if (TREE_CODE (value) == INTEGER_CST) |
5091 | type = integer_type_node; |
5092 | else |
5093 | type = double_type_node; |
5094 | } |
5095 | else if (id_equal (id: suffix_id, str: "if" )) |
5096 | type = float_type_node; |
5097 | else /* if (id_equal (suffix_id, "il")) */ |
5098 | type = long_double_type_node; |
5099 | |
5100 | value = fold_build2 (COMPLEX_EXPR, build_complex_type (type), |
5101 | build_zero_cst (type), fold_convert (type, value)); |
5102 | } |
5103 | |
5104 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5105 | /* Avoid repeated diagnostics. */ |
5106 | token->u.value = value; |
5107 | return value; |
5108 | } |
5109 | |
5110 | /* Parse a user-defined string constant. Returns a call to a user-defined |
5111 | literal operator taking a character pointer and the length of the string |
5112 | as arguments. */ |
5113 | |
5114 | static tree |
5115 | finish_userdef_string_literal (tree literal) |
5116 | { |
5117 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
5118 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
5119 | tree value = USERDEF_LITERAL_VALUE (literal); |
5120 | int len = TREE_STRING_LENGTH (value) |
5121 | / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1; |
5122 | tree decl; |
5123 | |
5124 | /* Build up a call to the user-defined operator. */ |
5125 | /* Lookup the name we got back from the id-expression. */ |
5126 | releasing_vec args; |
5127 | vec_safe_push (r&: args, t: value); |
5128 | vec_safe_push (r&: args, t: build_int_cst (size_type_node, len)); |
5129 | decl = lookup_literal_operator (name, args); |
5130 | |
5131 | if (decl && decl != error_mark_node) |
5132 | return finish_call_expr (decl, &args, false, true, |
5133 | tf_warning_or_error); |
5134 | |
5135 | /* Look for a suitable template function, either (C++20) with a single |
5136 | parameter of class type, or (N3599) with typename parameter CharT and |
5137 | parameter pack CharT... */ |
5138 | args->truncate (size: 0); |
5139 | decl = lookup_literal_operator (name, args); |
5140 | if (decl && decl != error_mark_node) |
5141 | { |
5142 | /* Use resolve_nondeduced_context to try to choose one form of template |
5143 | or the other. */ |
5144 | tree tmpl_args = make_tree_vec (1); |
5145 | TREE_VEC_ELT (tmpl_args, 0) = value; |
5146 | decl = lookup_template_function (decl, tmpl_args); |
5147 | tree res = resolve_nondeduced_context (decl, tf_none); |
5148 | if (DECL_P (res)) |
5149 | decl = res; |
5150 | else |
5151 | { |
5152 | TREE_OPERAND (decl, 1) = make_string_pack (value); |
5153 | res = resolve_nondeduced_context (decl, tf_none); |
5154 | if (DECL_P (res)) |
5155 | decl = res; |
5156 | } |
5157 | if (!DECL_P (decl) && cxx_dialect > cxx17) |
5158 | TREE_OPERAND (decl, 1) = tmpl_args; |
5159 | return finish_call_expr (decl, &args, false, true, |
5160 | tf_warning_or_error); |
5161 | } |
5162 | |
5163 | error ("unable to find string literal operator %qD with %qT, %qT arguments" , |
5164 | name, TREE_TYPE (value), size_type_node); |
5165 | return error_mark_node; |
5166 | } |
5167 | |
5168 | |
5169 | /* Basic concepts [gram.basic] */ |
5170 | |
5171 | /* Parse a translation-unit. |
5172 | |
5173 | translation-unit: |
5174 | declaration-seq [opt] */ |
5175 | |
5176 | static void |
5177 | cp_parser_translation_unit (cp_parser* parser) |
5178 | { |
5179 | gcc_checking_assert (!cp_error_declarator); |
5180 | |
5181 | /* Create the declarator obstack. */ |
5182 | gcc_obstack_init (&declarator_obstack); |
5183 | /* Create the error declarator. */ |
5184 | cp_error_declarator = make_declarator (kind: cdk_error); |
5185 | /* Create the empty parameter list. */ |
5186 | no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE, |
5187 | UNKNOWN_LOCATION); |
5188 | /* Remember where the base of the declarator obstack lies. */ |
5189 | void *declarator_obstack_base = obstack_next_free (&declarator_obstack); |
5190 | |
5191 | push_deferring_access_checks (flag_access_control |
5192 | ? dk_no_deferred : dk_no_check); |
5193 | |
5194 | module_parse mp_state = MP_NOT_MODULE; |
5195 | if (modules_p () && !header_module_p ()) |
5196 | mp_state = MP_FIRST; |
5197 | |
5198 | bool implicit_extern_c = false; |
5199 | |
5200 | /* Parse until EOF. */ |
5201 | for (;;) |
5202 | { |
5203 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
5204 | |
5205 | /* If we're entering or exiting a region that's implicitly |
5206 | extern "C", modify the lang context appropriately. This is |
5207 | so horrible. Please die. */ |
5208 | if (implicit_extern_c |
5209 | != cp_lexer_peek_token (lexer: parser->lexer)->implicit_extern_c) |
5210 | { |
5211 | implicit_extern_c = !implicit_extern_c; |
5212 | if (implicit_extern_c) |
5213 | push_lang_context (lang_name_c); |
5214 | else |
5215 | pop_lang_context (); |
5216 | } |
5217 | |
5218 | if (token->type == CPP_EOF) |
5219 | break; |
5220 | |
5221 | if (modules_p ()) |
5222 | { |
5223 | /* Top-level module declarations are ok, and change the |
5224 | portion of file we're in. Top-level import declarations |
5225 | are significant for the import portions. */ |
5226 | |
5227 | cp_token *next = token; |
5228 | bool exporting = token->keyword == RID__EXPORT; |
5229 | if (exporting) |
5230 | { |
5231 | cp_lexer_consume_token (lexer: parser->lexer); |
5232 | next = cp_lexer_peek_token (lexer: parser->lexer); |
5233 | } |
5234 | if (next->keyword == RID__MODULE) |
5235 | { |
5236 | mp_state |
5237 | = cp_parser_module_declaration (parser, mp_state, exporting); |
5238 | continue; |
5239 | } |
5240 | else if (next->keyword == RID__IMPORT) |
5241 | { |
5242 | if (mp_state == MP_FIRST) |
5243 | mp_state = MP_NOT_MODULE; |
5244 | cp_parser_import_declaration (parser, mp_state, exporting); |
5245 | continue; |
5246 | } |
5247 | else |
5248 | gcc_checking_assert (!exporting); |
5249 | |
5250 | if (mp_state == MP_GLOBAL && token->main_source_p) |
5251 | { |
5252 | static bool warned = false; |
5253 | if (!warned) |
5254 | { |
5255 | warned = true; |
5256 | pedwarn (token->location, OPT_Wglobal_module, |
5257 | "global module fragment contents must be" |
5258 | " from preprocessor inclusion" ); |
5259 | } |
5260 | } |
5261 | } |
5262 | |
5263 | /* This relies on the ordering of module_parse values. */ |
5264 | if (mp_state == MP_PURVIEW_IMPORTS || mp_state == MP_PRIVATE_IMPORTS) |
5265 | /* We're no longer in the import portion of a named module. */ |
5266 | mp_state = module_parse (mp_state + 1); |
5267 | else if (mp_state == MP_FIRST) |
5268 | mp_state = MP_NOT_MODULE; |
5269 | |
5270 | if (token->type == CPP_CLOSE_BRACE) |
5271 | { |
5272 | cp_parser_error (parser, gmsgid: "expected declaration" ); |
5273 | cp_lexer_consume_token (lexer: parser->lexer); |
5274 | /* If the next token is now a `;', consume it. */ |
5275 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
5276 | cp_lexer_consume_token (lexer: parser->lexer); |
5277 | } |
5278 | else |
5279 | cp_parser_toplevel_declaration (parser); |
5280 | } |
5281 | |
5282 | /* Get rid of the token array; we don't need it any more. */ |
5283 | cp_lexer_destroy (lexer: parser->lexer); |
5284 | parser->lexer = NULL; |
5285 | |
5286 | /* The EOF should have reset this. */ |
5287 | gcc_checking_assert (!implicit_extern_c); |
5288 | |
5289 | /* Make sure the declarator obstack was fully cleaned up. */ |
5290 | gcc_assert (obstack_next_free (&declarator_obstack) |
5291 | == declarator_obstack_base); |
5292 | } |
5293 | |
5294 | /* Return the appropriate tsubst flags for parsing, possibly in N3276 |
5295 | decltype context. */ |
5296 | |
5297 | static inline tsubst_flags_t |
5298 | complain_flags (bool decltype_p) |
5299 | { |
5300 | tsubst_flags_t complain = tf_warning_or_error; |
5301 | if (decltype_p) |
5302 | complain |= tf_decltype; |
5303 | return complain; |
5304 | } |
5305 | |
5306 | /* We're about to parse a collection of statements. If we're currently |
5307 | parsing tentatively, set up a firewall so that any nested |
5308 | cp_parser_commit_to_tentative_parse won't affect the current context. */ |
5309 | |
5310 | static cp_token_position |
5311 | cp_parser_start_tentative_firewall (cp_parser *parser) |
5312 | { |
5313 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5314 | return 0; |
5315 | |
5316 | cp_parser_parse_tentatively (parser); |
5317 | cp_parser_commit_to_topmost_tentative_parse (parser); |
5318 | return cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
5319 | } |
5320 | |
5321 | /* We've finished parsing the collection of statements. Wrap up the |
5322 | firewall and replace the relevant tokens with the parsed form. */ |
5323 | |
5324 | static void |
5325 | cp_parser_end_tentative_firewall (cp_parser *parser, cp_token_position start, |
5326 | tree expr) |
5327 | { |
5328 | if (!start) |
5329 | return; |
5330 | |
5331 | /* Finish the firewall level. */ |
5332 | cp_parser_parse_definitely (parser); |
5333 | /* And remember the result of the parse for when we try again. */ |
5334 | cp_token *token = cp_lexer_token_at (parser->lexer, pos: start); |
5335 | token->type = CPP_PREPARSED_EXPR; |
5336 | token->u.value = expr; |
5337 | token->keyword = RID_MAX; |
5338 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
5339 | } |
5340 | |
5341 | /* Like the above functions, but let the user modify the tokens. Used by |
5342 | CPP_DECLTYPE and CPP_TEMPLATE_ID, where we are saving the side-effects for |
5343 | later parses, so it makes sense to localize the effects of |
5344 | cp_parser_commit_to_tentative_parse. */ |
5345 | |
5346 | struct tentative_firewall |
5347 | { |
5348 | cp_parser *parser; |
5349 | bool set; |
5350 | |
5351 | tentative_firewall (cp_parser *p): parser(p) |
5352 | { |
5353 | /* If we're currently parsing tentatively, start a committed level as a |
5354 | firewall and then an inner tentative parse. */ |
5355 | if ((set = cp_parser_uncommitted_to_tentative_parse_p (parser))) |
5356 | { |
5357 | cp_parser_parse_tentatively (parser); |
5358 | cp_parser_commit_to_topmost_tentative_parse (parser); |
5359 | cp_parser_parse_tentatively (parser); |
5360 | } |
5361 | } |
5362 | |
5363 | ~tentative_firewall() |
5364 | { |
5365 | if (set) |
5366 | { |
5367 | /* Finish the inner tentative parse and the firewall, propagating any |
5368 | uncommitted error state to the outer tentative parse. */ |
5369 | bool err = cp_parser_error_occurred (parser); |
5370 | cp_parser_parse_definitely (parser); |
5371 | cp_parser_parse_definitely (parser); |
5372 | if (err) |
5373 | cp_parser_simulate_error (parser); |
5374 | } |
5375 | } |
5376 | }; |
5377 | |
5378 | /* Some tokens naturally come in pairs e.g.'(' and ')'. |
5379 | This class is for tracking such a matching pair of symbols. |
5380 | In particular, it tracks the location of the first token, |
5381 | so that if the second token is missing, we can highlight the |
5382 | location of the first token when notifying the user about the |
5383 | problem. */ |
5384 | |
5385 | template <typename traits_t> |
5386 | class token_pair |
5387 | { |
5388 | public: |
5389 | /* token_pair's ctor. */ |
5390 | token_pair () : m_open_loc (UNKNOWN_LOCATION) {} |
5391 | |
5392 | /* If the next token is the opening symbol for this pair, consume it and |
5393 | return true. |
5394 | Otherwise, issue an error and return false. |
5395 | In either case, record the location of the opening token. */ |
5396 | |
5397 | bool require_open (cp_parser *parser) |
5398 | { |
5399 | m_open_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5400 | return cp_parser_require (parser, traits_t::open_token_type, |
5401 | traits_t::required_token_open); |
5402 | } |
5403 | |
5404 | /* Consume the next token from PARSER, recording its location as |
5405 | that of the opening token within the pair. */ |
5406 | |
5407 | cp_token * consume_open (cp_parser *parser) |
5408 | { |
5409 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
5410 | gcc_assert (tok->type == traits_t::open_token_type); |
5411 | m_open_loc = tok->location; |
5412 | return tok; |
5413 | } |
5414 | |
5415 | /* If the next token is the closing symbol for this pair, consume it |
5416 | and return it. |
5417 | Otherwise, issue an error, highlighting the location of the |
5418 | corresponding opening token, and return NULL. */ |
5419 | |
5420 | cp_token *require_close (cp_parser *parser) const |
5421 | { |
5422 | return cp_parser_require (parser, traits_t::close_token_type, |
5423 | traits_t::required_token_close, |
5424 | m_open_loc); |
5425 | } |
5426 | |
5427 | location_t open_location () const { return m_open_loc; } |
5428 | |
5429 | private: |
5430 | location_t m_open_loc; |
5431 | }; |
5432 | |
5433 | /* Traits for token_pair<T> for tracking matching pairs of parentheses. */ |
5434 | |
5435 | struct matching_paren_traits |
5436 | { |
5437 | static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; |
5438 | static const enum required_token required_token_open = RT_OPEN_PAREN; |
5439 | static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; |
5440 | static const enum required_token required_token_close = RT_CLOSE_PAREN; |
5441 | }; |
5442 | |
5443 | /* "matching_parens" is a token_pair<T> class for tracking matching |
5444 | pairs of parentheses. */ |
5445 | |
5446 | typedef token_pair<matching_paren_traits> matching_parens; |
5447 | |
5448 | /* Traits for token_pair<T> for tracking matching pairs of braces. */ |
5449 | |
5450 | struct matching_brace_traits |
5451 | { |
5452 | static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; |
5453 | static const enum required_token required_token_open = RT_OPEN_BRACE; |
5454 | static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; |
5455 | static const enum required_token required_token_close = RT_CLOSE_BRACE; |
5456 | }; |
5457 | |
5458 | /* "matching_braces" is a token_pair<T> class for tracking matching |
5459 | pairs of braces. */ |
5460 | |
5461 | typedef token_pair<matching_brace_traits> matching_braces; |
5462 | |
5463 | |
5464 | /* Parse a GNU statement-expression, i.e. ({ stmts }), except for the |
5465 | enclosing parentheses. */ |
5466 | |
5467 | static cp_expr |
5468 | cp_parser_statement_expr (cp_parser *parser) |
5469 | { |
5470 | cp_token_position start = cp_parser_start_tentative_firewall (parser); |
5471 | auto oas = make_temp_override (var&: parser->omp_array_section_p, overrider: false); |
5472 | |
5473 | /* Consume the '('. */ |
5474 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5475 | matching_parens parens; |
5476 | parens.consume_open (parser); |
5477 | /* Start the statement-expression. */ |
5478 | tree expr = begin_stmt_expr (); |
5479 | /* Parse the compound-statement. */ |
5480 | cp_parser_compound_statement (parser, expr, BCS_STMT_EXPR, false); |
5481 | /* Finish up. */ |
5482 | expr = finish_stmt_expr (expr, false); |
5483 | /* Consume the ')'. */ |
5484 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5485 | if (!parens.require_close (parser)) |
5486 | cp_parser_skip_to_end_of_statement (parser); |
5487 | |
5488 | cp_parser_end_tentative_firewall (parser, start, expr); |
5489 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
5490 | return cp_expr (expr, combined_loc); |
5491 | } |
5492 | |
5493 | /* Expressions [gram.expr] */ |
5494 | |
5495 | /* Parse a fold-operator. |
5496 | |
5497 | fold-operator: |
5498 | - * / % ^ & | = < > << >> |
5499 | = -= *= /= %= ^= &= |= <<= >>= |
5500 | == != <= >= && || , .* ->* |
5501 | |
5502 | This returns the tree code corresponding to the matched operator |
5503 | as an int. When the current token matches a compound assignment |
5504 | operator, the resulting tree code is the negative value of the |
5505 | non-assignment operator. */ |
5506 | |
5507 | static int |
5508 | cp_parser_fold_operator (cp_token *token) |
5509 | { |
5510 | switch (token->type) |
5511 | { |
5512 | case CPP_PLUS: return PLUS_EXPR; |
5513 | case CPP_MINUS: return MINUS_EXPR; |
5514 | case CPP_MULT: return MULT_EXPR; |
5515 | case CPP_DIV: return TRUNC_DIV_EXPR; |
5516 | case CPP_MOD: return TRUNC_MOD_EXPR; |
5517 | case CPP_XOR: return BIT_XOR_EXPR; |
5518 | case CPP_AND: return BIT_AND_EXPR; |
5519 | case CPP_OR: return BIT_IOR_EXPR; |
5520 | case CPP_LSHIFT: return LSHIFT_EXPR; |
5521 | case CPP_RSHIFT: return RSHIFT_EXPR; |
5522 | |
5523 | case CPP_EQ: return -NOP_EXPR; |
5524 | case CPP_PLUS_EQ: return -PLUS_EXPR; |
5525 | case CPP_MINUS_EQ: return -MINUS_EXPR; |
5526 | case CPP_MULT_EQ: return -MULT_EXPR; |
5527 | case CPP_DIV_EQ: return -TRUNC_DIV_EXPR; |
5528 | case CPP_MOD_EQ: return -TRUNC_MOD_EXPR; |
5529 | case CPP_XOR_EQ: return -BIT_XOR_EXPR; |
5530 | case CPP_AND_EQ: return -BIT_AND_EXPR; |
5531 | case CPP_OR_EQ: return -BIT_IOR_EXPR; |
5532 | case CPP_LSHIFT_EQ: return -LSHIFT_EXPR; |
5533 | case CPP_RSHIFT_EQ: return -RSHIFT_EXPR; |
5534 | |
5535 | case CPP_EQ_EQ: return EQ_EXPR; |
5536 | case CPP_NOT_EQ: return NE_EXPR; |
5537 | case CPP_LESS: return LT_EXPR; |
5538 | case CPP_GREATER: return GT_EXPR; |
5539 | case CPP_LESS_EQ: return LE_EXPR; |
5540 | case CPP_GREATER_EQ: return GE_EXPR; |
5541 | |
5542 | case CPP_AND_AND: return TRUTH_ANDIF_EXPR; |
5543 | case CPP_OR_OR: return TRUTH_ORIF_EXPR; |
5544 | |
5545 | case CPP_COMMA: return COMPOUND_EXPR; |
5546 | |
5547 | case CPP_DOT_STAR: return DOTSTAR_EXPR; |
5548 | case CPP_DEREF_STAR: return MEMBER_REF; |
5549 | |
5550 | default: return ERROR_MARK; |
5551 | } |
5552 | } |
5553 | |
5554 | /* Returns true if CODE indicates a binary expression, which is not allowed in |
5555 | the LHS of a fold-expression. More codes will need to be added to use this |
5556 | function in other contexts. */ |
5557 | |
5558 | static bool |
5559 | is_binary_op (tree_code code) |
5560 | { |
5561 | switch (code) |
5562 | { |
5563 | case PLUS_EXPR: |
5564 | case POINTER_PLUS_EXPR: |
5565 | case MINUS_EXPR: |
5566 | case MULT_EXPR: |
5567 | case TRUNC_DIV_EXPR: |
5568 | case TRUNC_MOD_EXPR: |
5569 | case BIT_XOR_EXPR: |
5570 | case BIT_AND_EXPR: |
5571 | case BIT_IOR_EXPR: |
5572 | case LSHIFT_EXPR: |
5573 | case RSHIFT_EXPR: |
5574 | |
5575 | case MODOP_EXPR: |
5576 | |
5577 | case EQ_EXPR: |
5578 | case NE_EXPR: |
5579 | case LE_EXPR: |
5580 | case GE_EXPR: |
5581 | case LT_EXPR: |
5582 | case GT_EXPR: |
5583 | |
5584 | case TRUTH_ANDIF_EXPR: |
5585 | case TRUTH_ORIF_EXPR: |
5586 | |
5587 | case COMPOUND_EXPR: |
5588 | |
5589 | case DOTSTAR_EXPR: |
5590 | case MEMBER_REF: |
5591 | return true; |
5592 | |
5593 | default: |
5594 | return false; |
5595 | } |
5596 | } |
5597 | |
5598 | /* If the next token is a suitable fold operator, consume it and return as |
5599 | the function above. */ |
5600 | |
5601 | static int |
5602 | cp_parser_fold_operator (cp_parser *parser) |
5603 | { |
5604 | cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
5605 | int code = cp_parser_fold_operator (token); |
5606 | if (code != ERROR_MARK) |
5607 | cp_lexer_consume_token (lexer: parser->lexer); |
5608 | return code; |
5609 | } |
5610 | |
5611 | /* Parse a fold-expression. |
5612 | |
5613 | fold-expression: |
5614 | ( ... folding-operator cast-expression) |
5615 | ( cast-expression folding-operator ... ) |
5616 | ( cast-expression folding operator ... folding-operator cast-expression) |
5617 | |
5618 | Note that the '(' and ')' are matched in primary expression. */ |
5619 | |
5620 | static cp_expr |
5621 | cp_parser_fold_expression (cp_parser *parser, tree expr1) |
5622 | { |
5623 | cp_id_kind pidk; |
5624 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5625 | const cp_token *token = nullptr; |
5626 | |
5627 | // Left fold. |
5628 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5629 | { |
5630 | if (expr1) |
5631 | return error_mark_node; |
5632 | cp_lexer_consume_token (lexer: parser->lexer); |
5633 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5634 | int op = cp_parser_fold_operator (parser); |
5635 | if (op == ERROR_MARK) |
5636 | { |
5637 | cp_parser_error (parser, gmsgid: "expected binary operator" ); |
5638 | return error_mark_node; |
5639 | } |
5640 | |
5641 | tree expr = cp_parser_cast_expression (parser, false, false, |
5642 | false, &pidk); |
5643 | if (expr == error_mark_node) |
5644 | return error_mark_node; |
5645 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5646 | return finish_left_unary_fold_expr (loc, expr, op); |
5647 | } |
5648 | |
5649 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5650 | int op = cp_parser_fold_operator (parser); |
5651 | if (op == ERROR_MARK) |
5652 | { |
5653 | cp_parser_error (parser, gmsgid: "expected binary operator" ); |
5654 | return error_mark_node; |
5655 | } |
5656 | |
5657 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5658 | { |
5659 | cp_parser_error (parser, gmsgid: "expected ..." ); |
5660 | return error_mark_node; |
5661 | } |
5662 | cp_lexer_consume_token (lexer: parser->lexer); |
5663 | |
5664 | /* The operands of a fold-expression are cast-expressions, so binary or |
5665 | conditional expressions are not allowed. We check this here to avoid |
5666 | tentative parsing. */ |
5667 | if (EXPR_P (expr1) && warning_suppressed_p (expr1, OPT_Wparentheses)) |
5668 | /* OK, the expression was parenthesized. */; |
5669 | else if (is_binary_op (TREE_CODE (expr1))) |
5670 | error_at (location_of (expr1), |
5671 | "binary expression in operand of fold-expression" ); |
5672 | else if (TREE_CODE (expr1) == COND_EXPR |
5673 | || (REFERENCE_REF_P (expr1) |
5674 | && TREE_CODE (TREE_OPERAND (expr1, 0)) == COND_EXPR)) |
5675 | error_at (location_of (expr1), |
5676 | "conditional expression in operand of fold-expression" ); |
5677 | |
5678 | // Right fold. |
5679 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
5680 | { |
5681 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5682 | return finish_right_unary_fold_expr (loc, expr1, op); |
5683 | } |
5684 | |
5685 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: token->type)) |
5686 | { |
5687 | cp_parser_error (parser, gmsgid: "mismatched operator in fold-expression" ); |
5688 | return error_mark_node; |
5689 | } |
5690 | cp_lexer_consume_token (lexer: parser->lexer); |
5691 | |
5692 | // Binary left or right fold. |
5693 | tree expr2 = cp_parser_cast_expression (parser, false, false, false, &pidk); |
5694 | if (expr2 == error_mark_node) |
5695 | return error_mark_node; |
5696 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5697 | return finish_binary_fold_expr (loc, expr1, expr2, op); |
5698 | } |
5699 | |
5700 | /* Parse a primary-expression. |
5701 | |
5702 | primary-expression: |
5703 | literal |
5704 | this |
5705 | ( expression ) |
5706 | id-expression |
5707 | lambda-expression (C++11) |
5708 | |
5709 | GNU Extensions: |
5710 | |
5711 | primary-expression: |
5712 | ( compound-statement ) |
5713 | __builtin_va_arg ( assignment-expression , type-id ) |
5714 | __builtin_offsetof ( type-id , offsetof-expression ) |
5715 | |
5716 | C++ Extensions: |
5717 | __has_nothrow_assign ( type-id ) |
5718 | __has_nothrow_constructor ( type-id ) |
5719 | __has_nothrow_copy ( type-id ) |
5720 | __has_trivial_assign ( type-id ) |
5721 | __has_trivial_constructor ( type-id ) |
5722 | __has_trivial_copy ( type-id ) |
5723 | __has_trivial_destructor ( type-id ) |
5724 | __has_virtual_destructor ( type-id ) |
5725 | __is_abstract ( type-id ) |
5726 | __is_base_of ( type-id , type-id ) |
5727 | __is_class ( type-id ) |
5728 | __is_empty ( type-id ) |
5729 | __is_enum ( type-id ) |
5730 | __is_final ( type-id ) |
5731 | __is_literal_type ( type-id ) |
5732 | __is_pod ( type-id ) |
5733 | __is_polymorphic ( type-id ) |
5734 | __is_std_layout ( type-id ) |
5735 | __is_trivial ( type-id ) |
5736 | __is_union ( type-id ) |
5737 | |
5738 | Objective-C++ Extension: |
5739 | |
5740 | primary-expression: |
5741 | objc-expression |
5742 | |
5743 | literal: |
5744 | __null |
5745 | |
5746 | ADDRESS_P is true iff this expression was immediately preceded by |
5747 | "&" and therefore might denote a pointer-to-member. CAST_P is true |
5748 | iff this expression is the target of a cast. TEMPLATE_ARG_P is |
5749 | true iff this expression is a template argument. |
5750 | |
5751 | Returns a representation of the expression. Upon return, *IDK |
5752 | indicates what kind of id-expression (if any) was present. */ |
5753 | |
5754 | static cp_expr |
5755 | cp_parser_primary_expression (cp_parser *parser, |
5756 | bool address_p, |
5757 | bool cast_p, |
5758 | bool template_arg_p, |
5759 | bool decltype_p, |
5760 | cp_id_kind *idk) |
5761 | { |
5762 | cp_token *token = NULL; |
5763 | |
5764 | /* Assume the primary expression is not an id-expression. */ |
5765 | *idk = CP_ID_KIND_NONE; |
5766 | |
5767 | /* Peek at the next token. */ |
5768 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5769 | switch ((int) token->type) |
5770 | { |
5771 | /* literal: |
5772 | integer-literal |
5773 | character-literal |
5774 | floating-literal |
5775 | string-literal |
5776 | boolean-literal |
5777 | pointer-literal |
5778 | user-defined-literal */ |
5779 | case CPP_CHAR: |
5780 | case CPP_CHAR16: |
5781 | case CPP_CHAR32: |
5782 | case CPP_WCHAR: |
5783 | case CPP_UTF8CHAR: |
5784 | case CPP_NUMBER: |
5785 | case CPP_PREPARSED_EXPR: |
5786 | if (TREE_CODE (token->u.value) == USERDEF_LITERAL) |
5787 | return cp_parser_userdef_numeric_literal (parser); |
5788 | token = cp_lexer_consume_token (lexer: parser->lexer); |
5789 | if (TREE_CODE (token->u.value) == FIXED_CST) |
5790 | { |
5791 | error_at (token->location, |
5792 | "fixed-point types not supported in C++" ); |
5793 | return error_mark_node; |
5794 | } |
5795 | /* Floating-point literals are only allowed in an integral |
5796 | constant expression if they are cast to an integral or |
5797 | enumeration type. */ |
5798 | if ((TREE_CODE (token->u.value) == REAL_CST |
5799 | || (TREE_CODE (token->u.value) == EXCESS_PRECISION_EXPR |
5800 | && TREE_CODE (TREE_OPERAND (token->u.value, 0)) == REAL_CST)) |
5801 | && parser->integral_constant_expression_p |
5802 | && pedantic) |
5803 | { |
5804 | /* CAST_P will be set even in invalid code like "int(2.7 + |
5805 | ...)". Therefore, we have to check that the next token |
5806 | is sure to end the cast. */ |
5807 | if (cast_p) |
5808 | { |
5809 | cp_token *next_token; |
5810 | |
5811 | next_token = cp_lexer_peek_token (lexer: parser->lexer); |
5812 | if (/* The comma at the end of an |
5813 | enumerator-definition. */ |
5814 | next_token->type != CPP_COMMA |
5815 | /* The curly brace at the end of an enum-specifier. */ |
5816 | && next_token->type != CPP_CLOSE_BRACE |
5817 | /* The end of a statement. */ |
5818 | && next_token->type != CPP_SEMICOLON |
5819 | /* The end of the cast-expression. */ |
5820 | && next_token->type != CPP_CLOSE_PAREN |
5821 | /* The end of an array bound. */ |
5822 | && next_token->type != CPP_CLOSE_SQUARE |
5823 | /* The closing ">" in a template-argument-list. */ |
5824 | && (next_token->type != CPP_GREATER |
5825 | || parser->greater_than_is_operator_p) |
5826 | /* C++0x only: A ">>" treated like two ">" tokens, |
5827 | in a template-argument-list. */ |
5828 | && (next_token->type != CPP_RSHIFT |
5829 | || (cxx_dialect == cxx98) |
5830 | || parser->greater_than_is_operator_p)) |
5831 | cast_p = false; |
5832 | } |
5833 | |
5834 | /* If we are within a cast, then the constraint that the |
5835 | cast is to an integral or enumeration type will be |
5836 | checked at that point. If we are not within a cast, then |
5837 | this code is invalid. */ |
5838 | if (!cast_p) |
5839 | cp_parser_non_integral_constant_expression (parser, thing: NIC_FLOAT); |
5840 | } |
5841 | return (cp_expr (token->u.value, token->location, token->flags & DECIMAL_INT) |
5842 | .maybe_add_location_wrapper ()); |
5843 | |
5844 | case CPP_CHAR_USERDEF: |
5845 | case CPP_CHAR16_USERDEF: |
5846 | case CPP_CHAR32_USERDEF: |
5847 | case CPP_WCHAR_USERDEF: |
5848 | case CPP_UTF8CHAR_USERDEF: |
5849 | return cp_parser_userdef_char_literal (parser); |
5850 | |
5851 | case CPP_STRING: |
5852 | case CPP_STRING16: |
5853 | case CPP_STRING32: |
5854 | case CPP_WSTRING: |
5855 | case CPP_UTF8STRING: |
5856 | case CPP_STRING_USERDEF: |
5857 | case CPP_STRING16_USERDEF: |
5858 | case CPP_STRING32_USERDEF: |
5859 | case CPP_WSTRING_USERDEF: |
5860 | case CPP_UTF8STRING_USERDEF: |
5861 | /* ??? Should wide strings be allowed when parser->translate_strings_p |
5862 | is false (i.e. in attributes)? If not, we can kill the third |
5863 | argument to cp_parser_string_literal. */ |
5864 | if (parser->translate_strings_p) |
5865 | return (cp_parser_userdef_string_literal (parser, |
5866 | /*lookup_udlit=*/true) |
5867 | .maybe_add_location_wrapper ()); |
5868 | else |
5869 | return (cp_parser_string_literal (parser, |
5870 | /*translate=*/false, |
5871 | /*wide_ok=*/true) |
5872 | .maybe_add_location_wrapper ()); |
5873 | |
5874 | case CPP_OPEN_PAREN: |
5875 | /* If we see `( { ' then we are looking at the beginning of |
5876 | a GNU statement-expression. */ |
5877 | if (cp_parser_allow_gnu_extensions_p (parser) |
5878 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_BRACE)) |
5879 | { |
5880 | /* Statement-expressions are not allowed by the standard. */ |
5881 | pedwarn (token->location, OPT_Wpedantic, |
5882 | "ISO C++ forbids braced-groups within expressions" ); |
5883 | |
5884 | /* And they're not allowed outside of a function-body; you |
5885 | cannot, for example, write: |
5886 | |
5887 | int i = ({ int j = 3; j + 1; }); |
5888 | |
5889 | at class or namespace scope. */ |
5890 | if (!parser->in_function_body |
5891 | || parser->in_template_argument_list_p) |
5892 | { |
5893 | error_at (token->location, |
5894 | "statement-expressions are not allowed outside " |
5895 | "functions nor in template-argument lists" ); |
5896 | cp_parser_skip_to_end_of_block_or_statement (parser); |
5897 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
5898 | cp_lexer_consume_token (lexer: parser->lexer); |
5899 | return error_mark_node; |
5900 | } |
5901 | else |
5902 | return cp_parser_statement_expr (parser); |
5903 | } |
5904 | /* Otherwise it's a normal parenthesized expression. */ |
5905 | { |
5906 | cp_expr expr; |
5907 | bool saved_greater_than_is_operator_p; |
5908 | |
5909 | location_t open_paren_loc = token->location; |
5910 | |
5911 | /* Consume the `('. */ |
5912 | matching_parens parens; |
5913 | parens.consume_open (parser); |
5914 | /* Within a parenthesized expression, a `>' token is always |
5915 | the greater-than operator. */ |
5916 | saved_greater_than_is_operator_p |
5917 | = parser->greater_than_is_operator_p; |
5918 | parser->greater_than_is_operator_p = true; |
5919 | |
5920 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5921 | /* Left fold expression. */ |
5922 | expr = NULL_TREE; |
5923 | else |
5924 | /* Parse the parenthesized expression. */ |
5925 | expr = cp_parser_expression (parser, idk, cast_p, decltype_p); |
5926 | |
5927 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5928 | if (token->type == CPP_ELLIPSIS || cp_parser_fold_operator (token)) |
5929 | { |
5930 | expr = cp_parser_fold_expression (parser, expr1: expr); |
5931 | if (expr != error_mark_node |
5932 | && cxx_dialect < cxx17) |
5933 | pedwarn (input_location, OPT_Wc__17_extensions, |
5934 | "fold-expressions only available with %<-std=c++17%> " |
5935 | "or %<-std=gnu++17%>" ); |
5936 | } |
5937 | else |
5938 | /* Let the front end know that this expression was |
5939 | enclosed in parentheses. This matters in case, for |
5940 | example, the expression is of the form `A::B', since |
5941 | `&A::B' might be a pointer-to-member, but `&(A::B)' is |
5942 | not. */ |
5943 | expr = finish_parenthesized_expr (expr); |
5944 | |
5945 | /* DR 705: Wrapping an unqualified name in parentheses |
5946 | suppresses arg-dependent lookup. We want to pass back |
5947 | CP_ID_KIND_QUALIFIED for suppressing vtable lookup |
5948 | (c++/37862), but none of the others. */ |
5949 | if (*idk != CP_ID_KIND_QUALIFIED) |
5950 | *idk = CP_ID_KIND_NONE; |
5951 | |
5952 | /* The `>' token might be the end of a template-id or |
5953 | template-parameter-list now. */ |
5954 | parser->greater_than_is_operator_p |
5955 | = saved_greater_than_is_operator_p; |
5956 | |
5957 | /* Consume the `)'. */ |
5958 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5959 | location_t close_paren_loc = token->location; |
5960 | bool no_wparens = warning_suppressed_p (expr, OPT_Wparentheses); |
5961 | expr.set_range (start: open_paren_loc, finish: close_paren_loc); |
5962 | if (no_wparens) |
5963 | suppress_warning (expr, OPT_Wparentheses); |
5964 | if (!parens.require_close (parser) |
5965 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5966 | cp_parser_skip_to_end_of_statement (parser); |
5967 | |
5968 | return expr; |
5969 | } |
5970 | |
5971 | case CPP_OPEN_SQUARE: |
5972 | { |
5973 | if (c_dialect_objc ()) |
5974 | { |
5975 | /* We might have an Objective-C++ message. */ |
5976 | cp_parser_parse_tentatively (parser); |
5977 | tree msg = cp_parser_objc_message_expression (parser); |
5978 | /* If that works out, we're done ... */ |
5979 | if (cp_parser_parse_definitely (parser)) |
5980 | return msg; |
5981 | /* ... else, fall though to see if it's a lambda. */ |
5982 | } |
5983 | cp_expr lam = cp_parser_lambda_expression (parser); |
5984 | /* Don't warn about a failed tentative parse. */ |
5985 | if (cp_parser_error_occurred (parser)) |
5986 | return error_mark_node; |
5987 | maybe_warn_cpp0x (str: CPP0X_LAMBDA_EXPR); |
5988 | return lam; |
5989 | } |
5990 | |
5991 | case CPP_OBJC_STRING: |
5992 | if (c_dialect_objc ()) |
5993 | /* We have an Objective-C++ string literal. */ |
5994 | return cp_parser_objc_expression (parser); |
5995 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
5996 | return error_mark_node; |
5997 | |
5998 | case CPP_KEYWORD: |
5999 | switch (token->keyword) |
6000 | { |
6001 | /* These two are the boolean literals. */ |
6002 | case RID_TRUE: |
6003 | cp_lexer_consume_token (lexer: parser->lexer); |
6004 | return cp_expr (boolean_true_node, token->location); |
6005 | case RID_FALSE: |
6006 | cp_lexer_consume_token (lexer: parser->lexer); |
6007 | return cp_expr (boolean_false_node, token->location); |
6008 | |
6009 | /* The `__null' literal. */ |
6010 | case RID_NULL: |
6011 | cp_lexer_consume_token (lexer: parser->lexer); |
6012 | return cp_expr (null_node, token->location); |
6013 | |
6014 | /* The `nullptr' literal. */ |
6015 | case RID_NULLPTR: |
6016 | cp_lexer_consume_token (lexer: parser->lexer); |
6017 | return cp_expr (nullptr_node, token->location); |
6018 | |
6019 | /* Recognize the `this' keyword. */ |
6020 | case RID_THIS: |
6021 | cp_lexer_consume_token (lexer: parser->lexer); |
6022 | if (parser->local_variables_forbidden_p & THIS_FORBIDDEN) |
6023 | { |
6024 | error_at (token->location, |
6025 | "%<this%> may not be used in this context" ); |
6026 | return error_mark_node; |
6027 | } |
6028 | /* Pointers cannot appear in constant-expressions. */ |
6029 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_THIS)) |
6030 | return error_mark_node; |
6031 | return cp_expr (finish_this_expr (), token->location); |
6032 | |
6033 | /* The `operator' keyword can be the beginning of an |
6034 | id-expression. */ |
6035 | case RID_OPERATOR: |
6036 | goto id_expression; |
6037 | |
6038 | case RID_FUNCTION_NAME: |
6039 | case RID_PRETTY_FUNCTION_NAME: |
6040 | case RID_C99_FUNCTION_NAME: |
6041 | { |
6042 | non_integral_constant name; |
6043 | |
6044 | /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and |
6045 | __func__ are the names of variables -- but they are |
6046 | treated specially. Therefore, they are handled here, |
6047 | rather than relying on the generic id-expression logic |
6048 | below. Grammatically, these names are id-expressions. |
6049 | |
6050 | Consume the token. */ |
6051 | token = cp_lexer_consume_token (lexer: parser->lexer); |
6052 | |
6053 | switch (token->keyword) |
6054 | { |
6055 | case RID_FUNCTION_NAME: |
6056 | name = NIC_FUNC_NAME; |
6057 | break; |
6058 | case RID_PRETTY_FUNCTION_NAME: |
6059 | name = NIC_PRETTY_FUNC; |
6060 | break; |
6061 | case RID_C99_FUNCTION_NAME: |
6062 | name = NIC_C99_FUNC; |
6063 | break; |
6064 | default: |
6065 | gcc_unreachable (); |
6066 | } |
6067 | |
6068 | if (cp_parser_non_integral_constant_expression (parser, thing: name)) |
6069 | return error_mark_node; |
6070 | |
6071 | /* Look up the name. */ |
6072 | return finish_fname (token->u.value); |
6073 | } |
6074 | |
6075 | case RID_VA_ARG: |
6076 | { |
6077 | tree expression; |
6078 | tree type; |
6079 | location_t type_location; |
6080 | location_t start_loc |
6081 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6082 | /* The `__builtin_va_arg' construct is used to handle |
6083 | `va_arg'. Consume the `__builtin_va_arg' token. */ |
6084 | cp_lexer_consume_token (lexer: parser->lexer); |
6085 | /* Look for the opening `('. */ |
6086 | matching_parens parens; |
6087 | parens.require_open (parser); |
6088 | /* Now, parse the assignment-expression. */ |
6089 | expression = cp_parser_assignment_expression (parser); |
6090 | /* Look for the `,'. */ |
6091 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
6092 | type_location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6093 | /* Parse the type-id. */ |
6094 | { |
6095 | type_id_in_expr_sentinel s (parser); |
6096 | type = cp_parser_type_id (parser); |
6097 | } |
6098 | /* Look for the closing `)'. */ |
6099 | location_t finish_loc |
6100 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6101 | parens.require_close (parser); |
6102 | /* Using `va_arg' in a constant-expression is not |
6103 | allowed. */ |
6104 | if (cp_parser_non_integral_constant_expression (parser, |
6105 | thing: NIC_VA_ARG)) |
6106 | return error_mark_node; |
6107 | /* Construct a location of the form: |
6108 | __builtin_va_arg (v, int) |
6109 | ~~~~~~~~~~~~~~~~~~~~~^~~~ |
6110 | with the caret at the type, ranging from the start of the |
6111 | "__builtin_va_arg" token to the close paren. */ |
6112 | location_t combined_loc |
6113 | = make_location (caret: type_location, start: start_loc, finish: finish_loc); |
6114 | return build_x_va_arg (combined_loc, expression, type); |
6115 | } |
6116 | |
6117 | case RID_OFFSETOF: |
6118 | return cp_parser_builtin_offsetof (parser); |
6119 | |
6120 | // C++ concepts |
6121 | case RID_REQUIRES: |
6122 | return cp_parser_requires_expression (parser); |
6123 | |
6124 | /* Objective-C++ expressions. */ |
6125 | case RID_AT_ENCODE: |
6126 | case RID_AT_PROTOCOL: |
6127 | case RID_AT_SELECTOR: |
6128 | return cp_parser_objc_expression (parser); |
6129 | |
6130 | case RID_OMP_ALL_MEMORY: |
6131 | gcc_assert (flag_openmp); |
6132 | cp_lexer_consume_token (lexer: parser->lexer); |
6133 | error_at (token->location, |
6134 | "%<omp_all_memory%> may only be used in OpenMP " |
6135 | "%<depend%> clause" ); |
6136 | return error_mark_node; |
6137 | |
6138 | case RID_TEMPLATE: |
6139 | if (parser->in_function_body |
6140 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
6141 | == CPP_LESS)) |
6142 | { |
6143 | error_at (token->location, |
6144 | "a template declaration cannot appear at block scope" ); |
6145 | cp_parser_skip_to_end_of_block_or_statement (parser); |
6146 | return error_mark_node; |
6147 | } |
6148 | /* FALLTHRU */ |
6149 | default: |
6150 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
6151 | return error_mark_node; |
6152 | } |
6153 | |
6154 | /* An id-expression can start with either an identifier, a |
6155 | `::' as the beginning of a qualified-id, or the "operator" |
6156 | keyword. */ |
6157 | case CPP_NAME: |
6158 | if (const cp_trait* trait = cp_lexer_peek_trait_expr (lexer: parser->lexer)) |
6159 | return cp_parser_trait (parser, trait); |
6160 | /* FALLTHRU */ |
6161 | case CPP_SCOPE: |
6162 | case CPP_TEMPLATE_ID: |
6163 | case CPP_NESTED_NAME_SPECIFIER: |
6164 | { |
6165 | id_expression: |
6166 | cp_expr id_expression; |
6167 | cp_expr decl; |
6168 | const char *error_msg; |
6169 | bool template_p; |
6170 | bool done; |
6171 | cp_token *id_expr_token; |
6172 | |
6173 | /* Parse the id-expression. */ |
6174 | id_expression |
6175 | = cp_parser_id_expression (parser, |
6176 | /*template_keyword_p=*/false, |
6177 | /*check_dependency_p=*/true, |
6178 | &template_p, |
6179 | /*declarator_p=*/false, |
6180 | /*optional_p=*/false); |
6181 | if (id_expression == error_mark_node) |
6182 | return error_mark_node; |
6183 | id_expr_token = token; |
6184 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6185 | done = (token->type != CPP_OPEN_SQUARE |
6186 | && token->type != CPP_OPEN_PAREN |
6187 | && token->type != CPP_DOT |
6188 | && token->type != CPP_DEREF |
6189 | && token->type != CPP_PLUS_PLUS |
6190 | && token->type != CPP_MINUS_MINUS); |
6191 | /* If we have a template-id, then no further lookup is |
6192 | required. If the template-id was for a template-class, we |
6193 | will sometimes have a TYPE_DECL at this point. */ |
6194 | if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR |
6195 | || TREE_CODE (id_expression) == TYPE_DECL) |
6196 | decl = id_expression; |
6197 | /* Look up the name. */ |
6198 | else |
6199 | { |
6200 | tree ambiguous_decls; |
6201 | |
6202 | /* If we already know that this lookup is ambiguous, then |
6203 | we've already issued an error message; there's no reason |
6204 | to check again. */ |
6205 | if (id_expr_token->type == CPP_NAME |
6206 | && id_expr_token->error_reported) |
6207 | { |
6208 | cp_parser_simulate_error (parser); |
6209 | return error_mark_node; |
6210 | } |
6211 | |
6212 | decl = cp_parser_lookup_name (parser, id_expression, |
6213 | none_type, |
6214 | template_p, |
6215 | /*is_namespace=*/false, |
6216 | /*check_dependency=*/true, |
6217 | &ambiguous_decls, |
6218 | id_expression.get_location ()); |
6219 | /* If the lookup was ambiguous, an error will already have |
6220 | been issued. */ |
6221 | if (ambiguous_decls) |
6222 | return error_mark_node; |
6223 | |
6224 | /* In Objective-C++, we may have an Objective-C 2.0 |
6225 | dot-syntax for classes here. */ |
6226 | if (c_dialect_objc () |
6227 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT |
6228 | && TREE_CODE (decl) == TYPE_DECL |
6229 | && objc_is_class_name (decl)) |
6230 | { |
6231 | tree component; |
6232 | cp_lexer_consume_token (lexer: parser->lexer); |
6233 | component = cp_parser_identifier (parser); |
6234 | if (component == error_mark_node) |
6235 | return error_mark_node; |
6236 | |
6237 | tree result = objc_build_class_component_ref (id_expression, |
6238 | component); |
6239 | /* Build a location of the form: |
6240 | expr.component |
6241 | ~~~~~^~~~~~~~~ |
6242 | with caret at the start of the component name (at |
6243 | input_location), ranging from the start of the id_expression |
6244 | to the end of the component name. */ |
6245 | location_t combined_loc |
6246 | = make_location (caret: input_location, start: id_expression.get_start (), |
6247 | finish: get_finish (loc: input_location)); |
6248 | protected_set_expr_location (result, combined_loc); |
6249 | return result; |
6250 | } |
6251 | |
6252 | /* In Objective-C++, an instance variable (ivar) may be preferred |
6253 | to whatever cp_parser_lookup_name() found. |
6254 | Call objc_lookup_ivar. To avoid exposing cp_expr to the |
6255 | rest of c-family, we have to do a little extra work to preserve |
6256 | any location information in cp_expr "decl". Given that |
6257 | objc_lookup_ivar is implemented in "c-family" and "objc", we |
6258 | have a trip through the pure "tree" type, rather than cp_expr. |
6259 | Naively copying it back to "decl" would implicitly give the |
6260 | new cp_expr value an UNKNOWN_LOCATION for nodes that don't |
6261 | store an EXPR_LOCATION. Hence we only update "decl" (and |
6262 | hence its location_t) if we get back a different tree node. */ |
6263 | tree decl_tree = objc_lookup_ivar (decl.get_value (), |
6264 | id_expression); |
6265 | if (decl_tree != decl.get_value ()) |
6266 | decl = cp_expr (decl_tree); |
6267 | |
6268 | /* If name lookup gives us a SCOPE_REF, then the |
6269 | qualifying scope was dependent. */ |
6270 | if (TREE_CODE (decl) == SCOPE_REF) |
6271 | { |
6272 | /* At this point, we do not know if DECL is a valid |
6273 | integral constant expression. We assume that it is |
6274 | in fact such an expression, so that code like: |
6275 | |
6276 | template <int N> struct A { |
6277 | int a[B<N>::i]; |
6278 | }; |
6279 | |
6280 | is accepted. At template-instantiation time, we |
6281 | will check that B<N>::i is actually a constant. */ |
6282 | return decl; |
6283 | } |
6284 | /* Check to see if DECL is a local variable in a context |
6285 | where that is forbidden. */ |
6286 | if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) |
6287 | && local_variable_p (decl) |
6288 | /* DR 2082 permits local variables in unevaluated contexts |
6289 | within a default argument. */ |
6290 | && !cp_unevaluated_operand) |
6291 | { |
6292 | const char *msg |
6293 | = (TREE_CODE (decl) == PARM_DECL |
6294 | ? G_("parameter %qD may not appear in this context" ) |
6295 | : G_("local variable %qD may not appear in this context" )); |
6296 | error_at (id_expression.get_location (), msg, |
6297 | decl.get_value ()); |
6298 | return error_mark_node; |
6299 | } |
6300 | } |
6301 | |
6302 | decl = (finish_id_expression |
6303 | (id_expression, decl, parser->scope, |
6304 | idk, |
6305 | parser->integral_constant_expression_p, |
6306 | parser->allow_non_integral_constant_expression_p, |
6307 | &parser->non_integral_constant_expression_p, |
6308 | template_p, done, address_p, |
6309 | template_arg_p, |
6310 | &error_msg, |
6311 | id_expression.get_location ())); |
6312 | if (error_msg) |
6313 | cp_parser_error (parser, gmsgid: error_msg); |
6314 | /* Build a location for an id-expression of the form: |
6315 | ::ns::id |
6316 | ~~~~~~^~ |
6317 | or: |
6318 | id |
6319 | ^~ |
6320 | i.e. from the start of the first token to the end of the final |
6321 | token, with the caret at the start of the unqualified-id. */ |
6322 | location_t caret_loc = get_pure_location (loc: id_expression.get_location ()); |
6323 | location_t start_loc = get_start (loc: id_expr_token->location); |
6324 | location_t finish_loc = get_finish (loc: id_expression.get_location ()); |
6325 | location_t combined_loc |
6326 | = make_location (caret: caret_loc, start: start_loc, finish: finish_loc); |
6327 | |
6328 | decl.set_location (combined_loc); |
6329 | return decl; |
6330 | } |
6331 | |
6332 | /* Anything else is an error. */ |
6333 | default: |
6334 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
6335 | return error_mark_node; |
6336 | } |
6337 | } |
6338 | |
6339 | static inline cp_expr |
6340 | cp_parser_primary_expression (cp_parser *parser, |
6341 | bool address_p, |
6342 | bool cast_p, |
6343 | bool template_arg_p, |
6344 | cp_id_kind *idk) |
6345 | { |
6346 | return cp_parser_primary_expression (parser, address_p, cast_p, template_arg_p, |
6347 | /*decltype*/decltype_p: false, idk); |
6348 | } |
6349 | |
6350 | /* Complain about missing template keyword when naming a dependent |
6351 | member template. */ |
6352 | |
6353 | static void |
6354 | missing_template_diag (location_t loc, diagnostic_t diag_kind = DK_WARNING) |
6355 | { |
6356 | if (warning_suppressed_at (loc, OPT_Wmissing_template_keyword)) |
6357 | return; |
6358 | |
6359 | gcc_rich_location richloc (loc); |
6360 | richloc.add_fixit_insert_before (new_content: "template" ); |
6361 | emit_diagnostic (diag_kind, &richloc, OPT_Wmissing_template_keyword, |
6362 | "expected %qs keyword before dependent " |
6363 | "template name" , "template" ); |
6364 | suppress_warning_at (loc, OPT_Wmissing_template_keyword); |
6365 | } |
6366 | |
6367 | /* Parse an id-expression. |
6368 | |
6369 | id-expression: |
6370 | unqualified-id |
6371 | qualified-id |
6372 | |
6373 | qualified-id: |
6374 | :: [opt] nested-name-specifier template [opt] unqualified-id |
6375 | :: identifier |
6376 | :: operator-function-id |
6377 | :: template-id |
6378 | |
6379 | Return a representation of the unqualified portion of the |
6380 | identifier. Sets PARSER->SCOPE to the qualifying scope if there is |
6381 | a `::' or nested-name-specifier. |
6382 | |
6383 | Often, if the id-expression was a qualified-id, the caller will |
6384 | want to make a SCOPE_REF to represent the qualified-id. This |
6385 | function does not do this in order to avoid wastefully creating |
6386 | SCOPE_REFs when they are not required. |
6387 | |
6388 | If TEMPLATE_KEYWORD_P is true, then we have just seen the |
6389 | `template' keyword. |
6390 | |
6391 | If CHECK_DEPENDENCY_P is false, then names are looked up inside |
6392 | uninstantiated templates. |
6393 | |
6394 | If *TEMPLATE_P is non-NULL, it is set to true iff the |
6395 | `template' keyword is used to explicitly indicate that the entity |
6396 | named is a template. |
6397 | |
6398 | If DECLARATOR_P is true, the id-expression is appearing as part of |
6399 | a declarator, rather than as part of an expression. */ |
6400 | |
6401 | static cp_expr |
6402 | cp_parser_id_expression (cp_parser *parser, |
6403 | bool template_keyword_p, |
6404 | bool check_dependency_p, |
6405 | bool *template_p, |
6406 | bool declarator_p, |
6407 | bool optional_p) |
6408 | { |
6409 | bool global_scope_p; |
6410 | bool nested_name_specifier_p; |
6411 | |
6412 | /* Assume the `template' keyword was not used. */ |
6413 | if (template_p) |
6414 | *template_p = template_keyword_p; |
6415 | |
6416 | /* Look for the optional `::' operator. */ |
6417 | global_scope_p |
6418 | = (!template_keyword_p |
6419 | && (cp_parser_global_scope_opt (parser, |
6420 | /*current_scope_valid_p=*/false) |
6421 | != NULL_TREE)); |
6422 | |
6423 | /* Look for the optional nested-name-specifier. */ |
6424 | nested_name_specifier_p |
6425 | = (cp_parser_nested_name_specifier_opt (parser, |
6426 | /*typename_keyword_p=*/false, |
6427 | check_dependency_p, |
6428 | /*type_p=*/false, |
6429 | declarator_p, |
6430 | template_keyword_p) |
6431 | != NULL_TREE); |
6432 | |
6433 | cp_expr id = NULL_TREE; |
6434 | tree scope = parser->scope; |
6435 | |
6436 | /* Peek at the next token. */ |
6437 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
6438 | |
6439 | /* If there is a nested-name-specifier, then we are looking at |
6440 | the first qualified-id production. */ |
6441 | if (nested_name_specifier_p) |
6442 | { |
6443 | tree saved_object_scope; |
6444 | tree saved_qualifying_scope; |
6445 | |
6446 | /* See if the next token is the `template' keyword. */ |
6447 | if (!template_p) |
6448 | template_p = &template_keyword_p; |
6449 | *template_p = cp_parser_optional_template_keyword (parser); |
6450 | /* Name lookup we do during the processing of the |
6451 | unqualified-id might obliterate SCOPE. */ |
6452 | saved_object_scope = parser->object_scope; |
6453 | saved_qualifying_scope = parser->qualifying_scope; |
6454 | /* Process the final unqualified-id. */ |
6455 | id = cp_parser_unqualified_id (parser, *template_p, |
6456 | check_dependency_p, |
6457 | declarator_p, |
6458 | /*optional_p=*/false); |
6459 | /* Restore the SAVED_SCOPE for our caller. */ |
6460 | parser->scope = scope; |
6461 | parser->object_scope = saved_object_scope; |
6462 | parser->qualifying_scope = saved_qualifying_scope; |
6463 | } |
6464 | /* Otherwise, if we are in global scope, then we are looking at one |
6465 | of the other qualified-id productions. */ |
6466 | else if (global_scope_p) |
6467 | { |
6468 | /* If it's an identifier, and the next token is not a "<", then |
6469 | we can avoid the template-id case. This is an optimization |
6470 | for this common case. */ |
6471 | if (token->type == CPP_NAME |
6472 | && !cp_parser_nth_token_starts_template_argument_list_p |
6473 | (parser, 2)) |
6474 | return cp_parser_identifier (parser); |
6475 | |
6476 | cp_parser_parse_tentatively (parser); |
6477 | /* Try a template-id. */ |
6478 | id = cp_parser_template_id_expr (parser, |
6479 | /*template_keyword_p=*/false, |
6480 | /*check_dependency_p=*/true, |
6481 | declarator_p); |
6482 | /* If that worked, we're done. */ |
6483 | if (cp_parser_parse_definitely (parser)) |
6484 | return id; |
6485 | |
6486 | /* Peek at the next token. (Changes in the token buffer may |
6487 | have invalidated the pointer obtained above.) */ |
6488 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6489 | |
6490 | switch (token->type) |
6491 | { |
6492 | case CPP_NAME: |
6493 | id = cp_parser_identifier (parser); |
6494 | break; |
6495 | |
6496 | case CPP_KEYWORD: |
6497 | if (token->keyword == RID_OPERATOR) |
6498 | { |
6499 | id = cp_parser_operator_function_id (parser); |
6500 | break; |
6501 | } |
6502 | /* Fall through. */ |
6503 | |
6504 | default: |
6505 | cp_parser_error (parser, gmsgid: "expected id-expression" ); |
6506 | return error_mark_node; |
6507 | } |
6508 | } |
6509 | else |
6510 | { |
6511 | if (!scope) |
6512 | scope = parser->context->object_type; |
6513 | id = cp_parser_unqualified_id (parser, template_keyword_p, |
6514 | /*check_dependency_p=*/true, |
6515 | declarator_p, |
6516 | optional_p); |
6517 | } |
6518 | |
6519 | if (id && TREE_CODE (id) == IDENTIFIER_NODE |
6520 | && warn_missing_template_keyword |
6521 | && !template_keyword_p |
6522 | /* Don't warn if we're looking inside templates. */ |
6523 | && check_dependency_p |
6524 | /* In a template argument list a > could be closing |
6525 | the enclosing targs. */ |
6526 | && !parser->in_template_argument_list_p |
6527 | && scope && dependentish_scope_p (scope) |
6528 | /* Don't confuse an ill-formed constructor declarator for a missing |
6529 | template keyword in a return type. */ |
6530 | && !(declarator_p && constructor_name_p (id, scope)) |
6531 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1) |
6532 | && warning_enabled_at (loc: token->location, |
6533 | opt: OPT_Wmissing_template_keyword)) |
6534 | { |
6535 | saved_token_sentinel toks (parser->lexer, STS_ROLLBACK); |
6536 | if (cp_parser_skip_entire_template_parameter_list (parser) |
6537 | /* An operator after the > suggests that the > ends a |
6538 | template-id; a name or literal suggests that the > is an |
6539 | operator. */ |
6540 | && (cp_lexer_peek_token (lexer: parser->lexer)->type |
6541 | <= CPP_LAST_PUNCTUATOR)) |
6542 | missing_template_diag (loc: token->location); |
6543 | } |
6544 | |
6545 | return id; |
6546 | } |
6547 | |
6548 | /* Parse an unqualified-id. |
6549 | |
6550 | unqualified-id: |
6551 | identifier |
6552 | operator-function-id |
6553 | conversion-function-id |
6554 | ~ class-name |
6555 | template-id |
6556 | |
6557 | If TEMPLATE_KEYWORD_P is TRUE, we have just seen the `template' |
6558 | keyword, in a construct like `A::template ...'. |
6559 | |
6560 | Returns a representation of unqualified-id. For the `identifier' |
6561 | production, an IDENTIFIER_NODE is returned. For the `~ class-name' |
6562 | production a BIT_NOT_EXPR is returned; the operand of the |
6563 | BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the |
6564 | other productions, see the documentation accompanying the |
6565 | corresponding parsing functions. If CHECK_DEPENDENCY_P is false, |
6566 | names are looked up in uninstantiated templates. If DECLARATOR_P |
6567 | is true, the unqualified-id is appearing as part of a declarator, |
6568 | rather than as part of an expression. */ |
6569 | |
6570 | static cp_expr |
6571 | cp_parser_unqualified_id (cp_parser* parser, |
6572 | bool template_keyword_p, |
6573 | bool check_dependency_p, |
6574 | bool declarator_p, |
6575 | bool optional_p) |
6576 | { |
6577 | cp_token *token; |
6578 | |
6579 | /* Peek at the next token. */ |
6580 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6581 | |
6582 | switch ((int) token->type) |
6583 | { |
6584 | case CPP_NAME: |
6585 | { |
6586 | tree id; |
6587 | |
6588 | /* We don't know yet whether or not this will be a |
6589 | template-id. */ |
6590 | cp_parser_parse_tentatively (parser); |
6591 | /* Try a template-id. */ |
6592 | id = cp_parser_template_id_expr (parser, template_keyword_p, |
6593 | check_dependency_p, |
6594 | declarator_p); |
6595 | /* If it worked, we're done. */ |
6596 | if (cp_parser_parse_definitely (parser)) |
6597 | return id; |
6598 | /* Otherwise, it's an ordinary identifier. */ |
6599 | return cp_parser_identifier (parser); |
6600 | } |
6601 | |
6602 | case CPP_TEMPLATE_ID: |
6603 | return cp_parser_template_id_expr (parser, template_keyword_p, |
6604 | check_dependency_p, |
6605 | declarator_p); |
6606 | |
6607 | case CPP_COMPL: |
6608 | { |
6609 | tree type_decl; |
6610 | tree qualifying_scope; |
6611 | tree object_scope; |
6612 | tree scope; |
6613 | bool done; |
6614 | location_t tilde_loc = token->location; |
6615 | |
6616 | /* Consume the `~' token. */ |
6617 | cp_lexer_consume_token (lexer: parser->lexer); |
6618 | /* Parse the class-name. The standard, as written, seems to |
6619 | say that: |
6620 | |
6621 | template <typename T> struct S { ~S (); }; |
6622 | template <typename T> S<T>::~S() {} |
6623 | |
6624 | is invalid, since `~' must be followed by a class-name, but |
6625 | `S<T>' is dependent, and so not known to be a class. |
6626 | That's not right; we need to look in uninstantiated |
6627 | templates. A further complication arises from: |
6628 | |
6629 | template <typename T> void f(T t) { |
6630 | t.T::~T(); |
6631 | } |
6632 | |
6633 | Here, it is not possible to look up `T' in the scope of `T' |
6634 | itself. We must look in both the current scope, and the |
6635 | scope of the containing complete expression. |
6636 | |
6637 | Yet another issue is: |
6638 | |
6639 | struct S { |
6640 | int S; |
6641 | ~S(); |
6642 | }; |
6643 | |
6644 | S::~S() {} |
6645 | |
6646 | The standard does not seem to say that the `S' in `~S' |
6647 | should refer to the type `S' and not the data member |
6648 | `S::S'. */ |
6649 | |
6650 | /* DR 244 says that we look up the name after the "~" in the |
6651 | same scope as we looked up the qualifying name. That idea |
6652 | isn't fully worked out; it's more complicated than that. */ |
6653 | scope = parser->scope; |
6654 | object_scope = parser->object_scope; |
6655 | qualifying_scope = parser->qualifying_scope; |
6656 | |
6657 | /* Check for invalid scopes. */ |
6658 | if (scope == error_mark_node) |
6659 | { |
6660 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
6661 | cp_lexer_consume_token (lexer: parser->lexer); |
6662 | return error_mark_node; |
6663 | } |
6664 | if (scope && TREE_CODE (scope) == NAMESPACE_DECL) |
6665 | { |
6666 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6667 | error_at (token->location, |
6668 | "scope %qT before %<~%> is not a class-name" , |
6669 | scope); |
6670 | cp_parser_simulate_error (parser); |
6671 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
6672 | cp_lexer_consume_token (lexer: parser->lexer); |
6673 | return error_mark_node; |
6674 | } |
6675 | if (template_keyword_p) |
6676 | { |
6677 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6678 | error_at (tilde_loc, "%<template%> keyword not permitted in " |
6679 | "destructor name" ); |
6680 | cp_parser_simulate_error (parser); |
6681 | return error_mark_node; |
6682 | } |
6683 | |
6684 | gcc_assert (!scope || TYPE_P (scope)); |
6685 | |
6686 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6687 | |
6688 | /* Create a location with caret == start at the tilde, |
6689 | finishing at the end of the peeked token, e.g: |
6690 | ~token |
6691 | ^~~~~~. */ |
6692 | location_t loc |
6693 | = make_location (caret: tilde_loc, start: tilde_loc, finish: token->location); |
6694 | |
6695 | /* If the name is of the form "X::~X" it's OK even if X is a |
6696 | typedef. */ |
6697 | |
6698 | if (scope |
6699 | && token->type == CPP_NAME |
6700 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
6701 | != CPP_LESS) |
6702 | && (token->u.value == TYPE_IDENTIFIER (scope) |
6703 | || (CLASS_TYPE_P (scope) |
6704 | && constructor_name_p (token->u.value, scope)))) |
6705 | { |
6706 | cp_lexer_consume_token (lexer: parser->lexer); |
6707 | return build_min_nt_loc (loc, BIT_NOT_EXPR, scope); |
6708 | } |
6709 | |
6710 | /* ~auto means the destructor of whatever the object is. */ |
6711 | if (cp_parser_is_keyword (token, keyword: RID_AUTO)) |
6712 | { |
6713 | if (cxx_dialect < cxx14) |
6714 | pedwarn (loc, OPT_Wc__14_extensions, |
6715 | "%<~auto%> only available with " |
6716 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
6717 | cp_lexer_consume_token (lexer: parser->lexer); |
6718 | return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ()); |
6719 | } |
6720 | |
6721 | /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the |
6722 | declarator-id of a constructor or destructor. */ |
6723 | if (token->type == CPP_TEMPLATE_ID && declarator_p) |
6724 | { |
6725 | auto_diagnostic_group d; |
6726 | bool w = false; |
6727 | if (cxx_dialect >= cxx20 && !cp_parser_simulate_error (parser)) |
6728 | w = pedwarn (tilde_loc, OPT_Wtemplate_id_cdtor, |
6729 | "template-id not allowed for destructor in C++20" ); |
6730 | else if (cxx_dialect < cxx20 |
6731 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6732 | w = warning_at (tilde_loc, OPT_Wtemplate_id_cdtor, |
6733 | "template-id not allowed for destructor in C++20" ); |
6734 | if (w) |
6735 | inform (tilde_loc, "remove the %qs" , "< >" ); |
6736 | } |
6737 | |
6738 | /* If there was an explicit qualification (S::~T), first look |
6739 | in the scope given by the qualification (i.e., S). |
6740 | |
6741 | Note: in the calls to cp_parser_class_name below we pass |
6742 | typename_type so that lookup finds the injected-class-name |
6743 | rather than the constructor. */ |
6744 | done = false; |
6745 | type_decl = NULL_TREE; |
6746 | if (scope) |
6747 | { |
6748 | cp_parser_parse_tentatively (parser); |
6749 | type_decl = cp_parser_class_name (parser, |
6750 | /*typename_keyword_p=*/false, |
6751 | /*template_keyword_p=*/false, |
6752 | typename_type, |
6753 | /*check_dependency=*/false, |
6754 | /*class_head_p=*/false, |
6755 | declarator_p); |
6756 | if (cp_parser_parse_definitely (parser)) |
6757 | done = true; |
6758 | } |
6759 | /* In "N::S::~S", look in "N" as well. */ |
6760 | if (!done && scope && qualifying_scope) |
6761 | { |
6762 | cp_parser_parse_tentatively (parser); |
6763 | parser->scope = qualifying_scope; |
6764 | parser->object_scope = NULL_TREE; |
6765 | parser->qualifying_scope = NULL_TREE; |
6766 | type_decl |
6767 | = cp_parser_class_name (parser, |
6768 | /*typename_keyword_p=*/false, |
6769 | /*template_keyword_p=*/false, |
6770 | typename_type, |
6771 | /*check_dependency=*/false, |
6772 | /*class_head_p=*/false, |
6773 | declarator_p); |
6774 | if (cp_parser_parse_definitely (parser)) |
6775 | done = true; |
6776 | } |
6777 | /* In "p->S::~T", look in the scope given by "*p" as well. */ |
6778 | else if (!done && object_scope) |
6779 | { |
6780 | cp_parser_parse_tentatively (parser); |
6781 | parser->scope = object_scope; |
6782 | parser->object_scope = NULL_TREE; |
6783 | parser->qualifying_scope = NULL_TREE; |
6784 | type_decl |
6785 | = cp_parser_class_name (parser, |
6786 | /*typename_keyword_p=*/false, |
6787 | /*template_keyword_p=*/false, |
6788 | typename_type, |
6789 | /*check_dependency=*/false, |
6790 | /*class_head_p=*/false, |
6791 | declarator_p); |
6792 | if (cp_parser_parse_definitely (parser)) |
6793 | done = true; |
6794 | } |
6795 | /* Look in the surrounding context. */ |
6796 | if (!done) |
6797 | { |
6798 | parser->scope = NULL_TREE; |
6799 | parser->object_scope = NULL_TREE; |
6800 | parser->qualifying_scope = NULL_TREE; |
6801 | if (processing_template_decl) |
6802 | cp_parser_parse_tentatively (parser); |
6803 | type_decl |
6804 | = cp_parser_class_name (parser, |
6805 | /*typename_keyword_p=*/false, |
6806 | /*template_keyword_p=*/false, |
6807 | typename_type, |
6808 | /*check_dependency=*/false, |
6809 | /*class_head_p=*/false, |
6810 | declarator_p); |
6811 | if (processing_template_decl |
6812 | && ! cp_parser_parse_definitely (parser)) |
6813 | { |
6814 | /* We couldn't find a type with this name. If we're parsing |
6815 | tentatively, fail and try something else. */ |
6816 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6817 | { |
6818 | cp_parser_simulate_error (parser); |
6819 | return error_mark_node; |
6820 | } |
6821 | /* Otherwise, accept it and check for a match at instantiation |
6822 | time. */ |
6823 | type_decl = cp_parser_identifier (parser); |
6824 | if (type_decl != error_mark_node) |
6825 | type_decl = build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl); |
6826 | return type_decl; |
6827 | } |
6828 | } |
6829 | /* If an error occurred, assume that the name of the |
6830 | destructor is the same as the name of the qualifying |
6831 | class. That allows us to keep parsing after running |
6832 | into ill-formed destructor names. */ |
6833 | if (type_decl == error_mark_node && scope) |
6834 | return build_min_nt_loc (loc, BIT_NOT_EXPR, scope); |
6835 | else if (type_decl == error_mark_node) |
6836 | return error_mark_node; |
6837 | |
6838 | /* Check that destructor name and scope match. */ |
6839 | if (declarator_p && scope && !check_dtor_name (scope, type_decl)) |
6840 | { |
6841 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6842 | error_at (loc, |
6843 | "declaration of %<~%T%> as member of %qT" , |
6844 | type_decl, scope); |
6845 | cp_parser_simulate_error (parser); |
6846 | return error_mark_node; |
6847 | } |
6848 | |
6849 | /* [class.dtor] |
6850 | |
6851 | A typedef-name that names a class shall not be used as the |
6852 | identifier in the declarator for a destructor declaration. */ |
6853 | if (declarator_p |
6854 | && !DECL_IMPLICIT_TYPEDEF_P (type_decl) |
6855 | && !DECL_SELF_REFERENCE_P (type_decl) |
6856 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6857 | error_at (loc, |
6858 | "typedef-name %qD used as destructor declarator" , |
6859 | type_decl); |
6860 | |
6861 | return build_min_nt_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type_decl)); |
6862 | } |
6863 | |
6864 | case CPP_KEYWORD: |
6865 | if (token->keyword == RID_OPERATOR) |
6866 | { |
6867 | cp_expr id; |
6868 | |
6869 | /* This could be a template-id, so we try that first. */ |
6870 | cp_parser_parse_tentatively (parser); |
6871 | /* Try a template-id. */ |
6872 | id = cp_parser_template_id_expr (parser, template_keyword_p, |
6873 | /*check_dependency_p=*/true, |
6874 | declarator_p); |
6875 | /* If that worked, we're done. */ |
6876 | if (cp_parser_parse_definitely (parser)) |
6877 | return id; |
6878 | /* We still don't know whether we're looking at an |
6879 | operator-function-id or a conversion-function-id. */ |
6880 | cp_parser_parse_tentatively (parser); |
6881 | /* Try an operator-function-id. */ |
6882 | id = cp_parser_operator_function_id (parser); |
6883 | /* If that didn't work, try a conversion-function-id. */ |
6884 | if (!cp_parser_parse_definitely (parser)) |
6885 | id = cp_parser_conversion_function_id (parser); |
6886 | |
6887 | return id; |
6888 | } |
6889 | /* Fall through. */ |
6890 | |
6891 | default: |
6892 | if (optional_p) |
6893 | return NULL_TREE; |
6894 | cp_parser_error (parser, gmsgid: "expected unqualified-id" ); |
6895 | return error_mark_node; |
6896 | } |
6897 | } |
6898 | |
6899 | /* Check [temp.names]/5: A name prefixed by the keyword template shall |
6900 | be a template-id or the name shall refer to a class template or an |
6901 | alias template. */ |
6902 | |
6903 | static void |
6904 | check_template_keyword_in_nested_name_spec (tree name) |
6905 | { |
6906 | if (CLASS_TYPE_P (name) |
6907 | && ((CLASSTYPE_USE_TEMPLATE (name) |
6908 | && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (name))) |
6909 | || CLASSTYPE_IS_TEMPLATE (name))) |
6910 | return; |
6911 | |
6912 | if (TREE_CODE (name) == TYPENAME_TYPE |
6913 | && TREE_CODE (TYPENAME_TYPE_FULLNAME (name)) == TEMPLATE_ID_EXPR) |
6914 | return; |
6915 | /* Alias templates are also OK. */ |
6916 | else if (alias_template_specialization_p (name, nt_opaque)) |
6917 | return; |
6918 | |
6919 | permerror (input_location, TYPE_P (name) |
6920 | ? G_("%qT is not a template" ) |
6921 | : G_("%qD is not a template" ), |
6922 | name); |
6923 | } |
6924 | |
6925 | /* Parse an (optional) nested-name-specifier. |
6926 | |
6927 | nested-name-specifier: [C++98] |
6928 | class-or-namespace-name :: nested-name-specifier [opt] |
6929 | class-or-namespace-name :: template nested-name-specifier [opt] |
6930 | |
6931 | nested-name-specifier: [C++0x] |
6932 | type-name :: |
6933 | namespace-name :: |
6934 | nested-name-specifier identifier :: |
6935 | nested-name-specifier template [opt] simple-template-id :: |
6936 | |
6937 | PARSER->SCOPE should be set appropriately before this function is |
6938 | called. TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in |
6939 | effect. TYPE_P is TRUE if we non-type bindings should be ignored |
6940 | in name lookups. |
6941 | |
6942 | Sets PARSER->SCOPE to the class (TYPE) or namespace |
6943 | (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves |
6944 | it unchanged if there is no nested-name-specifier. Returns the new |
6945 | scope iff there is a nested-name-specifier, or NULL_TREE otherwise. |
6946 | |
6947 | If CHECK_DEPENDENCY_P is FALSE, names are looked up in dependent scopes. |
6948 | |
6949 | If IS_DECLARATION is TRUE, the nested-name-specifier is known to be |
6950 | part of a declaration and/or decl-specifier. */ |
6951 | |
6952 | static tree |
6953 | cp_parser_nested_name_specifier_opt (cp_parser *parser, |
6954 | bool typename_keyword_p, |
6955 | bool check_dependency_p, |
6956 | bool type_p, |
6957 | bool is_declaration, |
6958 | bool template_keyword_p /* = false */) |
6959 | { |
6960 | bool success = false; |
6961 | cp_token_position start = 0; |
6962 | cp_token *token; |
6963 | |
6964 | /* Remember where the nested-name-specifier starts. */ |
6965 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
6966 | && cp_lexer_next_token_is_not (lexer: parser->lexer, CPP_NESTED_NAME_SPECIFIER)) |
6967 | { |
6968 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
6969 | push_deferring_access_checks (dk_deferred); |
6970 | } |
6971 | |
6972 | while (true) |
6973 | { |
6974 | tree new_scope; |
6975 | tree old_scope; |
6976 | tree saved_qualifying_scope; |
6977 | |
6978 | /* Spot cases that cannot be the beginning of a |
6979 | nested-name-specifier. */ |
6980 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6981 | |
6982 | /* If the next token is CPP_NESTED_NAME_SPECIFIER, just process |
6983 | the already parsed nested-name-specifier. */ |
6984 | if (token->type == CPP_NESTED_NAME_SPECIFIER) |
6985 | { |
6986 | /* Grab the nested-name-specifier and continue the loop. */ |
6987 | cp_parser_pre_parsed_nested_name_specifier (parser); |
6988 | /* If we originally encountered this nested-name-specifier |
6989 | with CHECK_DEPENDENCY_P set to true, we will not have |
6990 | resolved TYPENAME_TYPEs, so we must do so here. */ |
6991 | if (is_declaration |
6992 | && !check_dependency_p |
6993 | && TREE_CODE (parser->scope) == TYPENAME_TYPE) |
6994 | { |
6995 | new_scope = resolve_typename_type (parser->scope, |
6996 | /*only_current_p=*/false); |
6997 | if (TREE_CODE (new_scope) != TYPENAME_TYPE) |
6998 | parser->scope = new_scope; |
6999 | } |
7000 | success = true; |
7001 | continue; |
7002 | } |
7003 | |
7004 | /* Spot cases that cannot be the beginning of a |
7005 | nested-name-specifier. On the second and subsequent times |
7006 | through the loop, we look for the `template' keyword. */ |
7007 | if (success && token->keyword == RID_TEMPLATE) |
7008 | ; |
7009 | /* A template-id can start a nested-name-specifier. */ |
7010 | else if (token->type == CPP_TEMPLATE_ID) |
7011 | ; |
7012 | /* DR 743: decltype can be used in a nested-name-specifier. */ |
7013 | else if (token_is_decltype (t: token)) |
7014 | ; |
7015 | else |
7016 | { |
7017 | /* If the next token is not an identifier, then it is |
7018 | definitely not a type-name or namespace-name. */ |
7019 | if (token->type != CPP_NAME) |
7020 | break; |
7021 | /* If the following token is neither a `<' (to begin a |
7022 | template-id), nor a `::', then we are not looking at a |
7023 | nested-name-specifier. */ |
7024 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
7025 | |
7026 | if (token->type == CPP_COLON |
7027 | && parser->colon_corrects_to_scope_p |
7028 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_NAME |
7029 | /* name:name is a valid sequence in an Objective C message. */ |
7030 | && !parser->objective_c_message_context_p) |
7031 | { |
7032 | gcc_rich_location richloc (token->location); |
7033 | richloc.add_fixit_replace (new_content: "::" ); |
7034 | error_at (&richloc, |
7035 | "found %<:%> in nested-name-specifier, " |
7036 | "expected %<::%>" ); |
7037 | token->type = CPP_SCOPE; |
7038 | } |
7039 | |
7040 | if (token->type != CPP_SCOPE |
7041 | && !cp_parser_nth_token_starts_template_argument_list_p |
7042 | (parser, 2)) |
7043 | break; |
7044 | } |
7045 | |
7046 | /* The nested-name-specifier is optional, so we parse |
7047 | tentatively. */ |
7048 | cp_parser_parse_tentatively (parser); |
7049 | |
7050 | /* Look for the optional `template' keyword, if this isn't the |
7051 | first time through the loop. */ |
7052 | if (success) |
7053 | { |
7054 | template_keyword_p = cp_parser_optional_template_keyword (parser); |
7055 | /* DR1710: "In a qualified-id used as the name in |
7056 | a typename-specifier, elaborated-type-specifier, using-declaration, |
7057 | or class-or-decltype, an optional keyword template appearing at |
7058 | the top level is ignored." */ |
7059 | if (!template_keyword_p |
7060 | && typename_keyword_p |
7061 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) |
7062 | template_keyword_p = true; |
7063 | } |
7064 | |
7065 | /* Save the old scope since the name lookup we are about to do |
7066 | might destroy it. */ |
7067 | old_scope = parser->scope; |
7068 | saved_qualifying_scope = parser->qualifying_scope; |
7069 | /* In a declarator-id like "X<T>::I::Y<T>" we must be able to |
7070 | look up names in "X<T>::I" in order to determine that "Y" is |
7071 | a template. So, if we have a typename at this point, we make |
7072 | an effort to look through it. */ |
7073 | if (is_declaration |
7074 | && !check_dependency_p |
7075 | && !typename_keyword_p |
7076 | && parser->scope |
7077 | && TREE_CODE (parser->scope) == TYPENAME_TYPE) |
7078 | parser->scope = resolve_typename_type (parser->scope, |
7079 | /*only_current_p=*/false); |
7080 | /* Parse the qualifying entity. */ |
7081 | new_scope |
7082 | = cp_parser_qualifying_entity (parser, |
7083 | typename_keyword_p, |
7084 | template_keyword_p, |
7085 | check_dependency_p, |
7086 | type_p, |
7087 | is_declaration); |
7088 | /* Look for the `::' token. */ |
7089 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
7090 | |
7091 | /* If we found what we wanted, we keep going; otherwise, we're |
7092 | done. */ |
7093 | if (!cp_parser_parse_definitely (parser)) |
7094 | { |
7095 | bool error_p = false; |
7096 | |
7097 | /* Restore the OLD_SCOPE since it was valid before the |
7098 | failed attempt at finding the last |
7099 | class-or-namespace-name. */ |
7100 | parser->scope = old_scope; |
7101 | parser->qualifying_scope = saved_qualifying_scope; |
7102 | |
7103 | /* If the next token is a decltype, and the one after that is a |
7104 | `::', then the decltype has failed to resolve to a class or |
7105 | enumeration type. Give this error even when parsing |
7106 | tentatively since it can't possibly be valid--and we're going |
7107 | to replace it with a CPP_NESTED_NAME_SPECIFIER below, so we |
7108 | won't get another chance.*/ |
7109 | if (cp_lexer_next_token_is (lexer: parser->lexer, CPP_DECLTYPE) |
7110 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
7111 | == CPP_SCOPE)) |
7112 | { |
7113 | token = cp_lexer_consume_token (lexer: parser->lexer); |
7114 | tree dtype = token->u.tree_check_value->value; |
7115 | if (dtype != error_mark_node) |
7116 | error_at (token->location, "%<decltype%> evaluates to %qT, " |
7117 | "which is not a class or enumeration type" , |
7118 | dtype); |
7119 | parser->scope = error_mark_node; |
7120 | error_p = true; |
7121 | /* As below. */ |
7122 | success = true; |
7123 | cp_lexer_consume_token (lexer: parser->lexer); |
7124 | } |
7125 | |
7126 | if (cp_lexer_next_token_is (lexer: parser->lexer, CPP_TEMPLATE_ID) |
7127 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SCOPE)) |
7128 | { |
7129 | /* If we have a non-type template-id followed by ::, it can't |
7130 | possibly be valid. */ |
7131 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7132 | tree tid = token->u.tree_check_value->value; |
7133 | if (TREE_CODE (tid) == TEMPLATE_ID_EXPR |
7134 | && TREE_CODE (TREE_OPERAND (tid, 0)) != IDENTIFIER_NODE) |
7135 | { |
7136 | tree tmpl = NULL_TREE; |
7137 | if (is_overloaded_fn (tid)) |
7138 | { |
7139 | tree fns = get_fns (tid); |
7140 | if (OVL_SINGLE_P (fns)) |
7141 | tmpl = OVL_FIRST (fns); |
7142 | if (function_concept_p (t: fns)) |
7143 | error_at (token->location, "concept-id %qD " |
7144 | "in nested-name-specifier" , tid); |
7145 | else |
7146 | error_at (token->location, "function template-id " |
7147 | "%qD in nested-name-specifier" , tid); |
7148 | } |
7149 | else |
7150 | { |
7151 | tmpl = TREE_OPERAND (tid, 0); |
7152 | if (variable_concept_p (t: tmpl) |
7153 | || standard_concept_p (t: tmpl)) |
7154 | error_at (token->location, "concept-id %qD " |
7155 | "in nested-name-specifier" , tid); |
7156 | else |
7157 | { |
7158 | /* Variable template. */ |
7159 | gcc_assert (variable_template_p (tmpl)); |
7160 | error_at (token->location, "variable template-id " |
7161 | "%qD in nested-name-specifier" , tid); |
7162 | } |
7163 | } |
7164 | if (tmpl) |
7165 | inform (DECL_SOURCE_LOCATION (tmpl), |
7166 | "%qD declared here" , tmpl); |
7167 | |
7168 | parser->scope = error_mark_node; |
7169 | error_p = true; |
7170 | /* As below. */ |
7171 | success = true; |
7172 | cp_lexer_consume_token (lexer: parser->lexer); |
7173 | cp_lexer_consume_token (lexer: parser->lexer); |
7174 | } |
7175 | } |
7176 | |
7177 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
7178 | break; |
7179 | /* If the next token is an identifier, and the one after |
7180 | that is a `::', then any valid interpretation would have |
7181 | found a class-or-namespace-name. */ |
7182 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
7183 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
7184 | == CPP_SCOPE) |
7185 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
7186 | != CPP_COMPL)) |
7187 | { |
7188 | token = cp_lexer_consume_token (lexer: parser->lexer); |
7189 | if (!error_p) |
7190 | { |
7191 | if (!token->error_reported) |
7192 | { |
7193 | tree decl; |
7194 | tree ambiguous_decls; |
7195 | |
7196 | decl = cp_parser_lookup_name (parser, token->u.value, |
7197 | none_type, |
7198 | /*is_template=*/false, |
7199 | /*is_namespace=*/false, |
7200 | /*check_dependency=*/true, |
7201 | &ambiguous_decls, |
7202 | token->location); |
7203 | if (TREE_CODE (decl) == TEMPLATE_DECL) |
7204 | error_at (token->location, |
7205 | "%qD used without template arguments" , |
7206 | decl); |
7207 | else if (ambiguous_decls) |
7208 | { |
7209 | // cp_parser_lookup_name has the same diagnostic, |
7210 | // thus make sure to emit it at most once. |
7211 | if (cp_parser_uncommitted_to_tentative_parse_p |
7212 | (parser)) |
7213 | { |
7214 | error_at (token->location, |
7215 | "reference to %qD is ambiguous" , |
7216 | token->u.value); |
7217 | print_candidates (ambiguous_decls); |
7218 | } |
7219 | decl = error_mark_node; |
7220 | } |
7221 | else |
7222 | { |
7223 | if (cxx_dialect != cxx98) |
7224 | cp_parser_name_lookup_error |
7225 | (parser, name: token->u.value, decl, desired: NLE_NOT_CXX98, |
7226 | location: token->location); |
7227 | else |
7228 | cp_parser_name_lookup_error |
7229 | (parser, name: token->u.value, decl, desired: NLE_CXX98, |
7230 | location: token->location); |
7231 | } |
7232 | } |
7233 | parser->scope = error_mark_node; |
7234 | error_p = true; |
7235 | /* Treat this as a successful nested-name-specifier |
7236 | due to: |
7237 | |
7238 | [basic.lookup.qual] |
7239 | |
7240 | If the name found is not a class-name (clause |
7241 | _class_) or namespace-name (_namespace.def_), the |
7242 | program is ill-formed. */ |
7243 | success = true; |
7244 | } |
7245 | cp_lexer_consume_token (lexer: parser->lexer); |
7246 | } |
7247 | break; |
7248 | } |
7249 | /* We've found one valid nested-name-specifier. */ |
7250 | success = true; |
7251 | /* Name lookup always gives us a DECL. */ |
7252 | if (TREE_CODE (new_scope) == TYPE_DECL) |
7253 | new_scope = TREE_TYPE (new_scope); |
7254 | /* Uses of "template" must be followed by actual templates. */ |
7255 | if (template_keyword_p) |
7256 | check_template_keyword_in_nested_name_spec (name: new_scope); |
7257 | /* If it is a class scope, try to complete it; we are about to |
7258 | be looking up names inside the class. */ |
7259 | if (TYPE_P (new_scope) |
7260 | /* Since checking types for dependency can be expensive, |
7261 | avoid doing it if the type is already complete. */ |
7262 | && !COMPLETE_TYPE_P (new_scope) |
7263 | /* Do not try to complete dependent types. */ |
7264 | && !dependent_type_p (new_scope)) |
7265 | { |
7266 | new_scope = complete_type (new_scope); |
7267 | /* If it is a typedef to current class, use the current |
7268 | class instead, as the typedef won't have any names inside |
7269 | it yet. */ |
7270 | if (!COMPLETE_TYPE_P (new_scope) |
7271 | && currently_open_class (new_scope)) |
7272 | new_scope = TYPE_MAIN_VARIANT (new_scope); |
7273 | } |
7274 | /* Make sure we look in the right scope the next time through |
7275 | the loop. */ |
7276 | parser->scope = new_scope; |
7277 | } |
7278 | |
7279 | /* If parsing tentatively, replace the sequence of tokens that makes |
7280 | up the nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER |
7281 | token. That way, should we re-parse the token stream, we will |
7282 | not have to repeat the effort required to do the parse, nor will |
7283 | we issue duplicate error messages. */ |
7284 | if (success && start) |
7285 | { |
7286 | cp_token *token; |
7287 | |
7288 | token = cp_lexer_token_at (parser->lexer, pos: start); |
7289 | /* Reset the contents of the START token. */ |
7290 | token->type = CPP_NESTED_NAME_SPECIFIER; |
7291 | /* Retrieve any deferred checks. Do not pop this access checks yet |
7292 | so the memory will not be reclaimed during token replacing below. */ |
7293 | token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
7294 | token->tree_check_p = true; |
7295 | token->u.tree_check_value->value = parser->scope; |
7296 | token->u.tree_check_value->checks = get_deferred_access_checks (); |
7297 | token->u.tree_check_value->qualifying_scope = |
7298 | parser->qualifying_scope; |
7299 | token->keyword = RID_MAX; |
7300 | |
7301 | /* Purge all subsequent tokens. */ |
7302 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
7303 | } |
7304 | |
7305 | if (start) |
7306 | pop_to_parent_deferring_access_checks (); |
7307 | |
7308 | return success ? parser->scope : NULL_TREE; |
7309 | } |
7310 | |
7311 | /* Parse a nested-name-specifier. See |
7312 | cp_parser_nested_name_specifier_opt for details. This function |
7313 | behaves identically, except that it will an issue an error if no |
7314 | nested-name-specifier is present. */ |
7315 | |
7316 | static tree |
7317 | cp_parser_nested_name_specifier (cp_parser *parser, |
7318 | bool typename_keyword_p, |
7319 | bool check_dependency_p, |
7320 | bool type_p, |
7321 | bool is_declaration) |
7322 | { |
7323 | tree scope; |
7324 | |
7325 | /* Look for the nested-name-specifier. */ |
7326 | scope = cp_parser_nested_name_specifier_opt (parser, |
7327 | typename_keyword_p, |
7328 | check_dependency_p, |
7329 | type_p, |
7330 | is_declaration); |
7331 | /* If it was not present, issue an error message. */ |
7332 | if (!scope) |
7333 | { |
7334 | cp_parser_error (parser, gmsgid: "expected nested-name-specifier" ); |
7335 | parser->scope = NULL_TREE; |
7336 | } |
7337 | |
7338 | return scope; |
7339 | } |
7340 | |
7341 | /* Parse the qualifying entity in a nested-name-specifier. For C++98, |
7342 | this is either a class-name or a namespace-name (which corresponds |
7343 | to the class-or-namespace-name production in the grammar). For |
7344 | C++0x, it can also be a type-name that refers to an enumeration |
7345 | type or a simple-template-id. |
7346 | |
7347 | TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect. |
7348 | TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect. |
7349 | CHECK_DEPENDENCY_P is FALSE iff dependent names should be looked up. |
7350 | TYPE_P is TRUE iff the next name should be taken as a class-name, |
7351 | even the same name is declared to be another entity in the same |
7352 | scope. |
7353 | |
7354 | Returns the class (TYPE_DECL) or namespace (NAMESPACE_DECL) |
7355 | specified by the class-or-namespace-name. If neither is found the |
7356 | ERROR_MARK_NODE is returned. */ |
7357 | |
7358 | static tree |
7359 | cp_parser_qualifying_entity (cp_parser *parser, |
7360 | bool typename_keyword_p, |
7361 | bool template_keyword_p, |
7362 | bool check_dependency_p, |
7363 | bool type_p, |
7364 | bool is_declaration) |
7365 | { |
7366 | tree saved_scope; |
7367 | tree saved_qualifying_scope; |
7368 | tree saved_object_scope; |
7369 | tree scope; |
7370 | bool only_class_p; |
7371 | bool successful_parse_p; |
7372 | |
7373 | /* DR 743: decltype can appear in a nested-name-specifier. */ |
7374 | if (cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
7375 | { |
7376 | scope = cp_parser_decltype (parser); |
7377 | if (TREE_CODE (scope) != ENUMERAL_TYPE |
7378 | && !MAYBE_CLASS_TYPE_P (scope)) |
7379 | { |
7380 | cp_parser_simulate_error (parser); |
7381 | return error_mark_node; |
7382 | } |
7383 | if (TYPE_NAME (scope)) |
7384 | scope = TYPE_NAME (scope); |
7385 | return scope; |
7386 | } |
7387 | |
7388 | /* Before we try to parse the class-name, we must save away the |
7389 | current PARSER->SCOPE since cp_parser_class_name will destroy |
7390 | it. */ |
7391 | saved_scope = parser->scope; |
7392 | saved_qualifying_scope = parser->qualifying_scope; |
7393 | saved_object_scope = parser->object_scope; |
7394 | /* Try for a class-name first. If the SAVED_SCOPE is a type, then |
7395 | there is no need to look for a namespace-name. */ |
7396 | only_class_p = template_keyword_p |
7397 | || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98); |
7398 | if (!only_class_p) |
7399 | cp_parser_parse_tentatively (parser); |
7400 | scope = cp_parser_class_name (parser, |
7401 | typename_keyword_p, |
7402 | template_keyword_p, |
7403 | type_p ? class_type : none_type, |
7404 | check_dependency_p, |
7405 | /*class_head_p=*/false, |
7406 | is_declaration, |
7407 | /*enum_ok=*/cxx_dialect > cxx98); |
7408 | successful_parse_p = only_class_p || cp_parser_parse_definitely (parser); |
7409 | /* If that didn't work, try for a namespace-name. */ |
7410 | if (!only_class_p && !successful_parse_p) |
7411 | { |
7412 | /* Restore the saved scope. */ |
7413 | parser->scope = saved_scope; |
7414 | parser->qualifying_scope = saved_qualifying_scope; |
7415 | parser->object_scope = saved_object_scope; |
7416 | /* If we are not looking at an identifier followed by the scope |
7417 | resolution operator, then this is not part of a |
7418 | nested-name-specifier. (Note that this function is only used |
7419 | to parse the components of a nested-name-specifier.) */ |
7420 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME) |
7421 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE) |
7422 | return error_mark_node; |
7423 | scope = cp_parser_namespace_name (parser); |
7424 | } |
7425 | |
7426 | return scope; |
7427 | } |
7428 | |
7429 | /* Return true if we are looking at a compound-literal, false otherwise. */ |
7430 | |
7431 | static bool |
7432 | cp_parser_compound_literal_p (cp_parser *parser) |
7433 | { |
7434 | cp_lexer_save_tokens (lexer: parser->lexer); |
7435 | |
7436 | /* Skip tokens until the next token is a closing parenthesis. |
7437 | If we find the closing `)', and the next token is a `{', then |
7438 | we are looking at a compound-literal. */ |
7439 | bool compound_literal_p |
7440 | = (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
7441 | /*consume_paren=*/true) |
7442 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)); |
7443 | |
7444 | /* Roll back the tokens we skipped. */ |
7445 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
7446 | |
7447 | return compound_literal_p; |
7448 | } |
7449 | |
7450 | /* Return true if EXPR is the integer constant zero or a complex constant |
7451 | of zero, without any folding, but ignoring location wrappers. */ |
7452 | |
7453 | bool |
7454 | literal_integer_zerop (const_tree expr) |
7455 | { |
7456 | return (location_wrapper_p (exp: expr) |
7457 | && integer_zerop (TREE_OPERAND (expr, 0))); |
7458 | } |
7459 | |
7460 | /* Parse a postfix-expression. |
7461 | |
7462 | postfix-expression: |
7463 | primary-expression |
7464 | postfix-expression [ expression ] |
7465 | postfix-expression ( expression-list [opt] ) |
7466 | simple-type-specifier ( expression-list [opt] ) |
7467 | typename :: [opt] nested-name-specifier identifier |
7468 | ( expression-list [opt] ) |
7469 | typename :: [opt] nested-name-specifier template [opt] template-id |
7470 | ( expression-list [opt] ) |
7471 | postfix-expression . template [opt] id-expression |
7472 | postfix-expression -> template [opt] id-expression |
7473 | postfix-expression . pseudo-destructor-name |
7474 | postfix-expression -> pseudo-destructor-name |
7475 | postfix-expression ++ |
7476 | postfix-expression -- |
7477 | dynamic_cast < type-id > ( expression ) |
7478 | static_cast < type-id > ( expression ) |
7479 | reinterpret_cast < type-id > ( expression ) |
7480 | const_cast < type-id > ( expression ) |
7481 | typeid ( expression ) |
7482 | typeid ( type-id ) |
7483 | |
7484 | GNU Extension: |
7485 | |
7486 | postfix-expression: |
7487 | ( type-id ) { initializer-list , [opt] } |
7488 | |
7489 | This extension is a GNU version of the C99 compound-literal |
7490 | construct. (The C99 grammar uses `type-name' instead of `type-id', |
7491 | but they are essentially the same concept.) |
7492 | |
7493 | If ADDRESS_P is true, the postfix expression is the operand of the |
7494 | `&' operator. CAST_P is true if this expression is the target of a |
7495 | cast. |
7496 | |
7497 | If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are |
7498 | class member access expressions [expr.ref]. |
7499 | |
7500 | Returns a representation of the expression. */ |
7501 | |
7502 | static cp_expr |
7503 | cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, |
7504 | bool member_access_only_p, bool decltype_p, |
7505 | cp_id_kind * pidk_return) |
7506 | { |
7507 | cp_token *token; |
7508 | location_t loc; |
7509 | enum rid keyword; |
7510 | cp_id_kind idk = CP_ID_KIND_NONE; |
7511 | cp_expr postfix_expression = NULL_TREE; |
7512 | bool is_member_access = false; |
7513 | |
7514 | /* Peek at the next token. */ |
7515 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7516 | loc = token->location; |
7517 | location_t start_loc = get_range_from_loc (set: line_table, loc).m_start; |
7518 | |
7519 | /* Some of the productions are determined by keywords. */ |
7520 | keyword = token->keyword; |
7521 | switch (keyword) |
7522 | { |
7523 | case RID_DYNCAST: |
7524 | case RID_STATCAST: |
7525 | case RID_REINTCAST: |
7526 | case RID_CONSTCAST: |
7527 | { |
7528 | tree type; |
7529 | cp_expr expression; |
7530 | const char *saved_message; |
7531 | bool saved_in_type_id_in_expr_p; |
7532 | |
7533 | /* All of these can be handled in the same way from the point |
7534 | of view of parsing. Begin by consuming the token |
7535 | identifying the cast. */ |
7536 | cp_lexer_consume_token (lexer: parser->lexer); |
7537 | |
7538 | /* New types cannot be defined in the cast. */ |
7539 | saved_message = parser->type_definition_forbidden_message; |
7540 | parser->type_definition_forbidden_message |
7541 | = G_("types may not be defined in casts" ); |
7542 | |
7543 | /* Look for the opening `<'. */ |
7544 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
7545 | /* Parse the type to which we are casting. */ |
7546 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7547 | parser->in_type_id_in_expr_p = true; |
7548 | type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
7549 | NULL); |
7550 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7551 | /* Look for the closing `>'. */ |
7552 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
7553 | /* Restore the old message. */ |
7554 | parser->type_definition_forbidden_message = saved_message; |
7555 | |
7556 | bool saved_greater_than_is_operator_p |
7557 | = parser->greater_than_is_operator_p; |
7558 | parser->greater_than_is_operator_p = true; |
7559 | |
7560 | /* And the expression which is being cast. */ |
7561 | matching_parens parens; |
7562 | parens.require_open (parser); |
7563 | expression = cp_parser_expression (parser, & idk, /*cast_p=*/true); |
7564 | cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, |
7565 | RT_CLOSE_PAREN); |
7566 | location_t end_loc = close_paren ? |
7567 | close_paren->location : UNKNOWN_LOCATION; |
7568 | |
7569 | parser->greater_than_is_operator_p |
7570 | = saved_greater_than_is_operator_p; |
7571 | |
7572 | /* Only type conversions to integral or enumeration types |
7573 | can be used in constant-expressions. */ |
7574 | if (!cast_valid_in_integral_constant_expression_p (type) |
7575 | && cp_parser_non_integral_constant_expression (parser, thing: NIC_CAST)) |
7576 | { |
7577 | postfix_expression = error_mark_node; |
7578 | break; |
7579 | } |
7580 | |
7581 | /* Construct a location e.g. : |
7582 | reinterpret_cast <int *> (expr) |
7583 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
7584 | ranging from the start of the "*_cast" token to the final closing |
7585 | paren, with the caret at the start. */ |
7586 | location_t cp_cast_loc = make_location (caret: start_loc, start: start_loc, finish: end_loc); |
7587 | |
7588 | switch (keyword) |
7589 | { |
7590 | case RID_DYNCAST: |
7591 | postfix_expression |
7592 | = build_dynamic_cast (cp_cast_loc, type, expression, |
7593 | tf_warning_or_error); |
7594 | break; |
7595 | case RID_STATCAST: |
7596 | postfix_expression |
7597 | = build_static_cast (cp_cast_loc, type, expression, |
7598 | tf_warning_or_error); |
7599 | break; |
7600 | case RID_REINTCAST: |
7601 | postfix_expression |
7602 | = build_reinterpret_cast (cp_cast_loc, type, expression, |
7603 | tf_warning_or_error); |
7604 | break; |
7605 | case RID_CONSTCAST: |
7606 | postfix_expression |
7607 | = build_const_cast (cp_cast_loc, type, expression, |
7608 | tf_warning_or_error); |
7609 | break; |
7610 | default: |
7611 | gcc_unreachable (); |
7612 | } |
7613 | } |
7614 | break; |
7615 | |
7616 | case RID_TYPEID: |
7617 | { |
7618 | tree type; |
7619 | const char *saved_message; |
7620 | bool saved_in_type_id_in_expr_p; |
7621 | |
7622 | /* Consume the `typeid' token. */ |
7623 | cp_lexer_consume_token (lexer: parser->lexer); |
7624 | /* Look for the `(' token. */ |
7625 | matching_parens parens; |
7626 | parens.require_open (parser); |
7627 | /* Types cannot be defined in a `typeid' expression. */ |
7628 | saved_message = parser->type_definition_forbidden_message; |
7629 | parser->type_definition_forbidden_message |
7630 | = G_("types may not be defined in a %<typeid%> expression" ); |
7631 | /* We can't be sure yet whether we're looking at a type-id or an |
7632 | expression. */ |
7633 | cp_parser_parse_tentatively (parser); |
7634 | /* Try a type-id first. */ |
7635 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7636 | parser->in_type_id_in_expr_p = true; |
7637 | type = cp_parser_type_id (parser); |
7638 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7639 | /* Look for the `)' token. Otherwise, we can't be sure that |
7640 | we're not looking at an expression: consider `typeid (int |
7641 | (3))', for example. */ |
7642 | cp_token *close_paren = parens.require_close (parser); |
7643 | /* If all went well, simply lookup the type-id. */ |
7644 | if (cp_parser_parse_definitely (parser)) |
7645 | postfix_expression = get_typeid (type, tf_warning_or_error); |
7646 | /* Otherwise, fall back to the expression variant. */ |
7647 | else |
7648 | { |
7649 | tree expression; |
7650 | |
7651 | /* Look for an expression. */ |
7652 | expression = cp_parser_expression (parser, & idk); |
7653 | /* Compute its typeid. */ |
7654 | postfix_expression = build_typeid (expression, tf_warning_or_error); |
7655 | /* Look for the `)' token. */ |
7656 | close_paren = parens.require_close (parser); |
7657 | } |
7658 | /* Restore the saved message. */ |
7659 | parser->type_definition_forbidden_message = saved_message; |
7660 | /* `typeid' may not appear in an integral constant expression. */ |
7661 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_TYPEID)) |
7662 | postfix_expression = error_mark_node; |
7663 | |
7664 | /* Construct a location e.g. : |
7665 | typeid (expr) |
7666 | ^~~~~~~~~~~~~ |
7667 | ranging from the start of the "typeid" token to the final closing |
7668 | paren, with the caret at the start. */ |
7669 | if (close_paren) |
7670 | { |
7671 | location_t typeid_loc |
7672 | = make_location (caret: start_loc, start: start_loc, finish: close_paren->location); |
7673 | postfix_expression.set_location (typeid_loc); |
7674 | postfix_expression.maybe_add_location_wrapper (); |
7675 | } |
7676 | } |
7677 | break; |
7678 | |
7679 | case RID_TYPENAME: |
7680 | { |
7681 | tree type; |
7682 | /* The syntax permitted here is the same permitted for an |
7683 | elaborated-type-specifier. */ |
7684 | ++parser->prevent_constrained_type_specifiers; |
7685 | type = cp_parser_elaborated_type_specifier (parser, |
7686 | /*is_friend=*/false, |
7687 | /*is_declaration=*/false); |
7688 | --parser->prevent_constrained_type_specifiers; |
7689 | postfix_expression = cp_parser_functional_cast (parser, type); |
7690 | } |
7691 | break; |
7692 | |
7693 | case RID_ADDRESSOF: |
7694 | case RID_BUILTIN_SHUFFLE: |
7695 | case RID_BUILTIN_SHUFFLEVECTOR: |
7696 | case RID_BUILTIN_LAUNDER: |
7697 | case RID_BUILTIN_ASSOC_BARRIER: |
7698 | { |
7699 | vec<tree, va_gc> *vec; |
7700 | |
7701 | cp_lexer_consume_token (lexer: parser->lexer); |
7702 | vec = cp_parser_parenthesized_expression_list (parser, non_attr, |
7703 | /*cast_p=*/false, /*allow_expansion_p=*/true, |
7704 | /*non_constant_p=*/NULL); |
7705 | if (vec == NULL) |
7706 | { |
7707 | postfix_expression = error_mark_node; |
7708 | break; |
7709 | } |
7710 | |
7711 | for (tree p : *vec) |
7712 | mark_exp_read (p); |
7713 | |
7714 | switch (keyword) |
7715 | { |
7716 | case RID_ADDRESSOF: |
7717 | if (vec->length () == 1) |
7718 | postfix_expression |
7719 | = cp_build_addressof (loc, (*vec)[0], tf_warning_or_error); |
7720 | else |
7721 | { |
7722 | error_at (loc, "wrong number of arguments to " |
7723 | "%<__builtin_addressof%>" ); |
7724 | postfix_expression = error_mark_node; |
7725 | } |
7726 | break; |
7727 | |
7728 | case RID_BUILTIN_LAUNDER: |
7729 | if (vec->length () == 1) |
7730 | postfix_expression = finish_builtin_launder (loc, (*vec)[0], |
7731 | tf_warning_or_error); |
7732 | else |
7733 | { |
7734 | error_at (loc, "wrong number of arguments to " |
7735 | "%<__builtin_launder%>" ); |
7736 | postfix_expression = error_mark_node; |
7737 | } |
7738 | break; |
7739 | |
7740 | case RID_BUILTIN_ASSOC_BARRIER: |
7741 | if (vec->length () == 1) |
7742 | postfix_expression = build1_loc (loc, code: PAREN_EXPR, |
7743 | TREE_TYPE ((*vec)[0]), |
7744 | arg1: (*vec)[0]); |
7745 | else |
7746 | { |
7747 | error_at (loc, "wrong number of arguments to " |
7748 | "%<__builtin_assoc_barrier%>" ); |
7749 | postfix_expression = error_mark_node; |
7750 | } |
7751 | break; |
7752 | |
7753 | case RID_BUILTIN_SHUFFLE: |
7754 | if (vec->length () == 2) |
7755 | postfix_expression |
7756 | = build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, |
7757 | (*vec)[1], tf_warning_or_error); |
7758 | else if (vec->length () == 3) |
7759 | postfix_expression |
7760 | = build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], |
7761 | (*vec)[2], tf_warning_or_error); |
7762 | else |
7763 | { |
7764 | error_at (loc, "wrong number of arguments to " |
7765 | "%<__builtin_shuffle%>" ); |
7766 | postfix_expression = error_mark_node; |
7767 | } |
7768 | break; |
7769 | |
7770 | case RID_BUILTIN_SHUFFLEVECTOR: |
7771 | if (vec->length () < 3) |
7772 | { |
7773 | error_at (loc, "wrong number of arguments to " |
7774 | "%<__builtin_shufflevector%>" ); |
7775 | postfix_expression = error_mark_node; |
7776 | } |
7777 | else |
7778 | { |
7779 | postfix_expression |
7780 | = build_x_shufflevector (loc, vec, tf_warning_or_error); |
7781 | } |
7782 | break; |
7783 | |
7784 | default: |
7785 | gcc_unreachable (); |
7786 | } |
7787 | break; |
7788 | } |
7789 | |
7790 | case RID_BUILTIN_CONVERTVECTOR: |
7791 | { |
7792 | tree expression; |
7793 | tree type; |
7794 | /* Consume the `__builtin_convertvector' token. */ |
7795 | cp_lexer_consume_token (lexer: parser->lexer); |
7796 | /* Look for the opening `('. */ |
7797 | matching_parens parens; |
7798 | parens.require_open (parser); |
7799 | /* Now, parse the assignment-expression. */ |
7800 | expression = cp_parser_assignment_expression (parser); |
7801 | /* Look for the `,'. */ |
7802 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
7803 | location_t type_location |
7804 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
7805 | /* Parse the type-id. */ |
7806 | { |
7807 | type_id_in_expr_sentinel s (parser); |
7808 | type = cp_parser_type_id (parser); |
7809 | } |
7810 | /* Look for the closing `)'. */ |
7811 | parens.require_close (parser); |
7812 | postfix_expression |
7813 | = cp_build_vec_convert (expression, type_location, type, |
7814 | tf_warning_or_error); |
7815 | break; |
7816 | } |
7817 | |
7818 | case RID_BUILTIN_BIT_CAST: |
7819 | { |
7820 | tree expression; |
7821 | tree type; |
7822 | /* Consume the `__builtin_bit_cast' token. */ |
7823 | cp_lexer_consume_token (lexer: parser->lexer); |
7824 | /* Look for the opening `('. */ |
7825 | matching_parens parens; |
7826 | parens.require_open (parser); |
7827 | location_t type_location |
7828 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
7829 | /* Parse the type-id. */ |
7830 | { |
7831 | type_id_in_expr_sentinel s (parser); |
7832 | type = cp_parser_type_id (parser); |
7833 | } |
7834 | /* Look for the `,'. */ |
7835 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
7836 | /* Now, parse the assignment-expression. */ |
7837 | expression = cp_parser_assignment_expression (parser); |
7838 | /* Look for the closing `)'. */ |
7839 | parens.require_close (parser); |
7840 | postfix_expression |
7841 | = cp_build_bit_cast (type_location, type, expression, |
7842 | tf_warning_or_error); |
7843 | break; |
7844 | } |
7845 | |
7846 | default: |
7847 | { |
7848 | tree type; |
7849 | |
7850 | /* If the next thing is a simple-type-specifier, we may be |
7851 | looking at a functional cast. We could also be looking at |
7852 | an id-expression. So, we try the functional cast, and if |
7853 | that doesn't work we fall back to the primary-expression. */ |
7854 | cp_parser_parse_tentatively (parser); |
7855 | /* Look for the simple-type-specifier. */ |
7856 | ++parser->prevent_constrained_type_specifiers; |
7857 | type = cp_parser_simple_type_specifier (parser, |
7858 | /*decl_specs=*/NULL, |
7859 | CP_PARSER_FLAGS_NONE); |
7860 | --parser->prevent_constrained_type_specifiers; |
7861 | /* Parse the cast itself. */ |
7862 | if (!cp_parser_error_occurred (parser)) |
7863 | postfix_expression |
7864 | = cp_parser_functional_cast (parser, type); |
7865 | /* If that worked, we're done. */ |
7866 | if (cp_parser_parse_definitely (parser)) |
7867 | break; |
7868 | |
7869 | /* If the functional-cast didn't work out, try a |
7870 | compound-literal. */ |
7871 | if (cp_parser_allow_gnu_extensions_p (parser) |
7872 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
7873 | { |
7874 | cp_expr initializer = NULL_TREE; |
7875 | |
7876 | cp_parser_parse_tentatively (parser); |
7877 | |
7878 | matching_parens parens; |
7879 | parens.consume_open (parser); |
7880 | |
7881 | /* Avoid calling cp_parser_type_id pointlessly, see comment |
7882 | in cp_parser_cast_expression about c++/29234. */ |
7883 | if (!cp_parser_compound_literal_p (parser)) |
7884 | cp_parser_simulate_error (parser); |
7885 | else |
7886 | { |
7887 | /* Parse the type. */ |
7888 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7889 | parser->in_type_id_in_expr_p = true; |
7890 | type = cp_parser_type_id (parser); |
7891 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7892 | parens.require_close (parser); |
7893 | } |
7894 | |
7895 | /* If things aren't going well, there's no need to |
7896 | keep going. */ |
7897 | if (!cp_parser_error_occurred (parser)) |
7898 | /* Parse the brace-enclosed initializer list. */ |
7899 | initializer = cp_parser_braced_list (parser); |
7900 | /* If that worked, we're definitely looking at a |
7901 | compound-literal expression. */ |
7902 | if (cp_parser_parse_definitely (parser)) |
7903 | { |
7904 | /* Warn the user that a compound literal is not |
7905 | allowed in standard C++. */ |
7906 | pedwarn (input_location, OPT_Wpedantic, |
7907 | "ISO C++ forbids compound-literals" ); |
7908 | /* For simplicity, we disallow compound literals in |
7909 | constant-expressions. We could |
7910 | allow compound literals of integer type, whose |
7911 | initializer was a constant, in constant |
7912 | expressions. Permitting that usage, as a further |
7913 | extension, would not change the meaning of any |
7914 | currently accepted programs. (Of course, as |
7915 | compound literals are not part of ISO C++, the |
7916 | standard has nothing to say.) */ |
7917 | if (cp_parser_non_integral_constant_expression (parser, |
7918 | thing: NIC_NCC)) |
7919 | { |
7920 | postfix_expression = error_mark_node; |
7921 | break; |
7922 | } |
7923 | /* Form the representation of the compound-literal. */ |
7924 | postfix_expression |
7925 | = finish_compound_literal (type, initializer, |
7926 | tf_warning_or_error, fcl_c99); |
7927 | postfix_expression.set_location (initializer.get_location ()); |
7928 | break; |
7929 | } |
7930 | } |
7931 | |
7932 | /* It must be a primary-expression. */ |
7933 | postfix_expression |
7934 | = cp_parser_primary_expression (parser, address_p, cast_p, |
7935 | /*template_arg_p=*/false, |
7936 | decltype_p, |
7937 | idk: &idk); |
7938 | } |
7939 | break; |
7940 | } |
7941 | |
7942 | /* Note that we don't need to worry about calling build_cplus_new on a |
7943 | class-valued CALL_EXPR in decltype when it isn't the end of the |
7944 | postfix-expression; unary_complex_lvalue will take care of that for |
7945 | all these cases. */ |
7946 | |
7947 | /* Keep looping until the postfix-expression is complete. */ |
7948 | while (true) |
7949 | { |
7950 | if (idk == CP_ID_KIND_UNQUALIFIED |
7951 | && identifier_p (t: postfix_expression) |
7952 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
7953 | /* It is not a Koenig lookup function call. */ |
7954 | postfix_expression |
7955 | = unqualified_name_lookup_error (postfix_expression); |
7956 | |
7957 | /* Peek at the next token. */ |
7958 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7959 | |
7960 | switch (token->type) |
7961 | { |
7962 | case CPP_OPEN_SQUARE: |
7963 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
7964 | { |
7965 | cp_parser_error (parser, |
7966 | gmsgid: "two consecutive %<[%> shall " |
7967 | "only introduce an attribute" ); |
7968 | return error_mark_node; |
7969 | } |
7970 | postfix_expression |
7971 | = cp_parser_postfix_open_square_expression (parser, |
7972 | postfix_expression, |
7973 | false, |
7974 | decltype_p); |
7975 | postfix_expression.set_range (start: start_loc, |
7976 | finish: postfix_expression.get_location ()); |
7977 | |
7978 | idk = CP_ID_KIND_NONE; |
7979 | is_member_access = false; |
7980 | break; |
7981 | |
7982 | case CPP_OPEN_PAREN: |
7983 | /* postfix-expression ( expression-list [opt] ) */ |
7984 | { |
7985 | bool koenig_p; |
7986 | bool is_builtin_constant_p; |
7987 | bool saved_integral_constant_expression_p = false; |
7988 | bool saved_non_integral_constant_expression_p = false; |
7989 | tsubst_flags_t complain = complain_flags (decltype_p); |
7990 | vec<tree, va_gc> *args; |
7991 | location_t close_paren_loc = UNKNOWN_LOCATION; |
7992 | location_t combined_loc = UNKNOWN_LOCATION; |
7993 | |
7994 | is_member_access = false; |
7995 | |
7996 | tree stripped_expression |
7997 | = tree_strip_any_location_wrapper (exp: postfix_expression); |
7998 | is_builtin_constant_p |
7999 | = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression); |
8000 | if (is_builtin_constant_p) |
8001 | { |
8002 | /* The whole point of __builtin_constant_p is to allow |
8003 | non-constant expressions to appear as arguments. */ |
8004 | saved_integral_constant_expression_p |
8005 | = parser->integral_constant_expression_p; |
8006 | saved_non_integral_constant_expression_p |
8007 | = parser->non_integral_constant_expression_p; |
8008 | parser->integral_constant_expression_p = false; |
8009 | } |
8010 | else if (TREE_CODE (stripped_expression) == FUNCTION_DECL |
8011 | && fndecl_built_in_p (node: stripped_expression, |
8012 | name1: BUILT_IN_CLASSIFY_TYPE)) |
8013 | { |
8014 | /* __builtin_classify_type (type) */ |
8015 | auto cl1 = make_temp_override |
8016 | (var&: parser->type_definition_forbidden_message, |
8017 | G_("types may not be defined in " |
8018 | "%<__builtin_classify_type%> calls" )); |
8019 | auto cl2 = make_temp_override |
8020 | (var&: parser->type_definition_forbidden_message_arg, |
8021 | NULL); |
8022 | auto cl3 = make_temp_override (var&: parser->in_type_id_in_expr_p, |
8023 | overrider: true); |
8024 | cp_unevaluated uev; |
8025 | cp_parser_parse_tentatively (parser); |
8026 | matching_parens parens; |
8027 | parens.consume_open (parser); |
8028 | tree type = cp_parser_type_id (parser); |
8029 | parens.require_close (parser); |
8030 | if (cp_parser_parse_definitely (parser)) |
8031 | { |
8032 | if (dependent_type_p (type)) |
8033 | { |
8034 | postfix_expression = build_vl_exp (CALL_EXPR, 4); |
8035 | CALL_EXPR_FN (postfix_expression) |
8036 | = stripped_expression; |
8037 | CALL_EXPR_STATIC_CHAIN (postfix_expression) = type; |
8038 | CALL_EXPR_ARG (postfix_expression, 0) |
8039 | = build_min (SIZEOF_EXPR, size_type_node, type); |
8040 | TREE_TYPE (postfix_expression) = integer_type_node; |
8041 | } |
8042 | else |
8043 | { |
8044 | postfix_expression |
8045 | = build_int_cst (integer_type_node, |
8046 | type_to_class (type)); |
8047 | } |
8048 | break; |
8049 | } |
8050 | } |
8051 | args = (cp_parser_parenthesized_expression_list |
8052 | (parser, non_attr, |
8053 | /*cast_p=*/false, /*allow_expansion_p=*/true, |
8054 | /*non_constant_p=*/NULL, |
8055 | /*close_paren_loc=*/&close_paren_loc, |
8056 | /*wrap_locations_p=*/true)); |
8057 | if (is_builtin_constant_p) |
8058 | { |
8059 | parser->integral_constant_expression_p |
8060 | = saved_integral_constant_expression_p; |
8061 | parser->non_integral_constant_expression_p |
8062 | = saved_non_integral_constant_expression_p; |
8063 | } |
8064 | |
8065 | if (args == NULL) |
8066 | { |
8067 | postfix_expression = error_mark_node; |
8068 | break; |
8069 | } |
8070 | |
8071 | /* Function calls are not permitted in |
8072 | constant-expressions. */ |
8073 | if (! builtin_valid_in_constant_expr_p (postfix_expression) |
8074 | && cp_parser_non_integral_constant_expression (parser, |
8075 | thing: NIC_FUNC_CALL)) |
8076 | { |
8077 | postfix_expression = error_mark_node; |
8078 | release_tree_vector (args); |
8079 | break; |
8080 | } |
8081 | |
8082 | koenig_p = false; |
8083 | if (idk == CP_ID_KIND_UNQUALIFIED |
8084 | || idk == CP_ID_KIND_TEMPLATE_ID) |
8085 | { |
8086 | if (identifier_p (t: postfix_expression) |
8087 | /* In C++20, we may need to perform ADL for a template |
8088 | name. */ |
8089 | || (TREE_CODE (postfix_expression) == TEMPLATE_ID_EXPR |
8090 | && identifier_p (TREE_OPERAND (postfix_expression, 0)))) |
8091 | { |
8092 | if (!args->is_empty ()) |
8093 | { |
8094 | koenig_p = true; |
8095 | if (!any_type_dependent_arguments_p (args)) |
8096 | postfix_expression |
8097 | = perform_koenig_lookup (postfix_expression, args, |
8098 | complain); |
8099 | } |
8100 | else |
8101 | postfix_expression |
8102 | = unqualified_fn_lookup_error (postfix_expression); |
8103 | } |
8104 | /* We do not perform argument-dependent lookup if |
8105 | normal lookup finds a non-function, in accordance |
8106 | with the expected resolution of DR 218. */ |
8107 | else if (!args->is_empty () |
8108 | && is_overloaded_fn (postfix_expression)) |
8109 | { |
8110 | /* Do not do argument dependent lookup if regular |
8111 | lookup finds a member function or a block-scope |
8112 | function declaration. [basic.lookup.argdep]/3 */ |
8113 | bool do_adl_p = true; |
8114 | tree fns = get_fns (postfix_expression); |
8115 | for (lkp_iterator iter (fns); iter; ++iter) |
8116 | { |
8117 | tree fn = STRIP_TEMPLATE (*iter); |
8118 | if ((TREE_CODE (fn) == USING_DECL |
8119 | && DECL_DEPENDENT_P (fn)) |
8120 | || DECL_FUNCTION_MEMBER_P (fn) |
8121 | || DECL_LOCAL_DECL_P (fn)) |
8122 | { |
8123 | do_adl_p = false; |
8124 | break; |
8125 | } |
8126 | } |
8127 | |
8128 | if (do_adl_p) |
8129 | { |
8130 | koenig_p = true; |
8131 | if (!any_type_dependent_arguments_p (args)) |
8132 | postfix_expression |
8133 | = perform_koenig_lookup (postfix_expression, args, |
8134 | complain); |
8135 | } |
8136 | } |
8137 | } |
8138 | |
8139 | /* Temporarily set input_location to the combined location |
8140 | with call expression range, as e.g. build_out_target_exprs |
8141 | called from convert_default_arg relies on input_location, |
8142 | so updating it only when the call is fully built results |
8143 | in inconsistencies between location handling in templates |
8144 | and outside of templates. */ |
8145 | if (close_paren_loc != UNKNOWN_LOCATION) |
8146 | combined_loc = make_location (caret: token->location, start: start_loc, |
8147 | finish: close_paren_loc); |
8148 | iloc_sentinel ils (combined_loc); |
8149 | |
8150 | if (TREE_CODE (postfix_expression) == OFFSET_REF |
8151 | || TREE_CODE (postfix_expression) == MEMBER_REF |
8152 | || TREE_CODE (postfix_expression) == DOTSTAR_EXPR) |
8153 | postfix_expression = (build_offset_ref_call_from_tree |
8154 | (postfix_expression, &args, |
8155 | complain)); |
8156 | else |
8157 | /* All other function calls. */ |
8158 | { |
8159 | if (DECL_P (postfix_expression) |
8160 | && parser->omp_for_parse_state |
8161 | && parser->omp_for_parse_state->in_intervening_code |
8162 | && omp_runtime_api_call (fndecl: postfix_expression)) |
8163 | { |
8164 | error_at (loc, "calls to the OpenMP runtime API are " |
8165 | "not permitted in intervening code" ); |
8166 | parser->omp_for_parse_state->fail = true; |
8167 | } |
8168 | bool disallow_virtual = (idk == CP_ID_KIND_QUALIFIED); |
8169 | postfix_expression |
8170 | = finish_call_expr (postfix_expression, &args, |
8171 | disallow_virtual, |
8172 | koenig_p, |
8173 | complain); |
8174 | } |
8175 | |
8176 | if (close_paren_loc != UNKNOWN_LOCATION) |
8177 | postfix_expression.set_location (combined_loc); |
8178 | |
8179 | /* The POSTFIX_EXPRESSION is certainly no longer an id. */ |
8180 | idk = CP_ID_KIND_NONE; |
8181 | |
8182 | release_tree_vector (args); |
8183 | } |
8184 | break; |
8185 | |
8186 | case CPP_DOT: |
8187 | case CPP_DEREF: |
8188 | /* postfix-expression . template [opt] id-expression |
8189 | postfix-expression . pseudo-destructor-name |
8190 | postfix-expression -> template [opt] id-expression |
8191 | postfix-expression -> pseudo-destructor-name */ |
8192 | |
8193 | /* Consume the `.' or `->' operator. */ |
8194 | cp_lexer_consume_token (lexer: parser->lexer); |
8195 | |
8196 | postfix_expression |
8197 | = cp_parser_postfix_dot_deref_expression (parser, token->type, |
8198 | postfix_expression, |
8199 | false, &idk, loc); |
8200 | |
8201 | is_member_access = true; |
8202 | break; |
8203 | |
8204 | case CPP_PLUS_PLUS: |
8205 | /* postfix-expression ++ */ |
8206 | /* Consume the `++' token. */ |
8207 | cp_lexer_consume_token (lexer: parser->lexer); |
8208 | /* Generate a representation for the complete expression. */ |
8209 | postfix_expression |
8210 | = finish_increment_expr (postfix_expression, |
8211 | POSTINCREMENT_EXPR); |
8212 | /* Increments may not appear in constant-expressions. */ |
8213 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_INC)) |
8214 | postfix_expression = error_mark_node; |
8215 | idk = CP_ID_KIND_NONE; |
8216 | is_member_access = false; |
8217 | break; |
8218 | |
8219 | case CPP_MINUS_MINUS: |
8220 | /* postfix-expression -- */ |
8221 | /* Consume the `--' token. */ |
8222 | cp_lexer_consume_token (lexer: parser->lexer); |
8223 | /* Generate a representation for the complete expression. */ |
8224 | postfix_expression |
8225 | = finish_increment_expr (postfix_expression, |
8226 | POSTDECREMENT_EXPR); |
8227 | /* Decrements may not appear in constant-expressions. */ |
8228 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_DEC)) |
8229 | postfix_expression = error_mark_node; |
8230 | idk = CP_ID_KIND_NONE; |
8231 | is_member_access = false; |
8232 | break; |
8233 | |
8234 | default: |
8235 | if (pidk_return != NULL) |
8236 | * pidk_return = idk; |
8237 | if (member_access_only_p) |
8238 | return is_member_access |
8239 | ? postfix_expression |
8240 | : cp_expr (error_mark_node); |
8241 | else |
8242 | return postfix_expression; |
8243 | } |
8244 | } |
8245 | } |
8246 | |
8247 | /* Helper function for cp_parser_parenthesized_expression_list and |
8248 | cp_parser_postfix_open_square_expression. Parse a single element |
8249 | of parenthesized expression list. */ |
8250 | |
8251 | static cp_expr |
8252 | cp_parser_parenthesized_expression_list_elt (cp_parser *parser, bool cast_p, |
8253 | bool allow_expansion_p, |
8254 | bool *non_constant_p) |
8255 | { |
8256 | cp_expr expr (NULL_TREE); |
8257 | bool expr_non_constant_p; |
8258 | |
8259 | /* Parse the next assignment-expression. */ |
8260 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
8261 | { |
8262 | /* A braced-init-list. */ |
8263 | cp_lexer_set_source_position (lexer: parser->lexer); |
8264 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
8265 | expr = cp_parser_braced_list (parser, |
8266 | (non_constant_p != nullptr |
8267 | ? &expr_non_constant_p |
8268 | : nullptr)); |
8269 | if (non_constant_p && expr_non_constant_p) |
8270 | *non_constant_p = true; |
8271 | } |
8272 | else if (non_constant_p) |
8273 | { |
8274 | expr = cp_parser_constant_expression (parser, |
8275 | /*allow_non_constant_p=*/true, |
8276 | &expr_non_constant_p); |
8277 | if (expr_non_constant_p) |
8278 | *non_constant_p = true; |
8279 | } |
8280 | else |
8281 | expr = cp_parser_assignment_expression (parser, /*pidk=*/NULL, cast_p); |
8282 | |
8283 | /* If we have an ellipsis, then this is an expression expansion. */ |
8284 | if (allow_expansion_p |
8285 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
8286 | { |
8287 | /* Consume the `...'. */ |
8288 | cp_lexer_consume_token (lexer: parser->lexer); |
8289 | |
8290 | /* Build the argument pack. */ |
8291 | expr = make_pack_expansion (expr); |
8292 | } |
8293 | return expr; |
8294 | } |
8295 | |
8296 | /* A subroutine of cp_parser_postfix_expression that also gets hijacked |
8297 | by cp_parser_builtin_offsetof. We're looking for |
8298 | |
8299 | postfix-expression [ expression ] |
8300 | postfix-expression [ braced-init-list ] (C++11) |
8301 | postfix-expression [ expression-list[opt] ] (C++23) |
8302 | |
8303 | FOR_OFFSETOF is set if we're being called in that context, which |
8304 | changes how we deal with integer constant expressions. */ |
8305 | |
8306 | static tree |
8307 | cp_parser_postfix_open_square_expression (cp_parser *parser, |
8308 | tree postfix_expression, |
8309 | bool for_offsetof, |
8310 | bool decltype_p) |
8311 | { |
8312 | tree index = NULL_TREE; |
8313 | releasing_vec expression_list = NULL; |
8314 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
8315 | bool saved_greater_than_is_operator_p; |
8316 | bool saved_colon_corrects_to_scope_p; |
8317 | |
8318 | /* Consume the `[' token. */ |
8319 | cp_lexer_consume_token (lexer: parser->lexer); |
8320 | |
8321 | saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; |
8322 | parser->greater_than_is_operator_p = true; |
8323 | |
8324 | saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
8325 | if (parser->omp_array_section_p) |
8326 | parser->colon_corrects_to_scope_p = false; |
8327 | |
8328 | /* Parse the index expression. */ |
8329 | /* ??? For offsetof, there is a question of what to allow here. If |
8330 | offsetof is not being used in an integral constant expression context, |
8331 | then we *could* get the right answer by computing the value at runtime. |
8332 | If we are in an integral constant expression context, then we might |
8333 | could accept any constant expression; hard to say without analysis. |
8334 | Rather than open the barn door too wide right away, allow only integer |
8335 | constant expressions here. */ |
8336 | if (for_offsetof) |
8337 | index = cp_parser_constant_expression (parser); |
8338 | else if (!parser->omp_array_section_p |
8339 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
8340 | { |
8341 | if (cxx_dialect >= cxx23 |
8342 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
8343 | *&expression_list = make_tree_vector (); |
8344 | else if (cxx_dialect >= cxx23) |
8345 | { |
8346 | while (true) |
8347 | { |
8348 | cp_expr expr |
8349 | = cp_parser_parenthesized_expression_list_elt (parser, |
8350 | /*cast_p=*/ |
8351 | false, |
8352 | /*allow_exp_p=*/ |
8353 | allow_expansion_p: true, |
8354 | /*non_cst_p=*/ |
8355 | NULL); |
8356 | |
8357 | if (expr == error_mark_node) |
8358 | index = error_mark_node; |
8359 | else if (expression_list.get () == NULL |
8360 | && !PACK_EXPANSION_P (expr.get_value ())) |
8361 | index = expr.get_value (); |
8362 | else |
8363 | vec_safe_push (r&: expression_list, t: expr.get_value ()); |
8364 | |
8365 | /* If the next token isn't a `,', then we are done. */ |
8366 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
8367 | break; |
8368 | |
8369 | if (expression_list.get () == NULL && index != error_mark_node) |
8370 | { |
8371 | *&expression_list = make_tree_vector_single (index); |
8372 | index = NULL_TREE; |
8373 | } |
8374 | |
8375 | /* Otherwise, consume the `,' and keep going. */ |
8376 | cp_lexer_consume_token (lexer: parser->lexer); |
8377 | } |
8378 | if (expression_list.get () && index == error_mark_node) |
8379 | expression_list.release (); |
8380 | } |
8381 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
8382 | { |
8383 | cp_lexer_set_source_position (lexer: parser->lexer); |
8384 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
8385 | index = cp_parser_braced_list (parser); |
8386 | } |
8387 | else |
8388 | index = cp_parser_expression (parser, NULL, /*cast_p=*/false, |
8389 | /*decltype_p=*/false, |
8390 | /*warn_comma_p=*/warn_comma_subscript); |
8391 | } |
8392 | |
8393 | parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; |
8394 | |
8395 | if (cxx_dialect >= cxx23 |
8396 | && parser->omp_array_section_p |
8397 | && expression_list.get () != NULL |
8398 | && vec_safe_length (r&: expression_list) > 1) |
8399 | { |
8400 | error_at (loc, "cannot use multidimensional subscript in OpenMP array " |
8401 | "section" ); |
8402 | index = error_mark_node; |
8403 | } |
8404 | if (parser->omp_array_section_p |
8405 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
8406 | { |
8407 | cp_lexer_consume_token (lexer: parser->lexer); |
8408 | tree length = NULL_TREE; |
8409 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
8410 | { |
8411 | if (cxx_dialect >= cxx23) |
8412 | { |
8413 | cp_expr expr |
8414 | = cp_parser_parenthesized_expression_list_elt (parser, |
8415 | /*cast_p=*/ |
8416 | false, |
8417 | /*allow_exp_p=*/ |
8418 | allow_expansion_p: true, |
8419 | /*non_cst_p=*/ |
8420 | NULL); |
8421 | |
8422 | if (expr == error_mark_node) |
8423 | length = error_mark_node; |
8424 | else |
8425 | length = expr.get_value (); |
8426 | |
8427 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
8428 | { |
8429 | error_at (loc, "cannot use multidimensional subscript in " |
8430 | "OpenMP array section" ); |
8431 | length = error_mark_node; |
8432 | } |
8433 | } |
8434 | else |
8435 | length |
8436 | = cp_parser_expression (parser, NULL, /*cast_p=*/false, |
8437 | /*decltype_p=*/false, |
8438 | /*warn_comma_p=*/warn_comma_subscript); |
8439 | } |
8440 | |
8441 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
8442 | |
8443 | if (index == error_mark_node || length == error_mark_node) |
8444 | { |
8445 | cp_parser_skip_to_closing_square_bracket (parser); |
8446 | return error_mark_node; |
8447 | } |
8448 | else |
8449 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
8450 | |
8451 | return grok_omp_array_section (input_location, postfix_expression, index, |
8452 | length); |
8453 | } |
8454 | |
8455 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
8456 | |
8457 | /* Look for the closing `]'. */ |
8458 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
8459 | |
8460 | /* Build the ARRAY_REF. */ |
8461 | postfix_expression = grok_array_decl (loc, postfix_expression, |
8462 | index, &expression_list, |
8463 | tf_warning_or_error |
8464 | | (decltype_p ? tf_decltype : 0)); |
8465 | |
8466 | /* When not doing offsetof, array references are not permitted in |
8467 | constant-expressions. */ |
8468 | if (!for_offsetof |
8469 | && (cp_parser_non_integral_constant_expression (parser, thing: NIC_ARRAY_REF))) |
8470 | postfix_expression = error_mark_node; |
8471 | |
8472 | return postfix_expression; |
8473 | } |
8474 | |
8475 | /* A subroutine of cp_parser_postfix_dot_deref_expression. Handle dot |
8476 | dereference of incomplete type, returns true if error_mark_node should |
8477 | be returned from caller, otherwise adjusts *SCOPE, *POSTFIX_EXPRESSION |
8478 | and *DEPENDENT_P. */ |
8479 | |
8480 | bool |
8481 | cp_parser_dot_deref_incomplete (tree *scope, cp_expr *postfix_expression, |
8482 | bool *dependent_p) |
8483 | { |
8484 | /* In a template, be permissive by treating an object expression |
8485 | of incomplete type as dependent (after a pedwarn). */ |
8486 | diagnostic_t kind = (processing_template_decl |
8487 | && MAYBE_CLASS_TYPE_P (*scope) ? DK_PEDWARN : DK_ERROR); |
8488 | |
8489 | switch (TREE_CODE (*postfix_expression)) |
8490 | { |
8491 | case CAST_EXPR: |
8492 | case REINTERPRET_CAST_EXPR: |
8493 | case CONST_CAST_EXPR: |
8494 | case STATIC_CAST_EXPR: |
8495 | case DYNAMIC_CAST_EXPR: |
8496 | case IMPLICIT_CONV_EXPR: |
8497 | case VIEW_CONVERT_EXPR: |
8498 | case NON_LVALUE_EXPR: |
8499 | kind = DK_ERROR; |
8500 | break; |
8501 | case OVERLOAD: |
8502 | /* Don't emit any diagnostic for OVERLOADs. */ |
8503 | kind = DK_IGNORED; |
8504 | break; |
8505 | default: |
8506 | /* Avoid clobbering e.g. DECLs. */ |
8507 | if (!EXPR_P (*postfix_expression)) |
8508 | kind = DK_ERROR; |
8509 | break; |
8510 | } |
8511 | |
8512 | if (kind == DK_IGNORED) |
8513 | return false; |
8514 | |
8515 | location_t exploc = location_of (*postfix_expression); |
8516 | cxx_incomplete_type_diagnostic (exploc, *postfix_expression, *scope, kind); |
8517 | if (!MAYBE_CLASS_TYPE_P (*scope)) |
8518 | return true; |
8519 | if (kind == DK_ERROR) |
8520 | *scope = *postfix_expression = error_mark_node; |
8521 | else if (processing_template_decl) |
8522 | { |
8523 | *dependent_p = true; |
8524 | *scope = TREE_TYPE (*postfix_expression) = NULL_TREE; |
8525 | } |
8526 | return false; |
8527 | } |
8528 | |
8529 | /* A subroutine of cp_parser_postfix_expression that also gets hijacked |
8530 | by cp_parser_builtin_offsetof. We're looking for |
8531 | |
8532 | postfix-expression . template [opt] id-expression |
8533 | postfix-expression . pseudo-destructor-name |
8534 | postfix-expression -> template [opt] id-expression |
8535 | postfix-expression -> pseudo-destructor-name |
8536 | |
8537 | FOR_OFFSETOF is set if we're being called in that context. That sorta |
8538 | limits what of the above we'll actually accept, but nevermind. |
8539 | TOKEN_TYPE is the "." or "->" token, which will already have been |
8540 | removed from the stream. */ |
8541 | |
8542 | static tree |
8543 | cp_parser_postfix_dot_deref_expression (cp_parser *parser, |
8544 | enum cpp_ttype token_type, |
8545 | cp_expr postfix_expression, |
8546 | bool for_offsetof, cp_id_kind *idk, |
8547 | location_t location) |
8548 | { |
8549 | tree name; |
8550 | bool dependent_p; |
8551 | bool pseudo_destructor_p; |
8552 | tree scope = NULL_TREE; |
8553 | location_t start_loc = postfix_expression.get_start (); |
8554 | |
8555 | /* If this is a `->' operator, dereference the pointer. */ |
8556 | if (token_type == CPP_DEREF) |
8557 | postfix_expression = build_x_arrow (location, postfix_expression, |
8558 | tf_warning_or_error); |
8559 | /* Check to see whether or not the expression is type-dependent and |
8560 | not the current instantiation. */ |
8561 | dependent_p = type_dependent_object_expression_p (postfix_expression); |
8562 | /* The identifier following the `->' or `.' is not qualified. */ |
8563 | parser->scope = NULL_TREE; |
8564 | parser->qualifying_scope = NULL_TREE; |
8565 | parser->object_scope = NULL_TREE; |
8566 | *idk = CP_ID_KIND_NONE; |
8567 | |
8568 | /* Enter the scope corresponding to the type of the object |
8569 | given by the POSTFIX_EXPRESSION. */ |
8570 | if (!dependent_p) |
8571 | { |
8572 | scope = TREE_TYPE (postfix_expression); |
8573 | /* According to the standard, no expression should ever have |
8574 | reference type. Unfortunately, we do not currently match |
8575 | the standard in this respect in that our internal representation |
8576 | of an expression may have reference type even when the standard |
8577 | says it does not. Therefore, we have to manually obtain the |
8578 | underlying type here. */ |
8579 | scope = non_reference (scope); |
8580 | /* The type of the POSTFIX_EXPRESSION must be complete. */ |
8581 | /* Unlike the object expression in other contexts, *this is not |
8582 | required to be of complete type for purposes of class member |
8583 | access (5.2.5) outside the member function body. */ |
8584 | if (postfix_expression != current_class_ref |
8585 | && scope != error_mark_node |
8586 | && !currently_open_class (scope)) |
8587 | { |
8588 | scope = complete_type (scope); |
8589 | if (!COMPLETE_TYPE_P (scope) |
8590 | && cp_parser_dot_deref_incomplete (scope: &scope, postfix_expression: &postfix_expression, |
8591 | dependent_p: &dependent_p)) |
8592 | return error_mark_node; |
8593 | } |
8594 | |
8595 | if (!dependent_p) |
8596 | { |
8597 | /* Let the name lookup machinery know that we are processing a |
8598 | class member access expression. */ |
8599 | parser->context->object_type = scope; |
8600 | /* If something went wrong, we want to be able to discern that case, |
8601 | as opposed to the case where there was no SCOPE due to the type |
8602 | of expression being dependent. */ |
8603 | if (!scope) |
8604 | scope = error_mark_node; |
8605 | /* If the SCOPE was erroneous, make the various semantic analysis |
8606 | functions exit quickly -- and without issuing additional error |
8607 | messages. */ |
8608 | if (scope == error_mark_node) |
8609 | postfix_expression = error_mark_node; |
8610 | } |
8611 | } |
8612 | |
8613 | if (dependent_p) |
8614 | { |
8615 | tree type = TREE_TYPE (postfix_expression); |
8616 | /* If we don't have a (type-dependent) object of class type, use |
8617 | typeof to figure out the type of the object. */ |
8618 | if (type == NULL_TREE || is_auto (type)) |
8619 | type = finish_typeof (postfix_expression); |
8620 | parser->context->object_type = type; |
8621 | } |
8622 | |
8623 | /* Assume this expression is not a pseudo-destructor access. */ |
8624 | pseudo_destructor_p = false; |
8625 | |
8626 | /* If the SCOPE is a scalar type, then, if this is a valid program, |
8627 | we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION |
8628 | is type dependent, it can be pseudo-destructor-name or something else. |
8629 | Try to parse it as pseudo-destructor-name first. */ |
8630 | if ((scope && SCALAR_TYPE_P (scope)) || dependent_p) |
8631 | { |
8632 | tree s; |
8633 | tree type; |
8634 | |
8635 | cp_parser_parse_tentatively (parser); |
8636 | /* Parse the pseudo-destructor-name. */ |
8637 | s = NULL_TREE; |
8638 | cp_parser_pseudo_destructor_name (parser, postfix_expression, |
8639 | &s, &type); |
8640 | if (dependent_p |
8641 | && (cp_parser_error_occurred (parser) |
8642 | || !SCALAR_TYPE_P (type))) |
8643 | cp_parser_abort_tentative_parse (parser); |
8644 | else if (cp_parser_parse_definitely (parser)) |
8645 | { |
8646 | pseudo_destructor_p = true; |
8647 | postfix_expression |
8648 | = finish_pseudo_destructor_expr (postfix_expression, |
8649 | s, type, location); |
8650 | } |
8651 | } |
8652 | |
8653 | if (!pseudo_destructor_p) |
8654 | { |
8655 | /* If the SCOPE is not a scalar type, we are looking at an |
8656 | ordinary class member access expression, rather than a |
8657 | pseudo-destructor-name. */ |
8658 | bool template_p; |
8659 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
8660 | /* Parse the id-expression. */ |
8661 | name = (cp_parser_id_expression |
8662 | (parser, |
8663 | template_keyword_p: cp_parser_optional_template_keyword (parser), |
8664 | /*check_dependency_p=*/true, |
8665 | template_p: &template_p, |
8666 | /*declarator_p=*/false, |
8667 | /*optional_p=*/false)); |
8668 | /* In general, build a SCOPE_REF if the member name is qualified. |
8669 | However, if the name was not dependent and has already been |
8670 | resolved; there is no need to build the SCOPE_REF. For example; |
8671 | |
8672 | struct X { void f(); }; |
8673 | template <typename T> void f(T* t) { t->X::f(); } |
8674 | |
8675 | Even though "t" is dependent, "X::f" is not and has been resolved |
8676 | to a BASELINK; there is no need to include scope information. */ |
8677 | |
8678 | /* But we do need to remember that there was an explicit scope for |
8679 | virtual function calls. */ |
8680 | if (parser->scope) |
8681 | *idk = CP_ID_KIND_QUALIFIED; |
8682 | |
8683 | /* If the name is a template-id that names a type, we will get a |
8684 | TYPE_DECL here. That is invalid code. */ |
8685 | if (TREE_CODE (name) == TYPE_DECL) |
8686 | { |
8687 | error_at (token->location, "invalid use of %qD" , name); |
8688 | postfix_expression = error_mark_node; |
8689 | } |
8690 | else |
8691 | { |
8692 | if (name != error_mark_node && !BASELINK_P (name) && parser->scope) |
8693 | { |
8694 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
8695 | { |
8696 | error_at (token->location, "%<%D::%D%> is not a class member" , |
8697 | parser->scope, name); |
8698 | postfix_expression = error_mark_node; |
8699 | } |
8700 | else |
8701 | name = build_qualified_name (/*type=*/NULL_TREE, |
8702 | parser->scope, |
8703 | name, |
8704 | template_p); |
8705 | parser->scope = NULL_TREE; |
8706 | parser->qualifying_scope = NULL_TREE; |
8707 | parser->object_scope = NULL_TREE; |
8708 | } |
8709 | if (parser->scope && name && BASELINK_P (name)) |
8710 | adjust_result_of_qualified_name_lookup |
8711 | (name, parser->scope, scope); |
8712 | postfix_expression |
8713 | = finish_class_member_access_expr (postfix_expression, name, |
8714 | template_p, |
8715 | tf_warning_or_error); |
8716 | /* Build a location e.g.: |
8717 | ptr->access_expr |
8718 | ~~~^~~~~~~~~~~~~ |
8719 | where the caret is at the deref token, ranging from |
8720 | the start of postfix_expression to the end of the access expr. */ |
8721 | location_t combined_loc |
8722 | = make_location (caret: input_location, start: start_loc, lexer: parser->lexer); |
8723 | protected_set_expr_location (postfix_expression, combined_loc); |
8724 | } |
8725 | } |
8726 | |
8727 | /* We no longer need to look up names in the scope of the object on |
8728 | the left-hand side of the `.' or `->' operator. */ |
8729 | parser->context->object_type = NULL_TREE; |
8730 | |
8731 | /* Outside of offsetof, these operators may not appear in |
8732 | constant-expressions. */ |
8733 | if (!for_offsetof |
8734 | && (cp_parser_non_integral_constant_expression |
8735 | (parser, thing: token_type == CPP_DEREF ? NIC_ARROW : NIC_POINT))) |
8736 | postfix_expression = error_mark_node; |
8737 | |
8738 | return postfix_expression; |
8739 | } |
8740 | |
8741 | /* Parse a parenthesized expression-list. |
8742 | |
8743 | expression-list: |
8744 | assignment-expression |
8745 | expression-list, assignment-expression |
8746 | |
8747 | attribute-list: |
8748 | expression-list |
8749 | identifier |
8750 | identifier, expression-list |
8751 | |
8752 | CAST_P is true if this expression is the target of a cast. |
8753 | |
8754 | ALLOW_EXPANSION_P is true if this expression allows expansion of an |
8755 | argument pack. |
8756 | |
8757 | WRAP_LOCATIONS_P is true if expressions within this list for which |
8758 | CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing |
8759 | their source locations. |
8760 | |
8761 | Returns a vector of trees. Each element is a representation of an |
8762 | assignment-expression. NULL is returned if the ( and or ) are |
8763 | missing. An empty, but allocated, vector is returned on no |
8764 | expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is id_attr |
8765 | if we are parsing an attribute list for an attribute that wants a |
8766 | plain identifier argument, normal_attr for an attribute that wants |
8767 | an expression, or non_attr if we aren't parsing an attribute list. If |
8768 | NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or |
8769 | not all of the expressions in the list were constant. |
8770 | If CLOSE_PAREN_LOC is non-NULL, and no errors occur, then *CLOSE_PAREN_LOC |
8771 | will be written to with the location of the closing parenthesis. If |
8772 | an error occurs, it may or may not be written to. */ |
8773 | |
8774 | static vec<tree, va_gc> * |
8775 | cp_parser_parenthesized_expression_list (cp_parser* parser, |
8776 | int is_attribute_list, |
8777 | bool cast_p, |
8778 | bool allow_expansion_p, |
8779 | bool *non_constant_p, |
8780 | location_t *close_paren_loc, |
8781 | bool wrap_locations_p) |
8782 | { |
8783 | vec<tree, va_gc> *expression_list; |
8784 | bool saved_greater_than_is_operator_p; |
8785 | bool saved_omp_array_section_p; |
8786 | |
8787 | /* Assume all the expressions will be constant. */ |
8788 | if (non_constant_p) |
8789 | *non_constant_p = false; |
8790 | |
8791 | matching_parens parens; |
8792 | if (!parens.require_open (parser)) |
8793 | return NULL; |
8794 | |
8795 | expression_list = make_tree_vector (); |
8796 | |
8797 | /* Within a parenthesized expression, a `>' token is always |
8798 | the greater-than operator. */ |
8799 | saved_greater_than_is_operator_p |
8800 | = parser->greater_than_is_operator_p; |
8801 | parser->greater_than_is_operator_p = true; |
8802 | |
8803 | saved_omp_array_section_p = parser->omp_array_section_p; |
8804 | parser->omp_array_section_p = false; |
8805 | |
8806 | cp_expr expr (NULL_TREE); |
8807 | |
8808 | /* Consume expressions until there are no more. */ |
8809 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
8810 | while (true) |
8811 | { |
8812 | /* At the beginning of attribute lists, check to see if the |
8813 | next token is an identifier. */ |
8814 | if (is_attribute_list == id_attr |
8815 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_NAME) |
8816 | expr = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
8817 | else if (is_attribute_list == assume_attr) |
8818 | expr = cp_parser_conditional_expression (parser); |
8819 | else if (is_attribute_list == uneval_string_attr) |
8820 | expr = cp_parser_unevaluated_string_literal (parser); |
8821 | else |
8822 | expr |
8823 | = cp_parser_parenthesized_expression_list_elt (parser, cast_p, |
8824 | allow_expansion_p, |
8825 | non_constant_p); |
8826 | |
8827 | if (wrap_locations_p) |
8828 | expr.maybe_add_location_wrapper (); |
8829 | |
8830 | /* Add it to the list. We add error_mark_node |
8831 | expressions to the list, so that we can still tell if |
8832 | the correct form for a parenthesized expression-list |
8833 | is found. That gives better errors. */ |
8834 | vec_safe_push (v&: expression_list, obj: expr.get_value ()); |
8835 | |
8836 | if (expr == error_mark_node) |
8837 | goto skip_comma; |
8838 | |
8839 | /* After the first item, attribute lists look the same as |
8840 | expression lists. */ |
8841 | is_attribute_list = non_attr; |
8842 | |
8843 | get_comma:; |
8844 | /* If the next token isn't a `,', then we are done. */ |
8845 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
8846 | break; |
8847 | |
8848 | /* Otherwise, consume the `,' and keep going. */ |
8849 | cp_lexer_consume_token (lexer: parser->lexer); |
8850 | } |
8851 | |
8852 | if (close_paren_loc) |
8853 | *close_paren_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
8854 | |
8855 | if (!parens.require_close (parser)) |
8856 | { |
8857 | int ending; |
8858 | |
8859 | skip_comma:; |
8860 | /* We try and resync to an unnested comma, as that will give the |
8861 | user better diagnostics. */ |
8862 | ending = cp_parser_skip_to_closing_parenthesis (parser, |
8863 | /*recovering=*/true, |
8864 | /*or_comma=*/true, |
8865 | /*consume_paren=*/true); |
8866 | if (ending < 0) |
8867 | goto get_comma; |
8868 | if (!ending) |
8869 | { |
8870 | parser->greater_than_is_operator_p |
8871 | = saved_greater_than_is_operator_p; |
8872 | parser->omp_array_section_p = saved_omp_array_section_p; |
8873 | return NULL; |
8874 | } |
8875 | } |
8876 | |
8877 | parser->greater_than_is_operator_p |
8878 | = saved_greater_than_is_operator_p; |
8879 | parser->omp_array_section_p = saved_omp_array_section_p; |
8880 | |
8881 | return expression_list; |
8882 | } |
8883 | |
8884 | /* Parse a pseudo-destructor-name. |
8885 | |
8886 | pseudo-destructor-name: |
8887 | :: [opt] nested-name-specifier [opt] type-name :: ~ type-name |
8888 | :: [opt] nested-name-specifier template template-id :: ~ type-name |
8889 | :: [opt] nested-name-specifier [opt] ~ type-name |
8890 | |
8891 | If either of the first two productions is used, sets *SCOPE to the |
8892 | TYPE specified before the final `::'. Otherwise, *SCOPE is set to |
8893 | NULL_TREE. *TYPE is set to the TYPE_DECL for the final type-name, |
8894 | or ERROR_MARK_NODE if the parse fails. */ |
8895 | |
8896 | static void |
8897 | cp_parser_pseudo_destructor_name (cp_parser* parser, |
8898 | tree object, |
8899 | tree* scope, |
8900 | tree* type) |
8901 | { |
8902 | bool nested_name_specifier_p; |
8903 | |
8904 | /* Handle ~auto. */ |
8905 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMPL) |
8906 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_AUTO) |
8907 | && !type_dependent_expression_p (object)) |
8908 | { |
8909 | if (cxx_dialect < cxx14) |
8910 | pedwarn (input_location, OPT_Wc__14_extensions, |
8911 | "%<~auto%> only available with " |
8912 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
8913 | cp_lexer_consume_token (lexer: parser->lexer); |
8914 | cp_lexer_consume_token (lexer: parser->lexer); |
8915 | *scope = NULL_TREE; |
8916 | *type = TREE_TYPE (object); |
8917 | return; |
8918 | } |
8919 | |
8920 | /* Assume that things will not work out. */ |
8921 | *type = error_mark_node; |
8922 | |
8923 | /* Look for the optional `::' operator. */ |
8924 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true); |
8925 | /* Look for the optional nested-name-specifier. */ |
8926 | nested_name_specifier_p |
8927 | = (cp_parser_nested_name_specifier_opt (parser, |
8928 | /*typename_keyword_p=*/false, |
8929 | /*check_dependency_p=*/true, |
8930 | /*type_p=*/false, |
8931 | /*is_declaration=*/false) |
8932 | != NULL_TREE); |
8933 | /* Now, if we saw a nested-name-specifier, we might be doing the |
8934 | second production. */ |
8935 | if (nested_name_specifier_p |
8936 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
8937 | { |
8938 | /* Consume the `template' keyword. */ |
8939 | cp_lexer_consume_token (lexer: parser->lexer); |
8940 | /* Parse the template-id. */ |
8941 | cp_parser_template_id (parser, |
8942 | /*template_keyword_p=*/true, |
8943 | /*check_dependency_p=*/false, |
8944 | class_type, |
8945 | /*is_declaration=*/true); |
8946 | /* Look for the `::' token. */ |
8947 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
8948 | } |
8949 | /* If the next token is not a `~', then there might be some |
8950 | additional qualification. */ |
8951 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMPL)) |
8952 | { |
8953 | /* At this point, we're looking for "type-name :: ~". The type-name |
8954 | must not be a class-name, since this is a pseudo-destructor. So, |
8955 | it must be either an enum-name, or a typedef-name -- both of which |
8956 | are just identifiers. So, we peek ahead to check that the "::" |
8957 | and "~" tokens are present; if they are not, then we can avoid |
8958 | calling type_name. */ |
8959 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_NAME |
8960 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE |
8961 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type != CPP_COMPL) |
8962 | { |
8963 | cp_parser_error (parser, gmsgid: "non-scalar type" ); |
8964 | return; |
8965 | } |
8966 | |
8967 | /* Look for the type-name. */ |
8968 | *scope = TREE_TYPE (cp_parser_nonclass_name (parser)); |
8969 | if (*scope == error_mark_node) |
8970 | return; |
8971 | |
8972 | /* Look for the `::' token. */ |
8973 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
8974 | } |
8975 | else |
8976 | *scope = NULL_TREE; |
8977 | |
8978 | /* Look for the `~'. */ |
8979 | cp_parser_require (parser, CPP_COMPL, RT_COMPL); |
8980 | |
8981 | /* Once we see the ~, this has to be a pseudo-destructor. */ |
8982 | if (!processing_template_decl && !cp_parser_error_occurred (parser)) |
8983 | cp_parser_commit_to_topmost_tentative_parse (parser); |
8984 | |
8985 | /* Look for the type-name again. We are not responsible for |
8986 | checking that it matches the first type-name. */ |
8987 | *type = TREE_TYPE (cp_parser_nonclass_name (parser)); |
8988 | } |
8989 | |
8990 | /* Parse a unary-expression. |
8991 | |
8992 | unary-expression: |
8993 | postfix-expression |
8994 | ++ cast-expression |
8995 | -- cast-expression |
8996 | await-expression |
8997 | unary-operator cast-expression |
8998 | sizeof unary-expression |
8999 | sizeof ( type-id ) |
9000 | alignof ( type-id ) [C++0x] |
9001 | new-expression |
9002 | delete-expression |
9003 | |
9004 | GNU Extensions: |
9005 | |
9006 | unary-expression: |
9007 | __extension__ cast-expression |
9008 | __alignof__ unary-expression |
9009 | __alignof__ ( type-id ) |
9010 | alignof unary-expression [C++0x] |
9011 | __real__ cast-expression |
9012 | __imag__ cast-expression |
9013 | && identifier |
9014 | sizeof ( type-id ) { initializer-list , [opt] } |
9015 | alignof ( type-id ) { initializer-list , [opt] } [C++0x] |
9016 | __alignof__ ( type-id ) { initializer-list , [opt] } |
9017 | |
9018 | ADDRESS_P is true iff the unary-expression is appearing as the |
9019 | operand of the `&' operator. CAST_P is true if this expression is |
9020 | the target of a cast. |
9021 | |
9022 | Returns a representation of the expression. */ |
9023 | |
9024 | static cp_expr |
9025 | cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, |
9026 | bool address_p, bool cast_p, bool decltype_p) |
9027 | { |
9028 | cp_token *token; |
9029 | enum tree_code unary_operator; |
9030 | |
9031 | /* Peek at the next token. */ |
9032 | token = cp_lexer_peek_token (lexer: parser->lexer); |
9033 | /* Some keywords give away the kind of expression. */ |
9034 | if (token->type == CPP_KEYWORD) |
9035 | { |
9036 | enum rid keyword = token->keyword; |
9037 | |
9038 | switch (keyword) |
9039 | { |
9040 | case RID_ALIGNOF: |
9041 | case RID_SIZEOF: |
9042 | { |
9043 | tree operand, ret; |
9044 | enum tree_code op; |
9045 | location_t start_loc = token->location; |
9046 | |
9047 | op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; |
9048 | bool std_alignof = id_equal (id: token->u.value, str: "alignof" ); |
9049 | |
9050 | /* Consume the token. */ |
9051 | cp_lexer_consume_token (lexer: parser->lexer); |
9052 | /* Parse the operand. */ |
9053 | operand = cp_parser_sizeof_operand (parser, keyword); |
9054 | |
9055 | /* Construct a location e.g. : |
9056 | alignof (expr) |
9057 | ^~~~~~~~~~~~~~ |
9058 | with start == caret at the start of the "alignof"/"sizeof" |
9059 | token, with the endpoint at the final closing paren. */ |
9060 | location_t compound_loc |
9061 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9062 | |
9063 | if (TYPE_P (operand)) |
9064 | ret = cxx_sizeof_or_alignof_type (compound_loc, operand, op, |
9065 | std_alignof, true); |
9066 | else |
9067 | { |
9068 | /* ISO C++ defines alignof only with types, not with |
9069 | expressions. So pedwarn if alignof is used with a non- |
9070 | type expression. However, __alignof__ is ok. */ |
9071 | if (std_alignof) |
9072 | pedwarn (token->location, OPT_Wpedantic, |
9073 | "ISO C++ does not allow %<alignof%> " |
9074 | "with a non-type" ); |
9075 | |
9076 | ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op, |
9077 | std_alignof, true); |
9078 | } |
9079 | /* For SIZEOF_EXPR, just issue diagnostics, but keep |
9080 | SIZEOF_EXPR with the original operand. */ |
9081 | if (op == SIZEOF_EXPR && ret != error_mark_node) |
9082 | { |
9083 | if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand)) |
9084 | { |
9085 | if (!processing_template_decl && TYPE_P (operand)) |
9086 | { |
9087 | ret = build_min (SIZEOF_EXPR, size_type_node, |
9088 | build1 (NOP_EXPR, operand, |
9089 | error_mark_node)); |
9090 | SIZEOF_EXPR_TYPE_P (ret) = 1; |
9091 | } |
9092 | else |
9093 | ret = build_min (SIZEOF_EXPR, size_type_node, operand); |
9094 | TREE_SIDE_EFFECTS (ret) = 0; |
9095 | TREE_READONLY (ret) = 1; |
9096 | SET_EXPR_LOCATION (ret, compound_loc); |
9097 | } |
9098 | } |
9099 | |
9100 | cp_expr ret_expr (ret, compound_loc); |
9101 | ret_expr = ret_expr.maybe_add_location_wrapper (); |
9102 | return ret_expr; |
9103 | } |
9104 | |
9105 | case RID_BUILTIN_HAS_ATTRIBUTE: |
9106 | return cp_parser_has_attribute_expression (parser); |
9107 | |
9108 | case RID_NEW: |
9109 | return cp_parser_new_expression (parser); |
9110 | |
9111 | case RID_DELETE: |
9112 | return cp_parser_delete_expression (parser); |
9113 | |
9114 | case RID_EXTENSION: |
9115 | { |
9116 | /* The saved value of the PEDANTIC flag. */ |
9117 | int saved_pedantic; |
9118 | tree expr; |
9119 | |
9120 | /* Save away the PEDANTIC flag. */ |
9121 | cp_parser_extension_opt (parser, &saved_pedantic); |
9122 | /* Parse the cast-expression. */ |
9123 | expr = cp_parser_simple_cast_expression (parser); |
9124 | /* Restore the PEDANTIC flag. */ |
9125 | pedantic = saved_pedantic; |
9126 | |
9127 | return expr; |
9128 | } |
9129 | |
9130 | case RID_REALPART: |
9131 | case RID_IMAGPART: |
9132 | { |
9133 | tree expression; |
9134 | |
9135 | /* Consume the `__real__' or `__imag__' token. */ |
9136 | cp_lexer_consume_token (lexer: parser->lexer); |
9137 | /* Parse the cast-expression. */ |
9138 | expression = cp_parser_simple_cast_expression (parser); |
9139 | /* Create the complete representation. */ |
9140 | return build_x_unary_op (token->location, |
9141 | (keyword == RID_REALPART |
9142 | ? REALPART_EXPR : IMAGPART_EXPR), |
9143 | expression, NULL_TREE, |
9144 | tf_warning_or_error); |
9145 | } |
9146 | break; |
9147 | |
9148 | case RID_TRANSACTION_ATOMIC: |
9149 | case RID_TRANSACTION_RELAXED: |
9150 | return cp_parser_transaction_expression (parser, keyword); |
9151 | |
9152 | case RID_NOEXCEPT: |
9153 | { |
9154 | tree expr; |
9155 | const char *saved_message; |
9156 | bool saved_integral_constant_expression_p; |
9157 | bool saved_non_integral_constant_expression_p; |
9158 | bool saved_greater_than_is_operator_p; |
9159 | |
9160 | location_t start_loc = token->location; |
9161 | |
9162 | cp_lexer_consume_token (lexer: parser->lexer); |
9163 | matching_parens parens; |
9164 | parens.require_open (parser); |
9165 | |
9166 | saved_message = parser->type_definition_forbidden_message; |
9167 | parser->type_definition_forbidden_message |
9168 | = G_("types may not be defined in %<noexcept%> expressions" ); |
9169 | |
9170 | saved_integral_constant_expression_p |
9171 | = parser->integral_constant_expression_p; |
9172 | saved_non_integral_constant_expression_p |
9173 | = parser->non_integral_constant_expression_p; |
9174 | parser->integral_constant_expression_p = false; |
9175 | |
9176 | saved_greater_than_is_operator_p |
9177 | = parser->greater_than_is_operator_p; |
9178 | parser->greater_than_is_operator_p = true; |
9179 | |
9180 | ++cp_unevaluated_operand; |
9181 | ++c_inhibit_evaluation_warnings; |
9182 | ++cp_noexcept_operand; |
9183 | expr = cp_parser_expression (parser); |
9184 | --cp_noexcept_operand; |
9185 | --c_inhibit_evaluation_warnings; |
9186 | --cp_unevaluated_operand; |
9187 | |
9188 | parser->greater_than_is_operator_p |
9189 | = saved_greater_than_is_operator_p; |
9190 | |
9191 | parser->integral_constant_expression_p |
9192 | = saved_integral_constant_expression_p; |
9193 | parser->non_integral_constant_expression_p |
9194 | = saved_non_integral_constant_expression_p; |
9195 | |
9196 | parser->type_definition_forbidden_message = saved_message; |
9197 | |
9198 | parens.require_close (parser); |
9199 | |
9200 | /* Construct a location of the form: |
9201 | noexcept (expr) |
9202 | ^~~~~~~~~~~~~~~ |
9203 | with start == caret, finishing at the close-paren. */ |
9204 | location_t noexcept_loc |
9205 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9206 | |
9207 | return cp_expr (finish_noexcept_expr (expr, tf_warning_or_error), |
9208 | noexcept_loc); |
9209 | } |
9210 | |
9211 | case RID_CO_AWAIT: |
9212 | { |
9213 | tree expr; |
9214 | location_t kw_loc = token->location; |
9215 | |
9216 | /* Consume the `co_await' token. */ |
9217 | cp_lexer_consume_token (lexer: parser->lexer); |
9218 | /* Parse its cast-expression. */ |
9219 | expr = cp_parser_simple_cast_expression (parser); |
9220 | if (expr == error_mark_node) |
9221 | return error_mark_node; |
9222 | |
9223 | /* Handle [expr.await]. */ |
9224 | return cp_expr (finish_co_await_expr (kw_loc, expr)); |
9225 | } |
9226 | |
9227 | default: |
9228 | break; |
9229 | } |
9230 | } |
9231 | |
9232 | /* Look for the `:: new' and `:: delete', which also signal the |
9233 | beginning of a new-expression, or delete-expression, |
9234 | respectively. If the next token is `::', then it might be one of |
9235 | these. */ |
9236 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
9237 | { |
9238 | enum rid keyword; |
9239 | |
9240 | /* See if the token after the `::' is one of the keywords in |
9241 | which we're interested. */ |
9242 | keyword = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->keyword; |
9243 | /* If it's `new', we have a new-expression. */ |
9244 | if (keyword == RID_NEW) |
9245 | return cp_parser_new_expression (parser); |
9246 | /* Similarly, for `delete'. */ |
9247 | else if (keyword == RID_DELETE) |
9248 | return cp_parser_delete_expression (parser); |
9249 | } |
9250 | |
9251 | /* Look for a unary operator. */ |
9252 | unary_operator = cp_parser_unary_operator (token); |
9253 | /* The `++' and `--' operators can be handled similarly, even though |
9254 | they are not technically unary-operators in the grammar. */ |
9255 | if (unary_operator == ERROR_MARK) |
9256 | { |
9257 | if (token->type == CPP_PLUS_PLUS) |
9258 | unary_operator = PREINCREMENT_EXPR; |
9259 | else if (token->type == CPP_MINUS_MINUS) |
9260 | unary_operator = PREDECREMENT_EXPR; |
9261 | /* Handle the GNU address-of-label extension. */ |
9262 | else if (cp_parser_allow_gnu_extensions_p (parser) |
9263 | && token->type == CPP_AND_AND) |
9264 | { |
9265 | tree identifier; |
9266 | tree expression; |
9267 | location_t start_loc = token->location; |
9268 | |
9269 | /* Consume the '&&' token. */ |
9270 | cp_lexer_consume_token (lexer: parser->lexer); |
9271 | /* Look for the identifier. */ |
9272 | identifier = cp_parser_identifier (parser); |
9273 | /* Construct a location of the form: |
9274 | &&label |
9275 | ^~~~~~~ |
9276 | with caret==start at the "&&", finish at the end of the label. */ |
9277 | location_t combined_loc |
9278 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9279 | /* Create an expression representing the address. */ |
9280 | expression = finish_label_address_expr (identifier, combined_loc); |
9281 | if (TREE_CODE (expression) == ADDR_EXPR) |
9282 | mark_label_addressed (identifier); |
9283 | if (cp_parser_non_integral_constant_expression (parser, |
9284 | thing: NIC_ADDR_LABEL)) |
9285 | expression = error_mark_node; |
9286 | return expression; |
9287 | } |
9288 | } |
9289 | if (unary_operator != ERROR_MARK) |
9290 | { |
9291 | cp_expr cast_expression; |
9292 | cp_expr expression = error_mark_node; |
9293 | non_integral_constant non_constant_p = NIC_NONE; |
9294 | location_t loc = token->location; |
9295 | tsubst_flags_t complain = complain_flags (decltype_p); |
9296 | |
9297 | /* Consume the operator token. */ |
9298 | token = cp_lexer_consume_token (lexer: parser->lexer); |
9299 | enum cpp_ttype op_ttype = cp_lexer_peek_token (lexer: parser->lexer)->type; |
9300 | |
9301 | /* Parse the cast-expression. */ |
9302 | cast_expression |
9303 | = cp_parser_cast_expression (parser, |
9304 | unary_operator == ADDR_EXPR, |
9305 | /*cast_p=*/false, |
9306 | /*decltype*/false, |
9307 | pidk); |
9308 | |
9309 | /* Make a location: |
9310 | OP_TOKEN CAST_EXPRESSION |
9311 | ^~~~~~~~~~~~~~~~~~~~~~~~~ |
9312 | with start==caret at the operator token, and |
9313 | extending to the end of the cast_expression. */ |
9314 | loc = make_location (caret: loc, start: loc, finish: cast_expression.get_finish ()); |
9315 | |
9316 | /* Now, build an appropriate representation. */ |
9317 | switch (unary_operator) |
9318 | { |
9319 | case INDIRECT_REF: |
9320 | non_constant_p = NIC_STAR; |
9321 | expression = build_x_indirect_ref (loc, cast_expression, |
9322 | RO_UNARY_STAR, NULL_TREE, |
9323 | complain); |
9324 | /* TODO: build_x_indirect_ref does not always honor the |
9325 | location, so ensure it is set. */ |
9326 | expression.set_location (loc); |
9327 | break; |
9328 | |
9329 | case ADDR_EXPR: |
9330 | non_constant_p = NIC_ADDR; |
9331 | /* Fall through. */ |
9332 | case BIT_NOT_EXPR: |
9333 | expression = build_x_unary_op (loc, unary_operator, |
9334 | cast_expression, |
9335 | NULL_TREE, complain); |
9336 | /* TODO: build_x_unary_op does not always honor the location, |
9337 | so ensure it is set. */ |
9338 | expression.set_location (loc); |
9339 | break; |
9340 | |
9341 | case PREINCREMENT_EXPR: |
9342 | case PREDECREMENT_EXPR: |
9343 | non_constant_p = unary_operator == PREINCREMENT_EXPR |
9344 | ? NIC_PREINCREMENT : NIC_PREDECREMENT; |
9345 | /* Fall through. */ |
9346 | case NEGATE_EXPR: |
9347 | /* Immediately fold negation of a constant, unless the constant is 0 |
9348 | (since -0 == 0) or it would overflow. */ |
9349 | if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER) |
9350 | { |
9351 | tree stripped_expr |
9352 | = tree_strip_any_location_wrapper (exp: cast_expression); |
9353 | if (CONSTANT_CLASS_P (stripped_expr) |
9354 | && !integer_zerop (stripped_expr) |
9355 | && !TREE_OVERFLOW (stripped_expr)) |
9356 | { |
9357 | tree folded = fold_build1 (unary_operator, |
9358 | TREE_TYPE (stripped_expr), |
9359 | stripped_expr); |
9360 | if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded)) |
9361 | { |
9362 | expression = maybe_wrap_with_location (folded, loc); |
9363 | break; |
9364 | } |
9365 | } |
9366 | } |
9367 | /* Fall through. */ |
9368 | case UNARY_PLUS_EXPR: |
9369 | case TRUTH_NOT_EXPR: |
9370 | expression = finish_unary_op_expr (loc, unary_operator, |
9371 | cast_expression, complain); |
9372 | break; |
9373 | |
9374 | default: |
9375 | gcc_unreachable (); |
9376 | } |
9377 | |
9378 | if (non_constant_p != NIC_NONE |
9379 | && cp_parser_non_integral_constant_expression (parser, |
9380 | thing: non_constant_p)) |
9381 | expression = error_mark_node; |
9382 | |
9383 | return expression; |
9384 | } |
9385 | |
9386 | return cp_parser_postfix_expression (parser, address_p, cast_p, |
9387 | /*member_access_only_p=*/false, |
9388 | decltype_p, |
9389 | pidk_return: pidk); |
9390 | } |
9391 | |
9392 | /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a |
9393 | unary-operator, the corresponding tree code is returned. */ |
9394 | |
9395 | static enum tree_code |
9396 | cp_parser_unary_operator (cp_token* token) |
9397 | { |
9398 | switch (token->type) |
9399 | { |
9400 | case CPP_MULT: |
9401 | return INDIRECT_REF; |
9402 | |
9403 | case CPP_AND: |
9404 | return ADDR_EXPR; |
9405 | |
9406 | case CPP_PLUS: |
9407 | return UNARY_PLUS_EXPR; |
9408 | |
9409 | case CPP_MINUS: |
9410 | return NEGATE_EXPR; |
9411 | |
9412 | case CPP_NOT: |
9413 | return TRUTH_NOT_EXPR; |
9414 | |
9415 | case CPP_COMPL: |
9416 | return BIT_NOT_EXPR; |
9417 | |
9418 | default: |
9419 | return ERROR_MARK; |
9420 | } |
9421 | } |
9422 | |
9423 | /* Parse a __builtin_has_attribute([expr|type], attribute-spec) expression. |
9424 | Returns a representation of the expression. */ |
9425 | |
9426 | static tree |
9427 | cp_parser_has_attribute_expression (cp_parser *parser) |
9428 | { |
9429 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9430 | |
9431 | /* Consume the __builtin_has_attribute token. */ |
9432 | cp_lexer_consume_token (lexer: parser->lexer); |
9433 | |
9434 | matching_parens parens; |
9435 | if (!parens.require_open (parser)) |
9436 | return error_mark_node; |
9437 | |
9438 | /* Types cannot be defined in a `sizeof' expression. Save away the |
9439 | old message. */ |
9440 | const char *saved_message = parser->type_definition_forbidden_message; |
9441 | const char *saved_message_arg |
9442 | = parser->type_definition_forbidden_message_arg; |
9443 | parser->type_definition_forbidden_message |
9444 | = G_("types may not be defined in %qs expressions" ); |
9445 | parser->type_definition_forbidden_message_arg |
9446 | = IDENTIFIER_POINTER (ridpointers[RID_BUILTIN_HAS_ATTRIBUTE]); |
9447 | |
9448 | /* The restrictions on constant-expressions do not apply inside |
9449 | sizeof expressions. */ |
9450 | bool saved_integral_constant_expression_p |
9451 | = parser->integral_constant_expression_p; |
9452 | bool saved_non_integral_constant_expression_p |
9453 | = parser->non_integral_constant_expression_p; |
9454 | parser->integral_constant_expression_p = false; |
9455 | |
9456 | /* Do not actually evaluate the expression. */ |
9457 | ++cp_unevaluated_operand; |
9458 | ++c_inhibit_evaluation_warnings; |
9459 | |
9460 | tree oper = NULL_TREE; |
9461 | |
9462 | /* We can't be sure yet whether we're looking at a type-id or an |
9463 | expression. */ |
9464 | cp_parser_parse_tentatively (parser); |
9465 | |
9466 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
9467 | parser->in_type_id_in_expr_p = true; |
9468 | /* Look for the type-id. */ |
9469 | oper = cp_parser_type_id (parser); |
9470 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
9471 | |
9472 | cp_parser_parse_definitely (parser); |
9473 | |
9474 | /* If the type-id production did not work out, then we must be |
9475 | looking at an expression. */ |
9476 | if (!oper || oper == error_mark_node) |
9477 | oper = cp_parser_assignment_expression (parser); |
9478 | |
9479 | STRIP_ANY_LOCATION_WRAPPER (oper); |
9480 | |
9481 | /* Go back to evaluating expressions. */ |
9482 | --cp_unevaluated_operand; |
9483 | --c_inhibit_evaluation_warnings; |
9484 | |
9485 | /* And restore the old one. */ |
9486 | parser->type_definition_forbidden_message = saved_message; |
9487 | parser->type_definition_forbidden_message_arg = saved_message_arg; |
9488 | parser->integral_constant_expression_p |
9489 | = saved_integral_constant_expression_p; |
9490 | parser->non_integral_constant_expression_p |
9491 | = saved_non_integral_constant_expression_p; |
9492 | |
9493 | /* Consume the comma if it's there. */ |
9494 | if (!cp_parser_require (parser, CPP_COMMA, RT_COMMA)) |
9495 | { |
9496 | cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
9497 | /*consume_paren=*/true); |
9498 | return error_mark_node; |
9499 | } |
9500 | |
9501 | /* Parse the attribute specification. */ |
9502 | bool ret = false; |
9503 | location_t atloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9504 | if (tree attr = cp_parser_gnu_attribute_list (parser, /*exactly_one=*/true)) |
9505 | { |
9506 | if (oper == error_mark_node) |
9507 | /* Nothing. */; |
9508 | else if (processing_template_decl && uses_template_parms (oper)) |
9509 | sorry_at (atloc, "%<__builtin_has_attribute%> with dependent argument " |
9510 | "not supported yet" ); |
9511 | else |
9512 | { |
9513 | /* Fold constant expressions used in attributes first. */ |
9514 | cp_check_const_attributes (attr); |
9515 | |
9516 | /* Finally, see if OPER has been declared with ATTR. */ |
9517 | ret = has_attribute (atloc, oper, attr, default_conversion); |
9518 | } |
9519 | |
9520 | parens.require_close (parser); |
9521 | } |
9522 | else |
9523 | { |
9524 | error_at (atloc, "expected identifier" ); |
9525 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
9526 | } |
9527 | |
9528 | /* Construct a location e.g. : |
9529 | __builtin_has_attribute (oper, attr) |
9530 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9531 | with start == caret at the start of the built-in token, |
9532 | and with the endpoint at the final closing paren. */ |
9533 | location_t compound_loc |
9534 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9535 | |
9536 | cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node); |
9537 | ret_expr.set_location (compound_loc); |
9538 | ret_expr = ret_expr.maybe_add_location_wrapper (); |
9539 | return ret_expr; |
9540 | } |
9541 | |
9542 | /* Parse a new-expression. |
9543 | |
9544 | new-expression: |
9545 | :: [opt] new new-placement [opt] new-type-id new-initializer [opt] |
9546 | :: [opt] new new-placement [opt] ( type-id ) new-initializer [opt] |
9547 | |
9548 | Returns a representation of the expression. */ |
9549 | |
9550 | static tree |
9551 | cp_parser_new_expression (cp_parser* parser) |
9552 | { |
9553 | bool global_scope_p; |
9554 | vec<tree, va_gc> *placement; |
9555 | tree type; |
9556 | vec<tree, va_gc> *initializer; |
9557 | tree nelts = NULL_TREE; |
9558 | tree ret; |
9559 | |
9560 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9561 | |
9562 | /* Look for the optional `::' operator. */ |
9563 | global_scope_p |
9564 | = (cp_parser_global_scope_opt (parser, |
9565 | /*current_scope_valid_p=*/false) |
9566 | != NULL_TREE); |
9567 | /* Look for the `new' operator. */ |
9568 | cp_parser_require_keyword (parser, RID_NEW, RT_NEW); |
9569 | /* There's no easy way to tell a new-placement from the |
9570 | `( type-id )' construct. */ |
9571 | cp_parser_parse_tentatively (parser); |
9572 | /* Look for a new-placement. */ |
9573 | placement = cp_parser_new_placement (parser); |
9574 | /* If that didn't work out, there's no new-placement. */ |
9575 | if (!cp_parser_parse_definitely (parser)) |
9576 | { |
9577 | if (placement != NULL) |
9578 | release_tree_vector (placement); |
9579 | placement = NULL; |
9580 | } |
9581 | |
9582 | /* If the next token is a `(', then we have a parenthesized |
9583 | type-id. */ |
9584 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
9585 | { |
9586 | cp_token *token; |
9587 | const char *saved_message = parser->type_definition_forbidden_message; |
9588 | |
9589 | /* Consume the `('. */ |
9590 | matching_parens parens; |
9591 | parens.consume_open (parser); |
9592 | |
9593 | /* Parse the type-id. */ |
9594 | parser->type_definition_forbidden_message |
9595 | = G_("types may not be defined in a new-expression" ); |
9596 | { |
9597 | type_id_in_expr_sentinel s (parser); |
9598 | type = cp_parser_type_id (parser); |
9599 | } |
9600 | parser->type_definition_forbidden_message = saved_message; |
9601 | |
9602 | /* Look for the closing `)'. */ |
9603 | parens.require_close (parser); |
9604 | token = cp_lexer_peek_token (lexer: parser->lexer); |
9605 | /* There should not be a direct-new-declarator in this production, |
9606 | but GCC used to allowed this, so we check and emit a sensible error |
9607 | message for this case. */ |
9608 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9609 | { |
9610 | error_at (token->location, |
9611 | "array bound forbidden after parenthesized type-id" ); |
9612 | inform (token->location, |
9613 | "try removing the parentheses around the type-id" ); |
9614 | cp_parser_direct_new_declarator (parser); |
9615 | } |
9616 | } |
9617 | /* Otherwise, there must be a new-type-id. */ |
9618 | else |
9619 | type = cp_parser_new_type_id (parser, &nelts); |
9620 | |
9621 | /* If the next token is a `(' or '{', then we have a new-initializer. */ |
9622 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
9623 | if (token->type == CPP_OPEN_PAREN |
9624 | || token->type == CPP_OPEN_BRACE) |
9625 | initializer = cp_parser_new_initializer (parser); |
9626 | else |
9627 | initializer = NULL; |
9628 | |
9629 | /* A new-expression may not appear in an integral constant |
9630 | expression. */ |
9631 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_NEW)) |
9632 | ret = error_mark_node; |
9633 | /* 5.3.4/2: "If the auto type-specifier appears in the type-specifier-seq |
9634 | of a new-type-id or type-id of a new-expression, the new-expression shall |
9635 | contain a new-initializer of the form ( assignment-expression )". |
9636 | Additionally, consistently with the spirit of DR 1467, we want to accept |
9637 | 'new auto { 2 }' too. */ |
9638 | else if ((ret = type_uses_auto (type)) |
9639 | && !CLASS_PLACEHOLDER_TEMPLATE (ret) |
9640 | && (vec_safe_length (v: initializer) != 1 |
9641 | || (BRACE_ENCLOSED_INITIALIZER_P ((*initializer)[0]) |
9642 | && CONSTRUCTOR_NELTS ((*initializer)[0]) != 1))) |
9643 | { |
9644 | error_at (token->location, |
9645 | "initialization of new-expression for type %<auto%> " |
9646 | "requires exactly one element" ); |
9647 | ret = error_mark_node; |
9648 | } |
9649 | else |
9650 | { |
9651 | /* Construct a location e.g.: |
9652 | ptr = new int[100] |
9653 | ^~~~~~~~~~~~ |
9654 | with caret == start at the start of the "new" token, and the end |
9655 | at the end of the final token we consumed. */ |
9656 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
9657 | lexer: parser->lexer); |
9658 | /* Create a representation of the new-expression. */ |
9659 | ret = build_new (combined_loc, &placement, type, nelts, &initializer, |
9660 | global_scope_p, tf_warning_or_error); |
9661 | } |
9662 | |
9663 | if (placement != NULL) |
9664 | release_tree_vector (placement); |
9665 | if (initializer != NULL) |
9666 | release_tree_vector (initializer); |
9667 | |
9668 | return ret; |
9669 | } |
9670 | |
9671 | /* Parse a new-placement. |
9672 | |
9673 | new-placement: |
9674 | ( expression-list ) |
9675 | |
9676 | Returns the same representation as for an expression-list. */ |
9677 | |
9678 | static vec<tree, va_gc> * |
9679 | cp_parser_new_placement (cp_parser* parser) |
9680 | { |
9681 | vec<tree, va_gc> *expression_list; |
9682 | |
9683 | /* Parse the expression-list. */ |
9684 | expression_list = (cp_parser_parenthesized_expression_list |
9685 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
9686 | /*allow_expansion_p=*/true, |
9687 | /*non_constant_p=*/NULL)); |
9688 | |
9689 | if (expression_list && expression_list->is_empty ()) |
9690 | error ("expected expression-list or type-id" ); |
9691 | |
9692 | return expression_list; |
9693 | } |
9694 | |
9695 | /* Parse a new-type-id. |
9696 | |
9697 | new-type-id: |
9698 | type-specifier-seq new-declarator [opt] |
9699 | |
9700 | Returns the TYPE allocated. If the new-type-id indicates an array |
9701 | type, *NELTS is set to the number of elements in the last array |
9702 | bound; the TYPE will not include the last array bound. */ |
9703 | |
9704 | static tree |
9705 | cp_parser_new_type_id (cp_parser* parser, tree *nelts) |
9706 | { |
9707 | cp_decl_specifier_seq type_specifier_seq; |
9708 | cp_declarator *new_declarator; |
9709 | cp_declarator *declarator; |
9710 | cp_declarator *outer_declarator; |
9711 | const char *saved_message; |
9712 | |
9713 | /* The type-specifier sequence must not contain type definitions. |
9714 | (It cannot contain declarations of new types either, but if they |
9715 | are not definitions we will catch that because they are not |
9716 | complete.) */ |
9717 | saved_message = parser->type_definition_forbidden_message; |
9718 | parser->type_definition_forbidden_message |
9719 | = G_("types may not be defined in a new-type-id" ); |
9720 | /* Parse the type-specifier-seq. */ |
9721 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
9722 | /*is_declaration=*/false, |
9723 | /*is_trailing_return=*/false, |
9724 | &type_specifier_seq); |
9725 | /* Restore the old message. */ |
9726 | parser->type_definition_forbidden_message = saved_message; |
9727 | |
9728 | if (type_specifier_seq.type == error_mark_node) |
9729 | return error_mark_node; |
9730 | |
9731 | /* Parse the new-declarator. */ |
9732 | new_declarator = cp_parser_new_declarator_opt (parser); |
9733 | |
9734 | /* Determine the number of elements in the last array dimension, if |
9735 | any. */ |
9736 | *nelts = NULL_TREE; |
9737 | /* Skip down to the last array dimension. */ |
9738 | declarator = new_declarator; |
9739 | outer_declarator = NULL; |
9740 | while (declarator && (declarator->kind == cdk_pointer |
9741 | || declarator->kind == cdk_ptrmem)) |
9742 | { |
9743 | outer_declarator = declarator; |
9744 | declarator = declarator->declarator; |
9745 | } |
9746 | while (declarator |
9747 | && declarator->kind == cdk_array |
9748 | && declarator->declarator |
9749 | && declarator->declarator->kind == cdk_array) |
9750 | { |
9751 | outer_declarator = declarator; |
9752 | declarator = declarator->declarator; |
9753 | } |
9754 | |
9755 | if (declarator && declarator->kind == cdk_array) |
9756 | { |
9757 | *nelts = declarator->u.array.bounds; |
9758 | if (*nelts == error_mark_node) |
9759 | *nelts = integer_one_node; |
9760 | |
9761 | if (*nelts == NULL_TREE) |
9762 | /* Leave [] in the declarator. */; |
9763 | else if (outer_declarator) |
9764 | outer_declarator->declarator = declarator->declarator; |
9765 | else |
9766 | new_declarator = NULL; |
9767 | } |
9768 | |
9769 | return groktypename (&type_specifier_seq, new_declarator, false); |
9770 | } |
9771 | |
9772 | /* Parse an (optional) new-declarator. |
9773 | |
9774 | new-declarator: |
9775 | ptr-operator new-declarator [opt] |
9776 | direct-new-declarator |
9777 | |
9778 | Returns the declarator. */ |
9779 | |
9780 | static cp_declarator * |
9781 | cp_parser_new_declarator_opt (cp_parser* parser) |
9782 | { |
9783 | enum tree_code code; |
9784 | tree type, std_attributes = NULL_TREE; |
9785 | cp_cv_quals cv_quals; |
9786 | |
9787 | /* We don't know if there's a ptr-operator next, or not. */ |
9788 | cp_parser_parse_tentatively (parser); |
9789 | /* Look for a ptr-operator. */ |
9790 | code = cp_parser_ptr_operator (parser, &type, &cv_quals, &std_attributes); |
9791 | /* If that worked, look for more new-declarators. */ |
9792 | if (cp_parser_parse_definitely (parser)) |
9793 | { |
9794 | cp_declarator *declarator; |
9795 | |
9796 | /* Parse another optional declarator. */ |
9797 | declarator = cp_parser_new_declarator_opt (parser); |
9798 | |
9799 | declarator = cp_parser_make_indirect_declarator |
9800 | (code, class_type: type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
9801 | |
9802 | return declarator; |
9803 | } |
9804 | |
9805 | /* If the next token is a `[', there is a direct-new-declarator. */ |
9806 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9807 | return cp_parser_direct_new_declarator (parser); |
9808 | |
9809 | return NULL; |
9810 | } |
9811 | |
9812 | /* Parse a direct-new-declarator. |
9813 | |
9814 | direct-new-declarator: |
9815 | [ expression ] |
9816 | direct-new-declarator [constant-expression] |
9817 | |
9818 | */ |
9819 | |
9820 | static cp_declarator * |
9821 | cp_parser_direct_new_declarator (cp_parser* parser) |
9822 | { |
9823 | cp_declarator *declarator = NULL; |
9824 | bool first_p = true; |
9825 | |
9826 | while (true) |
9827 | { |
9828 | tree expression; |
9829 | cp_token *token; |
9830 | |
9831 | /* Look for the opening `['. */ |
9832 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
9833 | |
9834 | token = cp_lexer_peek_token (lexer: parser->lexer); |
9835 | if (token->type == CPP_CLOSE_SQUARE && first_p) |
9836 | expression = NULL_TREE; |
9837 | else |
9838 | expression = cp_parser_expression (parser); |
9839 | /* The standard requires that the expression have integral |
9840 | type. DR 74 adds enumeration types. We believe that the |
9841 | real intent is that these expressions be handled like the |
9842 | expression in a `switch' condition, which also allows |
9843 | classes with a single conversion to integral or |
9844 | enumeration type. */ |
9845 | if (expression && !processing_template_decl) |
9846 | { |
9847 | expression |
9848 | = build_expr_type_conversion (WANT_INT | WANT_ENUM, |
9849 | expression, |
9850 | /*complain=*/true); |
9851 | if (!expression) |
9852 | { |
9853 | error_at (token->location, |
9854 | "expression in new-declarator must have integral " |
9855 | "or enumeration type" ); |
9856 | expression = error_mark_node; |
9857 | } |
9858 | } |
9859 | |
9860 | /* Look for the closing `]'. */ |
9861 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
9862 | |
9863 | /* Add this bound to the declarator. */ |
9864 | declarator = make_array_declarator (element: declarator, bounds: expression); |
9865 | |
9866 | /* If the next token is not a `[', then there are no more |
9867 | bounds. */ |
9868 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9869 | break; |
9870 | first_p = false; |
9871 | } |
9872 | |
9873 | return declarator; |
9874 | } |
9875 | |
9876 | /* Parse a new-initializer. |
9877 | |
9878 | new-initializer: |
9879 | ( expression-list [opt] ) |
9880 | braced-init-list |
9881 | |
9882 | Returns a representation of the expression-list. */ |
9883 | |
9884 | static vec<tree, va_gc> * |
9885 | cp_parser_new_initializer (cp_parser* parser) |
9886 | { |
9887 | vec<tree, va_gc> *expression_list; |
9888 | |
9889 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
9890 | { |
9891 | cp_lexer_set_source_position (lexer: parser->lexer); |
9892 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
9893 | tree t = cp_parser_braced_list (parser); |
9894 | CONSTRUCTOR_IS_DIRECT_INIT (t) = true; |
9895 | expression_list = make_tree_vector_single (t); |
9896 | } |
9897 | else |
9898 | expression_list = (cp_parser_parenthesized_expression_list |
9899 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
9900 | /*allow_expansion_p=*/true, |
9901 | /*non_constant_p=*/NULL)); |
9902 | |
9903 | return expression_list; |
9904 | } |
9905 | |
9906 | /* Parse a delete-expression. |
9907 | |
9908 | delete-expression: |
9909 | :: [opt] delete cast-expression |
9910 | :: [opt] delete [ ] cast-expression |
9911 | |
9912 | Returns a representation of the expression. */ |
9913 | |
9914 | static tree |
9915 | cp_parser_delete_expression (cp_parser* parser) |
9916 | { |
9917 | bool global_scope_p; |
9918 | bool array_p; |
9919 | tree expression; |
9920 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9921 | |
9922 | /* Look for the optional `::' operator. */ |
9923 | global_scope_p |
9924 | = (cp_parser_global_scope_opt (parser, |
9925 | /*current_scope_valid_p=*/false) |
9926 | != NULL_TREE); |
9927 | /* Look for the `delete' keyword. */ |
9928 | cp_parser_require_keyword (parser, RID_DELETE, RT_DELETE); |
9929 | /* See if the array syntax is in use. */ |
9930 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9931 | { |
9932 | /* Consume the `[' token. */ |
9933 | cp_lexer_consume_token (lexer: parser->lexer); |
9934 | /* Look for the `]' token. */ |
9935 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
9936 | /* Remember that this is the `[]' construct. */ |
9937 | array_p = true; |
9938 | } |
9939 | else |
9940 | array_p = false; |
9941 | |
9942 | /* Parse the cast-expression. */ |
9943 | expression = cp_parser_simple_cast_expression (parser); |
9944 | |
9945 | /* A delete-expression may not appear in an integral constant |
9946 | expression. */ |
9947 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_DEL)) |
9948 | return error_mark_node; |
9949 | |
9950 | /* Construct a location e.g.: |
9951 | delete [ ] ptr |
9952 | ^~~~~~~~~~~~~~ |
9953 | with caret == start at the start of the "delete" token, and |
9954 | the end at the end of the final token we consumed. */ |
9955 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
9956 | lexer: parser->lexer); |
9957 | expression = delete_sanity (combined_loc, expression, NULL_TREE, array_p, |
9958 | global_scope_p, tf_warning_or_error); |
9959 | |
9960 | return expression; |
9961 | } |
9962 | |
9963 | /* Returns 1 if TOKEN may start a cast-expression and isn't '++', '--', |
9964 | neither '[' in C++11; -1 if TOKEN is '++', '--', or '[' in C++11; |
9965 | 0 otherwise. */ |
9966 | |
9967 | static int |
9968 | cp_parser_tokens_start_cast_expression (cp_parser *parser) |
9969 | { |
9970 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
9971 | switch (token->type) |
9972 | { |
9973 | case CPP_COMMA: |
9974 | case CPP_SEMICOLON: |
9975 | case CPP_QUERY: |
9976 | case CPP_COLON: |
9977 | case CPP_CLOSE_SQUARE: |
9978 | case CPP_CLOSE_PAREN: |
9979 | case CPP_CLOSE_BRACE: |
9980 | case CPP_OPEN_BRACE: |
9981 | case CPP_DOT: |
9982 | case CPP_DOT_STAR: |
9983 | case CPP_DEREF: |
9984 | case CPP_DEREF_STAR: |
9985 | case CPP_DIV: |
9986 | case CPP_MOD: |
9987 | case CPP_LSHIFT: |
9988 | case CPP_RSHIFT: |
9989 | case CPP_LESS: |
9990 | case CPP_GREATER: |
9991 | case CPP_LESS_EQ: |
9992 | case CPP_GREATER_EQ: |
9993 | case CPP_EQ_EQ: |
9994 | case CPP_NOT_EQ: |
9995 | case CPP_EQ: |
9996 | case CPP_MULT_EQ: |
9997 | case CPP_DIV_EQ: |
9998 | case CPP_MOD_EQ: |
9999 | case CPP_PLUS_EQ: |
10000 | case CPP_MINUS_EQ: |
10001 | case CPP_RSHIFT_EQ: |
10002 | case CPP_LSHIFT_EQ: |
10003 | case CPP_AND_EQ: |
10004 | case CPP_XOR_EQ: |
10005 | case CPP_OR_EQ: |
10006 | case CPP_XOR: |
10007 | case CPP_OR: |
10008 | case CPP_OR_OR: |
10009 | case CPP_EOF: |
10010 | case CPP_ELLIPSIS: |
10011 | return 0; |
10012 | |
10013 | case CPP_OPEN_PAREN: |
10014 | /* In ((type ()) () the last () isn't a valid cast-expression, |
10015 | so the whole must be parsed as postfix-expression. */ |
10016 | return cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
10017 | != CPP_CLOSE_PAREN; |
10018 | |
10019 | case CPP_OPEN_SQUARE: |
10020 | /* '[' may start a primary-expression in obj-c++ and in C++11, |
10021 | as a lambda-expression, eg, '(void)[]{}'. */ |
10022 | if (cxx_dialect >= cxx11) |
10023 | return -1; |
10024 | return c_dialect_objc (); |
10025 | |
10026 | case CPP_PLUS_PLUS: |
10027 | case CPP_MINUS_MINUS: |
10028 | /* '++' and '--' may or may not start a cast-expression: |
10029 | |
10030 | struct T { void operator++(int); }; |
10031 | void f() { (T())++; } |
10032 | |
10033 | vs |
10034 | |
10035 | int a; |
10036 | (int)++a; */ |
10037 | return -1; |
10038 | |
10039 | default: |
10040 | return 1; |
10041 | } |
10042 | } |
10043 | |
10044 | /* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them |
10045 | in the order: const_cast, static_cast, reinterpret_cast. |
10046 | |
10047 | Don't suggest dynamic_cast. |
10048 | |
10049 | Return the first legal cast kind found, or NULL otherwise. */ |
10050 | |
10051 | static const char * |
10052 | get_cast_suggestion (tree dst_type, tree orig_expr) |
10053 | { |
10054 | tree trial; |
10055 | |
10056 | /* Reuse the parser logic by attempting to build the various kinds of |
10057 | cast, with "complain" disabled. |
10058 | Identify the first such cast that is valid. */ |
10059 | |
10060 | /* Don't attempt to run such logic within template processing. */ |
10061 | if (processing_template_decl) |
10062 | return NULL; |
10063 | |
10064 | /* First try const_cast. */ |
10065 | trial = build_const_cast (input_location, dst_type, orig_expr, tf_none); |
10066 | if (trial != error_mark_node) |
10067 | return "const_cast" ; |
10068 | |
10069 | /* If that fails, try static_cast. */ |
10070 | trial = build_static_cast (input_location, dst_type, orig_expr, tf_none); |
10071 | if (trial != error_mark_node) |
10072 | return "static_cast" ; |
10073 | |
10074 | /* Finally, try reinterpret_cast. */ |
10075 | trial = build_reinterpret_cast (input_location, dst_type, orig_expr, |
10076 | tf_none); |
10077 | if (trial != error_mark_node) |
10078 | return "reinterpret_cast" ; |
10079 | |
10080 | /* No such cast possible. */ |
10081 | return NULL; |
10082 | } |
10083 | |
10084 | /* If -Wold-style-cast is enabled, add fix-its to RICHLOC, |
10085 | suggesting how to convert a C-style cast of the form: |
10086 | |
10087 | (DST_TYPE)ORIG_EXPR |
10088 | |
10089 | to a C++-style cast. |
10090 | |
10091 | The primary range of RICHLOC is asssumed to be that of the original |
10092 | expression. OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations |
10093 | of the parens in the C-style cast. */ |
10094 | |
10095 | static void |
10096 | maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc, |
10097 | location_t close_paren_loc, tree orig_expr, |
10098 | tree dst_type) |
10099 | { |
10100 | /* This function is non-trivial, so bail out now if the warning isn't |
10101 | going to be emitted. */ |
10102 | if (!warn_old_style_cast) |
10103 | return; |
10104 | |
10105 | /* Try to find a legal C++ cast, trying them in order: |
10106 | const_cast, static_cast, reinterpret_cast. */ |
10107 | const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr); |
10108 | if (!cast_suggestion) |
10109 | return; |
10110 | |
10111 | /* Replace the open paren with "CAST_SUGGESTION<". */ |
10112 | pretty_printer pp; |
10113 | pp_string (&pp, cast_suggestion); |
10114 | pp_less (&pp); |
10115 | rich_loc->add_fixit_replace (where: open_paren_loc, new_content: pp_formatted_text (&pp)); |
10116 | |
10117 | /* Replace the close paren with "> (". */ |
10118 | rich_loc->add_fixit_replace (where: close_paren_loc, new_content: "> (" ); |
10119 | |
10120 | /* Add a closing paren after the expr (the primary range of RICH_LOC). */ |
10121 | rich_loc->add_fixit_insert_after (new_content: ")" ); |
10122 | } |
10123 | |
10124 | |
10125 | /* Parse a cast-expression. |
10126 | |
10127 | cast-expression: |
10128 | unary-expression |
10129 | ( type-id ) cast-expression |
10130 | |
10131 | ADDRESS_P is true iff the unary-expression is appearing as the |
10132 | operand of the `&' operator. CAST_P is true if this expression is |
10133 | the target of a cast. |
10134 | |
10135 | Returns a representation of the expression. */ |
10136 | |
10137 | static cp_expr |
10138 | cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, |
10139 | bool decltype_p, cp_id_kind * pidk) |
10140 | { |
10141 | /* If it's a `(', then we might be looking at a cast. */ |
10142 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
10143 | { |
10144 | tree type = NULL_TREE; |
10145 | cp_expr expr (NULL_TREE); |
10146 | int cast_expression = 0; |
10147 | const char *saved_message; |
10148 | |
10149 | /* There's no way to know yet whether or not this is a cast. |
10150 | For example, `(int (3))' is a unary-expression, while `(int) |
10151 | 3' is a cast. So, we resort to parsing tentatively. */ |
10152 | cp_parser_parse_tentatively (parser); |
10153 | /* Types may not be defined in a cast. */ |
10154 | saved_message = parser->type_definition_forbidden_message; |
10155 | parser->type_definition_forbidden_message |
10156 | = G_("types may not be defined in casts" ); |
10157 | /* Consume the `('. */ |
10158 | matching_parens parens; |
10159 | cp_token *open_paren = parens.consume_open (parser); |
10160 | location_t open_paren_loc = open_paren->location; |
10161 | location_t close_paren_loc = UNKNOWN_LOCATION; |
10162 | |
10163 | /* A very tricky bit is that `(struct S) { 3 }' is a |
10164 | compound-literal (which we permit in C++ as an extension). |
10165 | But, that construct is not a cast-expression -- it is a |
10166 | postfix-expression. (The reason is that `(struct S) { 3 }.i' |
10167 | is legal; if the compound-literal were a cast-expression, |
10168 | you'd need an extra set of parentheses.) But, if we parse |
10169 | the type-id, and it happens to be a class-specifier, then we |
10170 | will commit to the parse at that point, because we cannot |
10171 | undo the action that is done when creating a new class. So, |
10172 | then we cannot back up and do a postfix-expression. |
10173 | |
10174 | Another tricky case is the following (c++/29234): |
10175 | |
10176 | struct S { void operator () (); }; |
10177 | |
10178 | void foo () |
10179 | { |
10180 | ( S()() ); |
10181 | } |
10182 | |
10183 | As a type-id we parse the parenthesized S()() as a function |
10184 | returning a function, groktypename complains and we cannot |
10185 | back up in this case either. |
10186 | |
10187 | Therefore, we scan ahead to the closing `)', and check to see |
10188 | if the tokens after the `)' can start a cast-expression. Otherwise |
10189 | we are dealing with an unary-expression, a postfix-expression |
10190 | or something else. |
10191 | |
10192 | Yet another tricky case, in C++11, is the following (c++/54891): |
10193 | |
10194 | (void)[]{}; |
10195 | |
10196 | The issue is that usually, besides the case of lambda-expressions, |
10197 | the parenthesized type-id cannot be followed by '[', and, eg, we |
10198 | want to parse '(C ())[2];' in parse/pr26997.C as unary-expression. |
10199 | Thus, if cp_parser_tokens_start_cast_expression returns -1, below |
10200 | we don't commit, we try a cast-expression, then an unary-expression. |
10201 | |
10202 | Save tokens so that we can put them back. */ |
10203 | cp_lexer_save_tokens (lexer: parser->lexer); |
10204 | |
10205 | /* We may be looking at a cast-expression. */ |
10206 | if (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
10207 | /*consume_paren=*/true)) |
10208 | cast_expression |
10209 | = cp_parser_tokens_start_cast_expression (parser); |
10210 | |
10211 | /* Roll back the tokens we skipped. */ |
10212 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
10213 | /* If we aren't looking at a cast-expression, simulate an error so |
10214 | that the call to cp_parser_error_occurred below returns true. */ |
10215 | if (!cast_expression) |
10216 | cp_parser_simulate_error (parser); |
10217 | else |
10218 | { |
10219 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
10220 | parser->in_type_id_in_expr_p = true; |
10221 | /* Look for the type-id. */ |
10222 | type = cp_parser_type_id (parser); |
10223 | /* Look for the closing `)'. */ |
10224 | cp_token *close_paren = parens.require_close (parser); |
10225 | if (close_paren) |
10226 | close_paren_loc = close_paren->location; |
10227 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
10228 | } |
10229 | |
10230 | /* Restore the saved message. */ |
10231 | parser->type_definition_forbidden_message = saved_message; |
10232 | |
10233 | /* At this point this can only be either a cast or a |
10234 | parenthesized ctor such as `(T ())' that looks like a cast to |
10235 | function returning T. */ |
10236 | if (!cp_parser_error_occurred (parser)) |
10237 | { |
10238 | /* Only commit if the cast-expression doesn't start with |
10239 | '++', '--', or '[' in C++11. */ |
10240 | if (cast_expression > 0) |
10241 | cp_parser_commit_to_topmost_tentative_parse (parser); |
10242 | |
10243 | expr = cp_parser_cast_expression (parser, |
10244 | /*address_p=*/false, |
10245 | /*cast_p=*/true, |
10246 | /*decltype_p=*/false, |
10247 | pidk); |
10248 | |
10249 | if (cp_parser_parse_definitely (parser)) |
10250 | { |
10251 | /* Warn about old-style casts, if so requested. */ |
10252 | if (warn_old_style_cast |
10253 | && !in_system_header_at (loc: input_location) |
10254 | && !VOID_TYPE_P (type) |
10255 | && current_lang_name != lang_name_c) |
10256 | { |
10257 | gcc_rich_location rich_loc (input_location); |
10258 | maybe_add_cast_fixit (rich_loc: &rich_loc, open_paren_loc, close_paren_loc, |
10259 | orig_expr: expr, dst_type: type); |
10260 | warning_at (&rich_loc, OPT_Wold_style_cast, |
10261 | "use of old-style cast to %q#T" , type); |
10262 | } |
10263 | |
10264 | /* Only type conversions to integral or enumeration types |
10265 | can be used in constant-expressions. */ |
10266 | if (!cast_valid_in_integral_constant_expression_p (type) |
10267 | && cp_parser_non_integral_constant_expression (parser, |
10268 | thing: NIC_CAST)) |
10269 | return error_mark_node; |
10270 | |
10271 | /* Perform the cast. */ |
10272 | /* Make a location: |
10273 | (TYPE) EXPR |
10274 | ^~~~~~~~~~~ |
10275 | with start==caret at the open paren, extending to the |
10276 | end of "expr". */ |
10277 | location_t cast_loc = make_location (caret: open_paren_loc, |
10278 | start: open_paren_loc, |
10279 | finish: expr.get_finish ()); |
10280 | expr = build_c_cast (loc: cast_loc, type, expr); |
10281 | return expr; |
10282 | } |
10283 | } |
10284 | else |
10285 | cp_parser_abort_tentative_parse (parser); |
10286 | } |
10287 | |
10288 | /* If we get here, then it's not a cast, so it must be a |
10289 | unary-expression. */ |
10290 | return cp_parser_unary_expression (parser, pidk, address_p, |
10291 | cast_p, decltype_p); |
10292 | } |
10293 | |
10294 | /* Parse a binary expression of the general form: |
10295 | |
10296 | pm-expression: |
10297 | cast-expression |
10298 | pm-expression .* cast-expression |
10299 | pm-expression ->* cast-expression |
10300 | |
10301 | multiplicative-expression: |
10302 | pm-expression |
10303 | multiplicative-expression * pm-expression |
10304 | multiplicative-expression / pm-expression |
10305 | multiplicative-expression % pm-expression |
10306 | |
10307 | additive-expression: |
10308 | multiplicative-expression |
10309 | additive-expression + multiplicative-expression |
10310 | additive-expression - multiplicative-expression |
10311 | |
10312 | shift-expression: |
10313 | additive-expression |
10314 | shift-expression << additive-expression |
10315 | shift-expression >> additive-expression |
10316 | |
10317 | relational-expression: |
10318 | shift-expression |
10319 | relational-expression < shift-expression |
10320 | relational-expression > shift-expression |
10321 | relational-expression <= shift-expression |
10322 | relational-expression >= shift-expression |
10323 | |
10324 | GNU Extension: |
10325 | |
10326 | relational-expression: |
10327 | relational-expression <? shift-expression |
10328 | relational-expression >? shift-expression |
10329 | |
10330 | equality-expression: |
10331 | relational-expression |
10332 | equality-expression == relational-expression |
10333 | equality-expression != relational-expression |
10334 | |
10335 | and-expression: |
10336 | equality-expression |
10337 | and-expression & equality-expression |
10338 | |
10339 | exclusive-or-expression: |
10340 | and-expression |
10341 | exclusive-or-expression ^ and-expression |
10342 | |
10343 | inclusive-or-expression: |
10344 | exclusive-or-expression |
10345 | inclusive-or-expression | exclusive-or-expression |
10346 | |
10347 | logical-and-expression: |
10348 | inclusive-or-expression |
10349 | logical-and-expression && inclusive-or-expression |
10350 | |
10351 | logical-or-expression: |
10352 | logical-and-expression |
10353 | logical-or-expression || logical-and-expression |
10354 | |
10355 | All these are implemented with a single function like: |
10356 | |
10357 | binary-expression: |
10358 | simple-cast-expression |
10359 | binary-expression <token> binary-expression |
10360 | |
10361 | CAST_P is true if this expression is the target of a cast. |
10362 | |
10363 | The binops_by_token map is used to get the tree codes for each <token> type. |
10364 | binary-expressions are associated according to a precedence table. */ |
10365 | |
10366 | #define TOKEN_PRECEDENCE(token) \ |
10367 | (((token->type == CPP_GREATER \ |
10368 | || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)) \ |
10369 | && !parser->greater_than_is_operator_p) \ |
10370 | ? PREC_NOT_OPERATOR \ |
10371 | : binops_by_token[token->type].prec) |
10372 | |
10373 | static cp_expr |
10374 | cp_parser_binary_expression (cp_parser* parser, bool cast_p, |
10375 | bool no_toplevel_fold_p, |
10376 | bool decltype_p, |
10377 | enum cp_parser_prec prec, |
10378 | cp_id_kind * pidk) |
10379 | { |
10380 | cp_parser_expression_stack stack; |
10381 | cp_parser_expression_stack_entry *sp = &stack[0]; |
10382 | cp_parser_expression_stack_entry *disable_warnings_sp = NULL; |
10383 | cp_parser_expression_stack_entry current; |
10384 | cp_expr rhs; |
10385 | cp_token *token; |
10386 | enum tree_code rhs_type; |
10387 | enum cp_parser_prec new_prec, lookahead_prec; |
10388 | tree overload; |
10389 | |
10390 | /* Parse the first expression. */ |
10391 | current.lhs_type = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
10392 | ? TRUTH_NOT_EXPR : ERROR_MARK); |
10393 | current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false, |
10394 | cast_p, decltype_p, pidk); |
10395 | current.prec = prec; |
10396 | |
10397 | if (cp_parser_error_occurred (parser)) |
10398 | return error_mark_node; |
10399 | |
10400 | for (;;) |
10401 | { |
10402 | /* Get an operator token. */ |
10403 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10404 | |
10405 | if (warn_cxx11_compat |
10406 | && token->type == CPP_RSHIFT |
10407 | && !parser->greater_than_is_operator_p) |
10408 | { |
10409 | if (warning_at (token->location, OPT_Wc__11_compat, |
10410 | "%<>>%> operator is treated" |
10411 | " as two right angle brackets in C++11" )) |
10412 | inform (token->location, |
10413 | "suggest parentheses around %<>>%> expression" ); |
10414 | } |
10415 | |
10416 | new_prec = TOKEN_PRECEDENCE (token); |
10417 | if (new_prec != PREC_NOT_OPERATOR |
10418 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10419 | /* This is a fold-expression; handle it later. */ |
10420 | new_prec = PREC_NOT_OPERATOR; |
10421 | |
10422 | /* Popping an entry off the stack means we completed a subexpression: |
10423 | - either we found a token which is not an operator (`>' where it is not |
10424 | an operator, or prec == PREC_NOT_OPERATOR), in which case popping |
10425 | will happen repeatedly; |
10426 | - or, we found an operator which has lower priority. This is the case |
10427 | where the recursive descent *ascends*, as in `3 * 4 + 5' after |
10428 | parsing `3 * 4'. */ |
10429 | if (new_prec <= current.prec) |
10430 | { |
10431 | if (sp == stack) |
10432 | break; |
10433 | else |
10434 | goto pop; |
10435 | } |
10436 | |
10437 | get_rhs: |
10438 | current.tree_type = binops_by_token[token->type].tree_type; |
10439 | current.loc = token->location; |
10440 | current.flags = token->flags; |
10441 | |
10442 | /* We used the operator token. */ |
10443 | cp_lexer_consume_token (lexer: parser->lexer); |
10444 | |
10445 | /* For "false && x" or "true || x", x will never be executed; |
10446 | disable warnings while evaluating it. */ |
10447 | if ((current.tree_type == TRUTH_ANDIF_EXPR |
10448 | && cp_fully_fold (current.lhs) == truthvalue_false_node) |
10449 | || (current.tree_type == TRUTH_ORIF_EXPR |
10450 | && cp_fully_fold (current.lhs) == truthvalue_true_node)) |
10451 | { |
10452 | disable_warnings_sp = sp; |
10453 | ++c_inhibit_evaluation_warnings; |
10454 | } |
10455 | |
10456 | /* Extract another operand. It may be the RHS of this expression |
10457 | or the LHS of a new, higher priority expression. */ |
10458 | rhs_type = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
10459 | ? TRUTH_NOT_EXPR : ERROR_MARK); |
10460 | rhs = cp_parser_simple_cast_expression (parser); |
10461 | |
10462 | /* Get another operator token. Look up its precedence to avoid |
10463 | building a useless (immediately popped) stack entry for common |
10464 | cases such as 3 + 4 + 5 or 3 * 4 + 5. */ |
10465 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10466 | lookahead_prec = TOKEN_PRECEDENCE (token); |
10467 | if (lookahead_prec != PREC_NOT_OPERATOR |
10468 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10469 | lookahead_prec = PREC_NOT_OPERATOR; |
10470 | if (lookahead_prec > new_prec) |
10471 | { |
10472 | /* ... and prepare to parse the RHS of the new, higher priority |
10473 | expression. Since precedence levels on the stack are |
10474 | monotonically increasing, we do not have to care about |
10475 | stack overflows. */ |
10476 | *sp = current; |
10477 | ++sp; |
10478 | current.lhs = rhs; |
10479 | current.lhs_type = rhs_type; |
10480 | current.prec = new_prec; |
10481 | new_prec = lookahead_prec; |
10482 | goto get_rhs; |
10483 | |
10484 | pop: |
10485 | lookahead_prec = new_prec; |
10486 | /* If the stack is not empty, we have parsed into LHS the right side |
10487 | (`4' in the example above) of an expression we had suspended. |
10488 | We can use the information on the stack to recover the LHS (`3') |
10489 | from the stack together with the tree code (`MULT_EXPR'), and |
10490 | the precedence of the higher level subexpression |
10491 | (`PREC_ADDITIVE_EXPRESSION'). TOKEN is the CPP_PLUS token, |
10492 | which will be used to actually build the additive expression. */ |
10493 | rhs = current.lhs; |
10494 | rhs_type = current.lhs_type; |
10495 | --sp; |
10496 | current = *sp; |
10497 | } |
10498 | |
10499 | /* Undo the disabling of warnings done above. */ |
10500 | if (sp == disable_warnings_sp) |
10501 | { |
10502 | disable_warnings_sp = NULL; |
10503 | --c_inhibit_evaluation_warnings; |
10504 | } |
10505 | |
10506 | if (warn_logical_not_paren |
10507 | && TREE_CODE_CLASS (current.tree_type) == tcc_comparison |
10508 | && current.lhs_type == TRUTH_NOT_EXPR |
10509 | /* Avoid warning for !!x == y. */ |
10510 | && (TREE_CODE (current.lhs) != NE_EXPR |
10511 | || !integer_zerop (TREE_OPERAND (current.lhs, 1))) |
10512 | && (TREE_CODE (current.lhs) != TRUTH_NOT_EXPR |
10513 | || (TREE_CODE (TREE_OPERAND (current.lhs, 0)) != TRUTH_NOT_EXPR |
10514 | /* Avoid warning for !b == y where b is boolean. */ |
10515 | && (TREE_TYPE (TREE_OPERAND (current.lhs, 0)) == NULL_TREE |
10516 | || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0))) |
10517 | != BOOLEAN_TYPE)))) |
10518 | /* Avoid warning for !!b == y where b is boolean. */ |
10519 | && (!(DECL_P (tree_strip_any_location_wrapper (current.lhs)) |
10520 | || (TREE_CODE (current.lhs) == NON_LVALUE_EXPR |
10521 | && DECL_P (tree_strip_any_location_wrapper |
10522 | (TREE_OPERAND (current.lhs, 0))))) |
10523 | || TREE_TYPE (current.lhs) == NULL_TREE |
10524 | || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE)) |
10525 | warn_logical_not_parentheses (current.loc, current.tree_type, |
10526 | current.lhs, maybe_constant_value (rhs)); |
10527 | |
10528 | if (warn_xor_used_as_pow |
10529 | && current.tree_type == BIT_XOR_EXPR |
10530 | /* Don't warn for named "xor" (as opposed to '^'). */ |
10531 | && !(current.flags & NAMED_OP) |
10532 | && current.lhs.decimal_p () |
10533 | && rhs.decimal_p ()) |
10534 | check_for_xor_used_as_pow |
10535 | (lhs_loc: current.lhs.get_location (), |
10536 | lhs_val: tree_strip_any_location_wrapper (exp: current.lhs), |
10537 | operator_loc: current.loc, |
10538 | rhs_loc: rhs.get_location (), |
10539 | rhs_val: tree_strip_any_location_wrapper (exp: rhs)); |
10540 | |
10541 | overload = NULL; |
10542 | |
10543 | location_t combined_loc = make_location (caret: current.loc, |
10544 | start: current.lhs.get_start (), |
10545 | finish: rhs.get_finish ()); |
10546 | |
10547 | /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type == |
10548 | ERROR_MARK for everything that is not a binary expression. |
10549 | This makes warn_about_parentheses miss some warnings that |
10550 | involve unary operators. For unary expressions we should |
10551 | pass the correct tree_code unless the unary expression was |
10552 | surrounded by parentheses. |
10553 | */ |
10554 | if (no_toplevel_fold_p |
10555 | && lookahead_prec <= current.prec |
10556 | && sp == stack) |
10557 | { |
10558 | if (current.lhs == error_mark_node || rhs == error_mark_node) |
10559 | current.lhs = error_mark_node; |
10560 | else |
10561 | { |
10562 | current.lhs.maybe_add_location_wrapper (); |
10563 | rhs.maybe_add_location_wrapper (); |
10564 | current.lhs |
10565 | = build_min (current.tree_type, |
10566 | TREE_CODE_CLASS (current.tree_type) |
10567 | == tcc_comparison |
10568 | ? boolean_type_node : TREE_TYPE (current.lhs), |
10569 | current.lhs.get_value (), rhs.get_value ()); |
10570 | SET_EXPR_LOCATION (current.lhs, combined_loc); |
10571 | } |
10572 | } |
10573 | else |
10574 | { |
10575 | op_location_t op_loc (current.loc, combined_loc); |
10576 | current.lhs = build_x_binary_op (op_loc, current.tree_type, |
10577 | current.lhs, current.lhs_type, |
10578 | rhs, rhs_type, NULL_TREE, &overload, |
10579 | complain_flags (decltype_p)); |
10580 | /* TODO: build_x_binary_op doesn't always honor the location. */ |
10581 | current.lhs.set_location (combined_loc); |
10582 | } |
10583 | current.lhs_type = current.tree_type; |
10584 | |
10585 | /* If the binary operator required the use of an overloaded operator, |
10586 | then this expression cannot be an integral constant-expression. |
10587 | An overloaded operator can be used even if both operands are |
10588 | otherwise permissible in an integral constant-expression if at |
10589 | least one of the operands is of enumeration type. */ |
10590 | |
10591 | if (overload |
10592 | && cp_parser_non_integral_constant_expression (parser, |
10593 | thing: NIC_OVERLOADED)) |
10594 | return error_mark_node; |
10595 | } |
10596 | |
10597 | return current.lhs; |
10598 | } |
10599 | |
10600 | static cp_expr |
10601 | cp_parser_binary_expression (cp_parser* parser, bool cast_p, |
10602 | bool no_toplevel_fold_p, |
10603 | enum cp_parser_prec prec, |
10604 | cp_id_kind * pidk) |
10605 | { |
10606 | return cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p, |
10607 | /*decltype*/decltype_p: false, prec, pidk); |
10608 | } |
10609 | |
10610 | /* Parse the `? expression : assignment-expression' part of a |
10611 | conditional-expression. The LOGICAL_OR_EXPR is the |
10612 | logical-or-expression that started the conditional-expression. |
10613 | Returns a representation of the entire conditional-expression. |
10614 | |
10615 | This routine is used by cp_parser_assignment_expression |
10616 | and cp_parser_conditional_expression. |
10617 | |
10618 | ? expression : assignment-expression |
10619 | |
10620 | GNU Extensions: |
10621 | |
10622 | ? : assignment-expression */ |
10623 | |
10624 | static tree |
10625 | cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr) |
10626 | { |
10627 | tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr); |
10628 | cp_expr assignment_expr; |
10629 | struct cp_token *token; |
10630 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10631 | |
10632 | /* Consume the `?' token. */ |
10633 | cp_lexer_consume_token (lexer: parser->lexer); |
10634 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10635 | if (cp_parser_allow_gnu_extensions_p (parser) |
10636 | && token->type == CPP_COLON) |
10637 | { |
10638 | pedwarn (token->location, OPT_Wpedantic, |
10639 | "ISO C++ does not allow %<?:%> with omitted middle operand" ); |
10640 | /* Implicit true clause. */ |
10641 | expr = NULL_TREE; |
10642 | c_inhibit_evaluation_warnings += |
10643 | folded_logical_or_expr == truthvalue_true_node; |
10644 | warn_for_omitted_condop (token->location, logical_or_expr); |
10645 | } |
10646 | else |
10647 | { |
10648 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
10649 | parser->colon_corrects_to_scope_p = false; |
10650 | /* Parse the expression. */ |
10651 | c_inhibit_evaluation_warnings += |
10652 | folded_logical_or_expr == truthvalue_false_node; |
10653 | expr = cp_parser_expression (parser); |
10654 | c_inhibit_evaluation_warnings += |
10655 | ((folded_logical_or_expr == truthvalue_true_node) |
10656 | - (folded_logical_or_expr == truthvalue_false_node)); |
10657 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
10658 | } |
10659 | |
10660 | /* The next token should be a `:'. */ |
10661 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
10662 | /* Parse the assignment-expression. */ |
10663 | assignment_expr = cp_parser_assignment_expression (parser); |
10664 | c_inhibit_evaluation_warnings -= |
10665 | folded_logical_or_expr == truthvalue_true_node; |
10666 | |
10667 | /* Make a location: |
10668 | LOGICAL_OR_EXPR ? EXPR : ASSIGNMENT_EXPR |
10669 | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ |
10670 | with the caret at the "?", ranging from the start of |
10671 | the logical_or_expr to the end of the assignment_expr. */ |
10672 | loc = make_location (caret: loc, |
10673 | start: logical_or_expr.get_start (), |
10674 | finish: assignment_expr.get_finish ()); |
10675 | |
10676 | /* Build the conditional-expression. */ |
10677 | return build_x_conditional_expr (loc, logical_or_expr, |
10678 | expr, |
10679 | assignment_expr, |
10680 | tf_warning_or_error); |
10681 | } |
10682 | |
10683 | /* Parse a conditional-expression. |
10684 | |
10685 | conditional-expression: |
10686 | logical-or-expression |
10687 | logical-or-expression ? expression : assignment-expression |
10688 | |
10689 | GNU Extensions: |
10690 | |
10691 | logical-or-expression ? : assignment-expression */ |
10692 | |
10693 | static cp_expr |
10694 | cp_parser_conditional_expression (cp_parser *parser) |
10695 | { |
10696 | cp_expr expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, decltype_p: false, |
10697 | prec: PREC_NOT_OPERATOR, NULL); |
10698 | /* If the next token is a `?' then we're actually looking at |
10699 | a conditional-expression; otherwise we're done. */ |
10700 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
10701 | return cp_parser_question_colon_clause (parser, logical_or_expr: expr); |
10702 | return expr; |
10703 | } |
10704 | |
10705 | /* Parse an assignment-expression. |
10706 | |
10707 | assignment-expression: |
10708 | conditional-expression |
10709 | logical-or-expression assignment-operator assignment_expression |
10710 | throw-expression |
10711 | yield-expression |
10712 | |
10713 | CAST_P is true if this expression is the target of a cast. |
10714 | DECLTYPE_P is true if this expression is the operand of decltype. |
10715 | |
10716 | Returns a representation for the expression. */ |
10717 | |
10718 | static cp_expr |
10719 | cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk, |
10720 | bool cast_p, bool decltype_p) |
10721 | { |
10722 | cp_expr expr; |
10723 | |
10724 | /* If the next token is the `throw' keyword, then we're looking at |
10725 | a throw-expression. */ |
10726 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_THROW)) |
10727 | expr = cp_parser_throw_expression (parser); |
10728 | /* If the next token is the `co_yield' keyword, then we're looking at |
10729 | a yield-expression. */ |
10730 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CO_YIELD)) |
10731 | expr = cp_parser_yield_expression (parser); |
10732 | /* Otherwise, it must be that we are looking at a |
10733 | logical-or-expression. */ |
10734 | else |
10735 | { |
10736 | /* Parse the binary expressions (logical-or-expression). */ |
10737 | expr = cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p: false, |
10738 | decltype_p, |
10739 | prec: PREC_NOT_OPERATOR, pidk); |
10740 | /* If the next token is a `?' then we're actually looking at a |
10741 | conditional-expression. */ |
10742 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
10743 | return cp_parser_question_colon_clause (parser, logical_or_expr: expr); |
10744 | else |
10745 | { |
10746 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10747 | |
10748 | /* If it's an assignment-operator, we're using the second |
10749 | production. */ |
10750 | enum tree_code assignment_operator |
10751 | = cp_parser_assignment_operator_opt (parser); |
10752 | if (assignment_operator != ERROR_MARK) |
10753 | { |
10754 | /* Parse the right-hand side of the assignment. */ |
10755 | cp_expr rhs = cp_parser_initializer_clause (parser); |
10756 | |
10757 | if (BRACE_ENCLOSED_INITIALIZER_P (rhs)) |
10758 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
10759 | |
10760 | /* An assignment may not appear in a |
10761 | constant-expression. */ |
10762 | if (cp_parser_non_integral_constant_expression (parser, |
10763 | thing: NIC_ASSIGNMENT)) |
10764 | return error_mark_node; |
10765 | /* Build the assignment expression. Its default |
10766 | location: |
10767 | LHS = RHS |
10768 | ~~~~^~~~~ |
10769 | is the location of the '=' token as the |
10770 | caret, ranging from the start of the lhs to the |
10771 | end of the rhs. */ |
10772 | loc = make_location (caret: loc, |
10773 | start: expr.get_start (), |
10774 | finish: rhs.get_finish ()); |
10775 | expr = build_x_modify_expr (loc, expr, |
10776 | assignment_operator, |
10777 | rhs, NULL_TREE, |
10778 | complain_flags (decltype_p)); |
10779 | /* TODO: build_x_modify_expr doesn't honor the location, |
10780 | so we must set it here. */ |
10781 | expr.set_location (loc); |
10782 | } |
10783 | } |
10784 | } |
10785 | |
10786 | return expr; |
10787 | } |
10788 | |
10789 | /* Parse an (optional) assignment-operator. |
10790 | |
10791 | assignment-operator: one of |
10792 | = *= /= %= += -= >>= <<= &= ^= |= |
10793 | |
10794 | GNU Extension: |
10795 | |
10796 | assignment-operator: one of |
10797 | <?= >?= |
10798 | |
10799 | If the next token is an assignment operator, the corresponding tree |
10800 | code is returned, and the token is consumed. For example, for |
10801 | `+=', PLUS_EXPR is returned. For `=' itself, the code returned is |
10802 | NOP_EXPR. For `/', TRUNC_DIV_EXPR is returned; for `%', |
10803 | TRUNC_MOD_EXPR is returned. If TOKEN is not an assignment |
10804 | operator, ERROR_MARK is returned. */ |
10805 | |
10806 | static enum tree_code |
10807 | cp_parser_assignment_operator_opt (cp_parser* parser) |
10808 | { |
10809 | enum tree_code op; |
10810 | cp_token *token; |
10811 | |
10812 | /* Peek at the next token. */ |
10813 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10814 | |
10815 | switch (token->type) |
10816 | { |
10817 | case CPP_EQ: |
10818 | op = NOP_EXPR; |
10819 | break; |
10820 | |
10821 | case CPP_MULT_EQ: |
10822 | op = MULT_EXPR; |
10823 | break; |
10824 | |
10825 | case CPP_DIV_EQ: |
10826 | op = TRUNC_DIV_EXPR; |
10827 | break; |
10828 | |
10829 | case CPP_MOD_EQ: |
10830 | op = TRUNC_MOD_EXPR; |
10831 | break; |
10832 | |
10833 | case CPP_PLUS_EQ: |
10834 | op = PLUS_EXPR; |
10835 | break; |
10836 | |
10837 | case CPP_MINUS_EQ: |
10838 | op = MINUS_EXPR; |
10839 | break; |
10840 | |
10841 | case CPP_RSHIFT_EQ: |
10842 | op = RSHIFT_EXPR; |
10843 | break; |
10844 | |
10845 | case CPP_LSHIFT_EQ: |
10846 | op = LSHIFT_EXPR; |
10847 | break; |
10848 | |
10849 | case CPP_AND_EQ: |
10850 | op = BIT_AND_EXPR; |
10851 | break; |
10852 | |
10853 | case CPP_XOR_EQ: |
10854 | op = BIT_XOR_EXPR; |
10855 | break; |
10856 | |
10857 | case CPP_OR_EQ: |
10858 | op = BIT_IOR_EXPR; |
10859 | break; |
10860 | |
10861 | default: |
10862 | /* Nothing else is an assignment operator. */ |
10863 | op = ERROR_MARK; |
10864 | } |
10865 | |
10866 | /* An operator followed by ... is a fold-expression, handled elsewhere. */ |
10867 | if (op != ERROR_MARK |
10868 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10869 | op = ERROR_MARK; |
10870 | |
10871 | /* If it was an assignment operator, consume it. */ |
10872 | if (op != ERROR_MARK) |
10873 | cp_lexer_consume_token (lexer: parser->lexer); |
10874 | |
10875 | return op; |
10876 | } |
10877 | |
10878 | /* Parse an expression. |
10879 | |
10880 | expression: |
10881 | assignment-expression |
10882 | expression , assignment-expression |
10883 | |
10884 | CAST_P is true if this expression is the target of a cast. |
10885 | DECLTYPE_P is true if this expression is the immediate operand of decltype, |
10886 | except possibly parenthesized or on the RHS of a comma (N3276). |
10887 | WARN_COMMA_P is true if a comma should be diagnosed. |
10888 | |
10889 | Returns a representation of the expression. */ |
10890 | |
10891 | static cp_expr |
10892 | cp_parser_expression (cp_parser* parser, cp_id_kind * pidk, |
10893 | bool cast_p, bool decltype_p, bool warn_comma_p) |
10894 | { |
10895 | cp_expr expression = NULL_TREE; |
10896 | location_t loc = UNKNOWN_LOCATION; |
10897 | |
10898 | while (true) |
10899 | { |
10900 | cp_expr assignment_expression; |
10901 | |
10902 | /* Parse the next assignment-expression. */ |
10903 | assignment_expression |
10904 | = cp_parser_assignment_expression (parser, pidk, cast_p, decltype_p); |
10905 | |
10906 | /* We don't create a temporary for a call that is the immediate operand |
10907 | of decltype or on the RHS of a comma. But when we see a comma, we |
10908 | need to create a temporary for a call on the LHS. */ |
10909 | if (decltype_p && !processing_template_decl |
10910 | && TREE_CODE (assignment_expression) == CALL_EXPR |
10911 | && CLASS_TYPE_P (TREE_TYPE (assignment_expression)) |
10912 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
10913 | assignment_expression |
10914 | = build_cplus_new (TREE_TYPE (assignment_expression), |
10915 | assignment_expression, tf_warning_or_error); |
10916 | |
10917 | /* If this is the first assignment-expression, we can just |
10918 | save it away. */ |
10919 | if (!expression) |
10920 | expression = assignment_expression; |
10921 | else |
10922 | { |
10923 | /* Create a location with caret at the comma, ranging |
10924 | from the start of the LHS to the end of the RHS. */ |
10925 | loc = make_location (caret: loc, |
10926 | start: expression.get_start (), |
10927 | finish: assignment_expression.get_finish ()); |
10928 | expression = build_x_compound_expr (loc, expression, |
10929 | assignment_expression, NULL_TREE, |
10930 | complain_flags (decltype_p)); |
10931 | expression.set_location (loc); |
10932 | } |
10933 | /* If the next token is not a comma, or we're in a fold-expression, then |
10934 | we are done with the expression. */ |
10935 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
10936 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10937 | break; |
10938 | /* Consume the `,'. */ |
10939 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10940 | if (warn_comma_p) |
10941 | { |
10942 | /* [depr.comma.subscript]: A comma expression appearing as |
10943 | the expr-or-braced-init-list of a subscripting expression |
10944 | is deprecated. A parenthesized comma expression is not |
10945 | deprecated. */ |
10946 | warning_at (loc, OPT_Wcomma_subscript, |
10947 | "top-level comma expression in array subscript " |
10948 | "is deprecated" ); |
10949 | warn_comma_p = false; |
10950 | } |
10951 | cp_lexer_consume_token (lexer: parser->lexer); |
10952 | /* A comma operator cannot appear in a constant-expression. */ |
10953 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_COMMA)) |
10954 | expression = error_mark_node; |
10955 | } |
10956 | |
10957 | return expression; |
10958 | } |
10959 | |
10960 | /* Parse a constant-expression. |
10961 | |
10962 | constant-expression: |
10963 | conditional-expression |
10964 | |
10965 | If ALLOW_NON_CONSTANT_P a non-constant expression is silently |
10966 | accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not |
10967 | constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P |
10968 | is false, NON_CONSTANT_P should be NULL. If ALLOW_NON_CONSTANT_P is |
10969 | greater than 1, this isn't really a constant-expression, only a |
10970 | potentially constant-evaluated expression. If STRICT_P is true, |
10971 | only parse a conditional-expression, otherwise parse an |
10972 | assignment-expression. See below for rationale. */ |
10973 | |
10974 | static cp_expr |
10975 | cp_parser_constant_expression (cp_parser* parser, |
10976 | int allow_non_constant_p /* = 0 */, |
10977 | bool *non_constant_p /* = NULL */, |
10978 | bool strict_p /* = false */) |
10979 | { |
10980 | /* It might seem that we could simply parse the |
10981 | conditional-expression, and then check to see if it were |
10982 | TREE_CONSTANT. However, an expression that is TREE_CONSTANT is |
10983 | one that the compiler can figure out is constant, possibly after |
10984 | doing some simplifications or optimizations. The standard has a |
10985 | precise definition of constant-expression, and we must honor |
10986 | that, even though it is somewhat more restrictive. |
10987 | |
10988 | For example: |
10989 | |
10990 | int i[(2, 3)]; |
10991 | |
10992 | is not a legal declaration, because `(2, 3)' is not a |
10993 | constant-expression. The `,' operator is forbidden in a |
10994 | constant-expression. However, GCC's constant-folding machinery |
10995 | will fold this operation to an INTEGER_CST for `3'. */ |
10996 | |
10997 | /* Save the old settings. */ |
10998 | bool saved_integral_constant_expression_p |
10999 | = parser->integral_constant_expression_p; |
11000 | bool saved_allow_non_integral_constant_expression_p |
11001 | = parser->allow_non_integral_constant_expression_p; |
11002 | bool saved_non_integral_constant_expression_p |
11003 | = parser->non_integral_constant_expression_p; |
11004 | /* We are now parsing a constant-expression. */ |
11005 | parser->integral_constant_expression_p = true; |
11006 | parser->allow_non_integral_constant_expression_p |
11007 | = (allow_non_constant_p || cxx_dialect >= cxx11); |
11008 | parser->non_integral_constant_expression_p = false; |
11009 | |
11010 | /* A manifestly constant-evaluated expression is evaluated even in an |
11011 | unevaluated operand. */ |
11012 | cp_evaluated ev (/*reset if*/allow_non_constant_p <= 1); |
11013 | |
11014 | /* Although the grammar says "conditional-expression", when not STRICT_P, |
11015 | we parse an "assignment-expression", which also permits |
11016 | "throw-expression" and the use of assignment operators. In the case |
11017 | that ALLOW_NON_CONSTANT_P is false, we get better errors than we would |
11018 | otherwise. In the case that ALLOW_NON_CONSTANT_P is true, it is |
11019 | actually essential that we look for an assignment-expression. |
11020 | For example, cp_parser_initializer_clauses uses this function to |
11021 | determine whether a particular assignment-expression is in fact |
11022 | constant. */ |
11023 | cp_expr expression; |
11024 | if (strict_p) |
11025 | expression = cp_parser_conditional_expression (parser); |
11026 | else |
11027 | expression = cp_parser_assignment_expression (parser); |
11028 | /* Restore the old settings. */ |
11029 | parser->integral_constant_expression_p |
11030 | = saved_integral_constant_expression_p; |
11031 | parser->allow_non_integral_constant_expression_p |
11032 | = saved_allow_non_integral_constant_expression_p; |
11033 | if (cxx_dialect >= cxx11 |
11034 | && (!allow_non_constant_p || non_constant_p)) |
11035 | { |
11036 | /* Require an rvalue constant expression here; that's what our |
11037 | callers expect. Reference constant expressions are handled |
11038 | separately in e.g. cp_parser_template_argument. */ |
11039 | tree decay = expression; |
11040 | if (TREE_TYPE (expression) |
11041 | && TREE_CODE (TREE_TYPE (expression)) == ARRAY_TYPE) |
11042 | decay = build_address (expression); |
11043 | bool is_const = is_rvalue_constant_expression (decay); |
11044 | parser->non_integral_constant_expression_p = !is_const; |
11045 | if (!is_const && !allow_non_constant_p) |
11046 | require_rvalue_constant_expression (decay); |
11047 | } |
11048 | if (allow_non_constant_p && non_constant_p) |
11049 | *non_constant_p = parser->non_integral_constant_expression_p; |
11050 | parser->non_integral_constant_expression_p |
11051 | = saved_non_integral_constant_expression_p; |
11052 | |
11053 | return expression; |
11054 | } |
11055 | |
11056 | /* Parse __builtin_offsetof. |
11057 | |
11058 | offsetof-expression: |
11059 | "__builtin_offsetof" "(" type-id "," offsetof-member-designator ")" |
11060 | |
11061 | offsetof-member-designator: |
11062 | id-expression |
11063 | | offsetof-member-designator "." id-expression |
11064 | | offsetof-member-designator "[" expression "]" |
11065 | | offsetof-member-designator "->" id-expression */ |
11066 | |
11067 | static cp_expr |
11068 | cp_parser_builtin_offsetof (cp_parser *parser) |
11069 | { |
11070 | int save_ice_p, save_non_ice_p; |
11071 | tree type; |
11072 | cp_expr expr; |
11073 | cp_id_kind dummy; |
11074 | cp_token *token; |
11075 | location_t finish_loc; |
11076 | |
11077 | /* We're about to accept non-integral-constant things, but will |
11078 | definitely yield an integral constant expression. Save and |
11079 | restore these values around our local parsing. */ |
11080 | save_ice_p = parser->integral_constant_expression_p; |
11081 | save_non_ice_p = parser->non_integral_constant_expression_p; |
11082 | |
11083 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11084 | |
11085 | /* Consume the "__builtin_offsetof" token. */ |
11086 | cp_lexer_consume_token (lexer: parser->lexer); |
11087 | /* Consume the opening `('. */ |
11088 | matching_parens parens; |
11089 | parens.require_open (parser); |
11090 | /* Parse the type-id. */ |
11091 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11092 | { |
11093 | const char *saved_message = parser->type_definition_forbidden_message; |
11094 | parser->type_definition_forbidden_message |
11095 | = G_("types may not be defined within %<__builtin_offsetof%>" ); |
11096 | type = cp_parser_type_id (parser); |
11097 | parser->type_definition_forbidden_message = saved_message; |
11098 | } |
11099 | /* Look for the `,'. */ |
11100 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11101 | token = cp_lexer_peek_token (lexer: parser->lexer); |
11102 | |
11103 | /* Build the (type *)null that begins the traditional offsetof macro. */ |
11104 | tree object_ptr |
11105 | = build_static_cast (input_location, build_pointer_type (type), |
11106 | null_pointer_node, tf_warning_or_error); |
11107 | |
11108 | /* Parse the offsetof-member-designator. We begin as if we saw "expr->". */ |
11109 | expr = cp_parser_postfix_dot_deref_expression (parser, token_type: CPP_DEREF, postfix_expression: object_ptr, |
11110 | for_offsetof: true, idk: &dummy, location: token->location); |
11111 | while (true) |
11112 | { |
11113 | token = cp_lexer_peek_token (lexer: parser->lexer); |
11114 | switch (token->type) |
11115 | { |
11116 | case CPP_OPEN_SQUARE: |
11117 | /* offsetof-member-designator "[" expression "]" */ |
11118 | expr = cp_parser_postfix_open_square_expression (parser, postfix_expression: expr, |
11119 | for_offsetof: true, decltype_p: false); |
11120 | break; |
11121 | |
11122 | case CPP_DEREF: |
11123 | /* offsetof-member-designator "->" identifier */ |
11124 | expr = grok_array_decl (token->location, expr, integer_zero_node, |
11125 | NULL, tf_warning_or_error); |
11126 | /* FALLTHRU */ |
11127 | |
11128 | case CPP_DOT: |
11129 | /* offsetof-member-designator "." identifier */ |
11130 | cp_lexer_consume_token (lexer: parser->lexer); |
11131 | expr = cp_parser_postfix_dot_deref_expression (parser, token_type: CPP_DOT, |
11132 | postfix_expression: expr, for_offsetof: true, idk: &dummy, |
11133 | location: token->location); |
11134 | break; |
11135 | |
11136 | case CPP_CLOSE_PAREN: |
11137 | /* Consume the ")" token. */ |
11138 | finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11139 | cp_lexer_consume_token (lexer: parser->lexer); |
11140 | goto success; |
11141 | |
11142 | default: |
11143 | /* Error. We know the following require will fail, but |
11144 | that gives the proper error message. */ |
11145 | parens.require_close (parser); |
11146 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
11147 | expr = error_mark_node; |
11148 | goto failure; |
11149 | } |
11150 | } |
11151 | |
11152 | success: |
11153 | /* Make a location of the form: |
11154 | __builtin_offsetof (struct s, f) |
11155 | ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~ |
11156 | with caret at the type-id, ranging from the start of the |
11157 | "_builtin_offsetof" token to the close paren. */ |
11158 | loc = make_location (caret: loc, start: start_loc, finish: finish_loc); |
11159 | /* The result will be an INTEGER_CST, so we need to explicitly |
11160 | preserve the location. */ |
11161 | expr = cp_expr (finish_offsetof (object_ptr, expr, loc), loc); |
11162 | |
11163 | failure: |
11164 | parser->integral_constant_expression_p = save_ice_p; |
11165 | parser->non_integral_constant_expression_p = save_non_ice_p; |
11166 | |
11167 | expr = expr.maybe_add_location_wrapper (); |
11168 | return expr; |
11169 | } |
11170 | |
11171 | /* Parse a builtin trait expression or type. */ |
11172 | |
11173 | static cp_expr |
11174 | cp_parser_trait (cp_parser* parser, const cp_trait* trait) |
11175 | { |
11176 | const cp_trait_kind kind = trait->kind; |
11177 | tree type1, type2 = NULL_TREE; |
11178 | const bool binary = (trait->arity == 2); |
11179 | const bool variadic = (trait->arity == -1); |
11180 | const bool type = trait->type; |
11181 | |
11182 | /* Get location of initial token. */ |
11183 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11184 | |
11185 | /* Consume the token. */ |
11186 | cp_lexer_consume_token (lexer: parser->lexer); |
11187 | |
11188 | matching_parens parens; |
11189 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11190 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
11191 | else |
11192 | parens.require_open (parser); |
11193 | |
11194 | if (kind == CPTK_IS_DEDUCIBLE) |
11195 | { |
11196 | const cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
11197 | type1 = cp_parser_id_expression (parser, |
11198 | /*template_keyword_p=*/false, |
11199 | /*check_dependency_p=*/true, |
11200 | template_p: nullptr, |
11201 | /*declarator_p=*/false, |
11202 | /*optional_p=*/false); |
11203 | type1 = cp_parser_lookup_name_simple (parser, type1, token->location); |
11204 | } |
11205 | else if (kind == CPTK_TYPE_PACK_ELEMENT) |
11206 | /* __type_pack_element takes an expression as its first argument and uses |
11207 | template-id syntax instead of function call syntax (for consistency |
11208 | with Clang). We special case these properties of __type_pack_element |
11209 | here and elsewhere. */ |
11210 | type1 = cp_parser_constant_expression (parser); |
11211 | else |
11212 | { |
11213 | type_id_in_expr_sentinel s (parser); |
11214 | type1 = cp_parser_type_id (parser); |
11215 | } |
11216 | |
11217 | if (type1 == error_mark_node) |
11218 | return error_mark_node; |
11219 | |
11220 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11221 | { |
11222 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11223 | tree trailing = cp_parser_enclosed_template_argument_list (parser); |
11224 | for (tree elt : tree_vec_range (trailing)) |
11225 | { |
11226 | if (!TYPE_P (elt)) |
11227 | { |
11228 | error_at (cp_expr_loc_or_input_loc (t: elt), |
11229 | "trailing argument to %<__type_pack_element%> " |
11230 | "is not a type" ); |
11231 | return error_mark_node; |
11232 | } |
11233 | } |
11234 | type2 = trailing; |
11235 | } |
11236 | else if (binary) |
11237 | { |
11238 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11239 | |
11240 | { |
11241 | type_id_in_expr_sentinel s (parser); |
11242 | type2 = cp_parser_type_id (parser); |
11243 | } |
11244 | |
11245 | if (type2 == error_mark_node) |
11246 | return error_mark_node; |
11247 | } |
11248 | else if (variadic) |
11249 | { |
11250 | auto_vec<tree, 4> trailing; |
11251 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
11252 | { |
11253 | cp_lexer_consume_token (lexer: parser->lexer); |
11254 | tree elt = cp_parser_type_id (parser); |
11255 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11256 | { |
11257 | cp_lexer_consume_token (lexer: parser->lexer); |
11258 | elt = make_pack_expansion (elt); |
11259 | } |
11260 | if (elt == error_mark_node) |
11261 | return error_mark_node; |
11262 | trailing.safe_push (obj: elt); |
11263 | } |
11264 | type2 = make_tree_vec (trailing.length ()); |
11265 | for (int i = 0; i < TREE_VEC_LENGTH (type2); ++i) |
11266 | TREE_VEC_ELT (type2, i) = trailing[i]; |
11267 | } |
11268 | |
11269 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11270 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11271 | /* cp_parser_enclosed_template_argument_list above already took care |
11272 | of parsing the closing '>'. */; |
11273 | else |
11274 | parens.require_close (parser); |
11275 | |
11276 | /* Construct a location of the form: |
11277 | __is_trivially_copyable(_Tp) |
11278 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
11279 | with start == caret, finishing at the close-paren. */ |
11280 | location_t trait_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
11281 | |
11282 | /* Complete the trait expression, which may mean either processing |
11283 | the trait expr now or saving it for template instantiation. */ |
11284 | switch (kind) |
11285 | { |
11286 | case CPTK_BASES: |
11287 | return cp_expr (finish_bases (type1, false), trait_loc); |
11288 | case CPTK_DIRECT_BASES: |
11289 | return cp_expr (finish_bases (type1, true), trait_loc); |
11290 | default: |
11291 | if (type) |
11292 | return finish_trait_type (kind, type1, type2, tf_warning_or_error); |
11293 | else |
11294 | return finish_trait_expr (trait_loc, kind, type1, type2); |
11295 | } |
11296 | } |
11297 | |
11298 | /* Parse a lambda expression. |
11299 | |
11300 | lambda-expression: |
11301 | lambda-introducer lambda-declarator [opt] compound-statement |
11302 | lambda-introducer < template-parameter-list > requires-clause [opt] |
11303 | lambda-declarator [opt] compound-statement |
11304 | |
11305 | Returns a representation of the expression. */ |
11306 | |
11307 | static cp_expr |
11308 | cp_parser_lambda_expression (cp_parser* parser) |
11309 | { |
11310 | tree lambda_expr = build_lambda_expr (); |
11311 | tree type; |
11312 | bool ok = true; |
11313 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
11314 | cp_token_position start = 0; |
11315 | |
11316 | LAMBDA_EXPR_LOCATION (lambda_expr) = token->location; |
11317 | |
11318 | if (cxx_dialect >= cxx20) |
11319 | { |
11320 | /* C++20 allows lambdas in unevaluated context, but one in the type of a |
11321 | non-type parameter is nonsensical. |
11322 | |
11323 | Distinguish a lambda in the parameter type from a lambda in the |
11324 | default argument by looking at local_variables_forbidden_p, which is |
11325 | only set in default arguments. */ |
11326 | if (processing_template_parmlist && !parser->local_variables_forbidden_p) |
11327 | { |
11328 | error_at (token->location, |
11329 | "lambda-expression in template parameter type" ); |
11330 | token->error_reported = true; |
11331 | ok = false; |
11332 | } |
11333 | } |
11334 | else if (cp_unevaluated_operand) |
11335 | { |
11336 | if (!token->error_reported) |
11337 | { |
11338 | error_at (LAMBDA_EXPR_LOCATION (lambda_expr), |
11339 | "lambda-expression in unevaluated context" |
11340 | " only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
11341 | token->error_reported = true; |
11342 | } |
11343 | ok = false; |
11344 | } |
11345 | else if (parser->in_template_argument_list_p || processing_template_parmlist) |
11346 | { |
11347 | if (!token->error_reported) |
11348 | { |
11349 | error_at (token->location, "lambda-expression in template-argument" |
11350 | " only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
11351 | token->error_reported = true; |
11352 | } |
11353 | ok = false; |
11354 | } |
11355 | |
11356 | /* We may be in the middle of deferred access check. Disable |
11357 | it now. */ |
11358 | push_deferring_access_checks (dk_no_deferred); |
11359 | |
11360 | cp_parser_lambda_introducer (parser, lambda_expr); |
11361 | if (cp_parser_error_occurred (parser)) |
11362 | return error_mark_node; |
11363 | |
11364 | type = begin_lambda_type (lambda_expr); |
11365 | if (type == error_mark_node) |
11366 | return error_mark_node; |
11367 | |
11368 | record_lambda_scope (lambda: lambda_expr); |
11369 | record_lambda_scope_discriminator (lambda: lambda_expr); |
11370 | |
11371 | /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ |
11372 | determine_visibility (TYPE_NAME (type)); |
11373 | |
11374 | /* Now that we've started the type, add the capture fields for any |
11375 | explicit captures. */ |
11376 | register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); |
11377 | |
11378 | { |
11379 | /* Inside the class, surrounding template-parameter-lists do not apply. */ |
11380 | unsigned int saved_num_template_parameter_lists |
11381 | = parser->num_template_parameter_lists; |
11382 | unsigned char in_statement = parser->in_statement; |
11383 | bool in_switch_statement_p = parser->in_switch_statement_p; |
11384 | bool fully_implicit_function_template_p |
11385 | = parser->fully_implicit_function_template_p; |
11386 | tree implicit_template_parms = parser->implicit_template_parms; |
11387 | cp_binding_level* implicit_template_scope = parser->implicit_template_scope; |
11388 | bool auto_is_implicit_function_template_parm_p |
11389 | = parser->auto_is_implicit_function_template_parm_p; |
11390 | bool saved_omp_array_section_p = parser->omp_array_section_p; |
11391 | |
11392 | parser->num_template_parameter_lists = 0; |
11393 | parser->in_statement = 0; |
11394 | parser->in_switch_statement_p = false; |
11395 | parser->fully_implicit_function_template_p = false; |
11396 | parser->implicit_template_parms = 0; |
11397 | parser->implicit_template_scope = 0; |
11398 | parser->auto_is_implicit_function_template_parm_p = false; |
11399 | parser->omp_array_section_p = false; |
11400 | |
11401 | /* The body of a lambda in a discarded statement is not discarded. */ |
11402 | bool discarded = in_discarded_stmt; |
11403 | in_discarded_stmt = 0; |
11404 | |
11405 | /* Similarly the body of a lambda in immediate function context is not |
11406 | in immediate function context. */ |
11407 | bool save_in_consteval_if_p = in_consteval_if_p; |
11408 | in_consteval_if_p = false; |
11409 | |
11410 | /* By virtue of defining a local class, a lambda expression has access to |
11411 | the private variables of enclosing classes. */ |
11412 | |
11413 | if (cp_parser_start_tentative_firewall (parser)) |
11414 | start = token; |
11415 | |
11416 | ok &= cp_parser_lambda_declarator_opt (parser, lambda_expr); |
11417 | |
11418 | if (ok && cp_parser_error_occurred (parser)) |
11419 | ok = false; |
11420 | |
11421 | if (ok) |
11422 | cp_parser_lambda_body (parser, lambda_expr); |
11423 | else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) |
11424 | { |
11425 | if (cp_parser_skip_to_closing_brace (parser)) |
11426 | cp_lexer_consume_token (lexer: parser->lexer); |
11427 | } |
11428 | |
11429 | /* The capture list was built up in reverse order; fix that now. */ |
11430 | LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) |
11431 | = nreverse (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); |
11432 | |
11433 | if (ok) |
11434 | maybe_add_lambda_conv_op (type); |
11435 | |
11436 | finish_struct (type, /*attributes=*/NULL_TREE); |
11437 | |
11438 | in_consteval_if_p = save_in_consteval_if_p; |
11439 | in_discarded_stmt = discarded; |
11440 | |
11441 | parser->num_template_parameter_lists = saved_num_template_parameter_lists; |
11442 | parser->in_statement = in_statement; |
11443 | parser->in_switch_statement_p = in_switch_statement_p; |
11444 | parser->fully_implicit_function_template_p |
11445 | = fully_implicit_function_template_p; |
11446 | parser->implicit_template_parms = implicit_template_parms; |
11447 | parser->implicit_template_scope = implicit_template_scope; |
11448 | parser->auto_is_implicit_function_template_parm_p |
11449 | = auto_is_implicit_function_template_parm_p; |
11450 | parser->omp_array_section_p = saved_omp_array_section_p; |
11451 | } |
11452 | |
11453 | /* This field is only used during parsing of the lambda. */ |
11454 | LAMBDA_EXPR_THIS_CAPTURE (lambda_expr) = NULL_TREE; |
11455 | |
11456 | /* This lambda shouldn't have any proxies left at this point. */ |
11457 | gcc_assert (LAMBDA_EXPR_PENDING_PROXIES (lambda_expr) == NULL); |
11458 | /* And now that we're done, push proxies for an enclosing lambda. */ |
11459 | insert_pending_capture_proxies (); |
11460 | |
11461 | /* Update the lambda expression to a range. */ |
11462 | LAMBDA_EXPR_LOCATION (lambda_expr) = make_location (caret: token->location, |
11463 | start: token->location, |
11464 | lexer: parser->lexer); |
11465 | |
11466 | if (ok) |
11467 | lambda_expr = build_lambda_object (lambda_expr); |
11468 | else |
11469 | lambda_expr = error_mark_node; |
11470 | |
11471 | cp_parser_end_tentative_firewall (parser, start, expr: lambda_expr); |
11472 | |
11473 | pop_deferring_access_checks (); |
11474 | |
11475 | return lambda_expr; |
11476 | } |
11477 | |
11478 | /* Parse the beginning of a lambda expression. |
11479 | |
11480 | lambda-introducer: |
11481 | [ lambda-capture [opt] ] |
11482 | |
11483 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
11484 | |
11485 | static void |
11486 | cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) |
11487 | { |
11488 | /* Need commas after the first capture. */ |
11489 | bool first = true; |
11490 | |
11491 | /* Eat the leading `['. */ |
11492 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
11493 | |
11494 | /* Record default capture mode. "[&" "[=" "[&," "[=," */ |
11495 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND) |
11496 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS) |
11497 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME) |
11498 | && !cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11499 | LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE; |
11500 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
11501 | LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY; |
11502 | |
11503 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE) |
11504 | { |
11505 | cp_lexer_consume_token (lexer: parser->lexer); |
11506 | first = false; |
11507 | |
11508 | if (!(at_function_scope_p () || parsing_nsdmi ())) |
11509 | error ("non-local lambda expression cannot have a capture-default" ); |
11510 | } |
11511 | |
11512 | hash_set<tree, true> ids; |
11513 | tree first_capture_id = NULL_TREE; |
11514 | unsigned name_independent_cnt = 0; |
11515 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
11516 | { |
11517 | cp_token* capture_token; |
11518 | tree capture_id; |
11519 | tree capture_init_expr; |
11520 | cp_id_kind idk = CP_ID_KIND_NONE; |
11521 | bool explicit_init_p = false; |
11522 | |
11523 | enum capture_kind_type |
11524 | { |
11525 | BY_COPY, |
11526 | BY_REFERENCE |
11527 | }; |
11528 | enum capture_kind_type capture_kind = BY_COPY; |
11529 | |
11530 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
11531 | { |
11532 | error ("expected end of capture-list" ); |
11533 | return; |
11534 | } |
11535 | |
11536 | if (first) |
11537 | first = false; |
11538 | else |
11539 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11540 | |
11541 | /* Possibly capture `this'. */ |
11542 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_THIS)) |
11543 | { |
11544 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11545 | if (cxx_dialect < cxx20 && pedantic |
11546 | && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY) |
11547 | pedwarn (loc, OPT_Wc__20_extensions, |
11548 | "explicit by-copy capture of %<this%> " |
11549 | "with by-copy capture default only available with " |
11550 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11551 | cp_lexer_consume_token (lexer: parser->lexer); |
11552 | if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) |
11553 | pedwarn (input_location, 0, |
11554 | "already captured %qD in lambda expression" , |
11555 | this_identifier); |
11556 | else |
11557 | add_capture (lambda_expr, /*id=*/this_identifier, |
11558 | /*initializer=*/finish_this_expr (), |
11559 | /*by_reference_p=*/true, explicit_init_p, NULL); |
11560 | continue; |
11561 | } |
11562 | |
11563 | /* Possibly capture `*this'. */ |
11564 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT) |
11565 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11566 | { |
11567 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11568 | if (cxx_dialect < cxx17) |
11569 | pedwarn (loc, OPT_Wc__17_extensions, |
11570 | "%<*this%> capture only available with " |
11571 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
11572 | cp_lexer_consume_token (lexer: parser->lexer); |
11573 | cp_lexer_consume_token (lexer: parser->lexer); |
11574 | if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) |
11575 | pedwarn (input_location, 0, |
11576 | "already captured %qD in lambda expression" , |
11577 | this_identifier); |
11578 | else |
11579 | add_capture (lambda_expr, /*id=*/this_identifier, |
11580 | /*initializer=*/finish_this_expr (), |
11581 | /*by_reference_p=*/false, explicit_init_p, NULL); |
11582 | continue; |
11583 | } |
11584 | |
11585 | /* But reject `&this'. */ |
11586 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND) |
11587 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11588 | { |
11589 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
11590 | "%<this%> cannot be captured by reference" ); |
11591 | cp_lexer_consume_token (lexer: parser->lexer); |
11592 | cp_lexer_consume_token (lexer: parser->lexer); |
11593 | continue; |
11594 | } |
11595 | |
11596 | /* Remember whether we want to capture as a reference or not. */ |
11597 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND)) |
11598 | { |
11599 | capture_kind = BY_REFERENCE; |
11600 | cp_lexer_consume_token (lexer: parser->lexer); |
11601 | } |
11602 | |
11603 | bool init_pack_expansion = false; |
11604 | location_t ellipsis_loc = UNKNOWN_LOCATION; |
11605 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11606 | { |
11607 | ellipsis_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11608 | if (cxx_dialect < cxx20) |
11609 | pedwarn (ellipsis_loc, OPT_Wc__20_extensions, |
11610 | "pack init-capture only available with " |
11611 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11612 | cp_lexer_consume_token (lexer: parser->lexer); |
11613 | init_pack_expansion = true; |
11614 | } |
11615 | |
11616 | /* Early C++20 drafts had ...& instead of &...; be forgiving. */ |
11617 | if (init_pack_expansion && capture_kind != BY_REFERENCE |
11618 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND)) |
11619 | { |
11620 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
11621 | 0, "%<&%> should come before %<...%>" ); |
11622 | capture_kind = BY_REFERENCE; |
11623 | cp_lexer_consume_token (lexer: parser->lexer); |
11624 | } |
11625 | |
11626 | /* Get the identifier. */ |
11627 | capture_token = cp_lexer_peek_token (lexer: parser->lexer); |
11628 | capture_id = cp_parser_identifier (parser); |
11629 | |
11630 | if (capture_id == error_mark_node) |
11631 | /* Would be nice to have a cp_parser_skip_to_closing_x for general |
11632 | delimiters, but I modified this to stop on unnested ']' as well. It |
11633 | was already changed to stop on unnested '}', so the |
11634 | "closing_parenthesis" name is no more misleading with my change. */ |
11635 | { |
11636 | cp_parser_skip_to_closing_parenthesis (parser, |
11637 | /*recovering=*/true, |
11638 | /*or_comma=*/true, |
11639 | /*consume_paren=*/true); |
11640 | break; |
11641 | } |
11642 | |
11643 | /* Find the initializer for this capture. */ |
11644 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
11645 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
11646 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
11647 | { |
11648 | /* An explicit initializer exists. */ |
11649 | if (cxx_dialect < cxx14) |
11650 | pedwarn (input_location, OPT_Wc__14_extensions, |
11651 | "lambda capture initializers " |
11652 | "only available with %<-std=c++14%> or %<-std=gnu++14%>" ); |
11653 | capture_init_expr = cp_parser_initializer (parser, |
11654 | /*direct_init=*/nullptr, |
11655 | /*non_constant=*/nullptr, |
11656 | /*subexpression_p=*/true); |
11657 | explicit_init_p = true; |
11658 | if (capture_init_expr == NULL_TREE) |
11659 | { |
11660 | error ("empty initializer for lambda init-capture" ); |
11661 | capture_init_expr = error_mark_node; |
11662 | } |
11663 | if (init_pack_expansion) |
11664 | capture_init_expr = make_pack_expansion (capture_init_expr); |
11665 | } |
11666 | else |
11667 | { |
11668 | const char* error_msg; |
11669 | |
11670 | /* Turn the identifier into an id-expression. */ |
11671 | capture_init_expr |
11672 | = cp_parser_lookup_name_simple (parser, capture_id, |
11673 | capture_token->location); |
11674 | |
11675 | if (capture_init_expr == error_mark_node) |
11676 | { |
11677 | unqualified_name_lookup_error (capture_id); |
11678 | continue; |
11679 | } |
11680 | else if (!VAR_P (capture_init_expr) |
11681 | && TREE_CODE (capture_init_expr) != PARM_DECL) |
11682 | { |
11683 | error_at (capture_token->location, |
11684 | "capture of non-variable %qE" , |
11685 | capture_init_expr); |
11686 | if (DECL_P (capture_init_expr)) |
11687 | inform (DECL_SOURCE_LOCATION (capture_init_expr), |
11688 | "%q#D declared here" , capture_init_expr); |
11689 | continue; |
11690 | } |
11691 | if (VAR_P (capture_init_expr) |
11692 | && decl_storage_duration (capture_init_expr) != dk_auto) |
11693 | { |
11694 | if (pedwarn (capture_token->location, 0, "capture of variable " |
11695 | "%qD with non-automatic storage duration" , |
11696 | capture_init_expr)) |
11697 | inform (DECL_SOURCE_LOCATION (capture_init_expr), |
11698 | "%q#D declared here" , capture_init_expr); |
11699 | continue; |
11700 | } |
11701 | |
11702 | capture_init_expr |
11703 | = finish_id_expression |
11704 | (capture_id, |
11705 | capture_init_expr, |
11706 | parser->scope, |
11707 | &idk, |
11708 | /*integral_constant_expression_p=*/false, |
11709 | /*allow_non_integral_constant_expression_p=*/false, |
11710 | /*non_integral_constant_expression_p=*/NULL, |
11711 | /*template_p=*/false, |
11712 | /*done=*/true, |
11713 | /*address_p=*/false, |
11714 | /*template_arg_p=*/false, |
11715 | &error_msg, |
11716 | capture_token->location); |
11717 | |
11718 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11719 | { |
11720 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11721 | cp_lexer_consume_token (lexer: parser->lexer); |
11722 | capture_init_expr = make_pack_expansion (capture_init_expr); |
11723 | if (init_pack_expansion) |
11724 | { |
11725 | /* If what follows is an initializer, the second '...' is |
11726 | invalid. But for cases like [...xs...], the first one |
11727 | is invalid. */ |
11728 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
11729 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
11730 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
11731 | ellipsis_loc = loc; |
11732 | error_at (ellipsis_loc, "too many %<...%> in lambda capture" ); |
11733 | continue; |
11734 | } |
11735 | } |
11736 | } |
11737 | |
11738 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE |
11739 | && !explicit_init_p) |
11740 | { |
11741 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY |
11742 | && capture_kind == BY_COPY) |
11743 | pedwarn (capture_token->location, 0, "explicit by-copy capture " |
11744 | "of %qD redundant with by-copy capture default" , |
11745 | capture_id); |
11746 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_REFERENCE |
11747 | && capture_kind == BY_REFERENCE) |
11748 | pedwarn (capture_token->location, 0, "explicit by-reference " |
11749 | "capture of %qD redundant with by-reference capture " |
11750 | "default" , capture_id); |
11751 | } |
11752 | |
11753 | /* Check for duplicates. |
11754 | Optimize for the zero or one explicit captures cases and only create |
11755 | the hash_set after adding second capture. */ |
11756 | bool found = false; |
11757 | if (!ids.is_empty ()) |
11758 | found = ids.add (k: capture_id); |
11759 | else if (first_capture_id == NULL_TREE) |
11760 | first_capture_id = capture_id; |
11761 | else if (capture_id == first_capture_id) |
11762 | found = true; |
11763 | else |
11764 | { |
11765 | ids.add (k: first_capture_id); |
11766 | ids.add (k: capture_id); |
11767 | } |
11768 | if (found && explicit_init_p && id_equal (id: capture_id, str: "_" )) |
11769 | found = false; |
11770 | if (found) |
11771 | pedwarn (input_location, 0, |
11772 | "already captured %qD in lambda expression" , capture_id); |
11773 | else |
11774 | add_capture (lambda_expr, capture_id, capture_init_expr, |
11775 | /*by_reference_p=*/capture_kind == BY_REFERENCE, |
11776 | explicit_init_p, &name_independent_cnt); |
11777 | |
11778 | /* If there is any qualification still in effect, clear it |
11779 | now; we will be starting fresh with the next capture. */ |
11780 | parser->scope = NULL_TREE; |
11781 | parser->qualifying_scope = NULL_TREE; |
11782 | parser->object_scope = NULL_TREE; |
11783 | } |
11784 | |
11785 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
11786 | } |
11787 | |
11788 | /* Parse the (optional) middle of a lambda expression. |
11789 | |
11790 | lambda-declarator: |
11791 | ( parameter-declaration-clause ) lambda-specifiers requires-clause [opt] |
11792 | lambda-specifiers (C++23) |
11793 | |
11794 | lambda-specifiers: |
11795 | decl-specifier-seq [opt] noexcept-specifier [opt] |
11796 | attribute-specifier-seq [opt] trailing-return-type [opt] |
11797 | |
11798 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
11799 | |
11800 | static bool |
11801 | cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) |
11802 | { |
11803 | /* 5.1.1.4 of the standard says: |
11804 | If a lambda-expression does not include a lambda-declarator, it is as if |
11805 | the lambda-declarator were (). |
11806 | This means an empty parameter list, no attributes, and no exception |
11807 | specification. */ |
11808 | tree param_list = void_list_node; |
11809 | tree std_attrs = NULL_TREE; |
11810 | tree gnu_attrs = NULL_TREE; |
11811 | tree exception_spec = NULL_TREE; |
11812 | tree template_param_list = NULL_TREE; |
11813 | tree tx_qual = NULL_TREE; |
11814 | tree return_type = NULL_TREE; |
11815 | tree trailing_requires_clause = NULL_TREE; |
11816 | bool has_param_list = false; |
11817 | location_t omitted_parms_loc = UNKNOWN_LOCATION; |
11818 | cp_decl_specifier_seq lambda_specs; |
11819 | clear_decl_specs (decl_specs: &lambda_specs); |
11820 | /* A lambda op() is const unless explicitly 'mutable'. */ |
11821 | cp_cv_quals quals = TYPE_QUAL_CONST; |
11822 | |
11823 | /* The template-parameter-list is optional, but must begin with |
11824 | an opening angle if present. */ |
11825 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
11826 | { |
11827 | if (cxx_dialect < cxx20 |
11828 | && (pedantic || cxx_dialect < cxx14)) |
11829 | pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions, |
11830 | "lambda templates are only available with " |
11831 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11832 | |
11833 | cp_lexer_consume_token (lexer: parser->lexer); |
11834 | |
11835 | template_param_list = cp_parser_template_parameter_list (parser); |
11836 | cp_parser_require_end_of_template_parameter_list (parser); |
11837 | |
11838 | /* We may have a constrained generic lambda; parse the requires-clause |
11839 | immediately after the template-parameter-list and combine with any |
11840 | shorthand constraints present. */ |
11841 | tree dreqs = cp_parser_requires_clause_opt (parser, true); |
11842 | if (flag_concepts) |
11843 | { |
11844 | tree reqs = get_shorthand_constraints (current_template_parms); |
11845 | if (dreqs) |
11846 | reqs = combine_constraint_expressions (reqs, dreqs); |
11847 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
11848 | } |
11849 | |
11850 | /* We just processed one more parameter list. */ |
11851 | ++parser->num_template_parameter_lists; |
11852 | } |
11853 | |
11854 | /* Committee discussion supports allowing attributes here. */ |
11855 | lambda_specs.attributes = cp_parser_attributes_opt (parser); |
11856 | |
11857 | /* The parameter-declaration-clause is optional (unless |
11858 | template-parameter-list was given), but must begin with an |
11859 | opening parenthesis if present. */ |
11860 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
11861 | { |
11862 | matching_parens parens; |
11863 | parens.consume_open (parser); |
11864 | |
11865 | begin_scope (sk_function_parms, /*entity=*/NULL_TREE); |
11866 | |
11867 | /* Parse parameters. */ |
11868 | param_list |
11869 | = cp_parser_parameter_declaration_clause |
11870 | (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL); |
11871 | |
11872 | /* Default arguments shall not be specified in the |
11873 | parameter-declaration-clause of a lambda-declarator. */ |
11874 | if (pedantic && cxx_dialect < cxx14) |
11875 | for (tree t = param_list; t; t = TREE_CHAIN (t)) |
11876 | if (TREE_PURPOSE (t) && DECL_P (TREE_VALUE (t))) |
11877 | pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), |
11878 | OPT_Wc__14_extensions, |
11879 | "default argument specified for lambda parameter" ); |
11880 | |
11881 | parens.require_close (parser); |
11882 | has_param_list = true; |
11883 | } |
11884 | else if (cxx_dialect < cxx23) |
11885 | omitted_parms_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11886 | |
11887 | /* [expr.prim.lambda.general] |
11888 | lambda-specifier: |
11889 | consteval, constexpr, mutable, static |
11890 | [4] A lambda-specifier-seq shall contain at most one of each |
11891 | lambda-specifier and shall not contain both constexpr and consteval. |
11892 | The lambda-specifier-seq shall not contain both mutable and static. */ |
11893 | int declares_class_or_enum; |
11894 | if (cp_lexer_next_token_is_decl_specifier_keyword (lexer: parser->lexer)) |
11895 | cp_parser_decl_specifier_seq (parser, |
11896 | CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR, |
11897 | &lambda_specs, &declares_class_or_enum); |
11898 | |
11899 | if (omitted_parms_loc && lambda_specs.any_specifiers_p) |
11900 | { |
11901 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11902 | "parameter declaration before lambda declaration " |
11903 | "specifiers only optional with %<-std=c++2b%> or " |
11904 | "%<-std=gnu++2b%>" ); |
11905 | omitted_parms_loc = UNKNOWN_LOCATION; |
11906 | } |
11907 | /* Peek at the params, see if we have an xobj parameter. */ |
11908 | if (param_list && TREE_PURPOSE (param_list) == this_identifier) |
11909 | { |
11910 | quals = TYPE_UNQUALIFIED; |
11911 | /* We still need grokdeclarator to see that this is an xobj function |
11912 | and finish the rest of the work, don't mutate it. */ |
11913 | tree const xobj_param = TREE_VALUE (param_list); |
11914 | tree const param_type = TREE_TYPE (xobj_param); |
11915 | /* [expr.prim.lambda.closure-5] |
11916 | Given a lambda with a lambda-capture, the type of the explicit object |
11917 | parameter, if any, of the lambda's function call operator (possibly |
11918 | instantiated from a function call operator template) shall be either: |
11919 | -- the closure type, |
11920 | -- a class type derived from the closure type, or |
11921 | -- a reference to a possibly cv-qualified such type. */ |
11922 | bool const unrelated_with_captures |
11923 | = (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE |
11924 | || LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)) |
11925 | /* Since a lambda's type is anonymous, we can assume an xobj |
11926 | parameter is unrelated to the closure if it is non-dependent. |
11927 | If it is dependent we handle it at instantiation time. */ |
11928 | && !WILDCARD_TYPE_P (non_reference (param_type)); |
11929 | if (unrelated_with_captures) |
11930 | { |
11931 | error_at (DECL_SOURCE_LOCATION (xobj_param), |
11932 | "a lambda with captures may not have an explicit object " |
11933 | "parameter of an unrelated type" ); |
11934 | LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = NULL_TREE; |
11935 | } |
11936 | |
11937 | /* [expr.prim.lambda.general-4] |
11938 | If the lambda-declarator contains an explicit object parameter |
11939 | ([dcl.fct]), then no lambda-specifier in the lambda-specifier-seq |
11940 | shall be mutable or static. */ |
11941 | if (lambda_specs.storage_class == sc_mutable) |
11942 | { |
11943 | auto_diagnostic_group d; |
11944 | error_at (lambda_specs.locations[ds_storage_class], |
11945 | "%<mutable%> lambda specifier " |
11946 | "with explicit object parameter" ); |
11947 | /* Tell the user how to do what they probably meant, maybe fixits |
11948 | would be appropriate later? */ |
11949 | if (unrelated_with_captures) |
11950 | /* The following hints don't make sense when we already have an |
11951 | unrelated type with captures, don't emit them. */; |
11952 | else if (!TYPE_REF_P (param_type)) |
11953 | inform (DECL_SOURCE_LOCATION (xobj_param), |
11954 | "the passed in closure object will not be mutated because " |
11955 | "it is taken by value" ); |
11956 | else if (TYPE_READONLY (TREE_TYPE (param_type))) |
11957 | inform (DECL_SOURCE_LOCATION (xobj_param), |
11958 | "declare the explicit object parameter as non-const " |
11959 | "reference instead" ); |
11960 | else |
11961 | inform (DECL_SOURCE_LOCATION (xobj_param), |
11962 | "explicit object parameter is already a mutable " |
11963 | "reference" ); |
11964 | } |
11965 | else if (lambda_specs.storage_class == sc_static) |
11966 | { |
11967 | auto_diagnostic_group d; |
11968 | error_at (lambda_specs.locations[ds_storage_class], |
11969 | "%<static%> lambda specifier " |
11970 | "with explicit object parameter" ); |
11971 | inform (DECL_SOURCE_LOCATION (xobj_param), |
11972 | "explicit object parameter declared here" ); |
11973 | } |
11974 | } |
11975 | else if (lambda_specs.storage_class == sc_mutable) |
11976 | { |
11977 | quals = TYPE_UNQUALIFIED; |
11978 | } |
11979 | else if (lambda_specs.storage_class == sc_static) |
11980 | { |
11981 | /* [expr.prim.lambda.general-4] |
11982 | If the lambda-specifier-seq contains static, there shall be no |
11983 | lambda-capture. */ |
11984 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE |
11985 | || LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)) |
11986 | error_at (lambda_specs.locations[ds_storage_class], |
11987 | "%<static%> lambda specifier with lambda capture" ); |
11988 | else |
11989 | { |
11990 | LAMBDA_EXPR_STATIC_P (lambda_expr) = 1; |
11991 | quals = TYPE_UNQUALIFIED; |
11992 | } |
11993 | } |
11994 | |
11995 | tx_qual = cp_parser_tx_qualifier_opt (parser); |
11996 | if (omitted_parms_loc && tx_qual) |
11997 | { |
11998 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11999 | "parameter declaration before lambda transaction " |
12000 | "qualifier only optional with %<-std=c++2b%> or " |
12001 | "%<-std=gnu++2b%>" ); |
12002 | omitted_parms_loc = UNKNOWN_LOCATION; |
12003 | } |
12004 | |
12005 | /* Parse optional exception specification. */ |
12006 | exception_spec |
12007 | = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE); |
12008 | |
12009 | if (omitted_parms_loc && exception_spec) |
12010 | { |
12011 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
12012 | "parameter declaration before lambda exception " |
12013 | "specification only optional with %<-std=c++2b%> or " |
12014 | "%<-std=gnu++2b%>" ); |
12015 | omitted_parms_loc = UNKNOWN_LOCATION; |
12016 | } |
12017 | |
12018 | /* GCC 8 accepted attributes here, and this is the place for standard C++11 |
12019 | attributes that appertain to the function type. */ |
12020 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
12021 | gnu_attrs = cp_parser_gnu_attributes_opt (parser); |
12022 | else |
12023 | std_attrs = cp_parser_std_attribute_spec_seq (parser); |
12024 | |
12025 | /* Parse optional trailing return type. */ |
12026 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
12027 | { |
12028 | if (omitted_parms_loc) |
12029 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
12030 | "parameter declaration before lambda trailing " |
12031 | "return type only optional with %<-std=c++2b%> or " |
12032 | "%<-std=gnu++2b%>" ); |
12033 | cp_lexer_consume_token (lexer: parser->lexer); |
12034 | return_type = cp_parser_trailing_type_id (parser); |
12035 | } |
12036 | |
12037 | /* Also allow GNU attributes at the very end of the declaration, the usual |
12038 | place for GNU attributes. */ |
12039 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
12040 | gnu_attrs = chainon (gnu_attrs, cp_parser_gnu_attributes_opt (parser)); |
12041 | |
12042 | if (has_param_list) |
12043 | { |
12044 | /* Parse optional trailing requires clause. */ |
12045 | trailing_requires_clause = cp_parser_requires_clause_opt (parser, false); |
12046 | |
12047 | /* The function parameters must be in scope all the way until after the |
12048 | trailing-return-type in case of decltype. */ |
12049 | pop_bindings_and_leave_scope (); |
12050 | } |
12051 | |
12052 | /* Create the function call operator. |
12053 | |
12054 | Messing with declarators like this is no uglier than building up the |
12055 | FUNCTION_DECL by hand, and this is less likely to get out of sync with |
12056 | other code. */ |
12057 | { |
12058 | cp_decl_specifier_seq return_type_specs; |
12059 | cp_declarator* declarator; |
12060 | tree fco; |
12061 | void *p; |
12062 | |
12063 | clear_decl_specs (decl_specs: &return_type_specs); |
12064 | return_type_specs.type = make_auto (); |
12065 | |
12066 | if (lambda_specs.locations[ds_constexpr]) |
12067 | { |
12068 | if (cxx_dialect >= cxx17) |
12069 | return_type_specs.locations[ds_constexpr] |
12070 | = lambda_specs.locations[ds_constexpr]; |
12071 | else |
12072 | error_at (lambda_specs.locations[ds_constexpr], "%<constexpr%> " |
12073 | "lambda only available with %<-std=c++17%> or " |
12074 | "%<-std=gnu++17%>" ); |
12075 | } |
12076 | if (lambda_specs.locations[ds_consteval]) |
12077 | return_type_specs.locations[ds_consteval] |
12078 | = lambda_specs.locations[ds_consteval]; |
12079 | if (LAMBDA_EXPR_STATIC_P (lambda_expr)) |
12080 | { |
12081 | return_type_specs.storage_class = sc_static; |
12082 | return_type_specs.locations[ds_storage_class] |
12083 | = lambda_specs.locations[ds_storage_class]; |
12084 | } |
12085 | |
12086 | p = obstack_alloc (&declarator_obstack, 0); |
12087 | |
12088 | declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk: sfk_none, |
12089 | LAMBDA_EXPR_LOCATION (lambda_expr)); |
12090 | |
12091 | declarator = make_call_declarator (target: declarator, parms: param_list, cv_qualifiers: quals, |
12092 | virt_specifiers: VIRT_SPEC_UNSPECIFIED, |
12093 | ref_qualifier: REF_QUAL_NONE, |
12094 | tx_qualifier: tx_qual, |
12095 | exception_specification: exception_spec, |
12096 | late_return_type: return_type, |
12097 | requires_clause: trailing_requires_clause, |
12098 | std_attrs, |
12099 | UNKNOWN_LOCATION); |
12100 | |
12101 | fco = grokmethod (&return_type_specs, |
12102 | declarator, |
12103 | chainon (gnu_attrs, lambda_specs.attributes)); |
12104 | if (fco != error_mark_node) |
12105 | { |
12106 | DECL_INITIALIZED_IN_CLASS_P (fco) = 1; |
12107 | DECL_ARTIFICIAL (fco) = 1; |
12108 | if (DECL_IOBJ_MEMBER_FUNCTION_P (fco)) |
12109 | /* Give the object parameter a different name. */ |
12110 | DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier; |
12111 | DECL_SET_LAMBDA_FUNCTION (fco, true); |
12112 | } |
12113 | if (template_param_list) |
12114 | { |
12115 | fco = finish_member_template_decl (fco); |
12116 | finish_template_decl (template_param_list); |
12117 | --parser->num_template_parameter_lists; |
12118 | } |
12119 | else if (parser->fully_implicit_function_template_p) |
12120 | fco = finish_fully_implicit_template (parser, fco); |
12121 | |
12122 | finish_member_declaration (fco); |
12123 | record_lambda_scope_sig_discriminator (lambda: lambda_expr, fn: fco); |
12124 | |
12125 | obstack_free (&declarator_obstack, p); |
12126 | |
12127 | return (fco != error_mark_node); |
12128 | } |
12129 | } |
12130 | |
12131 | /* Parse the body of a lambda expression, which is simply |
12132 | |
12133 | compound-statement |
12134 | |
12135 | but which requires special handling. |
12136 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
12137 | |
12138 | static void |
12139 | cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) |
12140 | { |
12141 | bool nested = (current_function_decl != NULL_TREE); |
12142 | unsigned char local_variables_forbidden_p |
12143 | = parser->local_variables_forbidden_p; |
12144 | bool in_function_body = parser->in_function_body; |
12145 | |
12146 | /* The body of a lambda-expression is not a subexpression of the enclosing |
12147 | expression. */ |
12148 | cp_evaluated ev; |
12149 | |
12150 | if (nested) |
12151 | push_function_context (); |
12152 | else |
12153 | /* Still increment function_depth so that we don't GC in the |
12154 | middle of an expression. */ |
12155 | ++function_depth; |
12156 | |
12157 | auto odsd = make_temp_override (var&: parser->omp_declare_simd, NULL); |
12158 | auto ord = make_temp_override (var&: parser->oacc_routine, NULL); |
12159 | auto oafp = make_temp_override (var&: parser->omp_attrs_forbidden_p, overrider: false); |
12160 | vec<tree> omp_privatization_save; |
12161 | save_omp_privatization_clauses (omp_privatization_save); |
12162 | /* Clear this in case we're in the middle of a default argument. */ |
12163 | parser->local_variables_forbidden_p = 0; |
12164 | parser->in_function_body = true; |
12165 | |
12166 | { |
12167 | local_specialization_stack s (lss_copy); |
12168 | tree fco = lambda_function (lambda_expr); |
12169 | tree body = start_lambda_function (fn: fco, lambda_expr); |
12170 | |
12171 | /* Originally C++11 required us to peek for 'return expr'; and |
12172 | process it specially here to deduce the return type. N3638 |
12173 | removed the need for that. */ |
12174 | cp_parser_function_body (parser, false); |
12175 | |
12176 | finish_lambda_function (body); |
12177 | } |
12178 | |
12179 | restore_omp_privatization_clauses (omp_privatization_save); |
12180 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
12181 | parser->in_function_body = in_function_body; |
12182 | if (nested) |
12183 | pop_function_context(); |
12184 | else |
12185 | --function_depth; |
12186 | } |
12187 | |
12188 | /* Statements [gram.stmt.stmt] */ |
12189 | |
12190 | /* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ |
12191 | |
12192 | static void |
12193 | add_debug_begin_stmt (location_t loc) |
12194 | { |
12195 | if (!MAY_HAVE_DEBUG_MARKER_STMTS) |
12196 | return; |
12197 | if (DECL_DECLARED_CONCEPT_P (current_function_decl)) |
12198 | /* A concept is never expanded normally. */ |
12199 | return; |
12200 | |
12201 | tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node); |
12202 | SET_EXPR_LOCATION (stmt, loc); |
12203 | add_stmt (stmt); |
12204 | } |
12205 | |
12206 | struct cp_omp_attribute_data |
12207 | { |
12208 | cp_token_cache *tokens; |
12209 | const c_omp_directive *dir; |
12210 | c_omp_directive_kind kind; |
12211 | }; |
12212 | |
12213 | /* Handle omp::directive and omp::sequence attributes in ATTRS |
12214 | (if any) at the start of a statement or in attribute-declaration. */ |
12215 | |
12216 | static tree |
12217 | cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) |
12218 | { |
12219 | if (!flag_openmp && !flag_openmp_simd) |
12220 | return attrs; |
12221 | |
12222 | auto_vec<cp_omp_attribute_data, 16> vec; |
12223 | int cnt = 0; |
12224 | int tokens = 0; |
12225 | bool bad = false; |
12226 | for (tree *pa = &attrs; *pa; ) |
12227 | if (get_attribute_namespace (*pa) == omp_identifier |
12228 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
12229 | { |
12230 | cnt++; |
12231 | for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) |
12232 | { |
12233 | tree d = TREE_VALUE (a); |
12234 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
12235 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
12236 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
12237 | if (parser->omp_attrs_forbidden_p) |
12238 | { |
12239 | error_at (first->location, |
12240 | "mixing OpenMP directives with attribute and pragma " |
12241 | "syntax on the same statement" ); |
12242 | parser->omp_attrs_forbidden_p = false; |
12243 | bad = true; |
12244 | } |
12245 | else if (TREE_PUBLIC (d)) |
12246 | { |
12247 | error_at (first->location, |
12248 | "OpenMP %<omp::decl%> attribute on a statement" ); |
12249 | bad = true; |
12250 | } |
12251 | const char *directive[3] = {}; |
12252 | for (int i = 0; i < 3; i++) |
12253 | { |
12254 | tree id = NULL_TREE; |
12255 | if (first + i == last) |
12256 | break; |
12257 | if (first[i].type == CPP_NAME) |
12258 | id = first[i].u.value; |
12259 | else if (first[i].type == CPP_KEYWORD) |
12260 | id = ridpointers[(int) first[i].keyword]; |
12261 | else |
12262 | break; |
12263 | directive[i] = IDENTIFIER_POINTER (id); |
12264 | } |
12265 | const c_omp_directive *dir = NULL; |
12266 | if (directive[0]) |
12267 | dir = c_omp_categorize_directive (directive[0], directive[1], |
12268 | directive[2]); |
12269 | if (dir == NULL) |
12270 | { |
12271 | error_at (first->location, |
12272 | "unknown OpenMP directive name in %qs attribute " |
12273 | "argument" , |
12274 | TREE_PUBLIC (d) ? "omp::decl" : "omp::directive" ); |
12275 | continue; |
12276 | } |
12277 | c_omp_directive_kind kind = dir->kind; |
12278 | if (dir->id == PRAGMA_OMP_ORDERED) |
12279 | { |
12280 | /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain |
12281 | depend/doacross clause. */ |
12282 | if (directive[1] |
12283 | && (strcmp (s1: directive[1], s2: "depend" ) == 0 |
12284 | || strcmp (s1: directive[1], s2: "doacross" ) == 0)) |
12285 | kind = C_OMP_DIR_STANDALONE; |
12286 | else if (first + 2 < last |
12287 | && first[1].type == CPP_COMMA |
12288 | && first[2].type == CPP_NAME |
12289 | && (strcmp (IDENTIFIER_POINTER (first[2].u.value), |
12290 | s2: "depend" ) == 0 |
12291 | || strcmp (IDENTIFIER_POINTER (first[2].u.value), |
12292 | s2: "doacross" ) == 0)) |
12293 | kind = C_OMP_DIR_STANDALONE; |
12294 | } |
12295 | else if (dir->id == PRAGMA_OMP_ERROR) |
12296 | { |
12297 | /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */ |
12298 | int paren_depth = 0; |
12299 | for (int i = 1; first + i < last; i++) |
12300 | if (first[i].type == CPP_OPEN_PAREN) |
12301 | paren_depth++; |
12302 | else if (first[i].type == CPP_CLOSE_PAREN) |
12303 | paren_depth--; |
12304 | else if (paren_depth == 0 |
12305 | && first + i + 2 < last |
12306 | && first[i].type == CPP_NAME |
12307 | && first[i + 1].type == CPP_OPEN_PAREN |
12308 | && first[i + 2].type == CPP_NAME |
12309 | && !strcmp (IDENTIFIER_POINTER (first[i].u.value), |
12310 | s2: "at" ) |
12311 | && !strcmp (IDENTIFIER_POINTER (first[i |
12312 | + 2].u.value), |
12313 | s2: "execution" )) |
12314 | { |
12315 | kind = C_OMP_DIR_STANDALONE; |
12316 | break; |
12317 | } |
12318 | } |
12319 | cp_omp_attribute_data v = { DEFPARSE_TOKENS (d), .dir: dir, .kind: kind }; |
12320 | vec.safe_push (obj: v); |
12321 | if (flag_openmp || dir->simd) |
12322 | tokens += (last - first) + 1; |
12323 | } |
12324 | cp_omp_attribute_data v = {}; |
12325 | vec.safe_push (obj: v); |
12326 | *pa = TREE_CHAIN (*pa); |
12327 | } |
12328 | else |
12329 | pa = &TREE_CHAIN (*pa); |
12330 | |
12331 | if (bad) |
12332 | return attrs; |
12333 | |
12334 | unsigned int i; |
12335 | cp_omp_attribute_data *v; |
12336 | cp_omp_attribute_data *construct_seen = nullptr; |
12337 | cp_omp_attribute_data *standalone_seen = nullptr; |
12338 | cp_omp_attribute_data *prev_standalone_seen = nullptr; |
12339 | FOR_EACH_VEC_ELT (vec, i, v) |
12340 | if (v->tokens) |
12341 | { |
12342 | if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen) |
12343 | construct_seen = v; |
12344 | else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen) |
12345 | standalone_seen = v; |
12346 | } |
12347 | else |
12348 | { |
12349 | if (standalone_seen && !prev_standalone_seen) |
12350 | { |
12351 | prev_standalone_seen = standalone_seen; |
12352 | standalone_seen = nullptr; |
12353 | } |
12354 | } |
12355 | |
12356 | if (cnt > 1 && construct_seen) |
12357 | { |
12358 | error_at (construct_seen->tokens->first->location, |
12359 | "OpenMP construct among %<omp::directive%> attributes" |
12360 | " requires all %<omp::directive%> attributes on the" |
12361 | " same statement to be in the same %<omp::sequence%>" ); |
12362 | return attrs; |
12363 | } |
12364 | if (cnt > 1 && standalone_seen && prev_standalone_seen) |
12365 | { |
12366 | error_at (standalone_seen->tokens->first->location, |
12367 | "multiple OpenMP standalone directives among" |
12368 | " %<omp::directive%> attributes must be all within the" |
12369 | " same %<omp::sequence%>" ); |
12370 | return attrs; |
12371 | } |
12372 | |
12373 | if (prev_standalone_seen) |
12374 | standalone_seen = prev_standalone_seen; |
12375 | if (standalone_seen |
12376 | && !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12377 | { |
12378 | error_at (standalone_seen->tokens->first->location, |
12379 | "standalone OpenMP directives in %<omp::directive%> attribute" |
12380 | " can only appear on an empty statement" ); |
12381 | return attrs; |
12382 | } |
12383 | if (cnt && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
12384 | { |
12385 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
12386 | enum pragma_kind kind = cp_parser_pragma_kind (token); |
12387 | if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_) |
12388 | { |
12389 | error_at (token->location, |
12390 | "mixing OpenMP directives with attribute and pragma " |
12391 | "syntax on the same statement" ); |
12392 | return attrs; |
12393 | } |
12394 | } |
12395 | |
12396 | if (!tokens) |
12397 | return attrs; |
12398 | tokens++; |
12399 | cp_lexer *lexer = cp_lexer_alloc (); |
12400 | lexer->debugging_p = parser->lexer->debugging_p; |
12401 | vec_safe_reserve (v&: lexer->buffer, nelems: tokens, exact: true); |
12402 | FOR_EACH_VEC_ELT (vec, i, v) |
12403 | { |
12404 | if (!v->tokens) |
12405 | continue; |
12406 | if (!flag_openmp && !v->dir->simd) |
12407 | continue; |
12408 | cp_token *first = v->tokens->first; |
12409 | cp_token *last = v->tokens->last; |
12410 | cp_token tok = {}; |
12411 | tok.type = CPP_PRAGMA; |
12412 | tok.keyword = RID_MAX; |
12413 | tok.u.value = build_int_cst (NULL, v->dir->id); |
12414 | tok.location = first->location; |
12415 | lexer->buffer->quick_push (obj: tok); |
12416 | while (++first < last) |
12417 | lexer->buffer->quick_push (obj: *first); |
12418 | tok = {}; |
12419 | tok.type = CPP_PRAGMA_EOL; |
12420 | tok.keyword = RID_MAX; |
12421 | tok.location = last->location; |
12422 | lexer->buffer->quick_push (obj: tok); |
12423 | } |
12424 | cp_token tok = {}; |
12425 | tok.type = CPP_EOF; |
12426 | tok.keyword = RID_MAX; |
12427 | tok.location = lexer->buffer->last ().location; |
12428 | lexer->buffer->quick_push (obj: tok); |
12429 | lexer->next = parser->lexer; |
12430 | lexer->next_token = lexer->buffer->address (); |
12431 | lexer->last_token = lexer->next_token |
12432 | + lexer->buffer->length () |
12433 | - 1; |
12434 | lexer->in_omp_attribute_pragma = true; |
12435 | parser->lexer = lexer; |
12436 | /* Move the current source position to that of the first token in the |
12437 | new lexer. */ |
12438 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
12439 | return attrs; |
12440 | } |
12441 | |
12442 | /* True if and only if the name is one of the contract types. */ |
12443 | |
12444 | static bool |
12445 | contract_attribute_p (const_tree id) |
12446 | { |
12447 | return is_attribute_p (attr_name: "assert" , ident: id) |
12448 | || is_attribute_p (attr_name: "pre" , ident: id) |
12449 | || is_attribute_p (attr_name: "post" , ident: id); |
12450 | } |
12451 | |
12452 | /* Handle omp::directive and omp::sequence attributes in *PATTRS |
12453 | (if any) at the start or after declaration-id of a declaration. */ |
12454 | |
12455 | static void |
12456 | cp_parser_handle_directive_omp_attributes (cp_parser *parser, tree *pattrs, |
12457 | cp_omp_declare_simd_data *data, |
12458 | bool start) |
12459 | { |
12460 | if (!flag_openmp && !flag_openmp_simd) |
12461 | return; |
12462 | |
12463 | int cnt = 0; |
12464 | bool bad = false; |
12465 | bool variant_p = false; |
12466 | location_t loc = UNKNOWN_LOCATION; |
12467 | for (tree pa = *pattrs; pa; pa = TREE_CHAIN (pa)) |
12468 | if (get_attribute_namespace (pa) == omp_identifier |
12469 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (pa))) |
12470 | { |
12471 | for (tree a = TREE_VALUE (pa); a; a = TREE_CHAIN (a)) |
12472 | { |
12473 | tree d = TREE_VALUE (a); |
12474 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
12475 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
12476 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
12477 | const char *directive[3] = {}; |
12478 | for (int i = 0; i < 3; i++) |
12479 | { |
12480 | tree id = NULL_TREE; |
12481 | if (first + i == last) |
12482 | break; |
12483 | if (first[i].type == CPP_NAME) |
12484 | id = first[i].u.value; |
12485 | else if (first[i].type == CPP_KEYWORD) |
12486 | id = ridpointers[(int) first[i].keyword]; |
12487 | else |
12488 | break; |
12489 | directive[i] = IDENTIFIER_POINTER (id); |
12490 | } |
12491 | const c_omp_directive *dir = NULL; |
12492 | if (directive[0]) |
12493 | dir = c_omp_categorize_directive (directive[0], directive[1], |
12494 | directive[2]); |
12495 | if (dir == NULL) |
12496 | continue; |
12497 | if (dir->id == PRAGMA_OMP_DECLARE |
12498 | && (strcmp (s1: directive[1], s2: "simd" ) == 0 |
12499 | || strcmp (s1: directive[1], s2: "variant" ) == 0)) |
12500 | { |
12501 | if (cnt++ == 0) |
12502 | { |
12503 | variant_p = strcmp (s1: directive[1], s2: "variant" ) == 0; |
12504 | loc = first->location; |
12505 | } |
12506 | if (start && parser->omp_declare_simd && !bad) |
12507 | { |
12508 | error_at (first->location, |
12509 | "mixing OpenMP directives with attribute and " |
12510 | "pragma syntax on the same declaration" ); |
12511 | bad = true; |
12512 | } |
12513 | } |
12514 | } |
12515 | } |
12516 | |
12517 | if (bad) |
12518 | { |
12519 | for (tree *pa = pattrs; *pa; ) |
12520 | if (get_attribute_namespace (*pa) == omp_identifier |
12521 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
12522 | *pa = TREE_CHAIN (*pa); |
12523 | else |
12524 | pa = &TREE_CHAIN (*pa); |
12525 | return; |
12526 | } |
12527 | if (cnt == 0) |
12528 | return; |
12529 | |
12530 | if (parser->omp_declare_simd == NULL) |
12531 | { |
12532 | data->error_seen = false; |
12533 | data->fndecl_seen = false; |
12534 | data->variant_p = variant_p; |
12535 | data->loc = loc; |
12536 | data->tokens = vNULL; |
12537 | data->attribs[0] = NULL; |
12538 | data->attribs[1] = NULL; |
12539 | parser->omp_declare_simd = data; |
12540 | } |
12541 | parser->omp_declare_simd->attribs[!start] = pattrs; |
12542 | } |
12543 | |
12544 | /* Parse a statement. |
12545 | |
12546 | statement: |
12547 | labeled-statement |
12548 | expression-statement |
12549 | compound-statement |
12550 | selection-statement |
12551 | iteration-statement |
12552 | jump-statement |
12553 | declaration-statement |
12554 | try-block |
12555 | |
12556 | C++11: |
12557 | |
12558 | statement: |
12559 | labeled-statement |
12560 | attribute-specifier-seq (opt) expression-statement |
12561 | attribute-specifier-seq (opt) compound-statement |
12562 | attribute-specifier-seq (opt) selection-statement |
12563 | attribute-specifier-seq (opt) iteration-statement |
12564 | attribute-specifier-seq (opt) jump-statement |
12565 | declaration-statement |
12566 | attribute-specifier-seq (opt) try-block |
12567 | |
12568 | init-statement: |
12569 | expression-statement |
12570 | simple-declaration |
12571 | alias-declaration |
12572 | |
12573 | TM Extension: |
12574 | |
12575 | statement: |
12576 | atomic-statement |
12577 | |
12578 | IN_COMPOUND is true when the statement is nested inside a |
12579 | cp_parser_compound_statement. |
12580 | |
12581 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
12582 | is a (possibly labeled) if statement which is not enclosed in braces |
12583 | and has an else clause. This is used to implement -Wparentheses. |
12584 | |
12585 | CHAIN is a vector of if-else-if conditions. |
12586 | |
12587 | Note that this version of parsing restricts assertions to be attached to |
12588 | empty statements. */ |
12589 | |
12590 | static void |
12591 | cp_parser_statement (cp_parser* parser, tree in_statement_expr, |
12592 | const bool in_compound, bool *if_p, vec<tree> *chain, |
12593 | location_t *loc_after_labels) |
12594 | { |
12595 | tree statement, std_attrs = NULL_TREE; |
12596 | cp_token *token; |
12597 | location_t statement_location, attrs_loc; |
12598 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12599 | bool has_std_attrs; |
12600 | /* A copy of IN_COMPOUND which is set to false after seeing a label. |
12601 | This matters for certain pragmas. */ |
12602 | bool in_compound_for_pragma = in_compound; |
12603 | |
12604 | restart: |
12605 | if (if_p != NULL) |
12606 | *if_p = false; |
12607 | /* There is no statement yet. */ |
12608 | statement = NULL_TREE; |
12609 | |
12610 | saved_token_sentinel saved_tokens (parser->lexer); |
12611 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12612 | attrs_loc = token->location; |
12613 | if (c_dialect_objc ()) |
12614 | /* In obj-c++, seeing '[[' might be the either the beginning of |
12615 | c++11 attributes, or a nested objc-message-expression. So |
12616 | let's parse the c++11 attributes tentatively. */ |
12617 | cp_parser_parse_tentatively (parser); |
12618 | std_attrs = cp_parser_std_attribute_spec_seq (parser); |
12619 | if (std_attrs) |
12620 | attrs_loc = make_location (caret: attrs_loc, start: attrs_loc, lexer: parser->lexer); |
12621 | if (c_dialect_objc ()) |
12622 | { |
12623 | if (!cp_parser_parse_definitely (parser)) |
12624 | std_attrs = NULL_TREE; |
12625 | } |
12626 | has_std_attrs = cp_lexer_peek_token (lexer: parser->lexer) != token; |
12627 | |
12628 | /* Peek at the next token. */ |
12629 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12630 | |
12631 | /* If we have contracts, check that they're valid in this context. */ |
12632 | if (std_attrs != error_mark_node) |
12633 | { |
12634 | if (tree pre = lookup_attribute (attr_name: "pre" , list: std_attrs)) |
12635 | error_at (EXPR_LOCATION (TREE_VALUE (pre)), |
12636 | "preconditions cannot be statements" ); |
12637 | else if (tree post = lookup_attribute (attr_name: "post" , list: std_attrs)) |
12638 | error_at (EXPR_LOCATION (TREE_VALUE (post)), |
12639 | "postconditions cannot be statements" ); |
12640 | |
12641 | /* Check that assertions are null statements. */ |
12642 | if (cp_contract_assertion_p (std_attrs)) |
12643 | if (token->type != CPP_SEMICOLON) |
12644 | error_at (token->location, "assertions must be followed by %<;%>" ); |
12645 | } |
12646 | |
12647 | bool omp_attrs_forbidden_p; |
12648 | omp_attrs_forbidden_p = parser->omp_attrs_forbidden_p; |
12649 | |
12650 | if (std_attrs && (flag_openmp || flag_openmp_simd)) |
12651 | { |
12652 | bool handle_omp_attribs = false; |
12653 | if (token->type == CPP_KEYWORD) |
12654 | switch (token->keyword) |
12655 | { |
12656 | case RID_IF: |
12657 | case RID_SWITCH: |
12658 | case RID_WHILE: |
12659 | case RID_DO: |
12660 | case RID_FOR: |
12661 | case RID_BREAK: |
12662 | case RID_CONTINUE: |
12663 | case RID_RETURN: |
12664 | case RID_CO_RETURN: |
12665 | case RID_GOTO: |
12666 | case RID_AT_TRY: |
12667 | case RID_AT_CATCH: |
12668 | case RID_AT_FINALLY: |
12669 | case RID_AT_SYNCHRONIZED: |
12670 | case RID_AT_THROW: |
12671 | case RID_TRY: |
12672 | case RID_TRANSACTION_ATOMIC: |
12673 | case RID_TRANSACTION_RELAXED: |
12674 | case RID_SYNCHRONIZED: |
12675 | case RID_ATOMIC_NOEXCEPT: |
12676 | case RID_ATOMIC_CANCEL: |
12677 | case RID_TRANSACTION_CANCEL: |
12678 | handle_omp_attribs = true; |
12679 | break; |
12680 | default: |
12681 | break; |
12682 | } |
12683 | else if (token->type == CPP_SEMICOLON |
12684 | || token->type == CPP_OPEN_BRACE |
12685 | || token->type == CPP_PRAGMA) |
12686 | handle_omp_attribs = true; |
12687 | if (handle_omp_attribs) |
12688 | { |
12689 | std_attrs = cp_parser_handle_statement_omp_attributes (parser, |
12690 | attrs: std_attrs); |
12691 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12692 | } |
12693 | } |
12694 | parser->omp_attrs_forbidden_p = false; |
12695 | |
12696 | /* Remember the location of the first token in the statement. */ |
12697 | cp_token *statement_token = token; |
12698 | statement_location = token->location; |
12699 | add_debug_begin_stmt (loc: statement_location); |
12700 | /* If this is a keyword, then that will often determine what kind of |
12701 | statement we have. */ |
12702 | if (token->type == CPP_KEYWORD) |
12703 | { |
12704 | enum rid keyword = token->keyword; |
12705 | |
12706 | switch (keyword) |
12707 | { |
12708 | case RID_CASE: |
12709 | case RID_DEFAULT: |
12710 | /* Looks like a labeled-statement with a case label. |
12711 | Parse the label, and then use tail recursion to parse |
12712 | the statement. */ |
12713 | cp_parser_label_for_labeled_statement (parser, std_attrs); |
12714 | in_compound_for_pragma = false; |
12715 | in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12716 | goto restart; |
12717 | |
12718 | case RID_IF: |
12719 | case RID_SWITCH: |
12720 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12721 | statement = cp_parser_selection_statement (parser, if_p, chain); |
12722 | break; |
12723 | |
12724 | case RID_WHILE: |
12725 | case RID_DO: |
12726 | case RID_FOR: |
12727 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12728 | statement = cp_parser_iteration_statement (parser, if_p, false, |
12729 | NULL_TREE, false); |
12730 | break; |
12731 | |
12732 | case RID_BREAK: |
12733 | case RID_CONTINUE: |
12734 | case RID_RETURN: |
12735 | case RID_CO_RETURN: |
12736 | case RID_GOTO: |
12737 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12738 | statement = cp_parser_jump_statement (parser); |
12739 | break; |
12740 | |
12741 | /* Objective-C++ exception-handling constructs. */ |
12742 | case RID_AT_TRY: |
12743 | case RID_AT_CATCH: |
12744 | case RID_AT_FINALLY: |
12745 | case RID_AT_SYNCHRONIZED: |
12746 | case RID_AT_THROW: |
12747 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12748 | statement = cp_parser_objc_statement (parser); |
12749 | break; |
12750 | |
12751 | case RID_TRY: |
12752 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12753 | statement = cp_parser_try_block (parser); |
12754 | break; |
12755 | |
12756 | case RID_NAMESPACE: |
12757 | /* This must be a namespace alias definition. */ |
12758 | if (has_std_attrs) |
12759 | { |
12760 | /* Attributes should be parsed as part of the |
12761 | declaration, so let's un-parse them. */ |
12762 | saved_tokens.rollback(); |
12763 | std_attrs = NULL_TREE; |
12764 | } |
12765 | cp_parser_declaration_statement (parser); |
12766 | return; |
12767 | |
12768 | case RID_TRANSACTION_ATOMIC: |
12769 | case RID_TRANSACTION_RELAXED: |
12770 | case RID_SYNCHRONIZED: |
12771 | case RID_ATOMIC_NOEXCEPT: |
12772 | case RID_ATOMIC_CANCEL: |
12773 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12774 | statement = cp_parser_transaction (parser, token); |
12775 | break; |
12776 | case RID_TRANSACTION_CANCEL: |
12777 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12778 | statement = cp_parser_transaction_cancel (parser); |
12779 | break; |
12780 | |
12781 | default: |
12782 | /* It might be a keyword like `int' that can start a |
12783 | declaration-statement. */ |
12784 | break; |
12785 | } |
12786 | } |
12787 | else if (token->type == CPP_NAME) |
12788 | { |
12789 | /* If the next token is a `:', then we are looking at a |
12790 | labeled-statement. */ |
12791 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
12792 | if (token->type == CPP_COLON) |
12793 | { |
12794 | /* Looks like a labeled-statement with an ordinary label. |
12795 | Parse the label, and then use tail recursion to parse |
12796 | the statement. */ |
12797 | |
12798 | cp_parser_label_for_labeled_statement (parser, std_attrs); |
12799 | |
12800 | /* If there's no statement, it's not a labeled-statement, just |
12801 | a label. That's allowed in C++23, but only if we're at the |
12802 | end of a compound-statement. */ |
12803 | if (in_compound |
12804 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
12805 | { |
12806 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
12807 | if (cxx_dialect < cxx23) |
12808 | pedwarn (loc, OPT_Wc__23_extensions, |
12809 | "label at end of compound statement only available " |
12810 | "with %<-std=c++2b%> or %<-std=gnu++2b%>" ); |
12811 | return; |
12812 | } |
12813 | in_compound_for_pragma = false; |
12814 | in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12815 | goto restart; |
12816 | } |
12817 | } |
12818 | /* Anything that starts with a `{' must be a compound-statement. */ |
12819 | else if (token->type == CPP_OPEN_BRACE) |
12820 | { |
12821 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12822 | statement = cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); |
12823 | } |
12824 | /* CPP_PRAGMA is a #pragma inside a function body, which constitutes |
12825 | a statement all its own. */ |
12826 | else if (token->type == CPP_PRAGMA) |
12827 | { |
12828 | do_pragma:; |
12829 | cp_lexer *lexer = parser->lexer; |
12830 | bool do_restart = false; |
12831 | /* Only certain OpenMP pragmas are attached to statements, and thus |
12832 | are considered statements themselves. All others are not. In |
12833 | the context of a compound, accept the pragma as a "statement" and |
12834 | return so that we can check for a close brace. Otherwise we |
12835 | require a real statement and must go back and read one. */ |
12836 | if (in_compound_for_pragma) |
12837 | { |
12838 | if (cp_parser_pragma (parser, pragma_compound, if_p) |
12839 | && parser->omp_for_parse_state) |
12840 | check_omp_intervening_code (parser); |
12841 | } |
12842 | else if (!cp_parser_pragma (parser, pragma_stmt, if_p)) |
12843 | do_restart = true; |
12844 | else if (parser->omp_for_parse_state) |
12845 | check_omp_intervening_code (parser); |
12846 | if (parser->lexer != lexer |
12847 | && lexer->in_omp_attribute_pragma |
12848 | && (!in_omp_attribute_pragma || lexer->orphan_p)) |
12849 | { |
12850 | if (saved_tokens.lexer == lexer) |
12851 | { |
12852 | if (saved_tokens.mode == STS_COMMIT) |
12853 | cp_lexer_commit_tokens (lexer); |
12854 | gcc_assert (lexer->saved_tokens.length () == saved_tokens.len); |
12855 | saved_tokens.lexer = parser->lexer; |
12856 | saved_tokens.mode = STS_DONOTHING; |
12857 | saved_tokens.len = parser->lexer->saved_tokens.length (); |
12858 | } |
12859 | cp_lexer_destroy (lexer); |
12860 | lexer = parser->lexer; |
12861 | } |
12862 | if (do_restart) |
12863 | goto restart; |
12864 | if (parser->lexer == lexer |
12865 | && lexer->in_omp_attribute_pragma |
12866 | && !in_omp_attribute_pragma) |
12867 | parser->lexer->orphan_p = true; |
12868 | return; |
12869 | } |
12870 | else if (token->type == CPP_EOF) |
12871 | { |
12872 | cp_parser_error (parser, gmsgid: "expected statement" ); |
12873 | return; |
12874 | } |
12875 | |
12876 | /* Everything else must be a declaration-statement or an |
12877 | expression-statement. Try for the declaration-statement |
12878 | first, unless we are looking at a `;', in which case we know that |
12879 | we have an expression-statement. */ |
12880 | if (!statement) |
12881 | { |
12882 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12883 | { |
12884 | if (has_std_attrs) |
12885 | /* Attributes should be parsed as part of the declaration, |
12886 | so let's un-parse them. */ |
12887 | saved_tokens.rollback(); |
12888 | |
12889 | parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; |
12890 | cp_parser_parse_tentatively (parser); |
12891 | /* Try to parse the declaration-statement. */ |
12892 | cp_parser_declaration_statement (parser); |
12893 | parser->omp_attrs_forbidden_p = false; |
12894 | /* If that worked, we're done. */ |
12895 | if (cp_parser_parse_definitely (parser)) |
12896 | return; |
12897 | /* It didn't work, restore the post-attribute position. */ |
12898 | if (has_std_attrs) |
12899 | { |
12900 | cp_lexer_set_token_position (lexer: parser->lexer, pos: statement_token); |
12901 | if (flag_openmp || flag_openmp_simd) |
12902 | { |
12903 | size_t i = 1; |
12904 | bool handle_omp_attribs = true; |
12905 | while (cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->keyword |
12906 | == RID_EXTENSION) |
12907 | i++; |
12908 | switch (cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->keyword) |
12909 | { |
12910 | case RID_ASM: |
12911 | case RID_NAMESPACE: |
12912 | case RID_USING: |
12913 | case RID_LABEL: |
12914 | case RID_STATIC_ASSERT: |
12915 | /* Don't handle OpenMP attribs on keywords that |
12916 | always start a declaration statement but don't |
12917 | accept attribute before it and therefore |
12918 | the tentative cp_parser_declaration_statement |
12919 | fails to parse because of that. */ |
12920 | handle_omp_attribs = false; |
12921 | break; |
12922 | default: |
12923 | break; |
12924 | } |
12925 | |
12926 | if (handle_omp_attribs) |
12927 | { |
12928 | parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; |
12929 | std_attrs |
12930 | = cp_parser_handle_statement_omp_attributes |
12931 | (parser, attrs: std_attrs); |
12932 | parser->omp_attrs_forbidden_p = false; |
12933 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12934 | if (token->type == CPP_PRAGMA) |
12935 | goto do_pragma; |
12936 | } |
12937 | } |
12938 | } |
12939 | } |
12940 | /* All preceding labels have been parsed at this point. */ |
12941 | if (loc_after_labels != NULL) |
12942 | *loc_after_labels = statement_location; |
12943 | |
12944 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12945 | |
12946 | /* Look for an expression-statement instead. */ |
12947 | statement = cp_parser_expression_statement (parser, in_statement_expr); |
12948 | |
12949 | std_attrs = process_stmt_assume_attribute (std_attrs, statement, |
12950 | attrs_loc); |
12951 | |
12952 | /* Handle [[fallthrough]];. */ |
12953 | if (attribute_fallthrough_p (std_attrs)) |
12954 | { |
12955 | /* The next token after the fallthrough attribute is ';'. */ |
12956 | if (statement == NULL_TREE) |
12957 | { |
12958 | /* Turn [[fallthrough]]; into FALLTHROUGH ();. */ |
12959 | statement = build_call_expr_internal_loc (statement_location, |
12960 | IFN_FALLTHROUGH, |
12961 | void_type_node, 0); |
12962 | finish_expr_stmt (statement); |
12963 | } |
12964 | else |
12965 | warning_at (statement_location, OPT_Wattributes, |
12966 | "%<fallthrough%> attribute not followed by %<;%>" ); |
12967 | std_attrs = NULL_TREE; |
12968 | } |
12969 | |
12970 | /* Handle [[assert: ...]]; */ |
12971 | if (cp_contract_assertion_p (std_attrs)) |
12972 | { |
12973 | /* Add the assertion as a statement in the current block. */ |
12974 | gcc_assert (!statement || statement == error_mark_node); |
12975 | emit_assertion (std_attrs); |
12976 | std_attrs = NULL_TREE; |
12977 | } |
12978 | } |
12979 | |
12980 | /* Set the line number for the statement. */ |
12981 | if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) |
12982 | SET_EXPR_LOCATION (statement, statement_location); |
12983 | |
12984 | /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise. */ |
12985 | if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs)) |
12986 | warning_at (attrs_loc, OPT_Wattributes, |
12987 | "attributes at the beginning of statement are ignored" ); |
12988 | } |
12989 | |
12990 | /* Append ATTR to attribute list ATTRS. */ |
12991 | |
12992 | tree |
12993 | attr_chainon (tree attrs, tree attr) |
12994 | { |
12995 | if (attrs == error_mark_node) |
12996 | return error_mark_node; |
12997 | if (attr == error_mark_node) |
12998 | return error_mark_node; |
12999 | return chainon (attrs, attr); |
13000 | } |
13001 | |
13002 | /* Parse the label for a labeled-statement, i.e. |
13003 | |
13004 | label: |
13005 | attribute-specifier-seq[opt] identifier : |
13006 | attribute-specifier-seq[opt] case constant-expression : |
13007 | attribute-specifier-seq[opt] default : |
13008 | |
13009 | labeled-statement: |
13010 | label statement |
13011 | |
13012 | GNU Extension: |
13013 | case constant-expression ... constant-expression : statement |
13014 | |
13015 | When a label is parsed without errors, the label is added to the |
13016 | parse tree by the finish_* functions, so this function doesn't |
13017 | have to return the label. */ |
13018 | |
13019 | static void |
13020 | cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes) |
13021 | { |
13022 | cp_token *token; |
13023 | tree label = NULL_TREE; |
13024 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
13025 | |
13026 | /* The next token should be an identifier. */ |
13027 | token = cp_lexer_peek_token (lexer: parser->lexer); |
13028 | if (token->type != CPP_NAME |
13029 | && token->type != CPP_KEYWORD) |
13030 | { |
13031 | cp_parser_error (parser, gmsgid: "expected labeled-statement" ); |
13032 | return; |
13033 | } |
13034 | |
13035 | /* Remember whether this case or a user-defined label is allowed to fall |
13036 | through to. */ |
13037 | bool fallthrough_p = token->flags & PREV_FALLTHROUGH; |
13038 | |
13039 | parser->colon_corrects_to_scope_p = false; |
13040 | switch (token->keyword) |
13041 | { |
13042 | case RID_CASE: |
13043 | { |
13044 | tree expr, expr_hi; |
13045 | cp_token *ellipsis; |
13046 | |
13047 | /* Consume the `case' token. */ |
13048 | cp_lexer_consume_token (lexer: parser->lexer); |
13049 | /* Parse the constant-expression. */ |
13050 | expr = cp_parser_constant_expression (parser); |
13051 | if (check_for_bare_parameter_packs (expr)) |
13052 | expr = error_mark_node; |
13053 | |
13054 | ellipsis = cp_lexer_peek_token (lexer: parser->lexer); |
13055 | if (ellipsis->type == CPP_ELLIPSIS) |
13056 | { |
13057 | /* Consume the `...' token. */ |
13058 | cp_lexer_consume_token (lexer: parser->lexer); |
13059 | expr_hi = cp_parser_constant_expression (parser); |
13060 | if (check_for_bare_parameter_packs (expr_hi)) |
13061 | expr_hi = error_mark_node; |
13062 | |
13063 | /* We don't need to emit warnings here, as the common code |
13064 | will do this for us. */ |
13065 | } |
13066 | else |
13067 | expr_hi = NULL_TREE; |
13068 | |
13069 | if (parser->in_switch_statement_p) |
13070 | { |
13071 | tree l = finish_case_label (token->location, expr, expr_hi); |
13072 | if (l && TREE_CODE (l) == CASE_LABEL_EXPR) |
13073 | { |
13074 | label = CASE_LABEL (l); |
13075 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
13076 | } |
13077 | } |
13078 | else |
13079 | error_at (token->location, |
13080 | "case label %qE not within a switch statement" , |
13081 | expr); |
13082 | } |
13083 | break; |
13084 | |
13085 | case RID_DEFAULT: |
13086 | /* Consume the `default' token. */ |
13087 | cp_lexer_consume_token (lexer: parser->lexer); |
13088 | |
13089 | if (parser->in_switch_statement_p) |
13090 | { |
13091 | tree l = finish_case_label (token->location, NULL_TREE, NULL_TREE); |
13092 | if (l && TREE_CODE (l) == CASE_LABEL_EXPR) |
13093 | { |
13094 | label = CASE_LABEL (l); |
13095 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
13096 | } |
13097 | } |
13098 | else |
13099 | error_at (token->location, "case label not within a switch statement" ); |
13100 | break; |
13101 | |
13102 | default: |
13103 | /* Anything else must be an ordinary label. */ |
13104 | label = finish_label_stmt (cp_parser_identifier (parser)); |
13105 | if (label && TREE_CODE (label) == LABEL_DECL) |
13106 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
13107 | break; |
13108 | } |
13109 | |
13110 | /* Require the `:' token. */ |
13111 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
13112 | |
13113 | /* An ordinary label may optionally be followed by attributes. |
13114 | However, this is only permitted if the attributes are then |
13115 | followed by a semicolon. This is because, for backward |
13116 | compatibility, when parsing |
13117 | lab: __attribute__ ((unused)) int i; |
13118 | we want the attribute to attach to "i", not "lab". */ |
13119 | if (label != NULL_TREE |
13120 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
13121 | { |
13122 | tree attrs; |
13123 | cp_parser_parse_tentatively (parser); |
13124 | attrs = cp_parser_gnu_attributes_opt (parser); |
13125 | if (attrs == NULL_TREE |
13126 | /* And fallthrough always binds to the expression-statement. */ |
13127 | || attribute_fallthrough_p (attrs) |
13128 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13129 | cp_parser_abort_tentative_parse (parser); |
13130 | else if (!cp_parser_parse_definitely (parser)) |
13131 | ; |
13132 | else |
13133 | attributes = attr_chainon (attrs: attributes, attr: attrs); |
13134 | } |
13135 | |
13136 | if (attributes != NULL_TREE) |
13137 | cplus_decl_attributes (&label, attributes, 0); |
13138 | |
13139 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
13140 | } |
13141 | |
13142 | /* Parse an expression-statement. |
13143 | |
13144 | expression-statement: |
13145 | expression [opt] ; |
13146 | |
13147 | Returns the new EXPR_STMT -- or NULL_TREE if the expression |
13148 | statement consists of nothing more than an `;'. IN_STATEMENT_EXPR_P |
13149 | indicates whether this expression-statement is part of an |
13150 | expression statement. */ |
13151 | |
13152 | static tree |
13153 | cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) |
13154 | { |
13155 | tree statement = NULL_TREE; |
13156 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
13157 | location_t loc = token->location; |
13158 | |
13159 | /* There might be attribute fallthrough. */ |
13160 | tree attr = cp_parser_gnu_attributes_opt (parser); |
13161 | |
13162 | /* If the next token is a ';', then there is no expression |
13163 | statement. */ |
13164 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13165 | { |
13166 | statement = cp_parser_expression (parser); |
13167 | if (statement == error_mark_node |
13168 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
13169 | { |
13170 | /* If we ran into a problem, make sure we complained. */ |
13171 | gcc_assert (seen_error ()); |
13172 | |
13173 | cp_parser_skip_to_end_of_block_or_statement (parser); |
13174 | return error_mark_node; |
13175 | } |
13176 | } |
13177 | |
13178 | attr = process_stmt_assume_attribute (attr, statement, loc); |
13179 | |
13180 | /* Handle [[fallthrough]];. */ |
13181 | if (attribute_fallthrough_p (attr)) |
13182 | { |
13183 | /* The next token after the fallthrough attribute is ';'. */ |
13184 | if (statement == NULL_TREE) |
13185 | /* Turn [[fallthrough]]; into FALLTHROUGH ();. */ |
13186 | statement = build_call_expr_internal_loc (loc, IFN_FALLTHROUGH, |
13187 | void_type_node, 0); |
13188 | else |
13189 | warning_at (loc, OPT_Wattributes, |
13190 | "%<fallthrough%> attribute not followed by %<;%>" ); |
13191 | attr = NULL_TREE; |
13192 | } |
13193 | |
13194 | /* Allow "[[fallthrough]];", but warn otherwise. */ |
13195 | if (attr != NULL_TREE && any_nonignored_attribute_p (attr)) |
13196 | warning_at (loc, OPT_Wattributes, |
13197 | "attributes at the beginning of statement are ignored" ); |
13198 | |
13199 | /* Give a helpful message for "A<T>::type t;" and the like. */ |
13200 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON) |
13201 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
13202 | { |
13203 | if (TREE_CODE (statement) == SCOPE_REF) |
13204 | error_at (token->location, "need %<typename%> before %qE because " |
13205 | "%qT is a dependent scope" , |
13206 | statement, TREE_OPERAND (statement, 0)); |
13207 | else if (is_overloaded_fn (statement) |
13208 | && DECL_CONSTRUCTOR_P (get_first_fn (statement))) |
13209 | { |
13210 | /* A::A a; */ |
13211 | tree fn = get_first_fn (statement); |
13212 | error_at (token->location, |
13213 | "%<%T::%D%> names the constructor, not the type" , |
13214 | DECL_CONTEXT (fn), DECL_NAME (fn)); |
13215 | } |
13216 | } |
13217 | |
13218 | /* Consume the final `;'. */ |
13219 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
13220 | |
13221 | if (in_statement_expr |
13222 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
13223 | /* This is the final expression statement of a statement |
13224 | expression. */ |
13225 | statement = finish_stmt_expr_expr (statement, in_statement_expr); |
13226 | else if (statement) |
13227 | statement = finish_expr_stmt (statement); |
13228 | |
13229 | return statement; |
13230 | } |
13231 | |
13232 | /* Parse a compound-statement. |
13233 | |
13234 | compound-statement: |
13235 | { statement-seq [opt] label-seq [opt] } |
13236 | |
13237 | label-seq: |
13238 | label |
13239 | label-seq label |
13240 | |
13241 | GNU extension: |
13242 | |
13243 | compound-statement: |
13244 | { label-declaration-seq [opt] statement-seq [opt] } |
13245 | |
13246 | label-declaration-seq: |
13247 | label-declaration |
13248 | label-declaration-seq label-declaration |
13249 | |
13250 | Returns a tree representing the statement. */ |
13251 | |
13252 | static tree |
13253 | cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, |
13254 | int bcs_flags, bool function_body) |
13255 | { |
13256 | tree compound_stmt; |
13257 | matching_braces braces; |
13258 | |
13259 | /* Consume the `{'. */ |
13260 | if (!braces.require_open (parser)) |
13261 | return error_mark_node; |
13262 | if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
13263 | && !function_body && cxx_dialect < cxx14) |
13264 | pedwarn (input_location, OPT_Wpedantic, |
13265 | "compound-statement in %<constexpr%> function" ); |
13266 | /* Begin the compound-statement. */ |
13267 | compound_stmt = begin_compound_stmt (bcs_flags); |
13268 | /* If the next keyword is `__label__' we have a label declaration. */ |
13269 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_LABEL)) |
13270 | cp_parser_label_declaration (parser); |
13271 | /* Parse an (optional) statement-seq. */ |
13272 | cp_parser_statement_seq_opt (parser, in_statement_expr); |
13273 | |
13274 | /* Consume the `}'. */ |
13275 | braces.require_close (parser); |
13276 | |
13277 | /* Finish the compound-statement. */ |
13278 | finish_compound_stmt (compound_stmt); |
13279 | |
13280 | return compound_stmt; |
13281 | } |
13282 | |
13283 | /* Diagnose errors related to imperfectly nested loops in an OMP |
13284 | loop construct. This function is called when such code is seen. |
13285 | Only issue one such diagnostic no matter how much invalid |
13286 | intervening code there is in the loop. |
13287 | FIXME: maybe the location associated with the diagnostic should |
13288 | be the current parser token instead of the location of the outer loop |
13289 | nest. */ |
13290 | |
13291 | static void |
13292 | check_omp_intervening_code (cp_parser *parser) |
13293 | { |
13294 | struct omp_for_parse_data *omp_for_parse_state |
13295 | = parser->omp_for_parse_state; |
13296 | gcc_assert (omp_for_parse_state); |
13297 | |
13298 | if (!omp_for_parse_state->in_intervening_code) |
13299 | return; |
13300 | omp_for_parse_state->saw_intervening_code = true; |
13301 | |
13302 | /* Only diagnose errors related to perfect nesting once. */ |
13303 | if (!omp_for_parse_state->perfect_nesting_fail) |
13304 | { |
13305 | if (omp_for_parse_state->code == OACC_LOOP) |
13306 | { |
13307 | error_at (omp_for_parse_state->for_loc, |
13308 | "inner loops must be perfectly nested in " |
13309 | "%<#pragma acc loop%>" ); |
13310 | omp_for_parse_state->perfect_nesting_fail = true; |
13311 | } |
13312 | else if (omp_for_parse_state->ordered) |
13313 | { |
13314 | error_at (omp_for_parse_state->for_loc, |
13315 | "inner loops must be perfectly nested with " |
13316 | "%<ordered%> clause" ); |
13317 | omp_for_parse_state->perfect_nesting_fail = true; |
13318 | } |
13319 | else if (omp_for_parse_state->inscan) |
13320 | { |
13321 | error_at (omp_for_parse_state->for_loc, |
13322 | "inner loops must be perfectly nested with " |
13323 | "%<reduction%> %<inscan%> clause" ); |
13324 | omp_for_parse_state->perfect_nesting_fail = true; |
13325 | } |
13326 | /* TODO: Also reject loops with TILE directive. */ |
13327 | if (omp_for_parse_state->perfect_nesting_fail) |
13328 | omp_for_parse_state->fail = true; |
13329 | } |
13330 | } |
13331 | |
13332 | /* Parse an (optional) statement-seq. |
13333 | |
13334 | statement-seq: |
13335 | statement |
13336 | statement-seq [opt] statement */ |
13337 | |
13338 | static void |
13339 | cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) |
13340 | { |
13341 | struct omp_for_parse_data *omp_for_parse_state |
13342 | = parser->omp_for_parse_state; |
13343 | bool in_omp_loop_block |
13344 | = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false; |
13345 | |
13346 | /* Scan statements until there aren't any more. */ |
13347 | while (true) |
13348 | { |
13349 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
13350 | |
13351 | /* If we are looking at a `}', then we have run out of |
13352 | statements; the same is true if we have reached the end |
13353 | of file, or have stumbled upon a stray '@end'. */ |
13354 | if (token->type == CPP_CLOSE_BRACE |
13355 | || token->type == CPP_EOF |
13356 | || token->type == CPP_PRAGMA_EOL |
13357 | || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END)) |
13358 | break; |
13359 | |
13360 | /* If we are in a compound statement and find 'else' then |
13361 | something went wrong. */ |
13362 | else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE) |
13363 | { |
13364 | if (parser->in_statement & IN_IF_STMT) |
13365 | break; |
13366 | else |
13367 | { |
13368 | token = cp_lexer_consume_token (lexer: parser->lexer); |
13369 | error_at (token->location, "%<else%> without a previous %<if%>" ); |
13370 | } |
13371 | } |
13372 | |
13373 | /* Handle special cases for OMP FOR canonical loop syntax. */ |
13374 | else if (in_omp_loop_block) |
13375 | { |
13376 | bool want_nested_loop = omp_for_parse_state->want_nested_loop; |
13377 | if (want_nested_loop |
13378 | && token->type == CPP_KEYWORD && token->keyword == RID_FOR) |
13379 | { |
13380 | /* Found the nested loop. */ |
13381 | omp_for_parse_state->depth++; |
13382 | add_stmt (cp_parser_omp_loop_nest (parser, NULL)); |
13383 | omp_for_parse_state->depth--; |
13384 | } |
13385 | else if (token->type == CPP_SEMICOLON) |
13386 | { |
13387 | /* Prior to implementing the OpenMP 5.1 syntax for canonical |
13388 | loop form, GCC used to accept an empty statements as not |
13389 | being intervening code. Continue to do that, as an |
13390 | extension. */ |
13391 | /* FIXME: Maybe issue a warning or something here? */ |
13392 | cp_lexer_consume_token (lexer: parser->lexer); |
13393 | } |
13394 | else if (want_nested_loop && token->type == CPP_OPEN_BRACE) |
13395 | /* The nested compound statement may contain the next loop, or |
13396 | it might just be intervening code. */ |
13397 | { |
13398 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13399 | if (omp_for_parse_state->want_nested_loop) |
13400 | check_omp_intervening_code (parser); |
13401 | } |
13402 | else |
13403 | { |
13404 | /* This must be intervening code. */ |
13405 | omp_for_parse_state->want_nested_loop = false; |
13406 | /* Defer calling check_omp_intervening_code on pragmas until |
13407 | cp_parser_statement, because we can't know until we parse |
13408 | it whether or not the pragma is a statement. */ |
13409 | if (token->type != CPP_PRAGMA) |
13410 | check_omp_intervening_code (parser); |
13411 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13412 | omp_for_parse_state->want_nested_loop = want_nested_loop; |
13413 | } |
13414 | continue; |
13415 | } |
13416 | |
13417 | /* Parse the statement. */ |
13418 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13419 | } |
13420 | } |
13421 | |
13422 | /* Return true if this is the C++20 version of range-based-for with |
13423 | init-statement. */ |
13424 | |
13425 | static bool |
13426 | cp_parser_range_based_for_with_init_p (cp_parser *parser) |
13427 | { |
13428 | bool r = false; |
13429 | |
13430 | /* Save tokens so that we can put them back. */ |
13431 | cp_lexer_save_tokens (lexer: parser->lexer); |
13432 | |
13433 | /* There has to be an unnested ; followed by an unnested :. */ |
13434 | if (cp_parser_skip_to_closing_parenthesis_1 (parser, |
13435 | /*recovering=*/false, |
13436 | or_ttype: CPP_SEMICOLON, |
13437 | /*consume_paren=*/false) != -1) |
13438 | goto out; |
13439 | |
13440 | /* We found the semicolon, eat it now. */ |
13441 | cp_lexer_consume_token (lexer: parser->lexer); |
13442 | |
13443 | /* Now look for ':' that is not nested in () or {}. */ |
13444 | r = (cp_parser_skip_to_closing_parenthesis_1 (parser, |
13445 | /*recovering=*/false, |
13446 | or_ttype: CPP_COLON, |
13447 | /*consume_paren=*/false) == -1); |
13448 | |
13449 | out: |
13450 | /* Roll back the tokens we skipped. */ |
13451 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
13452 | |
13453 | return r; |
13454 | } |
13455 | |
13456 | /* Return true if we're looking at (init; cond), false otherwise. */ |
13457 | |
13458 | static bool |
13459 | cp_parser_init_statement_p (cp_parser *parser) |
13460 | { |
13461 | /* Save tokens so that we can put them back. */ |
13462 | cp_lexer_save_tokens (lexer: parser->lexer); |
13463 | |
13464 | /* Look for ';' that is not nested in () or {}. */ |
13465 | int ret = cp_parser_skip_to_closing_parenthesis_1 (parser, |
13466 | /*recovering=*/false, |
13467 | or_ttype: CPP_SEMICOLON, |
13468 | /*consume_paren=*/false); |
13469 | |
13470 | /* Roll back the tokens we skipped. */ |
13471 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
13472 | |
13473 | return ret == -1; |
13474 | } |
13475 | |
13476 | /* Parse a selection-statement. |
13477 | |
13478 | selection-statement: |
13479 | if ( init-statement [opt] condition ) statement |
13480 | if ( init-statement [opt] condition ) statement else statement |
13481 | switch ( init-statement [opt] condition ) statement |
13482 | |
13483 | Returns the new IF_STMT or SWITCH_STMT. |
13484 | |
13485 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
13486 | is a (possibly labeled) if statement which is not enclosed in |
13487 | braces and has an else clause. This is used to implement |
13488 | -Wparentheses. |
13489 | |
13490 | CHAIN is a vector of if-else-if conditions. This is used to implement |
13491 | -Wduplicated-cond. */ |
13492 | |
13493 | static tree |
13494 | cp_parser_selection_statement (cp_parser* parser, bool *if_p, |
13495 | vec<tree> *chain) |
13496 | { |
13497 | cp_token *token; |
13498 | enum rid keyword; |
13499 | token_indent_info guard_tinfo; |
13500 | |
13501 | if (if_p != NULL) |
13502 | *if_p = false; |
13503 | |
13504 | /* Peek at the next token. */ |
13505 | token = cp_parser_require (parser, CPP_KEYWORD, RT_SELECT); |
13506 | guard_tinfo = get_token_indent_info (token); |
13507 | |
13508 | /* See what kind of keyword it is. */ |
13509 | keyword = token->keyword; |
13510 | switch (keyword) |
13511 | { |
13512 | case RID_IF: |
13513 | case RID_SWITCH: |
13514 | { |
13515 | tree statement; |
13516 | tree condition; |
13517 | |
13518 | bool cx = false; |
13519 | if (keyword == RID_IF |
13520 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13521 | keyword: RID_CONSTEXPR)) |
13522 | { |
13523 | cx = true; |
13524 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
13525 | if (cxx_dialect < cxx17) |
13526 | pedwarn (tok->location, OPT_Wc__17_extensions, |
13527 | "%<if constexpr%> only available with " |
13528 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
13529 | } |
13530 | int ce = 0; |
13531 | if (keyword == RID_IF && !cx) |
13532 | { |
13533 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13534 | keyword: RID_CONSTEVAL)) |
13535 | ce = 1; |
13536 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
13537 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, |
13538 | keyword: RID_CONSTEVAL)) |
13539 | { |
13540 | ce = -1; |
13541 | cp_lexer_consume_token (lexer: parser->lexer); |
13542 | } |
13543 | } |
13544 | if (ce) |
13545 | { |
13546 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
13547 | if (cxx_dialect < cxx23) |
13548 | pedwarn (tok->location, OPT_Wc__23_extensions, |
13549 | "%<if consteval%> only available with " |
13550 | "%<-std=c++2b%> or %<-std=gnu++2b%>" ); |
13551 | |
13552 | bool save_in_consteval_if_p = in_consteval_if_p; |
13553 | statement = begin_if_stmt (); |
13554 | IF_STMT_CONSTEVAL_P (statement) = true; |
13555 | condition = finish_if_stmt_cond (boolean_false_node, statement); |
13556 | |
13557 | gcc_rich_location richloc (tok->location); |
13558 | bool non_compound_stmt_p = false; |
13559 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13560 | { |
13561 | non_compound_stmt_p = true; |
13562 | richloc.add_fixit_insert_after (where: tok->location, new_content: "{" ); |
13563 | } |
13564 | |
13565 | in_consteval_if_p |= ce > 0; |
13566 | cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo); |
13567 | |
13568 | if (non_compound_stmt_p) |
13569 | { |
13570 | location_t before_loc |
13571 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13572 | richloc.add_fixit_insert_before (where: before_loc, new_content: "}" ); |
13573 | error_at (&richloc, |
13574 | "%<if consteval%> requires compound statement" ); |
13575 | non_compound_stmt_p = false; |
13576 | } |
13577 | |
13578 | finish_then_clause (statement); |
13579 | |
13580 | /* If the next token is `else', parse the else-clause. */ |
13581 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13582 | keyword: RID_ELSE)) |
13583 | { |
13584 | cp_token *else_tok = cp_lexer_peek_token (lexer: parser->lexer); |
13585 | gcc_rich_location else_richloc (else_tok->location); |
13586 | guard_tinfo = get_token_indent_info (token: else_tok); |
13587 | /* Consume the `else' keyword. */ |
13588 | cp_lexer_consume_token (lexer: parser->lexer); |
13589 | |
13590 | begin_else_clause (statement); |
13591 | |
13592 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13593 | { |
13594 | non_compound_stmt_p = true; |
13595 | else_richloc.add_fixit_insert_after (where: else_tok->location, |
13596 | new_content: "{" ); |
13597 | } |
13598 | |
13599 | in_consteval_if_p = save_in_consteval_if_p | (ce < 0); |
13600 | cp_parser_implicitly_scoped_statement (parser, NULL, |
13601 | guard_tinfo); |
13602 | |
13603 | if (non_compound_stmt_p) |
13604 | { |
13605 | location_t before_loc |
13606 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13607 | else_richloc.add_fixit_insert_before (where: before_loc, new_content: "}" ); |
13608 | error_at (&else_richloc, |
13609 | "%<if consteval%> requires compound statement" ); |
13610 | } |
13611 | |
13612 | finish_else_clause (statement); |
13613 | } |
13614 | |
13615 | in_consteval_if_p = save_in_consteval_if_p; |
13616 | if (ce < 0) |
13617 | { |
13618 | std::swap (THEN_CLAUSE (statement), ELSE_CLAUSE (statement)); |
13619 | if (THEN_CLAUSE (statement) == NULL_TREE) |
13620 | THEN_CLAUSE (statement) = build_empty_stmt (tok->location); |
13621 | } |
13622 | |
13623 | finish_if_stmt (statement); |
13624 | return statement; |
13625 | } |
13626 | |
13627 | /* Look for the `('. */ |
13628 | matching_parens parens; |
13629 | if (!parens.require_open (parser)) |
13630 | { |
13631 | cp_parser_skip_to_end_of_statement (parser); |
13632 | return error_mark_node; |
13633 | } |
13634 | |
13635 | /* Begin the selection-statement. */ |
13636 | if (keyword == RID_IF) |
13637 | { |
13638 | statement = begin_if_stmt (); |
13639 | IF_STMT_CONSTEXPR_P (statement) = cx; |
13640 | } |
13641 | else |
13642 | statement = begin_switch_stmt (); |
13643 | |
13644 | /* Parse the optional init-statement. */ |
13645 | if (cp_parser_init_statement_p (parser)) |
13646 | { |
13647 | tree decl; |
13648 | if (cxx_dialect < cxx17) |
13649 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
13650 | OPT_Wc__17_extensions, |
13651 | "init-statement in selection statements only available " |
13652 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
13653 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13654 | /* A non-empty init-statement can have arbitrary side |
13655 | effects. */ |
13656 | vec_free (v&: chain); |
13657 | cp_parser_init_statement (parser, decl: &decl); |
13658 | } |
13659 | |
13660 | /* Parse the condition. */ |
13661 | condition = cp_parser_condition (parser); |
13662 | /* Look for the `)'. */ |
13663 | if (!parens.require_close (parser)) |
13664 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
13665 | /*consume_paren=*/true); |
13666 | |
13667 | if (keyword == RID_IF) |
13668 | { |
13669 | bool nested_if; |
13670 | unsigned char in_statement; |
13671 | |
13672 | /* Add the condition. */ |
13673 | condition = finish_if_stmt_cond (condition, statement); |
13674 | |
13675 | if (warn_duplicated_cond) |
13676 | warn_duplicated_cond_add_or_warn (token->location, condition, |
13677 | &chain); |
13678 | |
13679 | /* Parse the then-clause. */ |
13680 | in_statement = parser->in_statement; |
13681 | parser->in_statement |= IN_IF_STMT; |
13682 | |
13683 | /* Outside a template, the non-selected branch of a constexpr |
13684 | if is a 'discarded statement', i.e. unevaluated. */ |
13685 | bool was_discarded = in_discarded_stmt; |
13686 | bool discard_then = (cx && !processing_template_decl |
13687 | && integer_zerop (condition)); |
13688 | if (discard_then) |
13689 | { |
13690 | in_discarded_stmt = true; |
13691 | ++c_inhibit_evaluation_warnings; |
13692 | } |
13693 | |
13694 | cp_parser_implicitly_scoped_statement (parser, &nested_if, |
13695 | guard_tinfo); |
13696 | |
13697 | parser->in_statement = in_statement; |
13698 | |
13699 | finish_then_clause (statement); |
13700 | |
13701 | if (discard_then) |
13702 | { |
13703 | THEN_CLAUSE (statement) = NULL_TREE; |
13704 | in_discarded_stmt = was_discarded; |
13705 | --c_inhibit_evaluation_warnings; |
13706 | } |
13707 | |
13708 | /* If the next token is `else', parse the else-clause. */ |
13709 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13710 | keyword: RID_ELSE)) |
13711 | { |
13712 | bool discard_else = (cx && !processing_template_decl |
13713 | && integer_nonzerop (condition)); |
13714 | if (discard_else) |
13715 | { |
13716 | in_discarded_stmt = true; |
13717 | ++c_inhibit_evaluation_warnings; |
13718 | } |
13719 | |
13720 | guard_tinfo |
13721 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
13722 | /* Consume the `else' keyword. */ |
13723 | cp_lexer_consume_token (lexer: parser->lexer); |
13724 | if (warn_duplicated_cond) |
13725 | { |
13726 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13727 | keyword: RID_IF) |
13728 | && chain == NULL) |
13729 | { |
13730 | /* We've got "if (COND) else if (COND2)". Start |
13731 | the condition chain and add COND as the first |
13732 | element. */ |
13733 | chain = new vec<tree> (); |
13734 | if (!CONSTANT_CLASS_P (condition) |
13735 | && !TREE_SIDE_EFFECTS (condition)) |
13736 | { |
13737 | /* Wrap it in a NOP_EXPR so that we can set the |
13738 | location of the condition. */ |
13739 | tree e = build1 (NOP_EXPR, TREE_TYPE (condition), |
13740 | condition); |
13741 | SET_EXPR_LOCATION (e, token->location); |
13742 | chain->safe_push (obj: e); |
13743 | } |
13744 | } |
13745 | else if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13746 | keyword: RID_IF)) |
13747 | /* This is if-else without subsequent if. Zap the |
13748 | condition chain; we would have already warned at |
13749 | this point. */ |
13750 | vec_free (v&: chain); |
13751 | } |
13752 | begin_else_clause (statement); |
13753 | /* Parse the else-clause. */ |
13754 | cp_parser_implicitly_scoped_statement (parser, NULL, |
13755 | guard_tinfo, chain); |
13756 | |
13757 | finish_else_clause (statement); |
13758 | |
13759 | /* If we are currently parsing a then-clause, then |
13760 | IF_P will not be NULL. We set it to true to |
13761 | indicate that this if statement has an else clause. |
13762 | This may trigger the Wparentheses warning below |
13763 | when we get back up to the parent if statement. */ |
13764 | if (if_p != NULL) |
13765 | *if_p = true; |
13766 | |
13767 | if (discard_else) |
13768 | { |
13769 | ELSE_CLAUSE (statement) = NULL_TREE; |
13770 | in_discarded_stmt = was_discarded; |
13771 | --c_inhibit_evaluation_warnings; |
13772 | } |
13773 | } |
13774 | else |
13775 | { |
13776 | /* This if statement does not have an else clause. If |
13777 | NESTED_IF is true, then the then-clause has an if |
13778 | statement which does have an else clause. We warn |
13779 | about the potential ambiguity. */ |
13780 | if (nested_if) |
13781 | warning_at (EXPR_LOCATION (statement), OPT_Wdangling_else, |
13782 | "suggest explicit braces to avoid ambiguous" |
13783 | " %<else%>" ); |
13784 | if (warn_duplicated_cond) |
13785 | /* We don't need the condition chain anymore. */ |
13786 | vec_free (v&: chain); |
13787 | } |
13788 | |
13789 | /* Now we're all done with the if-statement. */ |
13790 | finish_if_stmt (statement); |
13791 | } |
13792 | else |
13793 | { |
13794 | bool in_switch_statement_p; |
13795 | unsigned char in_statement; |
13796 | |
13797 | /* Add the condition. */ |
13798 | finish_switch_cond (condition, statement); |
13799 | |
13800 | /* Parse the body of the switch-statement. */ |
13801 | in_switch_statement_p = parser->in_switch_statement_p; |
13802 | in_statement = parser->in_statement; |
13803 | parser->in_switch_statement_p = true; |
13804 | parser->in_statement |= IN_SWITCH_STMT; |
13805 | cp_parser_implicitly_scoped_statement (parser, if_p, |
13806 | guard_tinfo); |
13807 | parser->in_switch_statement_p = in_switch_statement_p; |
13808 | parser->in_statement = in_statement; |
13809 | |
13810 | /* Now we're all done with the switch-statement. */ |
13811 | finish_switch_stmt (statement); |
13812 | } |
13813 | |
13814 | return statement; |
13815 | } |
13816 | break; |
13817 | |
13818 | default: |
13819 | cp_parser_error (parser, gmsgid: "expected selection-statement" ); |
13820 | return error_mark_node; |
13821 | } |
13822 | } |
13823 | |
13824 | /* Helper function for cp_parser_condition and cp_parser_simple_declaration. |
13825 | If we have seen at least one decl-specifier, and the next token is not |
13826 | a parenthesis (after "int (" we might be looking at a functional cast) |
13827 | neither we are dealing with a concept-check expression then we must be |
13828 | looking at a declaration. */ |
13829 | |
13830 | static void |
13831 | cp_parser_maybe_commit_to_declaration (cp_parser* parser, |
13832 | cp_decl_specifier_seq *decl_specs) |
13833 | { |
13834 | if (decl_specs->any_specifiers_p |
13835 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
13836 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE) |
13837 | && !cp_parser_error_occurred (parser) |
13838 | && !(decl_specs->type |
13839 | && TREE_CODE (decl_specs->type) == TYPE_DECL |
13840 | && is_constrained_auto (TREE_TYPE (decl_specs->type)))) |
13841 | cp_parser_commit_to_tentative_parse (parser); |
13842 | } |
13843 | |
13844 | /* Helper function for cp_parser_condition. Enforces [stmt.stmt]/2: |
13845 | The declarator shall not specify a function or an array. Returns |
13846 | TRUE if the declarator is valid, FALSE otherwise. */ |
13847 | |
13848 | static bool |
13849 | cp_parser_check_condition_declarator (cp_parser* parser, |
13850 | cp_declarator *declarator, |
13851 | location_t loc) |
13852 | { |
13853 | if (declarator == cp_error_declarator |
13854 | || function_declarator_p (declarator) |
13855 | || declarator->kind == cdk_array) |
13856 | { |
13857 | if (declarator == cp_error_declarator) |
13858 | /* Already complained. */; |
13859 | else if (declarator->kind == cdk_array) |
13860 | error_at (loc, "condition declares an array" ); |
13861 | else |
13862 | error_at (loc, "condition declares a function" ); |
13863 | if (parser->fully_implicit_function_template_p) |
13864 | abort_fully_implicit_template (parser); |
13865 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
13866 | /*or_comma=*/false, |
13867 | /*consume_paren=*/false); |
13868 | return false; |
13869 | } |
13870 | else |
13871 | return true; |
13872 | } |
13873 | |
13874 | /* Parse a condition. |
13875 | |
13876 | condition: |
13877 | expression |
13878 | type-specifier-seq declarator = initializer-clause |
13879 | type-specifier-seq declarator braced-init-list |
13880 | |
13881 | GNU Extension: |
13882 | |
13883 | condition: |
13884 | type-specifier-seq declarator asm-specification [opt] |
13885 | attributes [opt] = assignment-expression |
13886 | |
13887 | Returns the expression that should be tested. */ |
13888 | |
13889 | static tree |
13890 | cp_parser_condition (cp_parser* parser) |
13891 | { |
13892 | cp_decl_specifier_seq type_specifiers; |
13893 | const char *saved_message; |
13894 | int declares_class_or_enum; |
13895 | |
13896 | /* Try the declaration first. */ |
13897 | cp_parser_parse_tentatively (parser); |
13898 | /* New types are not allowed in the type-specifier-seq for a |
13899 | condition. */ |
13900 | saved_message = parser->type_definition_forbidden_message; |
13901 | parser->type_definition_forbidden_message |
13902 | = G_("types may not be defined in conditions" ); |
13903 | /* Parse the type-specifier-seq. */ |
13904 | cp_parser_decl_specifier_seq (parser, |
13905 | CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR, |
13906 | &type_specifiers, |
13907 | &declares_class_or_enum); |
13908 | /* Restore the saved message. */ |
13909 | parser->type_definition_forbidden_message = saved_message; |
13910 | |
13911 | /* Gather the attributes that were provided with the |
13912 | decl-specifiers. */ |
13913 | tree prefix_attributes = type_specifiers.attributes; |
13914 | |
13915 | cp_parser_maybe_commit_to_declaration (parser, decl_specs: &type_specifiers); |
13916 | |
13917 | /* If all is well, we might be looking at a declaration. */ |
13918 | if (!cp_parser_error_occurred (parser)) |
13919 | { |
13920 | tree decl; |
13921 | tree asm_specification; |
13922 | tree attributes; |
13923 | cp_declarator *declarator; |
13924 | tree initializer = NULL_TREE; |
13925 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13926 | |
13927 | /* Parse the declarator. */ |
13928 | declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
13929 | CP_PARSER_FLAGS_NONE, |
13930 | /*ctor_dtor_or_conv_p=*/NULL, |
13931 | /*parenthesized_p=*/NULL, |
13932 | /*member_p=*/false, |
13933 | /*friend_p=*/false, |
13934 | /*static_p=*/false); |
13935 | /* Parse the attributes. */ |
13936 | attributes = cp_parser_attributes_opt (parser); |
13937 | /* Parse the asm-specification. */ |
13938 | asm_specification = cp_parser_asm_specification_opt (parser); |
13939 | /* If the next token is not an `=' or '{', then we might still be |
13940 | looking at an expression. For example: |
13941 | |
13942 | if (A(a).x) |
13943 | |
13944 | looks like a decl-specifier-seq and a declarator -- but then |
13945 | there is no `=', so this is an expression. */ |
13946 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
13947 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13948 | cp_parser_simulate_error (parser); |
13949 | |
13950 | /* If we did see an `=' or '{', then we are looking at a declaration |
13951 | for sure. */ |
13952 | if (cp_parser_parse_definitely (parser)) |
13953 | { |
13954 | tree pushed_scope; |
13955 | bool non_constant_p = false; |
13956 | int flags = LOOKUP_ONLYCONVERTING; |
13957 | |
13958 | if (!cp_parser_check_condition_declarator (parser, declarator, loc)) |
13959 | return error_mark_node; |
13960 | |
13961 | /* Create the declaration. */ |
13962 | decl = start_decl (declarator, &type_specifiers, |
13963 | /*initialized_p=*/true, |
13964 | attributes, prefix_attributes, |
13965 | &pushed_scope); |
13966 | |
13967 | declarator->init_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13968 | /* Parse the initializer. */ |
13969 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13970 | { |
13971 | initializer = cp_parser_braced_list (parser, &non_constant_p); |
13972 | CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1; |
13973 | flags = 0; |
13974 | } |
13975 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
13976 | { |
13977 | /* Consume the `='. */ |
13978 | cp_lexer_consume_token (lexer: parser->lexer); |
13979 | initializer = cp_parser_initializer_clause (parser, |
13980 | &non_constant_p); |
13981 | } |
13982 | else |
13983 | { |
13984 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
13985 | initializer = error_mark_node; |
13986 | } |
13987 | if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) |
13988 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
13989 | |
13990 | /* Process the initializer. */ |
13991 | cp_finish_decl (decl, |
13992 | initializer, !non_constant_p, |
13993 | asm_specification, |
13994 | flags); |
13995 | |
13996 | if (pushed_scope) |
13997 | pop_scope (pushed_scope); |
13998 | |
13999 | return convert_from_reference (decl); |
14000 | } |
14001 | } |
14002 | /* If we didn't even get past the declarator successfully, we are |
14003 | definitely not looking at a declaration. */ |
14004 | else |
14005 | cp_parser_abort_tentative_parse (parser); |
14006 | |
14007 | /* Otherwise, we are looking at an expression. */ |
14008 | return cp_parser_expression (parser); |
14009 | } |
14010 | |
14011 | /* Parses a for-statement or range-for-statement until the closing ')', |
14012 | not included. */ |
14013 | |
14014 | static tree |
14015 | cp_parser_for (cp_parser *parser, bool ivdep, tree unroll, bool novector) |
14016 | { |
14017 | tree init, scope, decl; |
14018 | bool is_range_for; |
14019 | |
14020 | /* Begin the for-statement. */ |
14021 | scope = begin_for_scope (&init); |
14022 | |
14023 | /* Maybe parse the optional init-statement in a range-based for loop. */ |
14024 | if (cp_parser_range_based_for_with_init_p (parser) |
14025 | /* Checked for diagnostic purposes only. */ |
14026 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14027 | { |
14028 | tree dummy; |
14029 | cp_parser_init_statement (parser, decl: &dummy); |
14030 | if (cxx_dialect < cxx20) |
14031 | { |
14032 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
14033 | OPT_Wc__20_extensions, |
14034 | "range-based %<for%> loops with initializer only " |
14035 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
14036 | decl = error_mark_node; |
14037 | } |
14038 | } |
14039 | |
14040 | /* Parse the initialization. */ |
14041 | is_range_for = cp_parser_init_statement (parser, decl: &decl); |
14042 | |
14043 | if (is_range_for) |
14044 | return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll, |
14045 | novector, false); |
14046 | else |
14047 | return cp_parser_c_for (parser, scope, init, ivdep, unroll, novector); |
14048 | } |
14049 | |
14050 | static tree |
14051 | cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, |
14052 | tree unroll, bool novector) |
14053 | { |
14054 | /* Normal for loop */ |
14055 | tree condition = NULL_TREE; |
14056 | tree expression = NULL_TREE; |
14057 | tree stmt; |
14058 | |
14059 | stmt = begin_for_stmt (scope, init); |
14060 | /* The init-statement has already been parsed in |
14061 | cp_parser_init_statement, so no work is needed here. */ |
14062 | finish_init_stmt (stmt); |
14063 | |
14064 | /* If there's a condition, process it. */ |
14065 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14066 | condition = cp_parser_condition (parser); |
14067 | else if (ivdep) |
14068 | { |
14069 | cp_parser_error (parser, gmsgid: "missing loop condition in loop with " |
14070 | "%<GCC ivdep%> pragma" ); |
14071 | condition = error_mark_node; |
14072 | } |
14073 | else if (unroll) |
14074 | { |
14075 | cp_parser_error (parser, gmsgid: "missing loop condition in loop with " |
14076 | "%<GCC unroll%> pragma" ); |
14077 | condition = error_mark_node; |
14078 | } |
14079 | finish_for_cond (condition, stmt, ivdep, unroll, novector); |
14080 | /* Look for the `;'. */ |
14081 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14082 | |
14083 | /* If there's an expression, process it. */ |
14084 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
14085 | expression = cp_parser_expression (parser); |
14086 | finish_for_expr (expression, stmt); |
14087 | |
14088 | return stmt; |
14089 | } |
14090 | |
14091 | /* Tries to parse a range-based for-statement: |
14092 | |
14093 | range-based-for: |
14094 | decl-specifier-seq declarator : expression |
14095 | |
14096 | The decl-specifier-seq declarator and the `:' are already parsed by |
14097 | cp_parser_init_statement. If processing_template_decl it returns a |
14098 | newly created RANGE_FOR_STMT; if not, it is converted to a |
14099 | regular FOR_STMT. */ |
14100 | |
14101 | static tree |
14102 | cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, |
14103 | bool ivdep, tree unroll, bool novector, bool is_omp) |
14104 | { |
14105 | tree stmt, range_expr; |
14106 | auto_vec <cxx_binding *, 16> bindings; |
14107 | auto_vec <tree, 16> names; |
14108 | cp_decomp decomp_d, *decomp = NULL; |
14109 | |
14110 | /* Get the range declaration momentarily out of the way so that |
14111 | the range expression doesn't clash with it. */ |
14112 | if (range_decl != error_mark_node) |
14113 | { |
14114 | if (DECL_HAS_VALUE_EXPR_P (range_decl)) |
14115 | { |
14116 | tree v = DECL_VALUE_EXPR (range_decl); |
14117 | /* For decomposition declaration get all of the corresponding |
14118 | declarations out of the way. */ |
14119 | if (TREE_CODE (v) == ARRAY_REF |
14120 | && VAR_P (TREE_OPERAND (v, 0)) |
14121 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
14122 | { |
14123 | tree d = range_decl; |
14124 | range_decl = TREE_OPERAND (v, 0); |
14125 | decomp = &decomp_d; |
14126 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
14127 | decomp->decl = d; |
14128 | for (unsigned int i = 0; i < decomp->count; |
14129 | i++, d = DECL_CHAIN (d)) |
14130 | { |
14131 | tree name = DECL_NAME (d); |
14132 | names.safe_push (obj: name); |
14133 | bindings.safe_push (IDENTIFIER_BINDING (name)); |
14134 | IDENTIFIER_BINDING (name) |
14135 | = IDENTIFIER_BINDING (name)->previous; |
14136 | } |
14137 | } |
14138 | } |
14139 | if (names.is_empty ()) |
14140 | { |
14141 | tree name = DECL_NAME (range_decl); |
14142 | names.safe_push (obj: name); |
14143 | bindings.safe_push (IDENTIFIER_BINDING (name)); |
14144 | IDENTIFIER_BINDING (name) = IDENTIFIER_BINDING (name)->previous; |
14145 | } |
14146 | } |
14147 | |
14148 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14149 | range_expr = cp_parser_braced_list (parser); |
14150 | else |
14151 | range_expr = cp_parser_expression (parser); |
14152 | |
14153 | /* Put the range declaration(s) back into scope. */ |
14154 | for (unsigned int i = 0; i < names.length (); i++) |
14155 | { |
14156 | cxx_binding *binding = bindings[i]; |
14157 | binding->previous = IDENTIFIER_BINDING (names[i]); |
14158 | IDENTIFIER_BINDING (names[i]) = binding; |
14159 | } |
14160 | |
14161 | /* finish_omp_for has its own code for the following, so just |
14162 | return the range_expr instead. */ |
14163 | if (is_omp) |
14164 | return range_expr; |
14165 | |
14166 | /* If in template, STMT is converted to a normal for-statement |
14167 | at instantiation. If not, it is done just ahead. */ |
14168 | if (processing_template_decl) |
14169 | { |
14170 | if (check_for_bare_parameter_packs (range_expr)) |
14171 | range_expr = error_mark_node; |
14172 | stmt = begin_range_for_stmt (scope, init); |
14173 | if (ivdep) |
14174 | RANGE_FOR_IVDEP (stmt) = 1; |
14175 | if (unroll) |
14176 | RANGE_FOR_UNROLL (stmt) = unroll; |
14177 | if (novector) |
14178 | RANGE_FOR_NOVECTOR (stmt) = 1; |
14179 | finish_range_for_decl (stmt, range_decl, range_expr); |
14180 | if (!type_dependent_expression_p (range_expr) |
14181 | /* do_auto_deduction doesn't mess with template init-lists. */ |
14182 | && !BRACE_ENCLOSED_INITIALIZER_P (range_expr)) |
14183 | do_range_for_auto_deduction (range_decl, range_expr, decomp); |
14184 | } |
14185 | else |
14186 | { |
14187 | stmt = begin_for_stmt (scope, init); |
14188 | stmt = cp_convert_range_for (stmt, range_decl, range_expr, decomp, |
14189 | ivdep, unroll, novector); |
14190 | } |
14191 | return stmt; |
14192 | } |
14193 | |
14194 | /* Subroutine of cp_convert_range_for: given the initializer expression, |
14195 | builds up the range temporary. */ |
14196 | |
14197 | static tree |
14198 | build_range_temp (tree range_expr) |
14199 | { |
14200 | /* Find out the type deduced by the declaration |
14201 | `auto &&__range = range_expr'. */ |
14202 | tree auto_node = make_auto (); |
14203 | tree range_type = cp_build_reference_type (auto_node, true); |
14204 | range_type = do_auto_deduction (range_type, range_expr, auto_node); |
14205 | |
14206 | /* Create the __range variable. */ |
14207 | tree range_temp = build_decl (input_location, VAR_DECL, |
14208 | for_range__identifier, range_type); |
14209 | TREE_USED (range_temp) = 1; |
14210 | DECL_ARTIFICIAL (range_temp) = 1; |
14211 | |
14212 | return range_temp; |
14213 | } |
14214 | |
14215 | /* Used by cp_parser_range_for in template context: we aren't going to |
14216 | do a full conversion yet, but we still need to resolve auto in the |
14217 | type of the for-range-declaration if present. This is basically |
14218 | a shortcut version of cp_convert_range_for. */ |
14219 | |
14220 | static void |
14221 | do_range_for_auto_deduction (tree decl, tree range_expr, cp_decomp *decomp) |
14222 | { |
14223 | tree auto_node = type_uses_auto (TREE_TYPE (decl)); |
14224 | if (auto_node) |
14225 | { |
14226 | tree begin_dummy, end_dummy, range_temp, iter_type, iter_decl; |
14227 | range_temp = convert_from_reference (build_range_temp (range_expr)); |
14228 | iter_type = (cp_parser_perform_range_for_lookup |
14229 | (range_temp, &begin_dummy, &end_dummy)); |
14230 | if (iter_type) |
14231 | { |
14232 | iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, |
14233 | iter_type); |
14234 | iter_decl = build_x_indirect_ref (input_location, iter_decl, |
14235 | RO_UNARY_STAR, NULL_TREE, |
14236 | tf_warning_or_error); |
14237 | TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), |
14238 | iter_decl, auto_node, |
14239 | tf_warning_or_error, |
14240 | adc_variable_type); |
14241 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
14242 | cp_finish_decomp (decl, decomp); |
14243 | } |
14244 | } |
14245 | } |
14246 | |
14247 | /* Warns when the loop variable should be changed to a reference type to |
14248 | avoid unnecessary copying. I.e., from |
14249 | |
14250 | for (const auto x : range) |
14251 | |
14252 | where range returns a reference, to |
14253 | |
14254 | for (const auto &x : range) |
14255 | |
14256 | if this version doesn't make a copy. |
14257 | |
14258 | This function also warns when the loop variable is initialized with |
14259 | a value of a different type resulting in a copy: |
14260 | |
14261 | int arr[10]; |
14262 | for (const double &x : arr) |
14263 | |
14264 | DECL is the RANGE_DECL; EXPR is the *__for_begin expression. |
14265 | This function is never called when processing_template_decl is on. */ |
14266 | |
14267 | static void |
14268 | warn_for_range_copy (tree decl, tree expr) |
14269 | { |
14270 | if (!warn_range_loop_construct |
14271 | || decl == error_mark_node) |
14272 | return; |
14273 | |
14274 | location_t loc = DECL_SOURCE_LOCATION (decl); |
14275 | tree type = TREE_TYPE (decl); |
14276 | |
14277 | if (from_macro_expansion_at (loc)) |
14278 | return; |
14279 | |
14280 | if (TYPE_REF_P (type)) |
14281 | { |
14282 | if (glvalue_p (expr) |
14283 | && ref_conv_binds_to_temporary (type, expr).is_true ()) |
14284 | { |
14285 | auto_diagnostic_group d; |
14286 | if (warning_at (loc, OPT_Wrange_loop_construct, |
14287 | "loop variable %qD of type %qT binds to a temporary " |
14288 | "constructed from type %qT" , decl, type, |
14289 | TREE_TYPE (expr))) |
14290 | { |
14291 | tree ref = cp_build_qualified_type (TREE_TYPE (expr), |
14292 | TYPE_QUAL_CONST); |
14293 | ref = cp_build_reference_type (ref, /*rval*/false); |
14294 | inform (loc, "use non-reference type %qT to make the copy " |
14295 | "explicit or %qT to prevent copying" , |
14296 | non_reference (type), ref); |
14297 | } |
14298 | } |
14299 | return; |
14300 | } |
14301 | else if (!CP_TYPE_CONST_P (type)) |
14302 | return; |
14303 | |
14304 | /* Since small trivially copyable types are cheap to copy, we suppress the |
14305 | warning for them. 64B is a common size of a cache line. */ |
14306 | if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST |
14307 | || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64 |
14308 | && trivially_copyable_p (type))) |
14309 | return; |
14310 | |
14311 | /* If we can initialize a reference directly, suggest that to avoid the |
14312 | copy. */ |
14313 | tree rtype = cp_build_reference_type (type, /*rval*/false); |
14314 | if (ref_conv_binds_to_temporary (rtype, expr).is_false ()) |
14315 | { |
14316 | auto_diagnostic_group d; |
14317 | if (warning_at (loc, OPT_Wrange_loop_construct, |
14318 | "loop variable %qD creates a copy from type %qT" , |
14319 | decl, type)) |
14320 | { |
14321 | gcc_rich_location richloc (loc); |
14322 | richloc.add_fixit_insert_before (new_content: "&" ); |
14323 | inform (&richloc, "use reference type to prevent copying" ); |
14324 | } |
14325 | } |
14326 | } |
14327 | |
14328 | /* Converts a range-based for-statement into a normal |
14329 | for-statement, as per the definition. |
14330 | |
14331 | for (RANGE_DECL : RANGE_EXPR) |
14332 | BLOCK |
14333 | |
14334 | should be equivalent to: |
14335 | |
14336 | { |
14337 | auto &&__range = RANGE_EXPR; |
14338 | for (auto __begin = BEGIN_EXPR, __end = END_EXPR; |
14339 | __begin != __end; |
14340 | ++__begin) |
14341 | { |
14342 | RANGE_DECL = *__begin; |
14343 | BLOCK |
14344 | } |
14345 | } |
14346 | |
14347 | If RANGE_EXPR is an array: |
14348 | BEGIN_EXPR = __range |
14349 | END_EXPR = __range + ARRAY_SIZE(__range) |
14350 | Else if RANGE_EXPR has a member 'begin' or 'end': |
14351 | BEGIN_EXPR = __range.begin() |
14352 | END_EXPR = __range.end() |
14353 | Else: |
14354 | BEGIN_EXPR = begin(__range) |
14355 | END_EXPR = end(__range); |
14356 | |
14357 | If __range has a member 'begin' but not 'end', or vice versa, we must |
14358 | still use the second alternative (it will surely fail, however). |
14359 | When calling begin()/end() in the third alternative we must use |
14360 | argument dependent lookup, but always considering 'std' as an associated |
14361 | namespace. */ |
14362 | |
14363 | tree |
14364 | cp_convert_range_for (tree statement, tree range_decl, tree range_expr, |
14365 | cp_decomp *decomp, bool ivdep, tree unroll, |
14366 | bool novector) |
14367 | { |
14368 | tree begin, end; |
14369 | tree iter_type, begin_expr, end_expr; |
14370 | tree condition, expression; |
14371 | |
14372 | range_expr = mark_lvalue_use (range_expr); |
14373 | |
14374 | if (range_decl == error_mark_node || range_expr == error_mark_node) |
14375 | /* If an error happened previously do nothing or else a lot of |
14376 | unhelpful errors would be issued. */ |
14377 | begin_expr = end_expr = iter_type = error_mark_node; |
14378 | else |
14379 | { |
14380 | tree range_temp; |
14381 | |
14382 | if (VAR_P (range_expr) |
14383 | && array_of_runtime_bound_p (TREE_TYPE (range_expr))) |
14384 | /* Can't bind a reference to an array of runtime bound. */ |
14385 | range_temp = range_expr; |
14386 | else |
14387 | { |
14388 | range_temp = build_range_temp (range_expr); |
14389 | pushdecl (range_temp); |
14390 | cp_finish_decl (range_temp, range_expr, |
14391 | /*is_constant_init*/false, NULL_TREE, |
14392 | LOOKUP_ONLYCONVERTING); |
14393 | range_temp = convert_from_reference (range_temp); |
14394 | } |
14395 | iter_type = cp_parser_perform_range_for_lookup (range_temp, |
14396 | &begin_expr, &end_expr); |
14397 | } |
14398 | |
14399 | /* The new for initialization statement. */ |
14400 | begin = build_decl (input_location, VAR_DECL, for_begin__identifier, |
14401 | iter_type); |
14402 | TREE_USED (begin) = 1; |
14403 | DECL_ARTIFICIAL (begin) = 1; |
14404 | pushdecl (begin); |
14405 | cp_finish_decl (begin, begin_expr, |
14406 | /*is_constant_init*/false, NULL_TREE, |
14407 | LOOKUP_ONLYCONVERTING); |
14408 | |
14409 | if (cxx_dialect >= cxx17) |
14410 | iter_type = cv_unqualified (TREE_TYPE (end_expr)); |
14411 | end = build_decl (input_location, VAR_DECL, for_end__identifier, iter_type); |
14412 | TREE_USED (end) = 1; |
14413 | DECL_ARTIFICIAL (end) = 1; |
14414 | pushdecl (end); |
14415 | cp_finish_decl (end, end_expr, |
14416 | /*is_constant_init*/false, NULL_TREE, |
14417 | LOOKUP_ONLYCONVERTING); |
14418 | |
14419 | finish_init_stmt (statement); |
14420 | |
14421 | /* The new for condition. */ |
14422 | condition = build_x_binary_op (input_location, NE_EXPR, |
14423 | begin, ERROR_MARK, |
14424 | end, ERROR_MARK, |
14425 | NULL_TREE, NULL, tf_warning_or_error); |
14426 | finish_for_cond (condition, statement, ivdep, unroll, novector); |
14427 | |
14428 | /* The new increment expression. */ |
14429 | expression = finish_unary_op_expr (input_location, |
14430 | PREINCREMENT_EXPR, begin, |
14431 | tf_warning_or_error); |
14432 | finish_for_expr (expression, statement); |
14433 | |
14434 | /* The declaration is initialized with *__begin inside the loop body. */ |
14435 | tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
14436 | NULL_TREE, tf_warning_or_error); |
14437 | cp_finish_decl (range_decl, deref_begin, |
14438 | /*is_constant_init*/false, NULL_TREE, |
14439 | LOOKUP_ONLYCONVERTING, decomp); |
14440 | if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl)) |
14441 | cp_finish_decomp (range_decl, decomp); |
14442 | |
14443 | warn_for_range_copy (decl: range_decl, expr: deref_begin); |
14444 | |
14445 | return statement; |
14446 | } |
14447 | |
14448 | /* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for. |
14449 | We need to solve both at the same time because the method used |
14450 | depends on the existence of members begin or end. |
14451 | Returns the type deduced for the iterator expression. */ |
14452 | |
14453 | static tree |
14454 | cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) |
14455 | { |
14456 | if (error_operand_p (t: range)) |
14457 | { |
14458 | *begin = *end = error_mark_node; |
14459 | return error_mark_node; |
14460 | } |
14461 | |
14462 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (range)))) |
14463 | { |
14464 | error ("range-based %<for%> expression of type %qT " |
14465 | "has incomplete type" , TREE_TYPE (range)); |
14466 | *begin = *end = error_mark_node; |
14467 | return error_mark_node; |
14468 | } |
14469 | if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE) |
14470 | { |
14471 | /* If RANGE is an array, we will use pointer arithmetic. */ |
14472 | *begin = decay_conversion (range, tf_warning_or_error); |
14473 | *end = build_binary_op (input_location, PLUS_EXPR, |
14474 | range, |
14475 | array_type_nelts_top (TREE_TYPE (range)), |
14476 | false); |
14477 | return TREE_TYPE (*begin); |
14478 | } |
14479 | else |
14480 | { |
14481 | /* If it is not an array, we must do a bit of magic. */ |
14482 | tree id_begin, id_end; |
14483 | tree member_begin, member_end; |
14484 | |
14485 | *begin = *end = error_mark_node; |
14486 | |
14487 | id_begin = get_identifier ("begin" ); |
14488 | id_end = get_identifier ("end" ); |
14489 | member_begin = lookup_member (TREE_TYPE (range), id_begin, |
14490 | /*protect=*/2, /*want_type=*/false, |
14491 | tf_warning_or_error); |
14492 | member_end = lookup_member (TREE_TYPE (range), id_end, |
14493 | /*protect=*/2, /*want_type=*/false, |
14494 | tf_warning_or_error); |
14495 | |
14496 | if (member_begin != NULL_TREE && member_end != NULL_TREE) |
14497 | { |
14498 | /* Use the member functions. */ |
14499 | *begin = cp_parser_range_for_member_function (range, id_begin); |
14500 | *end = cp_parser_range_for_member_function (range, id_end); |
14501 | } |
14502 | else |
14503 | { |
14504 | /* Use global functions with ADL. */ |
14505 | releasing_vec vec; |
14506 | |
14507 | vec_safe_push (r&: vec, t: range); |
14508 | |
14509 | member_begin = perform_koenig_lookup (id_begin, vec, |
14510 | tf_warning_or_error); |
14511 | *begin = finish_call_expr (member_begin, &vec, false, true, |
14512 | tf_warning_or_error); |
14513 | member_end = perform_koenig_lookup (id_end, vec, |
14514 | tf_warning_or_error); |
14515 | *end = finish_call_expr (member_end, &vec, false, true, |
14516 | tf_warning_or_error); |
14517 | } |
14518 | |
14519 | /* Last common checks. */ |
14520 | if (*begin == error_mark_node || *end == error_mark_node) |
14521 | { |
14522 | /* If one of the expressions is an error do no more checks. */ |
14523 | *begin = *end = error_mark_node; |
14524 | return error_mark_node; |
14525 | } |
14526 | else if (type_dependent_expression_p (*begin) |
14527 | || type_dependent_expression_p (*end)) |
14528 | /* Can happen, when, eg, in a template context, Koenig lookup |
14529 | can't resolve begin/end (c++/58503). */ |
14530 | return NULL_TREE; |
14531 | else |
14532 | { |
14533 | tree iter_type = cv_unqualified (TREE_TYPE (*begin)); |
14534 | /* The unqualified type of the __begin and __end temporaries should |
14535 | be the same, as required by the multiple auto declaration. */ |
14536 | if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end)))) |
14537 | { |
14538 | if (cxx_dialect >= cxx17 |
14539 | && (build_x_binary_op (input_location, NE_EXPR, |
14540 | *begin, ERROR_MARK, |
14541 | *end, ERROR_MARK, |
14542 | NULL_TREE, NULL, tf_none) |
14543 | != error_mark_node)) |
14544 | /* P0184R0 allows __begin and __end to have different types, |
14545 | but make sure they are comparable so we can give a better |
14546 | diagnostic. */; |
14547 | else |
14548 | error ("inconsistent begin/end types in range-based %<for%> " |
14549 | "statement: %qT and %qT" , |
14550 | TREE_TYPE (*begin), TREE_TYPE (*end)); |
14551 | } |
14552 | return iter_type; |
14553 | } |
14554 | } |
14555 | } |
14556 | |
14557 | /* Helper function for cp_parser_perform_range_for_lookup. |
14558 | Builds a tree for RANGE.IDENTIFIER(). */ |
14559 | |
14560 | static tree |
14561 | cp_parser_range_for_member_function (tree range, tree identifier) |
14562 | { |
14563 | tree member, res; |
14564 | |
14565 | member = finish_class_member_access_expr (range, identifier, |
14566 | false, tf_warning_or_error); |
14567 | if (member == error_mark_node) |
14568 | return error_mark_node; |
14569 | |
14570 | releasing_vec vec; |
14571 | res = finish_call_expr (member, &vec, |
14572 | /*disallow_virtual=*/false, |
14573 | /*koenig_p=*/false, |
14574 | tf_warning_or_error); |
14575 | return res; |
14576 | } |
14577 | |
14578 | /* Parse an iteration-statement. |
14579 | |
14580 | iteration-statement: |
14581 | while ( condition ) statement |
14582 | do statement while ( expression ) ; |
14583 | for ( init-statement condition [opt] ; expression [opt] ) |
14584 | statement |
14585 | |
14586 | Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */ |
14587 | |
14588 | static tree |
14589 | cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, |
14590 | tree unroll, bool novector) |
14591 | { |
14592 | cp_token *token; |
14593 | enum rid keyword; |
14594 | tree statement; |
14595 | unsigned char in_statement; |
14596 | token_indent_info guard_tinfo; |
14597 | |
14598 | /* Peek at the next token. */ |
14599 | token = cp_parser_require (parser, CPP_KEYWORD, RT_ITERATION); |
14600 | if (!token) |
14601 | return error_mark_node; |
14602 | |
14603 | guard_tinfo = get_token_indent_info (token); |
14604 | |
14605 | /* Remember whether or not we are already within an iteration |
14606 | statement. */ |
14607 | in_statement = parser->in_statement; |
14608 | |
14609 | /* Special case for OMP loop intervening code. Parsing of permitted |
14610 | collapsed loop nests is handled elsewhere. */ |
14611 | if (parser->omp_for_parse_state) |
14612 | { |
14613 | error_at (token->location, |
14614 | "loop not permitted in intervening code in OpenMP loop body" ); |
14615 | parser->omp_for_parse_state->fail = true; |
14616 | } |
14617 | |
14618 | /* See what kind of keyword it is. */ |
14619 | keyword = token->keyword; |
14620 | switch (keyword) |
14621 | { |
14622 | case RID_WHILE: |
14623 | { |
14624 | tree condition; |
14625 | |
14626 | /* Begin the while-statement. */ |
14627 | statement = begin_while_stmt (); |
14628 | /* Look for the `('. */ |
14629 | matching_parens parens; |
14630 | parens.require_open (parser); |
14631 | /* Parse the condition. */ |
14632 | condition = cp_parser_condition (parser); |
14633 | finish_while_stmt_cond (condition, statement, ivdep, unroll, novector); |
14634 | /* Look for the `)'. */ |
14635 | parens.require_close (parser); |
14636 | /* Parse the dependent statement. */ |
14637 | parser->in_statement = IN_ITERATION_STMT; |
14638 | bool prev = note_iteration_stmt_body_start (); |
14639 | cp_parser_already_scoped_statement (parser, if_p, guard_tinfo); |
14640 | note_iteration_stmt_body_end (prev); |
14641 | parser->in_statement = in_statement; |
14642 | /* We're done with the while-statement. */ |
14643 | finish_while_stmt (statement); |
14644 | } |
14645 | break; |
14646 | |
14647 | case RID_DO: |
14648 | { |
14649 | tree expression; |
14650 | |
14651 | /* Begin the do-statement. */ |
14652 | statement = begin_do_stmt (); |
14653 | /* Parse the body of the do-statement. */ |
14654 | parser->in_statement = IN_ITERATION_STMT; |
14655 | bool prev = note_iteration_stmt_body_start (); |
14656 | cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo); |
14657 | note_iteration_stmt_body_end (prev); |
14658 | parser->in_statement = in_statement; |
14659 | finish_do_body (statement); |
14660 | /* Look for the `while' keyword. */ |
14661 | cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE); |
14662 | /* Look for the `('. */ |
14663 | matching_parens parens; |
14664 | parens.require_open (parser); |
14665 | /* Parse the expression. */ |
14666 | expression = cp_parser_expression (parser); |
14667 | /* We're done with the do-statement. */ |
14668 | finish_do_stmt (expression, statement, ivdep, unroll, novector); |
14669 | /* Look for the `)'. */ |
14670 | parens.require_close (parser); |
14671 | /* Look for the `;'. */ |
14672 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14673 | } |
14674 | break; |
14675 | |
14676 | case RID_FOR: |
14677 | { |
14678 | /* Look for the `('. */ |
14679 | matching_parens parens; |
14680 | parens.require_open (parser); |
14681 | |
14682 | statement = cp_parser_for (parser, ivdep, unroll, novector); |
14683 | |
14684 | /* Look for the `)'. */ |
14685 | parens.require_close (parser); |
14686 | |
14687 | /* Parse the body of the for-statement. */ |
14688 | parser->in_statement = IN_ITERATION_STMT; |
14689 | bool prev = note_iteration_stmt_body_start (); |
14690 | cp_parser_already_scoped_statement (parser, if_p, guard_tinfo); |
14691 | note_iteration_stmt_body_end (prev); |
14692 | parser->in_statement = in_statement; |
14693 | |
14694 | /* We're done with the for-statement. */ |
14695 | finish_for_stmt (statement); |
14696 | } |
14697 | break; |
14698 | |
14699 | default: |
14700 | cp_parser_error (parser, gmsgid: "expected iteration-statement" ); |
14701 | statement = error_mark_node; |
14702 | break; |
14703 | } |
14704 | |
14705 | return statement; |
14706 | } |
14707 | |
14708 | /* Parse an init-statement or the declarator of a range-based-for. |
14709 | Returns true if a range-based-for declaration is seen. |
14710 | |
14711 | init-statement: |
14712 | expression-statement |
14713 | simple-declaration |
14714 | alias-declaration */ |
14715 | |
14716 | static bool |
14717 | cp_parser_init_statement (cp_parser *parser, tree *decl) |
14718 | { |
14719 | /* If the next token is a `;', then we have an empty |
14720 | expression-statement. Grammatically, this is also a |
14721 | simple-declaration, but an invalid one, because it does not |
14722 | declare anything. Therefore, if we did not handle this case |
14723 | specially, we would issue an error message about an invalid |
14724 | declaration. */ |
14725 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14726 | { |
14727 | bool is_range_for = false; |
14728 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
14729 | |
14730 | /* A colon is used in range-based for. */ |
14731 | parser->colon_corrects_to_scope_p = false; |
14732 | |
14733 | /* We're going to speculatively look for a declaration, falling back |
14734 | to an expression, if necessary. */ |
14735 | cp_parser_parse_tentatively (parser); |
14736 | bool expect_semicolon_p = true; |
14737 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
14738 | { |
14739 | cp_parser_alias_declaration (parser); |
14740 | expect_semicolon_p = false; |
14741 | if (cxx_dialect < cxx23 |
14742 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
14743 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
14744 | OPT_Wc__23_extensions, |
14745 | "alias-declaration in init-statement only " |
14746 | "available with %<-std=c++23%> or %<-std=gnu++23%>" ); |
14747 | } |
14748 | else |
14749 | /* Parse the declaration. */ |
14750 | cp_parser_simple_declaration (parser, |
14751 | /*function_definition_allowed_p=*/false, |
14752 | decl); |
14753 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
14754 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
14755 | { |
14756 | /* It is a range-for, consume the ':'. */ |
14757 | cp_lexer_consume_token (lexer: parser->lexer); |
14758 | is_range_for = true; |
14759 | if (cxx_dialect < cxx11) |
14760 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
14761 | OPT_Wc__11_extensions, |
14762 | "range-based %<for%> loops only available with " |
14763 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
14764 | } |
14765 | else if (expect_semicolon_p) |
14766 | /* The ';' is not consumed yet because we told |
14767 | cp_parser_simple_declaration not to. */ |
14768 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14769 | |
14770 | if (cp_parser_parse_definitely (parser)) |
14771 | return is_range_for; |
14772 | /* If the tentative parse failed, then we shall need to look for an |
14773 | expression-statement. */ |
14774 | } |
14775 | /* If we are here, it is an expression-statement. */ |
14776 | cp_parser_expression_statement (parser, NULL_TREE); |
14777 | return false; |
14778 | } |
14779 | |
14780 | /* Parse a jump-statement. |
14781 | |
14782 | jump-statement: |
14783 | break ; |
14784 | continue ; |
14785 | return expression [opt] ; |
14786 | return braced-init-list ; |
14787 | coroutine-return-statement; |
14788 | goto identifier ; |
14789 | |
14790 | GNU extension: |
14791 | |
14792 | jump-statement: |
14793 | goto * expression ; |
14794 | |
14795 | Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_EXPR, or GOTO_EXPR. */ |
14796 | |
14797 | static tree |
14798 | cp_parser_jump_statement (cp_parser* parser) |
14799 | { |
14800 | tree statement = error_mark_node; |
14801 | cp_token *token; |
14802 | enum rid keyword; |
14803 | unsigned char in_statement; |
14804 | |
14805 | /* Peek at the next token. */ |
14806 | token = cp_parser_require (parser, CPP_KEYWORD, RT_JUMP); |
14807 | if (!token) |
14808 | return error_mark_node; |
14809 | |
14810 | /* See what kind of keyword it is. */ |
14811 | keyword = token->keyword; |
14812 | switch (keyword) |
14813 | { |
14814 | case RID_BREAK: |
14815 | in_statement = parser->in_statement & ~IN_IF_STMT; |
14816 | switch (in_statement) |
14817 | { |
14818 | case 0: |
14819 | error_at (token->location, "break statement not within loop or switch" ); |
14820 | break; |
14821 | default: |
14822 | gcc_assert ((in_statement & IN_SWITCH_STMT) |
14823 | || in_statement == IN_ITERATION_STMT); |
14824 | statement = finish_break_stmt (); |
14825 | if (in_statement == IN_ITERATION_STMT) |
14826 | break_maybe_infinite_loop (); |
14827 | break; |
14828 | case IN_OMP_BLOCK: |
14829 | error_at (token->location, "invalid exit from OpenMP structured block" ); |
14830 | break; |
14831 | case IN_OMP_FOR: |
14832 | error_at (token->location, "break statement used with OpenMP for loop" ); |
14833 | break; |
14834 | } |
14835 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14836 | break; |
14837 | |
14838 | case RID_CONTINUE: |
14839 | switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT)) |
14840 | { |
14841 | case 0: |
14842 | error_at (token->location, "continue statement not within a loop" ); |
14843 | break; |
14844 | /* Fall through. */ |
14845 | case IN_ITERATION_STMT: |
14846 | case IN_OMP_FOR: |
14847 | statement = finish_continue_stmt (); |
14848 | break; |
14849 | case IN_OMP_BLOCK: |
14850 | error_at (token->location, "invalid exit from OpenMP structured block" ); |
14851 | break; |
14852 | default: |
14853 | gcc_unreachable (); |
14854 | } |
14855 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14856 | break; |
14857 | |
14858 | case RID_CO_RETURN: |
14859 | case RID_RETURN: |
14860 | { |
14861 | tree expr; |
14862 | |
14863 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14864 | { |
14865 | cp_lexer_set_source_position (lexer: parser->lexer); |
14866 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
14867 | expr = cp_parser_braced_list (parser); |
14868 | } |
14869 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14870 | expr = cp_parser_expression (parser); |
14871 | else |
14872 | /* If the next token is a `;', then there is no |
14873 | expression. */ |
14874 | expr = NULL_TREE; |
14875 | /* Build the return-statement, check co-return first, since type |
14876 | deduction is not valid there. */ |
14877 | if (keyword == RID_CO_RETURN) |
14878 | statement = finish_co_return_stmt (token->location, expr); |
14879 | else if (FNDECL_USED_AUTO (current_function_decl) && in_discarded_stmt) |
14880 | /* Don't deduce from a discarded return statement. */; |
14881 | else |
14882 | statement = finish_return_stmt (expr); |
14883 | /* Look for the final `;'. */ |
14884 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14885 | } |
14886 | break; |
14887 | |
14888 | case RID_GOTO: |
14889 | if (parser->in_function_body |
14890 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
14891 | && cxx_dialect < cxx23) |
14892 | { |
14893 | error ("%<goto%> in %<constexpr%> function only available with " |
14894 | "%<-std=c++2b%> or %<-std=gnu++2b%>" ); |
14895 | cp_function_chain->invalid_constexpr = true; |
14896 | } |
14897 | |
14898 | /* Create the goto-statement. */ |
14899 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT)) |
14900 | { |
14901 | /* Issue a warning about this use of a GNU extension. */ |
14902 | pedwarn (token->location, OPT_Wpedantic, "ISO C++ forbids computed gotos" ); |
14903 | /* Consume the '*' token. */ |
14904 | cp_lexer_consume_token (lexer: parser->lexer); |
14905 | /* Parse the dependent expression. */ |
14906 | finish_goto_stmt (cp_parser_expression (parser)); |
14907 | } |
14908 | else |
14909 | finish_goto_stmt (cp_parser_identifier (parser)); |
14910 | /* Look for the final `;'. */ |
14911 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14912 | break; |
14913 | |
14914 | default: |
14915 | cp_parser_error (parser, gmsgid: "expected jump-statement" ); |
14916 | break; |
14917 | } |
14918 | |
14919 | return statement; |
14920 | } |
14921 | |
14922 | /* Parse a declaration-statement. |
14923 | |
14924 | declaration-statement: |
14925 | block-declaration */ |
14926 | |
14927 | static void |
14928 | cp_parser_declaration_statement (cp_parser* parser) |
14929 | { |
14930 | void *p; |
14931 | |
14932 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
14933 | p = obstack_alloc (&declarator_obstack, 0); |
14934 | |
14935 | /* Parse the block-declaration. */ |
14936 | cp_parser_block_declaration (parser, /*statement_p=*/true); |
14937 | |
14938 | /* Free any declarators allocated. */ |
14939 | obstack_free (&declarator_obstack, p); |
14940 | } |
14941 | |
14942 | /* Some dependent statements (like `if (cond) statement'), are |
14943 | implicitly in their own scope. In other words, if the statement is |
14944 | a single statement (as opposed to a compound-statement), it is |
14945 | none-the-less treated as if it were enclosed in braces. Any |
14946 | declarations appearing in the dependent statement are out of scope |
14947 | after control passes that point. This function parses a statement, |
14948 | but ensures that is in its own scope, even if it is not a |
14949 | compound-statement. |
14950 | |
14951 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
14952 | is a (possibly labeled) if statement which is not enclosed in |
14953 | braces and has an else clause. This is used to implement |
14954 | -Wparentheses. |
14955 | |
14956 | CHAIN is a vector of if-else-if conditions. This is used to implement |
14957 | -Wduplicated-cond. |
14958 | |
14959 | Returns the new statement. */ |
14960 | |
14961 | static tree |
14962 | cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p, |
14963 | const token_indent_info &guard_tinfo, |
14964 | vec<tree> *chain) |
14965 | { |
14966 | tree statement; |
14967 | location_t body_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
14968 | location_t body_loc_after_labels = UNKNOWN_LOCATION; |
14969 | token_indent_info body_tinfo |
14970 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
14971 | |
14972 | if (if_p != NULL) |
14973 | *if_p = false; |
14974 | |
14975 | /* Mark if () ; with a special NOP_EXPR. */ |
14976 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14977 | { |
14978 | cp_lexer_consume_token (lexer: parser->lexer); |
14979 | statement = add_stmt (build_empty_stmt (body_loc)); |
14980 | |
14981 | if (guard_tinfo.keyword == RID_IF |
14982 | && !cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ELSE)) |
14983 | warning_at (body_loc, OPT_Wempty_body, |
14984 | "suggest braces around empty body in an %<if%> statement" ); |
14985 | else if (guard_tinfo.keyword == RID_ELSE) |
14986 | warning_at (body_loc, OPT_Wempty_body, |
14987 | "suggest braces around empty body in an %<else%> statement" ); |
14988 | } |
14989 | /* if a compound is opened, we simply parse the statement directly. */ |
14990 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14991 | statement = cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
14992 | /* If the token is not a `{', then we must take special action. */ |
14993 | else |
14994 | { |
14995 | /* Create a compound-statement. */ |
14996 | statement = begin_compound_stmt (0); |
14997 | /* Parse the dependent-statement. */ |
14998 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p, chain, |
14999 | loc_after_labels: &body_loc_after_labels); |
15000 | /* Finish the dummy compound-statement. */ |
15001 | finish_compound_stmt (statement); |
15002 | } |
15003 | |
15004 | token_indent_info next_tinfo |
15005 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
15006 | warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo); |
15007 | |
15008 | if (body_loc_after_labels != UNKNOWN_LOCATION |
15009 | && next_tinfo.type != CPP_SEMICOLON) |
15010 | warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location, |
15011 | guard_tinfo.location, guard_tinfo.keyword); |
15012 | |
15013 | /* Return the statement. */ |
15014 | return statement; |
15015 | } |
15016 | |
15017 | /* For some dependent statements (like `while (cond) statement'), we |
15018 | have already created a scope. Therefore, even if the dependent |
15019 | statement is a compound-statement, we do not want to create another |
15020 | scope. */ |
15021 | |
15022 | static void |
15023 | cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p, |
15024 | const token_indent_info &guard_tinfo) |
15025 | { |
15026 | /* If the token is a `{', then we must take special action. */ |
15027 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
15028 | { |
15029 | token_indent_info body_tinfo |
15030 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
15031 | location_t loc_after_labels = UNKNOWN_LOCATION; |
15032 | |
15033 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p, NULL, |
15034 | loc_after_labels: &loc_after_labels); |
15035 | token_indent_info next_tinfo |
15036 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
15037 | warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo); |
15038 | |
15039 | if (loc_after_labels != UNKNOWN_LOCATION |
15040 | && next_tinfo.type != CPP_SEMICOLON) |
15041 | warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, |
15042 | guard_tinfo.location, |
15043 | guard_tinfo.keyword); |
15044 | } |
15045 | else |
15046 | { |
15047 | /* Avoid calling cp_parser_compound_statement, so that we |
15048 | don't create a new scope. Do everything else by hand. */ |
15049 | matching_braces braces; |
15050 | braces.require_open (parser); |
15051 | /* If the next keyword is `__label__' we have a label declaration. */ |
15052 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_LABEL)) |
15053 | cp_parser_label_declaration (parser); |
15054 | /* Parse an (optional) statement-seq. */ |
15055 | cp_parser_statement_seq_opt (parser, NULL_TREE); |
15056 | braces.require_close (parser); |
15057 | } |
15058 | } |
15059 | |
15060 | /* Modules */ |
15061 | |
15062 | /* Parse a module-name or module-partition. |
15063 | |
15064 | module-name: |
15065 | module-name-qualifier [opt] identifier |
15066 | |
15067 | module-partition: |
15068 | : module-name-qualifier [opt] identifier |
15069 | |
15070 | module-name-qualifier: |
15071 | identifier . |
15072 | module-name-qualifier identifier . |
15073 | |
15074 | Returns a pointer to the module object, or NULL on failure. |
15075 | For PARTITION_P, PARENT is the module this is a partition of. */ |
15076 | |
15077 | static module_state * |
15078 | cp_parser_module_name (cp_parser *parser, bool partition_p = false, |
15079 | module_state *parent = NULL) |
15080 | { |
15081 | if (partition_p |
15082 | && cp_lexer_consume_token (lexer: parser->lexer)->type != CPP_COLON) |
15083 | return NULL; |
15084 | |
15085 | for (;;) |
15086 | { |
15087 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_NAME) |
15088 | { |
15089 | if (partition_p) |
15090 | cp_parser_error (parser, gmsgid: "expected module-partition" ); |
15091 | else |
15092 | cp_parser_error (parser, gmsgid: "expected module-name" ); |
15093 | return NULL; |
15094 | } |
15095 | |
15096 | tree name = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
15097 | parent = get_module (name, parent, partition: partition_p); |
15098 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_DOT) |
15099 | break; |
15100 | |
15101 | cp_lexer_consume_token (lexer: parser->lexer); |
15102 | } |
15103 | |
15104 | return parent; |
15105 | } |
15106 | |
15107 | /* Parse a module-partition. Defers to cp_parser_module_name. */ |
15108 | |
15109 | static module_state * |
15110 | cp_parser_module_partition (cp_parser *parser, module_state *parent = NULL) |
15111 | { |
15112 | return cp_parser_module_name (parser, /*partition_p=*/true, parent); |
15113 | } |
15114 | |
15115 | /* Named module-declaration |
15116 | __module ; PRAGMA_EOL |
15117 | __module : private ; PRAGMA_EOL (unimplemented) |
15118 | [__export] __module module-name module-partition [opt] |
15119 | attr-spec-seq-opt ; PRAGMA_EOL |
15120 | */ |
15121 | |
15122 | static module_parse |
15123 | cp_parser_module_declaration (cp_parser *parser, module_parse mp_state, |
15124 | bool exporting) |
15125 | { |
15126 | /* We're a pseudo pragma. */ |
15127 | parser->lexer->in_pragma = true; |
15128 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
15129 | |
15130 | if (flag_header_unit) |
15131 | { |
15132 | error_at (token->location, |
15133 | "module-declaration not permitted in header-unit" ); |
15134 | goto skip_eol; |
15135 | } |
15136 | else if (mp_state == MP_FIRST && !exporting |
15137 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15138 | { |
15139 | /* Start global module fragment. */ |
15140 | cp_lexer_consume_token (lexer: parser->lexer); |
15141 | module_kind = MK_NAMED; |
15142 | mp_state = MP_GLOBAL; |
15143 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
15144 | } |
15145 | else if (!exporting |
15146 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
15147 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_PRIVATE) |
15148 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_SEMICOLON)) |
15149 | { |
15150 | cp_lexer_consume_token (lexer: parser->lexer); |
15151 | cp_lexer_consume_token (lexer: parser->lexer); |
15152 | cp_lexer_consume_token (lexer: parser->lexer); |
15153 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
15154 | |
15155 | if ((mp_state == MP_PURVIEW || mp_state == MP_PURVIEW_IMPORTS) |
15156 | && module_has_cmi_p ()) |
15157 | { |
15158 | mp_state = MP_PRIVATE_IMPORTS; |
15159 | sorry_at (token->location, "private module fragment" ); |
15160 | } |
15161 | else |
15162 | error_at (token->location, |
15163 | "private module fragment only permitted in purview" |
15164 | " of module interface or partition" ); |
15165 | } |
15166 | else if (!(mp_state == MP_FIRST || mp_state == MP_GLOBAL)) |
15167 | { |
15168 | /* Neither the first declaration, nor in a GMF. */ |
15169 | error_at (token->location, "module-declaration only permitted as first" |
15170 | " declaration, or ending a global module fragment" ); |
15171 | skip_eol: |
15172 | cp_parser_skip_to_pragma_eol (parser, pragma_tok: token); |
15173 | } |
15174 | else |
15175 | { |
15176 | module_state *mod = cp_parser_module_name (parser); |
15177 | if (mod && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_COLON) |
15178 | mod = cp_parser_module_partition (parser, parent: mod); |
15179 | tree attrs = cp_parser_attributes_opt (parser); |
15180 | |
15181 | if (mod) |
15182 | mp_state = MP_PURVIEW_IMPORTS; |
15183 | if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
15184 | goto skip_eol; |
15185 | |
15186 | declare_module (mod, token->location, export_p: exporting, attr: attrs, parse_in); |
15187 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
15188 | } |
15189 | |
15190 | return mp_state; |
15191 | } |
15192 | |
15193 | /* Import-declaration |
15194 | __import module-name attr-spec-seq-opt ; PRAGMA_EOL |
15195 | __import module-partition attr-spec-seq-opt ; PRAGMA_EOL |
15196 | __import header-name attr-spec-seq-opt ; PRAGMA_EOL |
15197 | */ |
15198 | |
15199 | static void |
15200 | cp_parser_import_declaration (cp_parser *parser, module_parse mp_state, |
15201 | bool exporting) |
15202 | { |
15203 | /* We're a pseudo pragma. */ |
15204 | parser->lexer->in_pragma = true; |
15205 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
15206 | |
15207 | if (mp_state == MP_PURVIEW || mp_state == MP_PRIVATE) |
15208 | { |
15209 | error_at (token->location, "post-module-declaration" |
15210 | " imports must be contiguous" ); |
15211 | note_lexer: |
15212 | inform (token->location, "perhaps insert a line break, or other" |
15213 | " disambiguation, to prevent this being considered a" |
15214 | " module control-line" ); |
15215 | skip_eol: |
15216 | cp_parser_skip_to_pragma_eol (parser, pragma_tok: token); |
15217 | } |
15218 | else if (current_scope () != global_namespace) |
15219 | { |
15220 | error_at (token->location, "import-declaration must be at global scope" ); |
15221 | goto note_lexer; |
15222 | } |
15223 | else |
15224 | { |
15225 | module_state *mod = NULL; |
15226 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
15227 | if (next->type == CPP_HEADER_NAME) |
15228 | { |
15229 | cp_lexer_consume_token (lexer: parser->lexer); |
15230 | mod = get_module (name: next->u.value); |
15231 | } |
15232 | else if (next->type == CPP_COLON) |
15233 | { |
15234 | /* An import specifying a module-partition shall only appear after the |
15235 | module-declaration in a module unit: [module.import]/4. */ |
15236 | if (named_module_p () |
15237 | && (mp_state == MP_PURVIEW_IMPORTS |
15238 | || mp_state == MP_PRIVATE_IMPORTS)) |
15239 | mod = cp_parser_module_partition (parser); |
15240 | else |
15241 | error_at (next->location, "import specifying a module-partition" |
15242 | " must appear after a named module-declaration" ); |
15243 | } |
15244 | else |
15245 | mod = cp_parser_module_name (parser); |
15246 | tree attrs = cp_parser_attributes_opt (parser); |
15247 | |
15248 | if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
15249 | goto skip_eol; |
15250 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
15251 | |
15252 | if (parser->in_unbraced_linkage_specification_p) |
15253 | error_at (token->location, "import cannot appear directly in" |
15254 | " a linkage-specification" ); |
15255 | |
15256 | if (mp_state == MP_PURVIEW_IMPORTS || mp_state == MP_PRIVATE_IMPORTS) |
15257 | { |
15258 | /* Module-purview imports must not be from source inclusion |
15259 | [cpp.import]/7 */ |
15260 | if (attrs |
15261 | && private_lookup_attribute (attr_name: "__translated" , |
15262 | attr_len: strlen (s: "__translated" ), list: attrs)) |
15263 | error_at (token->location, "post-module-declaration imports" |
15264 | " must not be include-translated" ); |
15265 | else if (!token->main_source_p) |
15266 | error_at (token->location, "post-module-declaration imports" |
15267 | " must not be from header inclusion" ); |
15268 | } |
15269 | |
15270 | import_module (mod, token->location, export_p: exporting, attr: attrs, parse_in); |
15271 | } |
15272 | } |
15273 | |
15274 | /* export-declaration. |
15275 | |
15276 | export declaration |
15277 | export { declaration-seq-opt } */ |
15278 | |
15279 | static void |
15280 | cp_parser_module_export (cp_parser *parser) |
15281 | { |
15282 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT)); |
15283 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
15284 | |
15285 | if (!module_interface_p ()) |
15286 | error_at (token->location, |
15287 | "%qE may only occur after a module interface declaration" , |
15288 | token->u.value); |
15289 | |
15290 | bool braced = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE); |
15291 | |
15292 | unsigned mk = module_kind; |
15293 | if (module_exporting_p ()) |
15294 | error_at (token->location, |
15295 | "%qE may only occur once in an export declaration" , |
15296 | token->u.value); |
15297 | module_kind |= MK_EXPORTING; |
15298 | |
15299 | if (braced) |
15300 | { |
15301 | cp_ensure_no_omp_declare_simd (parser); |
15302 | cp_ensure_no_oacc_routine (parser); |
15303 | |
15304 | cp_lexer_consume_token (lexer: parser->lexer); |
15305 | cp_parser_declaration_seq_opt (parser); |
15306 | cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); |
15307 | } |
15308 | else |
15309 | { |
15310 | /* Explicitly check if the next tokens might be a |
15311 | module-directive line, so we can give a clearer error message |
15312 | about why the directive will be rejected. */ |
15313 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__MODULE) |
15314 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__IMPORT) |
15315 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__EXPORT)) |
15316 | error_at (token->location, "%<export%> not part of following" |
15317 | " module-directive" ); |
15318 | cp_parser_declaration (parser, NULL_TREE); |
15319 | } |
15320 | |
15321 | module_kind = mk; |
15322 | } |
15323 | |
15324 | /* Declarations [gram.dcl.dcl] */ |
15325 | |
15326 | /* Parse an optional declaration-sequence. TOP_LEVEL is true, if this |
15327 | is the top-level declaration sequence. That affects whether we |
15328 | deal with module-preamble. |
15329 | |
15330 | declaration-seq: |
15331 | declaration |
15332 | declaration-seq declaration */ |
15333 | |
15334 | static void |
15335 | cp_parser_declaration_seq_opt (cp_parser* parser) |
15336 | { |
15337 | while (true) |
15338 | { |
15339 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15340 | |
15341 | if (token->type == CPP_CLOSE_BRACE |
15342 | || token->type == CPP_EOF) |
15343 | break; |
15344 | else |
15345 | cp_parser_toplevel_declaration (parser); |
15346 | } |
15347 | } |
15348 | |
15349 | /* Parse a declaration. |
15350 | |
15351 | declaration: |
15352 | block-declaration |
15353 | function-definition |
15354 | template-declaration |
15355 | explicit-instantiation |
15356 | explicit-specialization |
15357 | linkage-specification |
15358 | namespace-definition |
15359 | |
15360 | C++17: |
15361 | deduction-guide |
15362 | |
15363 | modules: |
15364 | (all these are only allowed at the outermost level, check |
15365 | that semantically, for better diagnostics) |
15366 | module-declaration |
15367 | module-export-declaration |
15368 | module-import-declaration |
15369 | export-declaration |
15370 | |
15371 | GNU extension: |
15372 | |
15373 | declaration: |
15374 | __extension__ declaration */ |
15375 | |
15376 | static void |
15377 | cp_parser_declaration (cp_parser* parser, tree prefix_attrs) |
15378 | { |
15379 | int saved_pedantic; |
15380 | |
15381 | /* Check for the `__extension__' keyword. */ |
15382 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
15383 | { |
15384 | /* Parse the qualified declaration. */ |
15385 | cp_parser_declaration (parser, prefix_attrs); |
15386 | /* Restore the PEDANTIC flag. */ |
15387 | pedantic = saved_pedantic; |
15388 | |
15389 | return; |
15390 | } |
15391 | |
15392 | /* Try to figure out what kind of declaration is present. */ |
15393 | cp_token *token1 = cp_lexer_peek_token (lexer: parser->lexer); |
15394 | cp_token *token2 = (token1->type == CPP_EOF |
15395 | ? token1 : cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
15396 | |
15397 | if (token1->type == CPP_SEMICOLON) |
15398 | { |
15399 | cp_lexer_consume_token (lexer: parser->lexer); |
15400 | /* A declaration consisting of a single semicolon is invalid |
15401 | * before C++11. Allow it unless we're being pedantic. */ |
15402 | if (cxx_dialect < cxx11) |
15403 | pedwarn (input_location, OPT_Wpedantic, "extra %<;%>" ); |
15404 | return; |
15405 | } |
15406 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, |
15407 | n: cp_parser_skip_std_attribute_spec_seq (parser, |
15408 | 1), |
15409 | type: CPP_SEMICOLON)) |
15410 | { |
15411 | location_t attrs_loc = token1->location; |
15412 | tree std_attrs = cp_parser_std_attribute_spec_seq (parser); |
15413 | |
15414 | if (std_attrs && (flag_openmp || flag_openmp_simd)) |
15415 | { |
15416 | gcc_assert (!parser->lexer->in_omp_attribute_pragma); |
15417 | std_attrs = cp_parser_handle_statement_omp_attributes (parser, |
15418 | attrs: std_attrs); |
15419 | if (parser->lexer->in_omp_attribute_pragma) |
15420 | { |
15421 | cp_lexer *lexer = parser->lexer; |
15422 | while (parser->lexer->in_omp_attribute_pragma) |
15423 | { |
15424 | gcc_assert (cp_lexer_next_token_is (parser->lexer, |
15425 | CPP_PRAGMA)); |
15426 | cp_parser_pragma (parser, pragma_external, NULL); |
15427 | } |
15428 | cp_lexer_destroy (lexer); |
15429 | } |
15430 | } |
15431 | |
15432 | if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs)) |
15433 | warning_at (make_location (caret: attrs_loc, start: attrs_loc, lexer: parser->lexer), |
15434 | OPT_Wattributes, "attribute ignored" ); |
15435 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15436 | cp_lexer_consume_token (lexer: parser->lexer); |
15437 | return; |
15438 | } |
15439 | |
15440 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
15441 | void *p = obstack_alloc (&declarator_obstack, 0); |
15442 | |
15443 | tree attributes = NULL_TREE; |
15444 | |
15445 | /* Conditionally, allow attributes to precede a linkage specification. */ |
15446 | if (token1->keyword == RID_ATTRIBUTE) |
15447 | { |
15448 | cp_lexer_save_tokens (lexer: parser->lexer); |
15449 | attributes = cp_parser_attributes_opt (parser); |
15450 | cp_token *t1 = cp_lexer_peek_token (lexer: parser->lexer); |
15451 | cp_token *t2 = (t1->type == CPP_EOF |
15452 | ? t1 : cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
15453 | if (t1->keyword == RID_EXTERN |
15454 | && cp_parser_is_pure_string_literal (token: t2)) |
15455 | { |
15456 | cp_lexer_commit_tokens (lexer: parser->lexer); |
15457 | /* We might have already been here. */ |
15458 | if (!c_dialect_objc ()) |
15459 | { |
15460 | location_t where = get_finish (loc: t2->location); |
15461 | warning_at (token1->location, OPT_Wattributes, "attributes are" |
15462 | " not permitted in this position" ); |
15463 | where = linemap_position_for_loc_and_offset (set: line_table, |
15464 | loc: where, offset: 1); |
15465 | inform (where, "attributes may be inserted here" ); |
15466 | attributes = NULL_TREE; |
15467 | } |
15468 | token1 = t1; |
15469 | token2 = t2; |
15470 | } |
15471 | else |
15472 | { |
15473 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
15474 | attributes = NULL_TREE; |
15475 | } |
15476 | } |
15477 | /* If we already had some attributes, and we've added more, then prepend. |
15478 | Otherwise attributes just contains any that we just read. */ |
15479 | if (prefix_attrs) |
15480 | { |
15481 | if (attributes) |
15482 | TREE_CHAIN (prefix_attrs) = attributes; |
15483 | attributes = prefix_attrs; |
15484 | } |
15485 | |
15486 | /* If the next token is `extern' and the following token is a string |
15487 | literal, then we have a linkage specification. */ |
15488 | if (token1->keyword == RID_EXTERN |
15489 | && cp_parser_is_pure_string_literal (token: token2)) |
15490 | cp_parser_linkage_specification (parser, attributes); |
15491 | /* If the next token is `template', then we have either a template |
15492 | declaration, an explicit instantiation, or an explicit |
15493 | specialization. */ |
15494 | else if (token1->keyword == RID_TEMPLATE) |
15495 | { |
15496 | /* `template <>' indicates a template specialization. */ |
15497 | if (token2->type == CPP_LESS |
15498 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_GREATER) |
15499 | cp_parser_explicit_specialization (parser); |
15500 | /* `template <' indicates a template declaration. */ |
15501 | else if (token2->type == CPP_LESS) |
15502 | cp_parser_template_declaration (parser, /*member_p=*/false); |
15503 | /* Anything else must be an explicit instantiation. */ |
15504 | else |
15505 | cp_parser_explicit_instantiation (parser); |
15506 | } |
15507 | /* If the next token is `export', it's new-style modules or |
15508 | old-style template. */ |
15509 | else if (token1->keyword == RID_EXPORT) |
15510 | { |
15511 | if (!modules_p ()) |
15512 | cp_parser_template_declaration (parser, /*member_p=*/false); |
15513 | else |
15514 | cp_parser_module_export (parser); |
15515 | } |
15516 | else if (cp_token_is_module_directive (token: token1)) |
15517 | { |
15518 | bool exporting = token1->keyword == RID__EXPORT; |
15519 | cp_token *next = exporting ? token2 : token1; |
15520 | if (exporting) |
15521 | cp_lexer_consume_token (lexer: parser->lexer); |
15522 | // In module purview this will be ill-formed. |
15523 | auto state = (!named_module_p () ? MP_NOT_MODULE |
15524 | : module_purview_p () ? MP_PURVIEW |
15525 | : MP_GLOBAL); |
15526 | if (next->keyword == RID__MODULE) |
15527 | cp_parser_module_declaration (parser, mp_state: state, exporting); |
15528 | else |
15529 | cp_parser_import_declaration (parser, mp_state: state, exporting); |
15530 | } |
15531 | /* If the next token is `extern', 'static' or 'inline' and the one |
15532 | after that is `template', we have a GNU extended explicit |
15533 | instantiation directive. */ |
15534 | else if (cp_parser_allow_gnu_extensions_p (parser) |
15535 | && token2->keyword == RID_TEMPLATE |
15536 | && (token1->keyword == RID_EXTERN |
15537 | || token1->keyword == RID_STATIC |
15538 | || token1->keyword == RID_INLINE)) |
15539 | cp_parser_explicit_instantiation (parser); |
15540 | /* If the next token is `namespace', check for a named or unnamed |
15541 | namespace definition. */ |
15542 | else if (token1->keyword == RID_NAMESPACE |
15543 | && (/* A named namespace definition. */ |
15544 | (token2->type == CPP_NAME |
15545 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
15546 | != CPP_EQ)) |
15547 | || (token2->type == CPP_OPEN_SQUARE |
15548 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
15549 | == CPP_OPEN_SQUARE) |
15550 | /* An unnamed namespace definition. */ |
15551 | || token2->type == CPP_OPEN_BRACE |
15552 | || token2->keyword == RID_ATTRIBUTE)) |
15553 | cp_parser_namespace_definition (parser); |
15554 | /* An inline (associated) namespace definition. */ |
15555 | else if (token2->keyword == RID_NAMESPACE |
15556 | && token1->keyword == RID_INLINE) |
15557 | cp_parser_namespace_definition (parser); |
15558 | /* Objective-C++ declaration/definition. */ |
15559 | else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1->keyword)) |
15560 | cp_parser_objc_declaration (parser, attributes); |
15561 | else if (c_dialect_objc () |
15562 | && token1->keyword == RID_ATTRIBUTE |
15563 | && cp_parser_objc_valid_prefix_attributes (parser, &attributes)) |
15564 | cp_parser_objc_declaration (parser, attributes); |
15565 | /* At this point we may have a template declared by a concept |
15566 | introduction. */ |
15567 | else if (flag_concepts |
15568 | && cp_parser_template_declaration_after_export (parser, |
15569 | /*member_p=*/false)) |
15570 | /* We did. */; |
15571 | else |
15572 | /* Try to parse a block-declaration, or a function-definition. */ |
15573 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
15574 | |
15575 | /* Free any declarators allocated. */ |
15576 | obstack_free (&declarator_obstack, p); |
15577 | } |
15578 | |
15579 | /* Parse a namespace-scope declaration. */ |
15580 | |
15581 | static void |
15582 | cp_parser_toplevel_declaration (cp_parser* parser) |
15583 | { |
15584 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15585 | |
15586 | if (token->type == CPP_PRAGMA) |
15587 | /* A top-level declaration can consist solely of a #pragma. A |
15588 | nested declaration cannot, so this is done here and not in |
15589 | cp_parser_declaration. (A #pragma at block scope is |
15590 | handled in cp_parser_statement.) */ |
15591 | cp_parser_pragma (parser, pragma_external, NULL); |
15592 | else |
15593 | /* Parse the declaration itself. */ |
15594 | cp_parser_declaration (parser, NULL_TREE); |
15595 | } |
15596 | |
15597 | /* Parse a block-declaration. |
15598 | |
15599 | block-declaration: |
15600 | simple-declaration |
15601 | asm-definition |
15602 | namespace-alias-definition |
15603 | using-declaration |
15604 | using-directive |
15605 | |
15606 | GNU Extension: |
15607 | |
15608 | block-declaration: |
15609 | __extension__ block-declaration |
15610 | |
15611 | C++0x Extension: |
15612 | |
15613 | block-declaration: |
15614 | static_assert-declaration |
15615 | |
15616 | If STATEMENT_P is TRUE, then this block-declaration is occurring as |
15617 | part of a declaration-statement. */ |
15618 | |
15619 | static void |
15620 | cp_parser_block_declaration (cp_parser *parser, |
15621 | bool statement_p) |
15622 | { |
15623 | int saved_pedantic; |
15624 | |
15625 | /* Check for the `__extension__' keyword. */ |
15626 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
15627 | { |
15628 | /* Parse the qualified declaration. */ |
15629 | cp_parser_block_declaration (parser, statement_p); |
15630 | /* Restore the PEDANTIC flag. */ |
15631 | pedantic = saved_pedantic; |
15632 | |
15633 | return; |
15634 | } |
15635 | |
15636 | /* Peek at the next token to figure out which kind of declaration is |
15637 | present. */ |
15638 | cp_token *token1 = cp_lexer_peek_token (lexer: parser->lexer); |
15639 | |
15640 | /* If the next keyword is `asm', we have an asm-definition. */ |
15641 | if (token1->keyword == RID_ASM) |
15642 | { |
15643 | if (statement_p) |
15644 | cp_parser_commit_to_tentative_parse (parser); |
15645 | cp_parser_asm_definition (parser); |
15646 | } |
15647 | /* If the next keyword is `namespace', we have a |
15648 | namespace-alias-definition. */ |
15649 | else if (token1->keyword == RID_NAMESPACE) |
15650 | cp_parser_namespace_alias_definition (parser); |
15651 | /* If the next keyword is `using', we have a |
15652 | using-declaration, a using-directive, or an alias-declaration. */ |
15653 | else if (token1->keyword == RID_USING) |
15654 | { |
15655 | cp_token *token2; |
15656 | |
15657 | if (statement_p) |
15658 | cp_parser_commit_to_tentative_parse (parser); |
15659 | /* If the token after `using' is `namespace', then we have a |
15660 | using-directive. */ |
15661 | token2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
15662 | if (token2->keyword == RID_NAMESPACE) |
15663 | cp_parser_using_directive (parser); |
15664 | else if (token2->keyword == RID_ENUM) |
15665 | cp_parser_using_enum (parser); |
15666 | /* If the second token after 'using' is '=', then we have an |
15667 | alias-declaration. */ |
15668 | else if (cxx_dialect >= cxx11 |
15669 | && token2->type == CPP_NAME |
15670 | && ((cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_EQ) |
15671 | || (cp_nth_tokens_can_be_attribute_p (parser, 3)))) |
15672 | cp_parser_alias_declaration (parser); |
15673 | /* Otherwise, it's a using-declaration. */ |
15674 | else |
15675 | cp_parser_using_declaration (parser, |
15676 | /*access_declaration_p=*/false); |
15677 | } |
15678 | /* If the next keyword is `__label__' we have a misplaced label |
15679 | declaration. */ |
15680 | else if (token1->keyword == RID_LABEL) |
15681 | { |
15682 | cp_lexer_consume_token (lexer: parser->lexer); |
15683 | error_at (token1->location, "%<__label__%> not at the beginning of a block" ); |
15684 | cp_parser_skip_to_end_of_statement (parser); |
15685 | /* If the next token is now a `;', consume it. */ |
15686 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15687 | cp_lexer_consume_token (lexer: parser->lexer); |
15688 | } |
15689 | /* If the next token is `static_assert' we have a static assertion. */ |
15690 | else if (token1->keyword == RID_STATIC_ASSERT) |
15691 | cp_parser_static_assert (parser, /*member_p=*/false); |
15692 | else |
15693 | { |
15694 | size_t attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1); |
15695 | cp_token *after_attr = NULL; |
15696 | if (attr_idx != 1) |
15697 | after_attr = cp_lexer_peek_nth_token (lexer: parser->lexer, n: attr_idx); |
15698 | /* If the next tokens after attributes is `using namespace', then we have |
15699 | a using-directive. */ |
15700 | if (after_attr |
15701 | && after_attr->keyword == RID_USING |
15702 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: attr_idx + 1, |
15703 | keyword: RID_NAMESPACE)) |
15704 | { |
15705 | if (statement_p) |
15706 | cp_parser_commit_to_tentative_parse (parser); |
15707 | cp_parser_using_directive (parser); |
15708 | } |
15709 | /* If the next token after attributes is `asm', then we have |
15710 | an asm-definition. */ |
15711 | else if (after_attr && after_attr->keyword == RID_ASM) |
15712 | { |
15713 | if (statement_p) |
15714 | cp_parser_commit_to_tentative_parse (parser); |
15715 | cp_parser_asm_definition (parser); |
15716 | } |
15717 | /* Anything else must be a simple-declaration. */ |
15718 | else |
15719 | cp_parser_simple_declaration (parser, !statement_p, |
15720 | /*maybe_range_for_decl*/NULL); |
15721 | } |
15722 | } |
15723 | |
15724 | /* Parse a simple-declaration. |
15725 | |
15726 | simple-declaration: |
15727 | decl-specifier-seq [opt] init-declarator-list [opt] ; |
15728 | decl-specifier-seq ref-qualifier [opt] [ identifier-list ] |
15729 | brace-or-equal-initializer ; |
15730 | |
15731 | init-declarator-list: |
15732 | init-declarator |
15733 | init-declarator-list , init-declarator |
15734 | |
15735 | If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a |
15736 | function-definition as a simple-declaration. |
15737 | |
15738 | If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the |
15739 | parsed declaration if it is an uninitialized single declarator not followed |
15740 | by a `;', or to error_mark_node otherwise. Either way, the trailing `;', |
15741 | if present, will not be consumed. */ |
15742 | |
15743 | static void |
15744 | cp_parser_simple_declaration (cp_parser* parser, |
15745 | bool function_definition_allowed_p, |
15746 | tree *maybe_range_for_decl) |
15747 | { |
15748 | cp_decl_specifier_seq decl_specifiers; |
15749 | int declares_class_or_enum; |
15750 | bool saw_declarator; |
15751 | location_t comma_loc = UNKNOWN_LOCATION; |
15752 | location_t init_loc = UNKNOWN_LOCATION; |
15753 | |
15754 | if (maybe_range_for_decl) |
15755 | *maybe_range_for_decl = NULL_TREE; |
15756 | |
15757 | /* Defer access checks until we know what is being declared; the |
15758 | checks for names appearing in the decl-specifier-seq should be |
15759 | done as if we were in the scope of the thing being declared. */ |
15760 | push_deferring_access_checks (dk_deferred); |
15761 | |
15762 | /* Parse the decl-specifier-seq. We have to keep track of whether |
15763 | or not the decl-specifier-seq declares a named class or |
15764 | enumeration type, since that is the only case in which the |
15765 | init-declarator-list is allowed to be empty. |
15766 | |
15767 | [dcl.dcl] |
15768 | |
15769 | In a simple-declaration, the optional init-declarator-list can be |
15770 | omitted only when declaring a class or enumeration, that is when |
15771 | the decl-specifier-seq contains either a class-specifier, an |
15772 | elaborated-type-specifier, or an enum-specifier. */ |
15773 | cp_parser_decl_specifier_seq (parser, |
15774 | CP_PARSER_FLAGS_OPTIONAL, |
15775 | &decl_specifiers, |
15776 | &declares_class_or_enum); |
15777 | /* We no longer need to defer access checks. */ |
15778 | stop_deferring_access_checks (); |
15779 | |
15780 | cp_omp_declare_simd_data odsd; |
15781 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
15782 | cp_parser_handle_directive_omp_attributes (parser, |
15783 | pattrs: &decl_specifiers.attributes, |
15784 | data: &odsd, start: true); |
15785 | |
15786 | /* In a block scope, a valid declaration must always have a |
15787 | decl-specifier-seq. By not trying to parse declarators, we can |
15788 | resolve the declaration/expression ambiguity more quickly. */ |
15789 | if (!function_definition_allowed_p |
15790 | && !decl_specifiers.any_specifiers_p) |
15791 | { |
15792 | cp_parser_error (parser, gmsgid: "expected declaration" ); |
15793 | goto done; |
15794 | } |
15795 | |
15796 | /* If the next two tokens are both identifiers, the code is |
15797 | erroneous. The usual cause of this situation is code like: |
15798 | |
15799 | T t; |
15800 | |
15801 | where "T" should name a type -- but does not. */ |
15802 | if (!decl_specifiers.any_type_specifiers_p |
15803 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
15804 | { |
15805 | /* If parsing tentatively, we should commit; we really are |
15806 | looking at a declaration. */ |
15807 | cp_parser_commit_to_tentative_parse (parser); |
15808 | /* Give up. */ |
15809 | goto done; |
15810 | } |
15811 | |
15812 | cp_parser_maybe_commit_to_declaration (parser, decl_specs: &decl_specifiers); |
15813 | |
15814 | /* Look for C++17 decomposition declaration. */ |
15815 | for (size_t n = 1; ; n++) |
15816 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_AND) |
15817 | || cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_AND_AND)) |
15818 | continue; |
15819 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_OPEN_SQUARE) |
15820 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_SQUARE) |
15821 | && decl_specifiers.any_specifiers_p) |
15822 | { |
15823 | tree decl |
15824 | = cp_parser_decomposition_declaration (parser, &decl_specifiers, |
15825 | maybe_range_for_decl, |
15826 | &init_loc); |
15827 | |
15828 | /* The next token should be either a `,' or a `;'. */ |
15829 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15830 | /* If it's a `;', we are done. */ |
15831 | if (token->type == CPP_SEMICOLON) |
15832 | goto finish; |
15833 | else if (maybe_range_for_decl) |
15834 | { |
15835 | if (*maybe_range_for_decl == NULL_TREE) |
15836 | *maybe_range_for_decl = error_mark_node; |
15837 | goto finish; |
15838 | } |
15839 | /* Anything else is an error. */ |
15840 | else |
15841 | { |
15842 | /* If we have already issued an error message we don't need |
15843 | to issue another one. */ |
15844 | if ((decl != error_mark_node |
15845 | && DECL_INITIAL (decl) != error_mark_node) |
15846 | || cp_parser_uncommitted_to_tentative_parse_p (parser)) |
15847 | cp_parser_error (parser, gmsgid: "expected %<;%>" ); |
15848 | /* Skip tokens until we reach the end of the statement. */ |
15849 | cp_parser_skip_to_end_of_statement (parser); |
15850 | /* If the next token is now a `;', consume it. */ |
15851 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15852 | cp_lexer_consume_token (lexer: parser->lexer); |
15853 | goto done; |
15854 | } |
15855 | } |
15856 | else |
15857 | break; |
15858 | |
15859 | tree last_type; |
15860 | bool auto_specifier_p; |
15861 | /* NULL_TREE if both variable and function declaration are allowed, |
15862 | error_mark_node if function declaration are not allowed and |
15863 | a FUNCTION_DECL that should be diagnosed if it is followed by |
15864 | variable declarations. */ |
15865 | tree auto_function_declaration; |
15866 | |
15867 | last_type = NULL_TREE; |
15868 | auto_specifier_p |
15869 | = decl_specifiers.type && type_uses_auto (decl_specifiers.type); |
15870 | auto_function_declaration = NULL_TREE; |
15871 | |
15872 | /* Keep going until we hit the `;' at the end of the simple |
15873 | declaration. */ |
15874 | saw_declarator = false; |
15875 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, |
15876 | type: CPP_SEMICOLON)) |
15877 | { |
15878 | cp_token *token; |
15879 | bool function_definition_p; |
15880 | tree decl; |
15881 | tree auto_result = NULL_TREE; |
15882 | |
15883 | if (saw_declarator) |
15884 | { |
15885 | /* If we are processing next declarator, comma is expected */ |
15886 | token = cp_lexer_peek_token (lexer: parser->lexer); |
15887 | gcc_assert (token->type == CPP_COMMA); |
15888 | cp_lexer_consume_token (lexer: parser->lexer); |
15889 | if (maybe_range_for_decl) |
15890 | { |
15891 | *maybe_range_for_decl = error_mark_node; |
15892 | if (comma_loc == UNKNOWN_LOCATION) |
15893 | comma_loc = token->location; |
15894 | } |
15895 | } |
15896 | else |
15897 | saw_declarator = true; |
15898 | |
15899 | /* Parse the init-declarator. */ |
15900 | decl = cp_parser_init_declarator (parser, |
15901 | CP_PARSER_FLAGS_NONE, |
15902 | &decl_specifiers, |
15903 | /*checks=*/NULL, |
15904 | function_definition_allowed_p, |
15905 | /*member_p=*/false, |
15906 | declares_class_or_enum, |
15907 | &function_definition_p, |
15908 | maybe_range_for_decl, |
15909 | &init_loc, |
15910 | &auto_result); |
15911 | const bool fndecl_p = TREE_CODE (decl) == FUNCTION_DECL; |
15912 | /* If an error occurred while parsing tentatively, exit quickly. |
15913 | (That usually happens when in the body of a function; each |
15914 | statement is treated as a declaration-statement until proven |
15915 | otherwise.) */ |
15916 | if (cp_parser_error_occurred (parser)) |
15917 | goto done; |
15918 | |
15919 | if (auto_specifier_p && cxx_dialect >= cxx14) |
15920 | { |
15921 | /* If the init-declarator-list contains more than one |
15922 | init-declarator, they shall all form declarations of |
15923 | variables. */ |
15924 | if (auto_function_declaration == NULL_TREE) |
15925 | auto_function_declaration = fndecl_p ? decl : error_mark_node; |
15926 | else if (fndecl_p || auto_function_declaration != error_mark_node) |
15927 | { |
15928 | error_at (decl_specifiers.locations[ds_type_spec], |
15929 | "non-variable %qD in declaration with more than one " |
15930 | "declarator with placeholder type" , |
15931 | fndecl_p ? decl : auto_function_declaration); |
15932 | auto_function_declaration = error_mark_node; |
15933 | } |
15934 | } |
15935 | |
15936 | if (auto_result |
15937 | && (!processing_template_decl || !type_uses_auto (auto_result))) |
15938 | { |
15939 | if (last_type |
15940 | && last_type != error_mark_node |
15941 | && !same_type_p (auto_result, last_type)) |
15942 | { |
15943 | /* If the list of declarators contains more than one declarator, |
15944 | the type of each declared variable is determined as described |
15945 | above. If the type deduced for the template parameter U is not |
15946 | the same in each deduction, the program is ill-formed. */ |
15947 | error_at (decl_specifiers.locations[ds_type_spec], |
15948 | "inconsistent deduction for %qT: %qT and then %qT" , |
15949 | decl_specifiers.type, last_type, auto_result); |
15950 | last_type = error_mark_node; |
15951 | } |
15952 | else |
15953 | last_type = auto_result; |
15954 | } |
15955 | |
15956 | /* Handle function definitions specially. */ |
15957 | if (function_definition_p) |
15958 | { |
15959 | /* If the next token is a `,', then we are probably |
15960 | processing something like: |
15961 | |
15962 | void f() {}, *p; |
15963 | |
15964 | which is erroneous. */ |
15965 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
15966 | { |
15967 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15968 | error_at (token->location, |
15969 | "mixing" |
15970 | " declarations and function-definitions is forbidden" ); |
15971 | } |
15972 | /* Otherwise, we're done with the list of declarators. */ |
15973 | else |
15974 | { |
15975 | pop_deferring_access_checks (); |
15976 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
15977 | return; |
15978 | } |
15979 | } |
15980 | if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE) |
15981 | *maybe_range_for_decl = decl; |
15982 | /* The next token should be either a `,' or a `;'. */ |
15983 | token = cp_lexer_peek_token (lexer: parser->lexer); |
15984 | /* If it's a `,', there are more declarators to come. */ |
15985 | if (token->type == CPP_COMMA) |
15986 | /* will be consumed next time around */; |
15987 | /* If it's a `;', we are done. */ |
15988 | else if (token->type == CPP_SEMICOLON) |
15989 | break; |
15990 | else if (maybe_range_for_decl) |
15991 | { |
15992 | if ((declares_class_or_enum & 2) && token->type == CPP_COLON) |
15993 | permerror (decl_specifiers.locations[ds_type_spec], |
15994 | "types may not be defined in a for-range-declaration" ); |
15995 | break; |
15996 | } |
15997 | /* Anything else is an error. */ |
15998 | else |
15999 | { |
16000 | /* If we have already issued an error message we don't need |
16001 | to issue another one. */ |
16002 | if ((decl != error_mark_node |
16003 | /* grokfndecl sets DECL_INITIAL to error_mark_node for |
16004 | functions. */ |
16005 | && (fndecl_p || DECL_INITIAL (decl) != error_mark_node)) |
16006 | || cp_parser_uncommitted_to_tentative_parse_p (parser)) |
16007 | cp_parser_error (parser, gmsgid: "expected %<,%> or %<;%>" ); |
16008 | /* Skip tokens until we reach the end of the statement. */ |
16009 | cp_parser_skip_to_end_of_statement (parser); |
16010 | /* If the next token is now a `;', consume it. */ |
16011 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
16012 | cp_lexer_consume_token (lexer: parser->lexer); |
16013 | goto done; |
16014 | } |
16015 | /* After the first time around, a function-definition is not |
16016 | allowed -- even if it was OK at first. For example: |
16017 | |
16018 | int i, f() {} |
16019 | |
16020 | is not valid. */ |
16021 | function_definition_allowed_p = false; |
16022 | } |
16023 | |
16024 | /* Issue an error message if no declarators are present, and the |
16025 | decl-specifier-seq does not itself declare a class or |
16026 | enumeration: [dcl.dcl]/3. */ |
16027 | if (!saw_declarator) |
16028 | { |
16029 | if (cp_parser_declares_only_class_p (parser)) |
16030 | { |
16031 | if (!declares_class_or_enum |
16032 | && decl_specifiers.type |
16033 | && OVERLOAD_TYPE_P (decl_specifiers.type)) |
16034 | /* Ensure an error is issued anyway when finish_decltype_type, |
16035 | called via cp_parser_decl_specifier_seq, returns a class or |
16036 | an enumeration (c++/51786). */ |
16037 | decl_specifiers.type = NULL_TREE; |
16038 | shadow_tag (&decl_specifiers); |
16039 | } |
16040 | /* Perform any deferred access checks. */ |
16041 | perform_deferred_access_checks (tf_warning_or_error); |
16042 | } |
16043 | |
16044 | /* Consume the `;'. */ |
16045 | finish: |
16046 | if (!maybe_range_for_decl) |
16047 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
16048 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
16049 | { |
16050 | if (init_loc != UNKNOWN_LOCATION) |
16051 | error_at (init_loc, "initializer in range-based %<for%> loop" ); |
16052 | if (comma_loc != UNKNOWN_LOCATION) |
16053 | error_at (comma_loc, |
16054 | "multiple declarations in range-based %<for%> loop" ); |
16055 | } |
16056 | |
16057 | done: |
16058 | pop_deferring_access_checks (); |
16059 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
16060 | } |
16061 | |
16062 | /* Helper of cp_parser_simple_declaration, parse a decomposition declaration. |
16063 | decl-specifier-seq ref-qualifier [opt] [ identifier-list ] |
16064 | initializer ; */ |
16065 | |
16066 | static tree |
16067 | cp_parser_decomposition_declaration (cp_parser *parser, |
16068 | cp_decl_specifier_seq *decl_specifiers, |
16069 | tree *maybe_range_for_decl, |
16070 | location_t *init_loc) |
16071 | { |
16072 | cp_ref_qualifier ref_qual = cp_parser_ref_qualifier_opt (parser); |
16073 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16074 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
16075 | |
16076 | /* Parse the identifier-list. */ |
16077 | auto_vec<cp_expr, 10> v; |
16078 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
16079 | while (true) |
16080 | { |
16081 | cp_expr e = cp_parser_identifier (parser); |
16082 | if (e.get_value () == error_mark_node) |
16083 | break; |
16084 | v.safe_push (obj: e); |
16085 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
16086 | break; |
16087 | cp_lexer_consume_token (lexer: parser->lexer); |
16088 | } |
16089 | |
16090 | location_t end_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16091 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
16092 | { |
16093 | end_loc = UNKNOWN_LOCATION; |
16094 | cp_parser_skip_to_closing_parenthesis_1 (parser, recovering: true, or_ttype: CPP_CLOSE_SQUARE, |
16095 | consume_paren: false); |
16096 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
16097 | cp_lexer_consume_token (lexer: parser->lexer); |
16098 | else |
16099 | { |
16100 | cp_parser_skip_to_end_of_statement (parser); |
16101 | return error_mark_node; |
16102 | } |
16103 | } |
16104 | |
16105 | if (cxx_dialect < cxx17) |
16106 | pedwarn (loc, OPT_Wc__17_extensions, |
16107 | "structured bindings only available with " |
16108 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
16109 | |
16110 | tree pushed_scope; |
16111 | cp_declarator *declarator = make_declarator (kind: cdk_decomp); |
16112 | loc = end_loc == UNKNOWN_LOCATION ? loc : make_location (caret: loc, start: loc, finish: end_loc); |
16113 | declarator->id_loc = loc; |
16114 | if (ref_qual != REF_QUAL_NONE) |
16115 | declarator = make_reference_declarator (cv_qualifiers: TYPE_UNQUALIFIED, target: declarator, |
16116 | rvalue_ref: ref_qual == REF_QUAL_RVALUE, |
16117 | NULL_TREE); |
16118 | tree decl = start_decl (declarator, decl_specifiers, SD_INITIALIZED, |
16119 | NULL_TREE, decl_specifiers->attributes, |
16120 | &pushed_scope); |
16121 | tree orig_decl = decl; |
16122 | |
16123 | unsigned int i; |
16124 | cp_expr e; |
16125 | cp_decl_specifier_seq decl_specs; |
16126 | clear_decl_specs (decl_specs: &decl_specs); |
16127 | decl_specs.type = make_auto (); |
16128 | if (decl_specifiers->storage_class == sc_static) |
16129 | decl_specs.storage_class = sc_static; |
16130 | tree prev = decl; |
16131 | FOR_EACH_VEC_ELT (v, i, e) |
16132 | { |
16133 | if (i == 0) |
16134 | declarator = make_id_declarator (NULL_TREE, unqualified_name: e.get_value (), |
16135 | sfk: sfk_none, id_location: e.get_location ()); |
16136 | else |
16137 | { |
16138 | declarator->u.id.unqualified_name = e.get_value (); |
16139 | declarator->id_loc = e.get_location (); |
16140 | } |
16141 | tree elt_pushed_scope; |
16142 | tree decl2 = start_decl (declarator, &decl_specs, SD_DECOMPOSITION, |
16143 | NULL_TREE, NULL_TREE, &elt_pushed_scope); |
16144 | if (decl2 == error_mark_node) |
16145 | decl = error_mark_node; |
16146 | else if (decl != error_mark_node && DECL_CHAIN (decl2) != prev) |
16147 | { |
16148 | /* Ensure we've diagnosed redeclaration if we aren't creating |
16149 | a new VAR_DECL. */ |
16150 | gcc_assert (errorcount); |
16151 | decl = error_mark_node; |
16152 | } |
16153 | else |
16154 | prev = decl2; |
16155 | if (elt_pushed_scope) |
16156 | pop_scope (elt_pushed_scope); |
16157 | } |
16158 | |
16159 | if (v.is_empty ()) |
16160 | { |
16161 | error_at (loc, "empty structured binding declaration" ); |
16162 | decl = error_mark_node; |
16163 | } |
16164 | |
16165 | if (maybe_range_for_decl == NULL |
16166 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
16167 | { |
16168 | bool non_constant_p = false, is_direct_init = false; |
16169 | *init_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16170 | tree initializer = cp_parser_initializer (parser, &is_direct_init, |
16171 | &non_constant_p); |
16172 | if (initializer == NULL_TREE |
16173 | || (TREE_CODE (initializer) == TREE_LIST |
16174 | && TREE_CHAIN (initializer)) |
16175 | || (is_direct_init |
16176 | && BRACE_ENCLOSED_INITIALIZER_P (initializer) |
16177 | && CONSTRUCTOR_NELTS (initializer) != 1)) |
16178 | { |
16179 | error_at (loc, "invalid initializer for structured binding " |
16180 | "declaration" ); |
16181 | initializer = error_mark_node; |
16182 | } |
16183 | |
16184 | if (decl != error_mark_node) |
16185 | { |
16186 | cp_decomp decomp = { .decl: prev, .count: v.length () }; |
16187 | cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE, |
16188 | (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT), |
16189 | &decomp); |
16190 | cp_finish_decomp (decl, &decomp); |
16191 | } |
16192 | } |
16193 | else if (decl != error_mark_node) |
16194 | { |
16195 | *maybe_range_for_decl = prev; |
16196 | cp_decomp decomp = { .decl: prev, .count: v.length () }; |
16197 | /* Ensure DECL_VALUE_EXPR is created for all the decls but |
16198 | the underlying DECL. */ |
16199 | cp_finish_decomp (decl, &decomp); |
16200 | } |
16201 | |
16202 | if (pushed_scope) |
16203 | pop_scope (pushed_scope); |
16204 | |
16205 | if (decl == error_mark_node && DECL_P (orig_decl)) |
16206 | { |
16207 | if (DECL_NAMESPACE_SCOPE_P (orig_decl)) |
16208 | SET_DECL_ASSEMBLER_NAME (orig_decl, get_identifier ("<decomp>" )); |
16209 | } |
16210 | |
16211 | return decl; |
16212 | } |
16213 | |
16214 | /* Names of storage classes. */ |
16215 | |
16216 | static const char *const |
16217 | cp_storage_class_name[] = { |
16218 | "" , "auto" , "register" , "static" , "extern" , "mutable" |
16219 | }; |
16220 | |
16221 | /* Parse a decl-specifier-seq. |
16222 | |
16223 | decl-specifier-seq: |
16224 | decl-specifier-seq [opt] decl-specifier |
16225 | decl-specifier attribute-specifier-seq [opt] (C++11) |
16226 | |
16227 | decl-specifier: |
16228 | storage-class-specifier |
16229 | type-specifier |
16230 | function-specifier |
16231 | friend |
16232 | typedef |
16233 | |
16234 | GNU Extension: |
16235 | |
16236 | decl-specifier: |
16237 | attributes |
16238 | |
16239 | Concepts Extension: |
16240 | |
16241 | decl-specifier: |
16242 | concept |
16243 | |
16244 | Set *DECL_SPECS to a representation of the decl-specifier-seq. |
16245 | |
16246 | The parser flags FLAGS is used to control type-specifier parsing. |
16247 | |
16248 | *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following |
16249 | flags: |
16250 | |
16251 | 1: one of the decl-specifiers is an elaborated-type-specifier |
16252 | (i.e., a type declaration) |
16253 | 2: one of the decl-specifiers is an enum-specifier or a |
16254 | class-specifier (i.e., a type definition) |
16255 | |
16256 | */ |
16257 | |
16258 | static void |
16259 | cp_parser_decl_specifier_seq (cp_parser* parser, |
16260 | cp_parser_flags flags, |
16261 | cp_decl_specifier_seq *decl_specs, |
16262 | int* declares_class_or_enum) |
16263 | { |
16264 | bool constructor_possible_p = !parser->in_declarator_p; |
16265 | bool found_decl_spec = false; |
16266 | cp_token *start_token = NULL; |
16267 | cp_decl_spec ds; |
16268 | |
16269 | /* Clear DECL_SPECS. */ |
16270 | clear_decl_specs (decl_specs); |
16271 | |
16272 | /* Assume no class or enumeration type is declared. */ |
16273 | *declares_class_or_enum = 0; |
16274 | |
16275 | /* Keep a token that additionally will be used for diagnostics. */ |
16276 | cp_token *first_specifier = NULL; |
16277 | /* Keep reading specifiers until there are no more to read. */ |
16278 | while (true) |
16279 | { |
16280 | bool constructor_p; |
16281 | cp_token *token; |
16282 | ds = ds_last; |
16283 | |
16284 | /* Peek at the next token. */ |
16285 | token = cp_lexer_peek_token (lexer: parser->lexer); |
16286 | |
16287 | /* Save the first token of the decl spec list for error |
16288 | reporting. */ |
16289 | if (!start_token) |
16290 | start_token = token; |
16291 | /* Handle attributes. */ |
16292 | if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) == 0 |
16293 | && cp_next_tokens_can_be_attribute_p (parser)) |
16294 | { |
16295 | /* Parse the attributes. */ |
16296 | tree attrs = cp_parser_attributes_opt (parser); |
16297 | |
16298 | /* In a sequence of declaration specifiers, c++11 attributes |
16299 | appertain to the type that precede them. In that case |
16300 | [dcl.spec]/1 says: |
16301 | |
16302 | The attribute-specifier-seq affects the type only for |
16303 | the declaration it appears in, not other declarations |
16304 | involving the same type. |
16305 | |
16306 | But for now let's force the user to position the |
16307 | attribute either at the beginning of the declaration or |
16308 | after the declarator-id, which would clearly mean that it |
16309 | applies to the declarator. */ |
16310 | if (cxx11_attribute_p (attrs)) |
16311 | { |
16312 | if (!found_decl_spec) |
16313 | /* The c++11 attribute is at the beginning of the |
16314 | declaration. It appertains to the entity being |
16315 | declared. */; |
16316 | else |
16317 | { |
16318 | if (find_contract (attrs)) |
16319 | { |
16320 | diagnose_misapplied_contracts (attrs); |
16321 | attrs = NULL_TREE; |
16322 | } |
16323 | else if (decl_specs->type && CLASS_TYPE_P (decl_specs->type)) |
16324 | { |
16325 | /* This is an attribute following a |
16326 | class-specifier. */ |
16327 | if (decl_specs->type_definition_p) |
16328 | warn_misplaced_attr_for_class_type (location: token->location, |
16329 | class_type: decl_specs->type); |
16330 | attrs = NULL_TREE; |
16331 | } |
16332 | else |
16333 | { |
16334 | decl_specs->std_attributes |
16335 | = attr_chainon (attrs: decl_specs->std_attributes, attr: attrs); |
16336 | if (decl_specs->locations[ds_std_attribute] == 0) |
16337 | decl_specs->locations[ds_std_attribute] = token->location; |
16338 | } |
16339 | continue; |
16340 | } |
16341 | } |
16342 | |
16343 | decl_specs->attributes |
16344 | = attr_chainon (attrs: decl_specs->attributes, attr: attrs); |
16345 | if (decl_specs->locations[ds_attribute] == 0) |
16346 | decl_specs->locations[ds_attribute] = token->location; |
16347 | continue; |
16348 | } |
16349 | /* We know by this point that the token is not part of an attribute. */ |
16350 | if (!first_specifier) |
16351 | first_specifier = token; |
16352 | /* Special case for "this" specifier, indicating a parm is an xobj parm. |
16353 | The "this" specifier must be the first specifier in the declaration, |
16354 | after any attributes. */ |
16355 | if (token->keyword == RID_THIS && (flags & CP_PARSER_FLAGS_PARAMETER)) |
16356 | { |
16357 | cp_lexer_consume_token (lexer: parser->lexer); |
16358 | if (token != first_specifier) |
16359 | { |
16360 | /* Don't emit diagnostics if we have already seen "this", |
16361 | leave it for set_and_check_decl_spec_loc. */ |
16362 | if (decl_specs->locations[ds_this] == 0) |
16363 | { |
16364 | auto_diagnostic_group d; |
16365 | gcc_rich_location richloc (token->location); |
16366 | /* Works, need to add tests for it though. */ |
16367 | richloc.add_fixit_remove (); |
16368 | richloc.add_fixit_insert_before (where: first_specifier->location, |
16369 | new_content: "this " ); |
16370 | error_at (&richloc, |
16371 | "%<this%> must be the first specifier " |
16372 | "in a parameter declaration" ); |
16373 | } |
16374 | } |
16375 | set_and_check_decl_spec_loc (decl_specs, ds: ds_this, token); |
16376 | continue; |
16377 | } |
16378 | |
16379 | /* Assume we will find a decl-specifier keyword. */ |
16380 | found_decl_spec = true; |
16381 | /* If the next token is an appropriate keyword, we can simply |
16382 | add it to the list. */ |
16383 | switch (token->keyword) |
16384 | { |
16385 | /* decl-specifier: |
16386 | friend |
16387 | constexpr |
16388 | constinit */ |
16389 | case RID_FRIEND: |
16390 | if (!at_class_scope_p ()) |
16391 | { |
16392 | gcc_rich_location richloc (token->location); |
16393 | richloc.add_fixit_remove (); |
16394 | error_at (&richloc, "%<friend%> used outside of class" ); |
16395 | cp_lexer_purge_token (lexer: parser->lexer); |
16396 | } |
16397 | else |
16398 | { |
16399 | ds = ds_friend; |
16400 | /* Consume the token. */ |
16401 | cp_lexer_consume_token (lexer: parser->lexer); |
16402 | } |
16403 | break; |
16404 | |
16405 | case RID_CONSTEXPR: |
16406 | ds = ds_constexpr; |
16407 | cp_lexer_consume_token (lexer: parser->lexer); |
16408 | break; |
16409 | |
16410 | case RID_CONSTINIT: |
16411 | ds = ds_constinit; |
16412 | cp_lexer_consume_token (lexer: parser->lexer); |
16413 | break; |
16414 | |
16415 | case RID_CONSTEVAL: |
16416 | ds = ds_consteval; |
16417 | cp_lexer_consume_token (lexer: parser->lexer); |
16418 | break; |
16419 | |
16420 | case RID_CONCEPT: |
16421 | ds = ds_concept; |
16422 | cp_lexer_consume_token (lexer: parser->lexer); |
16423 | |
16424 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16425 | break; |
16426 | |
16427 | /* Warn for concept as a decl-specifier. We'll rewrite these as |
16428 | concept declarations later. */ |
16429 | if (!flag_concepts_ts) |
16430 | { |
16431 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
16432 | if (next->keyword == RID_BOOL) |
16433 | permerror (next->location, "the %<bool%> keyword is not " |
16434 | "allowed in a C++20 concept definition" ); |
16435 | else |
16436 | error_at (token->location, "C++20 concept definition syntax " |
16437 | "is %<concept <name> = <expr>%>" ); |
16438 | } |
16439 | |
16440 | /* In C++20 a concept definition is just 'concept name = expr;' |
16441 | Support that syntax as a TS extension by pretending we've seen |
16442 | the 'bool' specifier. */ |
16443 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
16444 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_EQ) |
16445 | && !decl_specs->any_type_specifiers_p) |
16446 | { |
16447 | cp_parser_set_decl_spec_type (decl_specs, boolean_type_node, |
16448 | token, /*type_definition*/false); |
16449 | decl_specs->any_type_specifiers_p = true; |
16450 | } |
16451 | break; |
16452 | |
16453 | /* function-specifier: |
16454 | inline |
16455 | virtual |
16456 | explicit */ |
16457 | case RID_INLINE: |
16458 | case RID_VIRTUAL: |
16459 | case RID_EXPLICIT: |
16460 | cp_parser_function_specifier_opt (parser, decl_specs); |
16461 | break; |
16462 | |
16463 | /* decl-specifier: |
16464 | typedef */ |
16465 | case RID_TYPEDEF: |
16466 | ds = ds_typedef; |
16467 | /* Consume the token. */ |
16468 | cp_lexer_consume_token (lexer: parser->lexer); |
16469 | |
16470 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16471 | break; |
16472 | |
16473 | /* A constructor declarator cannot appear in a typedef. */ |
16474 | constructor_possible_p = false; |
16475 | /* The "typedef" keyword can only occur in a declaration; we |
16476 | may as well commit at this point. */ |
16477 | cp_parser_commit_to_tentative_parse (parser); |
16478 | |
16479 | if (decl_specs->storage_class != sc_none) |
16480 | { |
16481 | if (decl_specs->conflicting_specifiers_p) |
16482 | break; |
16483 | gcc_rich_location richloc (token->location); |
16484 | location_t oloc = decl_specs->locations[ds_storage_class]; |
16485 | richloc.add_location_if_nearby (loc: oloc); |
16486 | error_at (&richloc, |
16487 | "%<typedef%> specifier conflicts with %qs" , |
16488 | cp_storage_class_name[decl_specs->storage_class]); |
16489 | decl_specs->conflicting_specifiers_p = true; |
16490 | } |
16491 | break; |
16492 | |
16493 | /* storage-class-specifier: |
16494 | auto |
16495 | register |
16496 | static |
16497 | extern |
16498 | mutable |
16499 | |
16500 | GNU Extension: |
16501 | thread */ |
16502 | case RID_AUTO: |
16503 | if (cxx_dialect == cxx98) |
16504 | { |
16505 | /* Consume the token. */ |
16506 | cp_lexer_consume_token (lexer: parser->lexer); |
16507 | |
16508 | /* Complain about `auto' as a storage specifier, if |
16509 | we're complaining about C++0x compatibility. */ |
16510 | gcc_rich_location richloc (token->location); |
16511 | richloc.add_fixit_remove (); |
16512 | warning_at (&richloc, OPT_Wc__11_compat, |
16513 | "%<auto%> changes meaning in C++11; " |
16514 | "please remove it" ); |
16515 | |
16516 | /* Set the storage class anyway. */ |
16517 | cp_parser_set_storage_class (parser, decl_specs, RID_AUTO, |
16518 | token); |
16519 | } |
16520 | else |
16521 | /* C++0x auto type-specifier. */ |
16522 | found_decl_spec = false; |
16523 | break; |
16524 | |
16525 | case RID_REGISTER: |
16526 | case RID_STATIC: |
16527 | case RID_EXTERN: |
16528 | case RID_MUTABLE: |
16529 | /* Consume the token. */ |
16530 | cp_lexer_consume_token (lexer: parser->lexer); |
16531 | cp_parser_set_storage_class (parser, decl_specs, token->keyword, |
16532 | token); |
16533 | break; |
16534 | case RID_THREAD: |
16535 | /* Consume the token. */ |
16536 | ds = ds_thread; |
16537 | cp_lexer_consume_token (lexer: parser->lexer); |
16538 | break; |
16539 | |
16540 | default: |
16541 | /* We did not yet find a decl-specifier yet. */ |
16542 | found_decl_spec = false; |
16543 | break; |
16544 | } |
16545 | |
16546 | if (found_decl_spec |
16547 | && (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR) |
16548 | && token->keyword != RID_CONSTEXPR) |
16549 | error ("%qD invalid in condition" , ridpointers[token->keyword]); |
16550 | |
16551 | if (found_decl_spec |
16552 | && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16553 | && token->keyword != RID_MUTABLE |
16554 | && token->keyword != RID_CONSTEXPR |
16555 | && token->keyword != RID_CONSTEVAL) |
16556 | { |
16557 | if (token->keyword != RID_STATIC) |
16558 | error_at (token->location, "%qD invalid in lambda" , |
16559 | ridpointers[token->keyword]); |
16560 | else if (cxx_dialect < cxx23) |
16561 | pedwarn (token->location, OPT_Wc__23_extensions, |
16562 | "%qD only valid in lambda with %<-std=c++23%> or " |
16563 | "%<-std=gnu++23%>" , ridpointers[token->keyword]); |
16564 | } |
16565 | |
16566 | if (ds != ds_last) |
16567 | set_and_check_decl_spec_loc (decl_specs, ds, token); |
16568 | |
16569 | /* Constructors are a special case. The `S' in `S()' is not a |
16570 | decl-specifier; it is the beginning of the declarator. */ |
16571 | constructor_p |
16572 | = (!found_decl_spec |
16573 | && constructor_possible_p |
16574 | && (cp_parser_constructor_declarator_p |
16575 | (parser, flags, decl_spec_seq_has_spec_p (decl_specs, |
16576 | ds_friend)))); |
16577 | |
16578 | /* If we don't have a DECL_SPEC yet, then we must be looking at |
16579 | a type-specifier. */ |
16580 | if (!found_decl_spec && !constructor_p) |
16581 | { |
16582 | int decl_spec_declares_class_or_enum; |
16583 | bool is_cv_qualifier; |
16584 | tree type_spec; |
16585 | |
16586 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16587 | flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS; |
16588 | |
16589 | type_spec |
16590 | = cp_parser_type_specifier (parser, flags, |
16591 | decl_specs, |
16592 | /*is_declaration=*/true, |
16593 | &decl_spec_declares_class_or_enum, |
16594 | &is_cv_qualifier); |
16595 | *declares_class_or_enum |= decl_spec_declares_class_or_enum; |
16596 | |
16597 | /* If this type-specifier referenced a user-defined type |
16598 | (a typedef, class-name, etc.), then we can't allow any |
16599 | more such type-specifiers henceforth. |
16600 | |
16601 | [dcl.spec] |
16602 | |
16603 | The longest sequence of decl-specifiers that could |
16604 | possibly be a type name is taken as the |
16605 | decl-specifier-seq of a declaration. The sequence shall |
16606 | be self-consistent as described below. |
16607 | |
16608 | [dcl.type] |
16609 | |
16610 | As a general rule, at most one type-specifier is allowed |
16611 | in the complete decl-specifier-seq of a declaration. The |
16612 | only exceptions are the following: |
16613 | |
16614 | -- const or volatile can be combined with any other |
16615 | type-specifier. |
16616 | |
16617 | -- signed or unsigned can be combined with char, long, |
16618 | short, or int. |
16619 | |
16620 | -- .. |
16621 | |
16622 | Example: |
16623 | |
16624 | typedef char* Pc; |
16625 | void g (const int Pc); |
16626 | |
16627 | Here, Pc is *not* part of the decl-specifier seq; it's |
16628 | the declarator. Therefore, once we see a type-specifier |
16629 | (other than a cv-qualifier), we forbid any additional |
16630 | user-defined types. We *do* still allow things like `int |
16631 | int' to be considered a decl-specifier-seq, and issue the |
16632 | error message later. */ |
16633 | if (type_spec && !is_cv_qualifier) |
16634 | flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; |
16635 | /* A constructor declarator cannot follow a type-specifier. */ |
16636 | if (type_spec) |
16637 | { |
16638 | constructor_possible_p = false; |
16639 | found_decl_spec = true; |
16640 | if (!is_cv_qualifier) |
16641 | decl_specs->any_type_specifiers_p = true; |
16642 | |
16643 | if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) != 0) |
16644 | error_at (token->location, "type-specifier invalid in lambda" ); |
16645 | } |
16646 | } |
16647 | |
16648 | /* If we still do not have a DECL_SPEC, then there are no more |
16649 | decl-specifiers. */ |
16650 | if (!found_decl_spec) |
16651 | break; |
16652 | |
16653 | if (decl_specs->std_attributes) |
16654 | { |
16655 | error_at (decl_specs->locations[ds_std_attribute], |
16656 | "standard attributes in middle of decl-specifiers" ); |
16657 | inform (decl_specs->locations[ds_std_attribute], |
16658 | "standard attributes must precede the decl-specifiers to " |
16659 | "apply to the declaration, or follow them to apply to " |
16660 | "the type" ); |
16661 | } |
16662 | |
16663 | decl_specs->any_specifiers_p = true; |
16664 | /* After we see one decl-specifier, further decl-specifiers are |
16665 | always optional. */ |
16666 | flags |= CP_PARSER_FLAGS_OPTIONAL; |
16667 | } |
16668 | |
16669 | /* Don't allow a friend specifier with a class definition. */ |
16670 | if (decl_spec_seq_has_spec_p (decl_specs, ds_friend) |
16671 | && (*declares_class_or_enum & 2)) |
16672 | error_at (decl_specs->locations[ds_friend], |
16673 | "class definition may not be declared a friend" ); |
16674 | } |
16675 | |
16676 | /* Parse an (optional) storage-class-specifier. |
16677 | |
16678 | storage-class-specifier: |
16679 | auto |
16680 | register |
16681 | static |
16682 | extern |
16683 | mutable |
16684 | |
16685 | GNU Extension: |
16686 | |
16687 | storage-class-specifier: |
16688 | thread |
16689 | |
16690 | Returns an IDENTIFIER_NODE corresponding to the keyword used. */ |
16691 | |
16692 | static tree |
16693 | cp_parser_storage_class_specifier_opt (cp_parser* parser) |
16694 | { |
16695 | switch (cp_lexer_peek_token (lexer: parser->lexer)->keyword) |
16696 | { |
16697 | case RID_AUTO: |
16698 | if (cxx_dialect != cxx98) |
16699 | return NULL_TREE; |
16700 | /* Fall through for C++98. */ |
16701 | gcc_fallthrough (); |
16702 | |
16703 | case RID_REGISTER: |
16704 | case RID_STATIC: |
16705 | case RID_EXTERN: |
16706 | case RID_MUTABLE: |
16707 | case RID_THREAD: |
16708 | /* Consume the token. */ |
16709 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16710 | |
16711 | default: |
16712 | return NULL_TREE; |
16713 | } |
16714 | } |
16715 | |
16716 | /* Parse an (optional) function-specifier. |
16717 | |
16718 | function-specifier: |
16719 | inline |
16720 | virtual |
16721 | explicit |
16722 | |
16723 | C++20 Extension: |
16724 | explicit(constant-expression) |
16725 | |
16726 | Returns an IDENTIFIER_NODE corresponding to the keyword used. |
16727 | Updates DECL_SPECS, if it is non-NULL. */ |
16728 | |
16729 | static tree |
16730 | cp_parser_function_specifier_opt (cp_parser* parser, |
16731 | cp_decl_specifier_seq *decl_specs) |
16732 | { |
16733 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
16734 | switch (token->keyword) |
16735 | { |
16736 | case RID_INLINE: |
16737 | set_and_check_decl_spec_loc (decl_specs, ds: ds_inline, token); |
16738 | break; |
16739 | |
16740 | case RID_VIRTUAL: |
16741 | /* 14.5.2.3 [temp.mem] |
16742 | |
16743 | A member function template shall not be virtual. */ |
16744 | if (PROCESSING_REAL_TEMPLATE_DECL_P () |
16745 | && current_class_type) |
16746 | error_at (token->location, "templates may not be %<virtual%>" ); |
16747 | else |
16748 | set_and_check_decl_spec_loc (decl_specs, ds: ds_virtual, token); |
16749 | break; |
16750 | |
16751 | case RID_EXPLICIT: |
16752 | { |
16753 | tree id = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16754 | /* If we see '(', it's C++20 explicit(bool). */ |
16755 | tree expr; |
16756 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
16757 | { |
16758 | matching_parens parens; |
16759 | parens.consume_open (parser); |
16760 | |
16761 | /* New types are not allowed in an explicit-specifier. */ |
16762 | const char *saved_message |
16763 | = parser->type_definition_forbidden_message; |
16764 | parser->type_definition_forbidden_message |
16765 | = G_("types may not be defined in explicit-specifier" ); |
16766 | |
16767 | if (cxx_dialect < cxx20) |
16768 | pedwarn (token->location, OPT_Wc__20_extensions, |
16769 | "%<explicit(bool)%> only available with %<-std=c++20%> " |
16770 | "or %<-std=gnu++20%>" ); |
16771 | |
16772 | /* Parse the constant-expression. */ |
16773 | expr = cp_parser_constant_expression (parser); |
16774 | |
16775 | /* Restore the saved message. */ |
16776 | parser->type_definition_forbidden_message = saved_message; |
16777 | parens.require_close (parser); |
16778 | } |
16779 | else |
16780 | /* The explicit-specifier explicit without a constant-expression is |
16781 | equivalent to the explicit-specifier explicit(true). */ |
16782 | expr = boolean_true_node; |
16783 | |
16784 | /* [dcl.fct.spec] |
16785 | "the constant-expression, if supplied, shall be a contextually |
16786 | converted constant expression of type bool." */ |
16787 | expr = build_explicit_specifier (expr, tf_warning_or_error); |
16788 | /* We could evaluate it -- mark the decl as appropriate. */ |
16789 | if (expr == boolean_true_node) |
16790 | set_and_check_decl_spec_loc (decl_specs, ds: ds_explicit, token); |
16791 | else if (expr == boolean_false_node) |
16792 | /* Don't mark the decl as explicit. */; |
16793 | else if (decl_specs) |
16794 | /* The expression was value-dependent. Remember it so that we can |
16795 | substitute it later. */ |
16796 | decl_specs->explicit_specifier = expr; |
16797 | return id; |
16798 | } |
16799 | |
16800 | default: |
16801 | return NULL_TREE; |
16802 | } |
16803 | |
16804 | /* Consume the token. */ |
16805 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16806 | } |
16807 | |
16808 | /* Parse a linkage-specification. |
16809 | |
16810 | linkage-specification: |
16811 | extern string-literal { declaration-seq [opt] } |
16812 | extern string-literal declaration */ |
16813 | |
16814 | static void |
16815 | cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr) |
16816 | { |
16817 | /* Look for the `extern' keyword. */ |
16818 | cp_token *extern_token |
16819 | = cp_parser_require_keyword (parser, RID_EXTERN, RT_EXTERN); |
16820 | |
16821 | /* Look for the string-literal. */ |
16822 | cp_token *string_token = cp_lexer_peek_token (lexer: parser->lexer); |
16823 | tree linkage; |
16824 | if (cxx_dialect >= cxx26) |
16825 | linkage = cp_parser_unevaluated_string_literal (parser); |
16826 | else |
16827 | linkage = cp_parser_string_literal (parser, /*translate=*/false, |
16828 | /*wide_ok=*/false); |
16829 | |
16830 | /* Transform the literal into an identifier. If the literal is a |
16831 | wide-character string, or contains embedded NULs, then we can't |
16832 | handle it as the user wants. */ |
16833 | if (linkage == error_mark_node |
16834 | || strlen (TREE_STRING_POINTER (linkage)) |
16835 | != (size_t) (TREE_STRING_LENGTH (linkage) - 1)) |
16836 | { |
16837 | cp_parser_error (parser, gmsgid: "invalid linkage-specification" ); |
16838 | /* Assume C++ linkage. */ |
16839 | linkage = lang_name_cplusplus; |
16840 | } |
16841 | else |
16842 | linkage = get_identifier (TREE_STRING_POINTER (linkage)); |
16843 | |
16844 | /* We're now using the new linkage. */ |
16845 | unsigned saved_module = module_kind; |
16846 | module_kind &= ~MK_ATTACH; |
16847 | push_lang_context (linkage); |
16848 | |
16849 | /* Preserve the location of the innermost linkage specification, |
16850 | tracking the locations of nested specifications via a local. */ |
16851 | location_t saved_location |
16852 | = parser->innermost_linkage_specification_location; |
16853 | /* Construct a location ranging from the start of the "extern" to |
16854 | the end of the string-literal, with the caret at the start, e.g.: |
16855 | extern "C" { |
16856 | ^~~~~~~~~~ |
16857 | */ |
16858 | parser->innermost_linkage_specification_location |
16859 | = make_location (caret: extern_token->location, |
16860 | start: extern_token->location, |
16861 | finish: get_finish (loc: string_token->location)); |
16862 | |
16863 | /* If the next token is a `{', then we're using the first |
16864 | production. */ |
16865 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
16866 | { |
16867 | cp_ensure_no_omp_declare_simd (parser); |
16868 | cp_ensure_no_oacc_routine (parser); |
16869 | |
16870 | /* Consume the `{' token. */ |
16871 | matching_braces braces; |
16872 | braces.consume_open (parser); |
16873 | /* Parse the declarations. */ |
16874 | cp_parser_declaration_seq_opt (parser); |
16875 | /* Look for the closing `}'. */ |
16876 | braces.require_close (parser); |
16877 | } |
16878 | /* Otherwise, there's just one declaration. */ |
16879 | else |
16880 | { |
16881 | bool saved_in_unbraced_linkage_specification_p; |
16882 | |
16883 | saved_in_unbraced_linkage_specification_p |
16884 | = parser->in_unbraced_linkage_specification_p; |
16885 | parser->in_unbraced_linkage_specification_p = true; |
16886 | cp_parser_declaration (parser, prefix_attrs: prefix_attr); |
16887 | parser->in_unbraced_linkage_specification_p |
16888 | = saved_in_unbraced_linkage_specification_p; |
16889 | } |
16890 | |
16891 | /* We're done with the linkage-specification. */ |
16892 | pop_lang_context (); |
16893 | module_kind = saved_module; |
16894 | |
16895 | /* Restore location of parent linkage specification, if any. */ |
16896 | parser->innermost_linkage_specification_location = saved_location; |
16897 | } |
16898 | |
16899 | /* Parse a static_assert-declaration. |
16900 | |
16901 | static_assert-declaration: |
16902 | static_assert ( constant-expression , string-literal ) ; |
16903 | static_assert ( constant-expression ) ; (C++17) |
16904 | static_assert ( constant-expression, conditional-expression ) ; (C++26) |
16905 | |
16906 | If MEMBER_P, this static_assert is a class member. */ |
16907 | |
16908 | static void |
16909 | cp_parser_static_assert (cp_parser *parser, bool member_p) |
16910 | { |
16911 | cp_expr condition; |
16912 | location_t token_loc; |
16913 | tree message; |
16914 | |
16915 | /* Peek at the `static_assert' token so we can keep track of exactly |
16916 | where the static assertion started. */ |
16917 | token_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16918 | |
16919 | /* Look for the `static_assert' keyword. */ |
16920 | if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, |
16921 | RT_STATIC_ASSERT)) |
16922 | return; |
16923 | |
16924 | /* We know we are in a static assertion; commit to any tentative |
16925 | parse. */ |
16926 | if (cp_parser_parsing_tentatively (parser)) |
16927 | cp_parser_commit_to_tentative_parse (parser); |
16928 | |
16929 | /* Parse the `(' starting the static assertion condition. */ |
16930 | matching_parens parens; |
16931 | parens.require_open (parser); |
16932 | |
16933 | /* Parse the constant-expression. Allow a non-constant expression |
16934 | here in order to give better diagnostics in finish_static_assert. */ |
16935 | condition |
16936 | = cp_parser_constant_expression (parser, |
16937 | /*allow_non_constant_p=*/true, |
16938 | /*non_constant_p=*/nullptr); |
16939 | |
16940 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
16941 | { |
16942 | if (pedantic && cxx_dialect < cxx17) |
16943 | pedwarn (input_location, OPT_Wc__17_extensions, |
16944 | "%<static_assert%> without a message " |
16945 | "only available with %<-std=c++17%> or %<-std=gnu++17%>" ); |
16946 | /* Eat the ')' */ |
16947 | cp_lexer_consume_token (lexer: parser->lexer); |
16948 | message = build_string (1, "" ); |
16949 | TREE_TYPE (message) = char_array_type_node; |
16950 | fix_string_type (message); |
16951 | } |
16952 | else |
16953 | { |
16954 | /* Parse the separating `,'. */ |
16955 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
16956 | |
16957 | /* Parse the message expression. */ |
16958 | bool string_lit = true; |
16959 | for (unsigned int i = 1; ; ++i) |
16960 | { |
16961 | cp_token *tok = cp_lexer_peek_nth_token (lexer: parser->lexer, n: i); |
16962 | if (cp_parser_is_pure_string_literal (token: tok)) |
16963 | continue; |
16964 | else if (tok->type == CPP_CLOSE_PAREN) |
16965 | break; |
16966 | string_lit = false; |
16967 | break; |
16968 | } |
16969 | if (!string_lit) |
16970 | { |
16971 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16972 | if (cxx_dialect < cxx26) |
16973 | pedwarn (loc, OPT_Wc__26_extensions, |
16974 | "%<static_assert%> with non-string message only " |
16975 | "available with %<-std=c++2c%> or %<-std=gnu++2c%>" ); |
16976 | |
16977 | message = cp_parser_conditional_expression (parser); |
16978 | if (TREE_CODE (message) == STRING_CST) |
16979 | message = build1_loc (loc, code: PAREN_EXPR, TREE_TYPE (message), |
16980 | arg1: message); |
16981 | } |
16982 | else if (cxx_dialect >= cxx26) |
16983 | message = cp_parser_unevaluated_string_literal (parser); |
16984 | else |
16985 | message = cp_parser_string_literal (parser, /*translate=*/false, |
16986 | /*wide_ok=*/true); |
16987 | |
16988 | /* A `)' completes the static assertion. */ |
16989 | if (!parens.require_close (parser)) |
16990 | cp_parser_skip_to_closing_parenthesis (parser, |
16991 | /*recovering=*/true, |
16992 | /*or_comma=*/false, |
16993 | /*consume_paren=*/true); |
16994 | } |
16995 | |
16996 | /* A semicolon terminates the declaration. */ |
16997 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
16998 | |
16999 | /* Get the location for the static assertion. Use that of the |
17000 | condition if available, otherwise, use that of the "static_assert" |
17001 | token. */ |
17002 | location_t assert_loc = condition.get_location (); |
17003 | if (assert_loc == UNKNOWN_LOCATION) |
17004 | assert_loc = token_loc; |
17005 | |
17006 | /* Complete the static assertion, which may mean either processing |
17007 | the static assert now or saving it for template instantiation. */ |
17008 | finish_static_assert (condition, message, assert_loc, member_p, |
17009 | /*show_expr_p=*/false); |
17010 | } |
17011 | |
17012 | /* Parse the expression in decltype ( expression ). */ |
17013 | |
17014 | static tree |
17015 | cp_parser_decltype_expr (cp_parser *parser, |
17016 | bool &id_expression_or_member_access_p) |
17017 | { |
17018 | cp_token *id_expr_start_token; |
17019 | tree expr; |
17020 | |
17021 | /* First, try parsing an id-expression. */ |
17022 | id_expr_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
17023 | cp_parser_parse_tentatively (parser); |
17024 | expr = cp_parser_id_expression (parser, |
17025 | /*template_keyword_p=*/false, |
17026 | /*check_dependency_p=*/true, |
17027 | /*template_p=*/NULL, |
17028 | /*declarator_p=*/false, |
17029 | /*optional_p=*/false); |
17030 | |
17031 | if (!cp_parser_error_occurred (parser) && expr != error_mark_node) |
17032 | { |
17033 | bool non_integral_constant_expression_p = false; |
17034 | tree id_expression = expr; |
17035 | cp_id_kind idk; |
17036 | const char *error_msg; |
17037 | |
17038 | if (identifier_p (t: expr)) |
17039 | /* Lookup the name we got back from the id-expression. */ |
17040 | expr = cp_parser_lookup_name_simple (parser, expr, |
17041 | id_expr_start_token->location); |
17042 | |
17043 | if (expr |
17044 | && expr != error_mark_node |
17045 | && TREE_CODE (expr) != TYPE_DECL |
17046 | && (TREE_CODE (expr) != BIT_NOT_EXPR |
17047 | || !TYPE_P (TREE_OPERAND (expr, 0))) |
17048 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
17049 | { |
17050 | /* Complete lookup of the id-expression. */ |
17051 | expr = (finish_id_expression |
17052 | (id_expression, expr, parser->scope, &idk, |
17053 | /*integral_constant_expression_p=*/false, |
17054 | /*allow_non_integral_constant_expression_p=*/true, |
17055 | &non_integral_constant_expression_p, |
17056 | /*template_p=*/false, |
17057 | /*done=*/true, |
17058 | /*address_p=*/false, |
17059 | /*template_arg_p=*/false, |
17060 | &error_msg, |
17061 | id_expr_start_token->location)); |
17062 | |
17063 | if (error_msg) |
17064 | { |
17065 | /* We found an id-expression, but it was something that we |
17066 | should not have found. This is an error, not something |
17067 | we can recover from, so report the error we found and |
17068 | we'll recover as gracefully as possible. */ |
17069 | cp_parser_parse_definitely (parser); |
17070 | cp_parser_error (parser, gmsgid: error_msg); |
17071 | id_expression_or_member_access_p = true; |
17072 | return error_mark_node; |
17073 | } |
17074 | } |
17075 | |
17076 | if (expr |
17077 | && expr != error_mark_node |
17078 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
17079 | /* We have an id-expression. */ |
17080 | id_expression_or_member_access_p = true; |
17081 | } |
17082 | |
17083 | if (!id_expression_or_member_access_p) |
17084 | { |
17085 | /* Abort the id-expression parse. */ |
17086 | cp_parser_abort_tentative_parse (parser); |
17087 | |
17088 | /* Parsing tentatively, again. */ |
17089 | cp_parser_parse_tentatively (parser); |
17090 | |
17091 | /* Parse a class member access. */ |
17092 | expr = cp_parser_postfix_expression (parser, /*address_p=*/false, |
17093 | /*cast_p=*/false, /*decltype*/member_access_only_p: true, |
17094 | /*member_access_only_p=*/decltype_p: true, NULL); |
17095 | |
17096 | if (expr |
17097 | && expr != error_mark_node |
17098 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
17099 | /* We have an id-expression. */ |
17100 | id_expression_or_member_access_p = true; |
17101 | } |
17102 | |
17103 | if (id_expression_or_member_access_p) |
17104 | /* We have parsed the complete id-expression or member access. */ |
17105 | cp_parser_parse_definitely (parser); |
17106 | else |
17107 | { |
17108 | /* Abort our attempt to parse an id-expression or member access |
17109 | expression. */ |
17110 | cp_parser_abort_tentative_parse (parser); |
17111 | |
17112 | /* Parse a full expression. */ |
17113 | expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false, |
17114 | /*decltype_p=*/true); |
17115 | } |
17116 | |
17117 | return expr; |
17118 | } |
17119 | |
17120 | /* Parse a `decltype' type. Returns the type. |
17121 | |
17122 | decltype-specifier: |
17123 | decltype ( expression ) |
17124 | C++14: |
17125 | decltype ( auto ) */ |
17126 | |
17127 | static tree |
17128 | cp_parser_decltype (cp_parser *parser) |
17129 | { |
17130 | bool id_expression_or_member_access_p = false; |
17131 | cp_token *start_token = cp_lexer_peek_token (lexer: parser->lexer); |
17132 | |
17133 | if (start_token->type == CPP_DECLTYPE) |
17134 | { |
17135 | /* Already parsed. */ |
17136 | cp_lexer_consume_token (lexer: parser->lexer); |
17137 | return saved_checks_value (check_value: start_token->u.tree_check_value); |
17138 | } |
17139 | |
17140 | /* Look for the `decltype' token. */ |
17141 | if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) |
17142 | return error_mark_node; |
17143 | |
17144 | /* Parse the opening `('. */ |
17145 | matching_parens parens; |
17146 | if (!parens.require_open (parser)) |
17147 | return error_mark_node; |
17148 | |
17149 | /* Since we're going to preserve any side-effects from this parse, set up a |
17150 | firewall to protect our callers from cp_parser_commit_to_tentative_parse |
17151 | in the expression. */ |
17152 | tentative_firewall firewall (parser); |
17153 | |
17154 | /* If in_declarator_p, a reparse as an expression might succeed (60361). |
17155 | Otherwise, commit now for better diagnostics. */ |
17156 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
17157 | && !parser->in_declarator_p) |
17158 | cp_parser_commit_to_topmost_tentative_parse (parser); |
17159 | |
17160 | push_deferring_access_checks (dk_deferred); |
17161 | |
17162 | tree expr = NULL_TREE; |
17163 | |
17164 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO) |
17165 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN)) |
17166 | { |
17167 | /* decltype (auto) */ |
17168 | cp_lexer_consume_token (lexer: parser->lexer); |
17169 | if (cxx_dialect < cxx14) |
17170 | { |
17171 | error_at (start_token->location, |
17172 | "%<decltype(auto)%> type specifier only available with " |
17173 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
17174 | expr = error_mark_node; |
17175 | } |
17176 | } |
17177 | else |
17178 | { |
17179 | /* decltype (expression) */ |
17180 | |
17181 | /* Types cannot be defined in a `decltype' expression. Save away the |
17182 | old message and set the new one. */ |
17183 | const char *saved_message = parser->type_definition_forbidden_message; |
17184 | parser->type_definition_forbidden_message |
17185 | = G_("types may not be defined in %<decltype%> expressions" ); |
17186 | |
17187 | /* The restrictions on constant-expressions do not apply inside |
17188 | decltype expressions. */ |
17189 | bool saved_integral_constant_expression_p |
17190 | = parser->integral_constant_expression_p; |
17191 | bool saved_non_integral_constant_expression_p |
17192 | = parser->non_integral_constant_expression_p; |
17193 | parser->integral_constant_expression_p = false; |
17194 | |
17195 | /* Within a parenthesized expression, a `>' token is always |
17196 | the greater-than operator. */ |
17197 | bool saved_greater_than_is_operator_p |
17198 | = parser->greater_than_is_operator_p; |
17199 | parser->greater_than_is_operator_p = true; |
17200 | |
17201 | /* Don't synthesize an implicit template type parameter here. This |
17202 | could happen with C++23 code like |
17203 | |
17204 | void f(decltype(new auto{0})); |
17205 | |
17206 | where we want to deduce the auto right away so that the parameter |
17207 | is of type 'int *'. */ |
17208 | auto cleanup = make_temp_override |
17209 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
17210 | |
17211 | /* Do not actually evaluate the expression. */ |
17212 | ++cp_unevaluated_operand; |
17213 | |
17214 | /* Do not warn about problems with the expression. */ |
17215 | ++c_inhibit_evaluation_warnings; |
17216 | |
17217 | expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); |
17218 | STRIP_ANY_LOCATION_WRAPPER (expr); |
17219 | |
17220 | /* Go back to evaluating expressions. */ |
17221 | --cp_unevaluated_operand; |
17222 | --c_inhibit_evaluation_warnings; |
17223 | |
17224 | /* The `>' token might be the end of a template-id or |
17225 | template-parameter-list now. */ |
17226 | parser->greater_than_is_operator_p |
17227 | = saved_greater_than_is_operator_p; |
17228 | |
17229 | /* Restore the old message and the integral constant expression |
17230 | flags. */ |
17231 | parser->type_definition_forbidden_message = saved_message; |
17232 | parser->integral_constant_expression_p |
17233 | = saved_integral_constant_expression_p; |
17234 | parser->non_integral_constant_expression_p |
17235 | = saved_non_integral_constant_expression_p; |
17236 | } |
17237 | |
17238 | /* Parse to the closing `)'. */ |
17239 | if (expr == error_mark_node || !parens.require_close (parser)) |
17240 | { |
17241 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
17242 | /*consume_paren=*/true); |
17243 | expr = error_mark_node; |
17244 | } |
17245 | |
17246 | /* If we got a parse error while tentative, bail out now. */ |
17247 | if (cp_parser_error_occurred (parser)) |
17248 | { |
17249 | pop_deferring_access_checks (); |
17250 | return error_mark_node; |
17251 | } |
17252 | |
17253 | if (!expr) |
17254 | /* Build auto. */ |
17255 | expr = make_decltype_auto (); |
17256 | else |
17257 | expr = finish_decltype_type (expr, id_expression_or_member_access_p, |
17258 | tf_warning_or_error); |
17259 | |
17260 | /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse |
17261 | it again. */ |
17262 | start_token->type = CPP_DECLTYPE; |
17263 | start_token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
17264 | start_token->tree_check_p = true; |
17265 | start_token->u.tree_check_value->value = expr; |
17266 | start_token->u.tree_check_value->checks = get_deferred_access_checks (); |
17267 | start_token->keyword = RID_MAX; |
17268 | |
17269 | location_t loc = start_token->location; |
17270 | loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
17271 | start_token->location = loc; |
17272 | |
17273 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_token); |
17274 | |
17275 | pop_to_parent_deferring_access_checks (); |
17276 | |
17277 | return expr; |
17278 | } |
17279 | |
17280 | /* Special member functions [gram.special] */ |
17281 | |
17282 | /* Parse a conversion-function-id. |
17283 | |
17284 | conversion-function-id: |
17285 | operator conversion-type-id |
17286 | |
17287 | Returns an IDENTIFIER_NODE representing the operator. */ |
17288 | |
17289 | static tree |
17290 | cp_parser_conversion_function_id (cp_parser* parser) |
17291 | { |
17292 | tree type; |
17293 | tree saved_scope; |
17294 | tree saved_qualifying_scope; |
17295 | tree saved_object_scope; |
17296 | tree pushed_scope = NULL_TREE; |
17297 | |
17298 | /* Look for the `operator' token. */ |
17299 | if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR)) |
17300 | return error_mark_node; |
17301 | /* When we parse the conversion-type-id, the current scope will be |
17302 | reset. However, we need that information in able to look up the |
17303 | conversion function later, so we save it here. */ |
17304 | saved_scope = parser->scope; |
17305 | saved_qualifying_scope = parser->qualifying_scope; |
17306 | saved_object_scope = parser->object_scope; |
17307 | /* We must enter the scope of the class so that the names of |
17308 | entities declared within the class are available in the |
17309 | conversion-type-id. For example, consider: |
17310 | |
17311 | struct S { |
17312 | typedef int I; |
17313 | operator I(); |
17314 | }; |
17315 | |
17316 | S::operator I() { ... } |
17317 | |
17318 | In order to see that `I' is a type-name in the definition, we |
17319 | must be in the scope of `S'. */ |
17320 | if (saved_scope) |
17321 | pushed_scope = push_scope (saved_scope); |
17322 | /* Parse the conversion-type-id. */ |
17323 | type = cp_parser_conversion_type_id (parser); |
17324 | /* Leave the scope of the class, if any. */ |
17325 | if (pushed_scope) |
17326 | pop_scope (pushed_scope); |
17327 | /* Restore the saved scope. */ |
17328 | parser->scope = saved_scope; |
17329 | parser->qualifying_scope = saved_qualifying_scope; |
17330 | parser->object_scope = saved_object_scope; |
17331 | /* If the TYPE is invalid, indicate failure. */ |
17332 | if (type == error_mark_node) |
17333 | return error_mark_node; |
17334 | return make_conv_op_name (type); |
17335 | } |
17336 | |
17337 | /* Parse a conversion-type-id: |
17338 | |
17339 | conversion-type-id: |
17340 | type-specifier-seq conversion-declarator [opt] |
17341 | |
17342 | Returns the TYPE specified. */ |
17343 | |
17344 | static tree |
17345 | cp_parser_conversion_type_id (cp_parser* parser) |
17346 | { |
17347 | tree attributes; |
17348 | cp_decl_specifier_seq type_specifiers; |
17349 | cp_declarator *declarator; |
17350 | tree type_specified; |
17351 | const char *saved_message; |
17352 | |
17353 | /* Parse the attributes. */ |
17354 | attributes = cp_parser_attributes_opt (parser); |
17355 | |
17356 | saved_message = parser->type_definition_forbidden_message; |
17357 | parser->type_definition_forbidden_message |
17358 | = G_("types may not be defined in a conversion-type-id" ); |
17359 | |
17360 | /* Parse the type-specifiers. DR 2413 clarifies that `typename' is |
17361 | optional in conversion-type-id. */ |
17362 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
17363 | /*is_declaration=*/false, |
17364 | /*is_trailing_return=*/false, |
17365 | &type_specifiers); |
17366 | |
17367 | parser->type_definition_forbidden_message = saved_message; |
17368 | |
17369 | /* If that didn't work, stop. */ |
17370 | if (type_specifiers.type == error_mark_node) |
17371 | return error_mark_node; |
17372 | /* Parse the conversion-declarator. */ |
17373 | declarator = cp_parser_conversion_declarator_opt (parser); |
17374 | |
17375 | type_specified = grokdeclarator (declarator, &type_specifiers, TYPENAME, |
17376 | /*initialized=*/0, &attributes); |
17377 | if (attributes) |
17378 | cplus_decl_attributes (&type_specified, attributes, /*flags=*/0); |
17379 | |
17380 | /* Don't give this error when parsing tentatively. This happens to |
17381 | work because we always parse this definitively once. */ |
17382 | if (! cp_parser_uncommitted_to_tentative_parse_p (parser) |
17383 | && type_uses_auto (type_specified)) |
17384 | { |
17385 | if (cxx_dialect < cxx14) |
17386 | { |
17387 | error ("invalid use of %<auto%> in conversion operator" ); |
17388 | return error_mark_node; |
17389 | } |
17390 | else if (template_parm_scope_p ()) |
17391 | warning (0, "use of %<auto%> in member template " |
17392 | "conversion operator can never be deduced" ); |
17393 | } |
17394 | |
17395 | return type_specified; |
17396 | } |
17397 | |
17398 | /* Parse an (optional) conversion-declarator. |
17399 | |
17400 | conversion-declarator: |
17401 | ptr-operator conversion-declarator [opt] |
17402 | |
17403 | */ |
17404 | |
17405 | static cp_declarator * |
17406 | cp_parser_conversion_declarator_opt (cp_parser* parser) |
17407 | { |
17408 | enum tree_code code; |
17409 | tree class_type, std_attributes = NULL_TREE; |
17410 | cp_cv_quals cv_quals; |
17411 | |
17412 | /* We don't know if there's a ptr-operator next, or not. */ |
17413 | cp_parser_parse_tentatively (parser); |
17414 | /* Try the ptr-operator. */ |
17415 | code = cp_parser_ptr_operator (parser, &class_type, &cv_quals, |
17416 | &std_attributes); |
17417 | /* If it worked, look for more conversion-declarators. */ |
17418 | if (cp_parser_parse_definitely (parser)) |
17419 | { |
17420 | cp_declarator *declarator; |
17421 | |
17422 | /* Parse another optional declarator. */ |
17423 | declarator = cp_parser_conversion_declarator_opt (parser); |
17424 | |
17425 | declarator = cp_parser_make_indirect_declarator |
17426 | (code, class_type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
17427 | |
17428 | return declarator; |
17429 | } |
17430 | |
17431 | return NULL; |
17432 | } |
17433 | |
17434 | /* Parse an (optional) ctor-initializer. |
17435 | |
17436 | ctor-initializer: |
17437 | : mem-initializer-list */ |
17438 | |
17439 | static void |
17440 | cp_parser_ctor_initializer_opt (cp_parser* parser) |
17441 | { |
17442 | /* If the next token is not a `:', then there is no |
17443 | ctor-initializer. */ |
17444 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
17445 | { |
17446 | /* Do default initialization of any bases and members. */ |
17447 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
17448 | finish_mem_initializers (NULL_TREE); |
17449 | return; |
17450 | } |
17451 | |
17452 | /* Consume the `:' token. */ |
17453 | cp_lexer_consume_token (lexer: parser->lexer); |
17454 | /* And the mem-initializer-list. */ |
17455 | cp_parser_mem_initializer_list (parser); |
17456 | } |
17457 | |
17458 | /* Parse a mem-initializer-list. |
17459 | |
17460 | mem-initializer-list: |
17461 | mem-initializer ... [opt] |
17462 | mem-initializer ... [opt] , mem-initializer-list */ |
17463 | |
17464 | static void |
17465 | cp_parser_mem_initializer_list (cp_parser* parser) |
17466 | { |
17467 | tree mem_initializer_list = NULL_TREE; |
17468 | tree target_ctor = error_mark_node; |
17469 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17470 | |
17471 | /* Let the semantic analysis code know that we are starting the |
17472 | mem-initializer-list. */ |
17473 | if (!DECL_CONSTRUCTOR_P (current_function_decl)) |
17474 | error_at (token->location, |
17475 | "only constructors take member initializers" ); |
17476 | |
17477 | /* Loop through the list. */ |
17478 | while (true) |
17479 | { |
17480 | tree mem_initializer; |
17481 | |
17482 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17483 | /* Parse the mem-initializer. */ |
17484 | mem_initializer = cp_parser_mem_initializer (parser); |
17485 | /* If the next token is a `...', we're expanding member initializers. */ |
17486 | bool ellipsis = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS); |
17487 | if (ellipsis |
17488 | || (mem_initializer != error_mark_node |
17489 | && check_for_bare_parameter_packs (TREE_PURPOSE |
17490 | (mem_initializer)))) |
17491 | { |
17492 | /* Consume the `...'. */ |
17493 | if (ellipsis) |
17494 | cp_lexer_consume_token (lexer: parser->lexer); |
17495 | |
17496 | /* The TREE_PURPOSE must be a _TYPE, because base-specifiers |
17497 | can be expanded but members cannot. */ |
17498 | if (mem_initializer != error_mark_node |
17499 | && !TYPE_P (TREE_PURPOSE (mem_initializer))) |
17500 | { |
17501 | error_at (token->location, |
17502 | "cannot expand initializer for member %qD" , |
17503 | TREE_PURPOSE (mem_initializer)); |
17504 | mem_initializer = error_mark_node; |
17505 | } |
17506 | |
17507 | /* Construct the pack expansion type. */ |
17508 | if (mem_initializer != error_mark_node) |
17509 | mem_initializer = make_pack_expansion (mem_initializer); |
17510 | } |
17511 | if (target_ctor != error_mark_node |
17512 | && mem_initializer != error_mark_node) |
17513 | { |
17514 | error ("mem-initializer for %qD follows constructor delegation" , |
17515 | TREE_PURPOSE (mem_initializer)); |
17516 | mem_initializer = error_mark_node; |
17517 | } |
17518 | /* Look for a target constructor. */ |
17519 | if (mem_initializer != error_mark_node |
17520 | && CLASS_TYPE_P (TREE_PURPOSE (mem_initializer)) |
17521 | && same_type_p (TREE_PURPOSE (mem_initializer), current_class_type)) |
17522 | { |
17523 | maybe_warn_cpp0x (str: CPP0X_DELEGATING_CTORS); |
17524 | if (mem_initializer_list) |
17525 | { |
17526 | error ("constructor delegation follows mem-initializer for %qD" , |
17527 | TREE_PURPOSE (mem_initializer_list)); |
17528 | mem_initializer = error_mark_node; |
17529 | } |
17530 | target_ctor = mem_initializer; |
17531 | } |
17532 | /* Add it to the list, unless it was erroneous. */ |
17533 | if (mem_initializer != error_mark_node) |
17534 | { |
17535 | TREE_CHAIN (mem_initializer) = mem_initializer_list; |
17536 | mem_initializer_list = mem_initializer; |
17537 | } |
17538 | /* If the next token is not a `,', we're done. */ |
17539 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
17540 | break; |
17541 | /* Consume the `,' token. */ |
17542 | cp_lexer_consume_token (lexer: parser->lexer); |
17543 | } |
17544 | |
17545 | /* Perform semantic analysis. */ |
17546 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
17547 | finish_mem_initializers (mem_initializer_list); |
17548 | } |
17549 | |
17550 | /* Parse a mem-initializer. |
17551 | |
17552 | mem-initializer: |
17553 | mem-initializer-id ( expression-list [opt] ) |
17554 | mem-initializer-id braced-init-list |
17555 | |
17556 | GNU extension: |
17557 | |
17558 | mem-initializer: |
17559 | ( expression-list [opt] ) |
17560 | |
17561 | Returns a TREE_LIST. The TREE_PURPOSE is the TYPE (for a base |
17562 | class) or FIELD_DECL (for a non-static data member) to initialize; |
17563 | the TREE_VALUE is the expression-list. An empty initialization |
17564 | list is represented by void_list_node. */ |
17565 | |
17566 | static tree |
17567 | cp_parser_mem_initializer (cp_parser* parser) |
17568 | { |
17569 | tree mem_initializer_id; |
17570 | tree expression_list; |
17571 | tree member; |
17572 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17573 | |
17574 | /* Find out what is being initialized. */ |
17575 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
17576 | { |
17577 | permerror (token->location, |
17578 | "anachronistic old-style base class initializer" ); |
17579 | mem_initializer_id = NULL_TREE; |
17580 | } |
17581 | else |
17582 | { |
17583 | mem_initializer_id = cp_parser_mem_initializer_id (parser); |
17584 | if (mem_initializer_id == error_mark_node) |
17585 | return mem_initializer_id; |
17586 | } |
17587 | member = expand_member_init (mem_initializer_id); |
17588 | if (member && !DECL_P (member)) |
17589 | in_base_initializer = 1; |
17590 | |
17591 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
17592 | { |
17593 | cp_lexer_set_source_position (lexer: parser->lexer); |
17594 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
17595 | expression_list = cp_parser_braced_list (parser); |
17596 | CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; |
17597 | expression_list = build_tree_list (NULL_TREE, expression_list); |
17598 | } |
17599 | else |
17600 | { |
17601 | vec<tree, va_gc> *vec; |
17602 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
17603 | /*cast_p=*/false, |
17604 | /*allow_expansion_p=*/true, |
17605 | /*non_constant_p=*/NULL, |
17606 | /*close_paren_loc=*/NULL, |
17607 | /*wrap_locations_p=*/true); |
17608 | if (vec == NULL) |
17609 | return error_mark_node; |
17610 | expression_list = build_tree_list_vec (vec); |
17611 | release_tree_vector (vec); |
17612 | } |
17613 | |
17614 | if (expression_list == error_mark_node) |
17615 | return error_mark_node; |
17616 | if (!expression_list) |
17617 | expression_list = void_type_node; |
17618 | |
17619 | in_base_initializer = 0; |
17620 | |
17621 | if (!member) |
17622 | return error_mark_node; |
17623 | tree node = build_tree_list (member, expression_list); |
17624 | |
17625 | /* We can't attach the source location of this initializer directly to |
17626 | the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR |
17627 | within the TREE_TYPE of the list node. */ |
17628 | location_t loc |
17629 | = make_location (caret: token->location, start: token->location, lexer: parser->lexer); |
17630 | tree dummy = build0 (EMPTY_CLASS_EXPR, NULL_TREE); |
17631 | SET_EXPR_LOCATION (dummy, loc); |
17632 | TREE_TYPE (node) = dummy; |
17633 | |
17634 | return node; |
17635 | } |
17636 | |
17637 | /* Parse a mem-initializer-id. |
17638 | |
17639 | mem-initializer-id: |
17640 | :: [opt] nested-name-specifier [opt] class-name |
17641 | decltype-specifier (C++11) |
17642 | identifier |
17643 | |
17644 | Returns a TYPE indicating the class to be initialized for the first |
17645 | production (and the second in C++11). Returns an IDENTIFIER_NODE |
17646 | indicating the data member to be initialized for the last production. */ |
17647 | |
17648 | static tree |
17649 | cp_parser_mem_initializer_id (cp_parser* parser) |
17650 | { |
17651 | bool global_scope_p; |
17652 | bool nested_name_specifier_p; |
17653 | bool template_p = false; |
17654 | tree id; |
17655 | |
17656 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17657 | |
17658 | /* `typename' is not allowed in this context ([temp.res]). */ |
17659 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
17660 | { |
17661 | error_at (token->location, |
17662 | "keyword %<typename%> not allowed in this context (a qualified " |
17663 | "member initializer is implicitly a type)" ); |
17664 | cp_lexer_consume_token (lexer: parser->lexer); |
17665 | } |
17666 | /* Look for the optional `::' operator. */ |
17667 | global_scope_p |
17668 | = (cp_parser_global_scope_opt (parser, |
17669 | /*current_scope_valid_p=*/false) |
17670 | != NULL_TREE); |
17671 | /* Look for the optional nested-name-specifier. The simplest way to |
17672 | implement: |
17673 | |
17674 | [temp.res] |
17675 | |
17676 | The keyword `typename' is not permitted in a base-specifier or |
17677 | mem-initializer; in these contexts a qualified name that |
17678 | depends on a template-parameter is implicitly assumed to be a |
17679 | type name. |
17680 | |
17681 | is to assume that we have seen the `typename' keyword at this |
17682 | point. */ |
17683 | nested_name_specifier_p |
17684 | = (cp_parser_nested_name_specifier_opt (parser, |
17685 | /*typename_keyword_p=*/true, |
17686 | /*check_dependency_p=*/true, |
17687 | /*type_p=*/true, |
17688 | /*is_declaration=*/true) |
17689 | != NULL_TREE); |
17690 | if (nested_name_specifier_p) |
17691 | template_p = cp_parser_optional_template_keyword (parser); |
17692 | /* If there is a `::' operator or a nested-name-specifier, then we |
17693 | are definitely looking for a class-name. */ |
17694 | if (global_scope_p || nested_name_specifier_p) |
17695 | return cp_parser_class_name (parser, |
17696 | /*typename_keyword_p=*/true, |
17697 | /*template_keyword_p=*/template_p, |
17698 | typename_type, |
17699 | /*check_dependency_p=*/true, |
17700 | /*class_head_p=*/false, |
17701 | /*is_declaration=*/true); |
17702 | /* Otherwise, we could also be looking for an ordinary identifier. */ |
17703 | cp_parser_parse_tentatively (parser); |
17704 | if (cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
17705 | /* Try a decltype-specifier. */ |
17706 | id = cp_parser_decltype (parser); |
17707 | else |
17708 | /* Otherwise, try a class-name. */ |
17709 | id = cp_parser_class_name (parser, |
17710 | /*typename_keyword_p=*/true, |
17711 | /*template_keyword_p=*/false, |
17712 | none_type, |
17713 | /*check_dependency_p=*/true, |
17714 | /*class_head_p=*/false, |
17715 | /*is_declaration=*/true); |
17716 | /* If we found one, we're done. */ |
17717 | if (cp_parser_parse_definitely (parser)) |
17718 | return id; |
17719 | /* Otherwise, look for an ordinary identifier. */ |
17720 | return cp_parser_identifier (parser); |
17721 | } |
17722 | |
17723 | /* Overloading [gram.over] */ |
17724 | |
17725 | /* Parse an operator-function-id. |
17726 | |
17727 | operator-function-id: |
17728 | operator operator |
17729 | |
17730 | Returns an IDENTIFIER_NODE for the operator which is a |
17731 | human-readable spelling of the identifier, e.g., `operator +'. */ |
17732 | |
17733 | static cp_expr |
17734 | cp_parser_operator_function_id (cp_parser* parser) |
17735 | { |
17736 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
17737 | /* Look for the `operator' keyword. */ |
17738 | if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR)) |
17739 | return error_mark_node; |
17740 | /* And then the name of the operator itself. */ |
17741 | return cp_parser_operator (parser, start_loc); |
17742 | } |
17743 | |
17744 | /* Return an identifier node for a user-defined literal operator. |
17745 | The suffix identifier is chained to the operator name identifier. */ |
17746 | |
17747 | tree |
17748 | cp_literal_operator_id (const char* name) |
17749 | { |
17750 | tree identifier; |
17751 | char *buffer = XNEWVEC (char, strlen (UDLIT_OP_ANSI_PREFIX) |
17752 | + strlen (name) + 10); |
17753 | sprintf (s: buffer, UDLIT_OP_ANSI_FORMAT, name); |
17754 | identifier = get_identifier (buffer); |
17755 | XDELETEVEC (buffer); |
17756 | |
17757 | return identifier; |
17758 | } |
17759 | |
17760 | /* Parse an operator. |
17761 | |
17762 | operator: |
17763 | new delete new[] delete[] + - * / % ^ & | ~ ! = < > |
17764 | += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && |
17765 | || ++ -- , ->* -> () [] |
17766 | |
17767 | GNU Extensions: |
17768 | |
17769 | operator: |
17770 | <? >? <?= >?= |
17771 | |
17772 | Returns an IDENTIFIER_NODE for the operator which is a |
17773 | human-readable spelling of the identifier, e.g., `operator +'. */ |
17774 | |
17775 | static cp_expr |
17776 | cp_parser_operator (cp_parser* parser, location_t start_loc) |
17777 | { |
17778 | tree id = NULL_TREE; |
17779 | cp_token *token; |
17780 | bool utf8 = false; |
17781 | |
17782 | /* Peek at the next token. */ |
17783 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17784 | |
17785 | location_t end_loc = token->location; |
17786 | |
17787 | /* Figure out which operator we have. */ |
17788 | enum tree_code op = ERROR_MARK; |
17789 | bool assop = false; |
17790 | bool consumed = false; |
17791 | switch (token->type) |
17792 | { |
17793 | case CPP_KEYWORD: |
17794 | { |
17795 | /* The keyword should be either `new', `delete' or `co_await'. */ |
17796 | if (token->keyword == RID_NEW) |
17797 | op = NEW_EXPR; |
17798 | else if (token->keyword == RID_DELETE) |
17799 | op = DELETE_EXPR; |
17800 | else if (token->keyword == RID_CO_AWAIT) |
17801 | op = CO_AWAIT_EXPR; |
17802 | else |
17803 | break; |
17804 | |
17805 | /* Consume the `new', `delete' or co_await token. */ |
17806 | end_loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
17807 | |
17808 | /* Peek at the next token. */ |
17809 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17810 | /* If it's a `[' token then this is the array variant of the |
17811 | operator. */ |
17812 | if (token->type == CPP_OPEN_SQUARE |
17813 | && op != CO_AWAIT_EXPR) |
17814 | { |
17815 | /* Consume the `[' token. */ |
17816 | cp_lexer_consume_token (lexer: parser->lexer); |
17817 | /* Look for the `]' token. */ |
17818 | if (cp_token *close_token |
17819 | = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
17820 | end_loc = close_token->location; |
17821 | op = op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR; |
17822 | } |
17823 | consumed = true; |
17824 | break; |
17825 | } |
17826 | |
17827 | case CPP_PLUS: |
17828 | op = PLUS_EXPR; |
17829 | break; |
17830 | |
17831 | case CPP_MINUS: |
17832 | op = MINUS_EXPR; |
17833 | break; |
17834 | |
17835 | case CPP_MULT: |
17836 | op = MULT_EXPR; |
17837 | break; |
17838 | |
17839 | case CPP_DIV: |
17840 | op = TRUNC_DIV_EXPR; |
17841 | break; |
17842 | |
17843 | case CPP_MOD: |
17844 | op = TRUNC_MOD_EXPR; |
17845 | break; |
17846 | |
17847 | case CPP_XOR: |
17848 | op = BIT_XOR_EXPR; |
17849 | break; |
17850 | |
17851 | case CPP_AND: |
17852 | op = BIT_AND_EXPR; |
17853 | break; |
17854 | |
17855 | case CPP_OR: |
17856 | op = BIT_IOR_EXPR; |
17857 | break; |
17858 | |
17859 | case CPP_COMPL: |
17860 | op = BIT_NOT_EXPR; |
17861 | break; |
17862 | |
17863 | case CPP_NOT: |
17864 | op = TRUTH_NOT_EXPR; |
17865 | break; |
17866 | |
17867 | case CPP_EQ: |
17868 | assop = true; |
17869 | op = NOP_EXPR; |
17870 | break; |
17871 | |
17872 | case CPP_LESS: |
17873 | op = LT_EXPR; |
17874 | break; |
17875 | |
17876 | case CPP_GREATER: |
17877 | op = GT_EXPR; |
17878 | break; |
17879 | |
17880 | case CPP_PLUS_EQ: |
17881 | assop = true; |
17882 | op = PLUS_EXPR; |
17883 | break; |
17884 | |
17885 | case CPP_MINUS_EQ: |
17886 | assop = true; |
17887 | op = MINUS_EXPR; |
17888 | break; |
17889 | |
17890 | case CPP_MULT_EQ: |
17891 | assop = true; |
17892 | op = MULT_EXPR; |
17893 | break; |
17894 | |
17895 | case CPP_DIV_EQ: |
17896 | assop = true; |
17897 | op = TRUNC_DIV_EXPR; |
17898 | break; |
17899 | |
17900 | case CPP_MOD_EQ: |
17901 | assop = true; |
17902 | op = TRUNC_MOD_EXPR; |
17903 | break; |
17904 | |
17905 | case CPP_XOR_EQ: |
17906 | assop = true; |
17907 | op = BIT_XOR_EXPR; |
17908 | break; |
17909 | |
17910 | case CPP_AND_EQ: |
17911 | assop = true; |
17912 | op = BIT_AND_EXPR; |
17913 | break; |
17914 | |
17915 | case CPP_OR_EQ: |
17916 | assop = true; |
17917 | op = BIT_IOR_EXPR; |
17918 | break; |
17919 | |
17920 | case CPP_LSHIFT: |
17921 | op = LSHIFT_EXPR; |
17922 | break; |
17923 | |
17924 | case CPP_RSHIFT: |
17925 | op = RSHIFT_EXPR; |
17926 | break; |
17927 | |
17928 | case CPP_LSHIFT_EQ: |
17929 | assop = true; |
17930 | op = LSHIFT_EXPR; |
17931 | break; |
17932 | |
17933 | case CPP_RSHIFT_EQ: |
17934 | assop = true; |
17935 | op = RSHIFT_EXPR; |
17936 | break; |
17937 | |
17938 | case CPP_EQ_EQ: |
17939 | op = EQ_EXPR; |
17940 | break; |
17941 | |
17942 | case CPP_NOT_EQ: |
17943 | op = NE_EXPR; |
17944 | break; |
17945 | |
17946 | case CPP_LESS_EQ: |
17947 | op = LE_EXPR; |
17948 | break; |
17949 | |
17950 | case CPP_GREATER_EQ: |
17951 | op = GE_EXPR; |
17952 | break; |
17953 | |
17954 | case CPP_SPACESHIP: |
17955 | op = SPACESHIP_EXPR; |
17956 | break; |
17957 | |
17958 | case CPP_AND_AND: |
17959 | op = TRUTH_ANDIF_EXPR; |
17960 | break; |
17961 | |
17962 | case CPP_OR_OR: |
17963 | op = TRUTH_ORIF_EXPR; |
17964 | break; |
17965 | |
17966 | case CPP_PLUS_PLUS: |
17967 | op = POSTINCREMENT_EXPR; |
17968 | break; |
17969 | |
17970 | case CPP_MINUS_MINUS: |
17971 | op = PREDECREMENT_EXPR; |
17972 | break; |
17973 | |
17974 | case CPP_COMMA: |
17975 | op = COMPOUND_EXPR; |
17976 | break; |
17977 | |
17978 | case CPP_DEREF_STAR: |
17979 | op = MEMBER_REF; |
17980 | break; |
17981 | |
17982 | case CPP_DEREF: |
17983 | op = COMPONENT_REF; |
17984 | break; |
17985 | |
17986 | case CPP_QUERY: |
17987 | op = COND_EXPR; |
17988 | /* Consume the `?'. */ |
17989 | cp_lexer_consume_token (lexer: parser->lexer); |
17990 | /* Look for the matching `:'. */ |
17991 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
17992 | consumed = true; |
17993 | break; |
17994 | |
17995 | case CPP_OPEN_PAREN: |
17996 | { |
17997 | /* Consume the `('. */ |
17998 | matching_parens parens; |
17999 | parens.consume_open (parser); |
18000 | /* Look for the matching `)'. */ |
18001 | token = parens.require_close (parser); |
18002 | if (token) |
18003 | end_loc = token->location; |
18004 | op = CALL_EXPR; |
18005 | consumed = true; |
18006 | break; |
18007 | } |
18008 | |
18009 | case CPP_OPEN_SQUARE: |
18010 | /* Consume the `['. */ |
18011 | cp_lexer_consume_token (lexer: parser->lexer); |
18012 | /* Look for the matching `]'. */ |
18013 | token = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
18014 | if (token) |
18015 | end_loc = token->location; |
18016 | op = ARRAY_REF; |
18017 | consumed = true; |
18018 | break; |
18019 | |
18020 | case CPP_UTF8STRING: |
18021 | case CPP_UTF8STRING_USERDEF: |
18022 | utf8 = true; |
18023 | /* FALLTHRU */ |
18024 | case CPP_STRING: |
18025 | case CPP_WSTRING: |
18026 | case CPP_STRING16: |
18027 | case CPP_STRING32: |
18028 | case CPP_STRING_USERDEF: |
18029 | case CPP_WSTRING_USERDEF: |
18030 | case CPP_STRING16_USERDEF: |
18031 | case CPP_STRING32_USERDEF: |
18032 | { |
18033 | tree string_tree; |
18034 | int sz, len; |
18035 | |
18036 | if (cxx_dialect == cxx98) |
18037 | maybe_warn_cpp0x (str: CPP0X_USER_DEFINED_LITERALS); |
18038 | |
18039 | /* Consume the string. */ |
18040 | cp_expr str = cp_parser_userdef_string_literal (parser, |
18041 | /*lookup_udlit=*/false); |
18042 | if (str == error_mark_node) |
18043 | return error_mark_node; |
18044 | else if (TREE_CODE (str) == USERDEF_LITERAL) |
18045 | { |
18046 | string_tree = USERDEF_LITERAL_VALUE (str.get_value ()); |
18047 | id = USERDEF_LITERAL_SUFFIX_ID (str.get_value ()); |
18048 | end_loc = str.get_location (); |
18049 | } |
18050 | else |
18051 | { |
18052 | string_tree = str; |
18053 | /* Look for the suffix identifier. */ |
18054 | token = cp_lexer_peek_token (lexer: parser->lexer); |
18055 | if (token->type == CPP_NAME) |
18056 | { |
18057 | id = cp_parser_identifier (parser); |
18058 | end_loc = token->location; |
18059 | } |
18060 | else if (token->type == CPP_KEYWORD) |
18061 | { |
18062 | error ("unexpected keyword;" |
18063 | " remove space between quotes and suffix identifier" ); |
18064 | return error_mark_node; |
18065 | } |
18066 | else |
18067 | { |
18068 | error ("expected suffix identifier" ); |
18069 | return error_mark_node; |
18070 | } |
18071 | } |
18072 | sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT |
18073 | (TREE_TYPE (TREE_TYPE (string_tree)))); |
18074 | len = TREE_STRING_LENGTH (string_tree) / sz - 1; |
18075 | if (len != 0) |
18076 | { |
18077 | error ("expected empty string after %<operator%> keyword" ); |
18078 | return error_mark_node; |
18079 | } |
18080 | if (utf8 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string_tree))) |
18081 | != char_type_node) |
18082 | { |
18083 | error ("invalid encoding prefix in literal operator" ); |
18084 | return error_mark_node; |
18085 | } |
18086 | if (id != error_mark_node) |
18087 | { |
18088 | const char *name = IDENTIFIER_POINTER (id); |
18089 | id = cp_literal_operator_id (name); |
18090 | } |
18091 | /* Generate a location of the form: |
18092 | "" _suffix_identifier |
18093 | ^~~~~~~~~~~~~~~~~~~~~ |
18094 | with caret == start at the start token, finish at the end of the |
18095 | suffix identifier. */ |
18096 | location_t combined_loc |
18097 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
18098 | return cp_expr (id, combined_loc); |
18099 | } |
18100 | |
18101 | default: |
18102 | /* Anything else is an error. */ |
18103 | break; |
18104 | } |
18105 | |
18106 | /* If we have selected an identifier, we need to consume the |
18107 | operator token. */ |
18108 | if (op != ERROR_MARK) |
18109 | { |
18110 | id = ovl_op_identifier (isass: assop, code: op); |
18111 | if (!consumed) |
18112 | cp_lexer_consume_token (lexer: parser->lexer); |
18113 | } |
18114 | /* Otherwise, no valid operator name was present. */ |
18115 | else |
18116 | { |
18117 | cp_parser_error (parser, gmsgid: "expected operator" ); |
18118 | id = error_mark_node; |
18119 | } |
18120 | |
18121 | start_loc = make_location (caret: start_loc, start: start_loc, finish: get_finish (loc: end_loc)); |
18122 | return cp_expr (id, start_loc); |
18123 | } |
18124 | |
18125 | /* Parse a template-declaration. |
18126 | |
18127 | template-declaration: |
18128 | export [opt] template < template-parameter-list > declaration |
18129 | |
18130 | If MEMBER_P is TRUE, this template-declaration occurs within a |
18131 | class-specifier. |
18132 | |
18133 | The grammar rule given by the standard isn't correct. What |
18134 | is really meant is: |
18135 | |
18136 | template-declaration: |
18137 | export [opt] template-parameter-list-seq |
18138 | decl-specifier-seq [opt] init-declarator [opt] ; |
18139 | export [opt] template-parameter-list-seq |
18140 | function-definition |
18141 | |
18142 | template-parameter-list-seq: |
18143 | template-parameter-list-seq [opt] |
18144 | template < template-parameter-list > |
18145 | |
18146 | Concept Extensions: |
18147 | |
18148 | template-parameter-list-seq: |
18149 | template < template-parameter-list > requires-clause [opt] |
18150 | |
18151 | requires-clause: |
18152 | requires logical-or-expression */ |
18153 | |
18154 | static void |
18155 | cp_parser_template_declaration (cp_parser* parser, bool member_p) |
18156 | { |
18157 | /* Check for `export'. */ |
18158 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_EXPORT)) |
18159 | { |
18160 | /* Consume the `export' token. */ |
18161 | cp_lexer_consume_token (lexer: parser->lexer); |
18162 | /* Warn that this use of export is deprecated. */ |
18163 | if (cxx_dialect < cxx11) |
18164 | warning (0, "keyword %<export%> not implemented, and will be ignored" ); |
18165 | else if (cxx_dialect < cxx20) |
18166 | warning (0, "keyword %<export%> is deprecated, and is ignored" ); |
18167 | else |
18168 | warning (0, "keyword %<export%> is enabled with %<-fmodules-ts%>" ); |
18169 | } |
18170 | |
18171 | cp_parser_template_declaration_after_export (parser, member_p); |
18172 | } |
18173 | |
18174 | /* Parse a template-parameter-list. |
18175 | |
18176 | template-parameter-list: |
18177 | template-parameter |
18178 | template-parameter-list , template-parameter |
18179 | |
18180 | Returns a TREE_LIST. Each node represents a template parameter. |
18181 | The nodes are connected via their TREE_CHAINs. */ |
18182 | |
18183 | static tree |
18184 | cp_parser_template_parameter_list (cp_parser* parser) |
18185 | { |
18186 | tree parameter_list = NULL_TREE; |
18187 | |
18188 | /* Don't create wrapper nodes within a template-parameter-list, |
18189 | since we don't want to have different types based on the |
18190 | spelling location of constants and decls within them. */ |
18191 | auto_suppress_location_wrappers sentinel; |
18192 | |
18193 | begin_template_parm_list (); |
18194 | |
18195 | /* The loop below parses the template parms. We first need to know |
18196 | the total number of template parms to be able to compute proper |
18197 | canonical types of each dependent type. So after the loop, when |
18198 | we know the total number of template parms, |
18199 | end_template_parm_list computes the proper canonical types and |
18200 | fixes up the dependent types accordingly. */ |
18201 | while (true) |
18202 | { |
18203 | tree parameter; |
18204 | bool is_non_type; |
18205 | bool is_parameter_pack; |
18206 | location_t parm_loc; |
18207 | |
18208 | /* Parse the template-parameter. */ |
18209 | parm_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
18210 | parameter = cp_parser_template_parameter (parser, |
18211 | &is_non_type, |
18212 | &is_parameter_pack); |
18213 | /* Add it to the list. */ |
18214 | if (parameter != error_mark_node) |
18215 | parameter_list = process_template_parm (parameter_list, |
18216 | parm_loc, |
18217 | parameter, |
18218 | is_non_type, |
18219 | is_parameter_pack); |
18220 | else |
18221 | { |
18222 | tree err_parm = build_tree_list (parameter, parameter); |
18223 | parameter_list = chainon (parameter_list, err_parm); |
18224 | } |
18225 | |
18226 | /* If the next token is not a `,', we're done. */ |
18227 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
18228 | break; |
18229 | /* Otherwise, consume the `,' token. */ |
18230 | cp_lexer_consume_token (lexer: parser->lexer); |
18231 | } |
18232 | |
18233 | return end_template_parm_list (parameter_list); |
18234 | } |
18235 | |
18236 | /* Parse a introduction-list. |
18237 | |
18238 | introduction-list: |
18239 | introduced-parameter |
18240 | introduction-list , introduced-parameter |
18241 | |
18242 | introduced-parameter: |
18243 | ...[opt] identifier |
18244 | |
18245 | Returns a TREE_VEC of WILDCARD_DECLs. If the parameter is a pack |
18246 | then the introduced parm will have WILDCARD_PACK_P set. In addition, the |
18247 | WILDCARD_DECL will also have DECL_NAME set and token location in |
18248 | DECL_SOURCE_LOCATION. */ |
18249 | |
18250 | static tree |
18251 | cp_parser_introduction_list (cp_parser *parser) |
18252 | { |
18253 | vec<tree, va_gc> *introduction_vec = make_tree_vector (); |
18254 | |
18255 | while (true) |
18256 | { |
18257 | bool is_pack = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS); |
18258 | if (is_pack) |
18259 | cp_lexer_consume_token (lexer: parser->lexer); |
18260 | |
18261 | tree identifier = cp_parser_identifier (parser); |
18262 | if (identifier == error_mark_node) |
18263 | break; |
18264 | |
18265 | /* Build placeholder. */ |
18266 | tree parm = build_nt (WILDCARD_DECL); |
18267 | DECL_SOURCE_LOCATION (parm) |
18268 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
18269 | DECL_NAME (parm) = identifier; |
18270 | WILDCARD_PACK_P (parm) = is_pack; |
18271 | vec_safe_push (v&: introduction_vec, obj: parm); |
18272 | |
18273 | /* If the next token is not a `,', we're done. */ |
18274 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
18275 | break; |
18276 | /* Otherwise, consume the `,' token. */ |
18277 | cp_lexer_consume_token (lexer: parser->lexer); |
18278 | } |
18279 | |
18280 | /* Convert the vec into a TREE_VEC. */ |
18281 | tree introduction_list = make_tree_vec (introduction_vec->length ()); |
18282 | unsigned int n; |
18283 | tree parm; |
18284 | FOR_EACH_VEC_ELT (*introduction_vec, n, parm) |
18285 | TREE_VEC_ELT (introduction_list, n) = parm; |
18286 | |
18287 | release_tree_vector (introduction_vec); |
18288 | return introduction_list; |
18289 | } |
18290 | |
18291 | /* Given a declarator, get the declarator-id part, or NULL_TREE if this |
18292 | is an abstract declarator. */ |
18293 | |
18294 | static inline cp_declarator* |
18295 | get_id_declarator (cp_declarator *declarator) |
18296 | { |
18297 | cp_declarator *d = declarator; |
18298 | while (d && d->kind != cdk_id) |
18299 | d = d->declarator; |
18300 | return d; |
18301 | } |
18302 | |
18303 | /* Get the unqualified-id from the DECLARATOR or NULL_TREE if this |
18304 | is an abstract declarator. */ |
18305 | |
18306 | static inline tree |
18307 | get_unqualified_id (cp_declarator *declarator) |
18308 | { |
18309 | declarator = get_id_declarator (declarator); |
18310 | if (declarator) |
18311 | return declarator->u.id.unqualified_name; |
18312 | else |
18313 | return NULL_TREE; |
18314 | } |
18315 | |
18316 | /* Returns true if TYPE would declare a constrained constrained-parameter. */ |
18317 | |
18318 | static inline bool |
18319 | is_constrained_parameter (tree type) |
18320 | { |
18321 | return (type |
18322 | && TREE_CODE (type) == TYPE_DECL |
18323 | && CONSTRAINED_PARM_CONCEPT (type) |
18324 | && DECL_P (CONSTRAINED_PARM_CONCEPT (type))); |
18325 | } |
18326 | |
18327 | /* Returns true if PARM declares a constrained-parameter. */ |
18328 | |
18329 | static inline bool |
18330 | is_constrained_parameter (cp_parameter_declarator *parm) |
18331 | { |
18332 | return is_constrained_parameter (type: parm->decl_specifiers.type); |
18333 | } |
18334 | |
18335 | /* Check that the type parameter is only a declarator-id, and that its |
18336 | type is not cv-qualified. */ |
18337 | |
18338 | bool |
18339 | cp_parser_check_constrained_type_parm (cp_parser *parser, |
18340 | cp_parameter_declarator *parm) |
18341 | { |
18342 | if (!parm->declarator) |
18343 | return true; |
18344 | |
18345 | if (parm->declarator->kind != cdk_id) |
18346 | { |
18347 | cp_parser_error (parser, gmsgid: "invalid constrained type parameter" ); |
18348 | return false; |
18349 | } |
18350 | |
18351 | /* Don't allow cv-qualified type parameters. */ |
18352 | if (decl_spec_seq_has_spec_p (&parm->decl_specifiers, ds_const) |
18353 | || decl_spec_seq_has_spec_p (&parm->decl_specifiers, ds_volatile)) |
18354 | { |
18355 | cp_parser_error (parser, gmsgid: "cv-qualified type parameter" ); |
18356 | return false; |
18357 | } |
18358 | |
18359 | return true; |
18360 | } |
18361 | |
18362 | /* Finish parsing/processing a template type parameter and checking |
18363 | various restrictions. */ |
18364 | |
18365 | static inline tree |
18366 | cp_parser_constrained_type_template_parm (cp_parser *parser, |
18367 | tree id, |
18368 | cp_parameter_declarator* parmdecl) |
18369 | { |
18370 | if (cp_parser_check_constrained_type_parm (parser, parm: parmdecl)) |
18371 | return finish_template_type_parm (class_type_node, id); |
18372 | else |
18373 | return error_mark_node; |
18374 | } |
18375 | |
18376 | static tree |
18377 | finish_constrained_template_template_parm (tree proto, tree id) |
18378 | { |
18379 | /* FIXME: This should probably be copied, and we may need to adjust |
18380 | the template parameter depths. */ |
18381 | tree saved_parms = current_template_parms; |
18382 | begin_template_parm_list (); |
18383 | current_template_parms = DECL_TEMPLATE_PARMS (proto); |
18384 | end_template_parm_list (); |
18385 | |
18386 | tree parm = finish_template_template_parm (class_type_node, id); |
18387 | current_template_parms = saved_parms; |
18388 | |
18389 | return parm; |
18390 | } |
18391 | |
18392 | /* Finish parsing/processing a template template parameter by borrowing |
18393 | the template parameter list from the prototype parameter. */ |
18394 | |
18395 | static tree |
18396 | cp_parser_constrained_template_template_parm (cp_parser *parser, |
18397 | tree proto, |
18398 | tree id, |
18399 | cp_parameter_declarator *parmdecl) |
18400 | { |
18401 | if (!cp_parser_check_constrained_type_parm (parser, parm: parmdecl)) |
18402 | return error_mark_node; |
18403 | return finish_constrained_template_template_parm (proto, id); |
18404 | } |
18405 | |
18406 | /* Create a new non-type template parameter from the given PARM |
18407 | declarator. */ |
18408 | |
18409 | static tree |
18410 | cp_parser_constrained_non_type_template_parm (bool *is_non_type, |
18411 | cp_parameter_declarator *parm) |
18412 | { |
18413 | *is_non_type = true; |
18414 | cp_declarator *decl = parm->declarator; |
18415 | cp_decl_specifier_seq *specs = &parm->decl_specifiers; |
18416 | specs->type = TREE_TYPE (DECL_INITIAL (specs->type)); |
18417 | return grokdeclarator (decl, specs, TPARM, 0, NULL); |
18418 | } |
18419 | |
18420 | /* Build a constrained template parameter based on the PARMDECL |
18421 | declarator. The type of PARMDECL is the constrained type, which |
18422 | refers to the prototype template parameter that ultimately |
18423 | specifies the type of the declared parameter. */ |
18424 | |
18425 | static tree |
18426 | finish_constrained_parameter (cp_parser *parser, |
18427 | cp_parameter_declarator *parmdecl, |
18428 | bool *is_non_type) |
18429 | { |
18430 | tree decl = parmdecl->decl_specifiers.type; |
18431 | tree id = get_unqualified_id (declarator: parmdecl->declarator); |
18432 | tree def = parmdecl->default_argument; |
18433 | tree proto = DECL_INITIAL (decl); |
18434 | |
18435 | /* Build the parameter. Return an error if the declarator was invalid. */ |
18436 | tree parm; |
18437 | if (TREE_CODE (proto) == TYPE_DECL) |
18438 | parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl); |
18439 | else if (TREE_CODE (proto) == TEMPLATE_DECL) |
18440 | parm = cp_parser_constrained_template_template_parm (parser, proto, id, |
18441 | parmdecl); |
18442 | else |
18443 | parm = cp_parser_constrained_non_type_template_parm (is_non_type, parm: parmdecl); |
18444 | if (parm == error_mark_node) |
18445 | return error_mark_node; |
18446 | |
18447 | /* Finish the parameter decl and create a node attaching the |
18448 | default argument and constraint. */ |
18449 | parm = build_tree_list (def, parm); |
18450 | TEMPLATE_PARM_CONSTRAINTS (parm) = decl; |
18451 | |
18452 | return parm; |
18453 | } |
18454 | |
18455 | /* Returns true if the parsed type actually represents the declaration |
18456 | of a type template-parameter. */ |
18457 | |
18458 | static bool |
18459 | declares_constrained_type_template_parameter (tree type) |
18460 | { |
18461 | return (is_constrained_parameter (type) |
18462 | && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TYPE_PARM); |
18463 | } |
18464 | |
18465 | /* Returns true if the parsed type actually represents the declaration of |
18466 | a template template-parameter. */ |
18467 | |
18468 | static bool |
18469 | declares_constrained_template_template_parameter (tree type) |
18470 | { |
18471 | return (is_constrained_parameter (type) |
18472 | && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TEMPLATE_PARM); |
18473 | } |
18474 | |
18475 | /* Parse a default argument for a type template-parameter. |
18476 | Note that diagnostics are handled in cp_parser_template_parameter. */ |
18477 | |
18478 | static tree |
18479 | cp_parser_default_type_template_argument (cp_parser *parser) |
18480 | { |
18481 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ)); |
18482 | |
18483 | /* Consume the `=' token. */ |
18484 | cp_lexer_consume_token (lexer: parser->lexer); |
18485 | |
18486 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
18487 | |
18488 | /* Tell cp_parser_lambda_expression this is a default argument. */ |
18489 | auto lvf = make_temp_override (var&: parser->local_variables_forbidden_p); |
18490 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
18491 | |
18492 | /* Parse the default-argument. */ |
18493 | push_deferring_access_checks (dk_no_deferred); |
18494 | tree default_argument = cp_parser_type_id (parser, |
18495 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
18496 | NULL); |
18497 | pop_deferring_access_checks (); |
18498 | |
18499 | if (flag_concepts && type_uses_auto (default_argument)) |
18500 | { |
18501 | error_at (token->location, |
18502 | "invalid use of %<auto%> in default template argument" ); |
18503 | return error_mark_node; |
18504 | } |
18505 | |
18506 | return default_argument; |
18507 | } |
18508 | |
18509 | /* Parse a default argument for a template template-parameter. */ |
18510 | |
18511 | static tree |
18512 | cp_parser_default_template_template_argument (cp_parser *parser) |
18513 | { |
18514 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ)); |
18515 | |
18516 | bool is_template; |
18517 | |
18518 | /* Consume the `='. */ |
18519 | cp_lexer_consume_token (lexer: parser->lexer); |
18520 | /* Parse the id-expression. */ |
18521 | push_deferring_access_checks (dk_no_deferred); |
18522 | /* save token before parsing the id-expression, for error |
18523 | reporting */ |
18524 | const cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
18525 | tree default_argument |
18526 | = cp_parser_id_expression (parser, |
18527 | /*template_keyword_p=*/false, |
18528 | /*check_dependency_p=*/true, |
18529 | /*template_p=*/&is_template, |
18530 | /*declarator_p=*/false, |
18531 | /*optional_p=*/false); |
18532 | if (TREE_CODE (default_argument) == TYPE_DECL) |
18533 | /* If the id-expression was a template-id that refers to |
18534 | a template-class, we already have the declaration here, |
18535 | so no further lookup is needed. */ |
18536 | ; |
18537 | else |
18538 | /* Look up the name. */ |
18539 | default_argument |
18540 | = cp_parser_lookup_name (parser, default_argument, |
18541 | none_type, |
18542 | /*is_template=*/is_template, |
18543 | /*is_namespace=*/false, |
18544 | /*check_dependency=*/true, |
18545 | /*ambiguous_decls=*/NULL, |
18546 | token->location); |
18547 | /* See if the default argument is valid. */ |
18548 | default_argument = check_template_template_default_arg (default_argument); |
18549 | pop_deferring_access_checks (); |
18550 | return default_argument; |
18551 | } |
18552 | |
18553 | /* Parse a template-parameter. |
18554 | |
18555 | template-parameter: |
18556 | type-parameter |
18557 | parameter-declaration |
18558 | |
18559 | If all goes well, returns a TREE_LIST. The TREE_VALUE represents |
18560 | the parameter. The TREE_PURPOSE is the default value, if any. |
18561 | Returns ERROR_MARK_NODE on failure. *IS_NON_TYPE is set to true |
18562 | iff this parameter is a non-type parameter. *IS_PARAMETER_PACK is |
18563 | set to true iff this parameter is a parameter pack. */ |
18564 | |
18565 | static tree |
18566 | cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, |
18567 | bool *is_parameter_pack) |
18568 | { |
18569 | cp_token *token; |
18570 | cp_parameter_declarator *parameter_declarator; |
18571 | tree parm; |
18572 | |
18573 | /* Assume it is a type parameter or a template parameter. */ |
18574 | *is_non_type = false; |
18575 | /* Assume it not a parameter pack. */ |
18576 | *is_parameter_pack = false; |
18577 | /* Peek at the next token. */ |
18578 | token = cp_lexer_peek_token (lexer: parser->lexer); |
18579 | /* If it is `template', we have a type-parameter. */ |
18580 | if (token->keyword == RID_TEMPLATE) |
18581 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18582 | /* If it is `class' or `typename' we do not know yet whether it is a |
18583 | type parameter or a non-type parameter. Consider: |
18584 | |
18585 | template <typename T, typename T::X X> ... |
18586 | |
18587 | or: |
18588 | |
18589 | template <class C, class D*> ... |
18590 | |
18591 | Here, the first parameter is a type parameter, and the second is |
18592 | a non-type parameter. We can tell by looking at the token after |
18593 | the identifier -- if it is a `,', `=', or `>' then we have a type |
18594 | parameter. */ |
18595 | if (token->keyword == RID_TYPENAME || token->keyword == RID_CLASS) |
18596 | { |
18597 | /* Peek at the token after `class' or `typename'. */ |
18598 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
18599 | /* If it's an ellipsis, we have a template type parameter |
18600 | pack. */ |
18601 | if (token->type == CPP_ELLIPSIS) |
18602 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18603 | /* If it's an identifier, skip it. */ |
18604 | if (token->type == CPP_NAME) |
18605 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3); |
18606 | /* Now, see if the token looks like the end of a template |
18607 | parameter. */ |
18608 | if (token->type == CPP_COMMA |
18609 | || token->type == CPP_EQ |
18610 | || token->type == CPP_GREATER) |
18611 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18612 | } |
18613 | |
18614 | /* Otherwise, it is a non-type parameter or a constrained parameter. |
18615 | |
18616 | [temp.param] |
18617 | |
18618 | When parsing a default template-argument for a non-type |
18619 | template-parameter, the first non-nested `>' is taken as the end |
18620 | of the template parameter-list rather than a greater-than |
18621 | operator. */ |
18622 | parameter_declarator |
18623 | = cp_parser_parameter_declaration (parser, |
18624 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
18625 | /*template_parm_p=*/true, |
18626 | /*parenthesized_p=*/NULL); |
18627 | |
18628 | if (!parameter_declarator) |
18629 | return error_mark_node; |
18630 | |
18631 | /* If the parameter declaration is marked as a parameter pack, set |
18632 | *IS_PARAMETER_PACK to notify the caller. */ |
18633 | if (parameter_declarator->template_parameter_pack_p) |
18634 | *is_parameter_pack = true; |
18635 | |
18636 | if (parameter_declarator->default_argument) |
18637 | { |
18638 | /* Can happen in some cases of erroneous input (c++/34892). */ |
18639 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18640 | /* Consume the `...' for better error recovery. */ |
18641 | cp_lexer_consume_token (lexer: parser->lexer); |
18642 | } |
18643 | |
18644 | /* The parameter may have been constrained type parameter. */ |
18645 | if (is_constrained_parameter (parm: parameter_declarator)) |
18646 | return finish_constrained_parameter (parser, |
18647 | parmdecl: parameter_declarator, |
18648 | is_non_type); |
18649 | |
18650 | // Now we're sure that the parameter is a non-type parameter. |
18651 | *is_non_type = true; |
18652 | |
18653 | parm = grokdeclarator (parameter_declarator->declarator, |
18654 | ¶meter_declarator->decl_specifiers, |
18655 | TPARM, /*initialized=*/0, |
18656 | /*attrlist=*/NULL); |
18657 | if (parm == error_mark_node) |
18658 | return error_mark_node; |
18659 | |
18660 | return build_tree_list (parameter_declarator->default_argument, parm); |
18661 | } |
18662 | |
18663 | /* Parse a type-parameter. |
18664 | |
18665 | type-parameter: |
18666 | class identifier [opt] |
18667 | class identifier [opt] = type-id |
18668 | typename identifier [opt] |
18669 | typename identifier [opt] = type-id |
18670 | template < template-parameter-list > class identifier [opt] |
18671 | template < template-parameter-list > class identifier [opt] |
18672 | = id-expression |
18673 | |
18674 | GNU Extension (variadic templates): |
18675 | |
18676 | type-parameter: |
18677 | class ... identifier [opt] |
18678 | typename ... identifier [opt] |
18679 | |
18680 | Returns a TREE_LIST. The TREE_VALUE is itself a TREE_LIST. The |
18681 | TREE_PURPOSE is the default-argument, if any. The TREE_VALUE is |
18682 | the declaration of the parameter. |
18683 | |
18684 | Sets *IS_PARAMETER_PACK if this is a template parameter pack. */ |
18685 | |
18686 | static tree |
18687 | cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) |
18688 | { |
18689 | cp_token *token; |
18690 | tree parameter; |
18691 | |
18692 | /* Look for a keyword to tell us what kind of parameter this is. */ |
18693 | token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_TYPENAME_TEMPLATE); |
18694 | if (!token) |
18695 | return error_mark_node; |
18696 | |
18697 | switch (token->keyword) |
18698 | { |
18699 | case RID_CLASS: |
18700 | case RID_TYPENAME: |
18701 | { |
18702 | tree identifier; |
18703 | tree default_argument; |
18704 | |
18705 | /* If the next token is an ellipsis, we have a template |
18706 | argument pack. */ |
18707 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18708 | { |
18709 | /* Consume the `...' token. */ |
18710 | cp_lexer_consume_token (lexer: parser->lexer); |
18711 | maybe_warn_variadic_templates (); |
18712 | |
18713 | *is_parameter_pack = true; |
18714 | } |
18715 | |
18716 | /* If the next token is an identifier, then it names the |
18717 | parameter. */ |
18718 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
18719 | identifier = cp_parser_identifier (parser); |
18720 | else |
18721 | identifier = NULL_TREE; |
18722 | |
18723 | /* Create the parameter. */ |
18724 | parameter = finish_template_type_parm (class_type_node, identifier); |
18725 | |
18726 | /* If the next token is an `=', we have a default argument. */ |
18727 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
18728 | { |
18729 | default_argument |
18730 | = cp_parser_default_type_template_argument (parser); |
18731 | |
18732 | /* Template parameter packs cannot have default |
18733 | arguments. */ |
18734 | if (*is_parameter_pack) |
18735 | { |
18736 | if (identifier) |
18737 | error_at (token->location, |
18738 | "template parameter pack %qD cannot have a " |
18739 | "default argument" , identifier); |
18740 | else |
18741 | error_at (token->location, |
18742 | "template parameter packs cannot have " |
18743 | "default arguments" ); |
18744 | default_argument = NULL_TREE; |
18745 | } |
18746 | else if (check_for_bare_parameter_packs (default_argument)) |
18747 | default_argument = error_mark_node; |
18748 | } |
18749 | else |
18750 | default_argument = NULL_TREE; |
18751 | |
18752 | /* Create the combined representation of the parameter and the |
18753 | default argument. */ |
18754 | parameter = build_tree_list (default_argument, parameter); |
18755 | } |
18756 | break; |
18757 | |
18758 | case RID_TEMPLATE: |
18759 | { |
18760 | tree identifier; |
18761 | tree default_argument; |
18762 | |
18763 | /* Look for the `<'. */ |
18764 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
18765 | /* Parse the template-parameter-list. */ |
18766 | cp_parser_template_parameter_list (parser); |
18767 | /* Look for the `>'. */ |
18768 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
18769 | |
18770 | /* If template requirements are present, parse them. */ |
18771 | if (flag_concepts) |
18772 | { |
18773 | tree reqs = get_shorthand_constraints (current_template_parms); |
18774 | if (tree dreqs = cp_parser_requires_clause_opt (parser, false)) |
18775 | reqs = combine_constraint_expressions (reqs, dreqs); |
18776 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
18777 | } |
18778 | |
18779 | /* Look for the `class' or 'typename' keywords. */ |
18780 | cp_parser_type_parameter_key (parser); |
18781 | /* If the next token is an ellipsis, we have a template |
18782 | argument pack. */ |
18783 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18784 | { |
18785 | /* Consume the `...' token. */ |
18786 | cp_lexer_consume_token (lexer: parser->lexer); |
18787 | maybe_warn_variadic_templates (); |
18788 | |
18789 | *is_parameter_pack = true; |
18790 | } |
18791 | /* If the next token is an `=', then there is a |
18792 | default-argument. If the next token is a `>', we are at |
18793 | the end of the parameter-list. If the next token is a `,', |
18794 | then we are at the end of this parameter. */ |
18795 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
18796 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_GREATER) |
18797 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
18798 | { |
18799 | identifier = cp_parser_identifier (parser); |
18800 | /* Treat invalid names as if the parameter were nameless. */ |
18801 | if (identifier == error_mark_node) |
18802 | identifier = NULL_TREE; |
18803 | } |
18804 | else |
18805 | identifier = NULL_TREE; |
18806 | |
18807 | /* Create the template parameter. */ |
18808 | parameter = finish_template_template_parm (class_type_node, |
18809 | identifier); |
18810 | |
18811 | /* If the next token is an `=', then there is a |
18812 | default-argument. */ |
18813 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
18814 | { |
18815 | default_argument |
18816 | = cp_parser_default_template_template_argument (parser); |
18817 | |
18818 | /* Template parameter packs cannot have default |
18819 | arguments. */ |
18820 | if (*is_parameter_pack) |
18821 | { |
18822 | if (identifier) |
18823 | error_at (token->location, |
18824 | "template parameter pack %qD cannot " |
18825 | "have a default argument" , |
18826 | identifier); |
18827 | else |
18828 | error_at (token->location, "template parameter packs cannot " |
18829 | "have default arguments" ); |
18830 | default_argument = NULL_TREE; |
18831 | } |
18832 | } |
18833 | else |
18834 | default_argument = NULL_TREE; |
18835 | |
18836 | /* Create the combined representation of the parameter and the |
18837 | default argument. */ |
18838 | parameter = build_tree_list (default_argument, parameter); |
18839 | } |
18840 | break; |
18841 | |
18842 | default: |
18843 | gcc_unreachable (); |
18844 | break; |
18845 | } |
18846 | |
18847 | return parameter; |
18848 | } |
18849 | |
18850 | /* Parse a template-id. |
18851 | |
18852 | template-id: |
18853 | template-name < template-argument-list [opt] > |
18854 | |
18855 | If TEMPLATE_KEYWORD_P is TRUE, then we have just seen the |
18856 | `template' keyword. In this case, a TEMPLATE_ID_EXPR will be |
18857 | returned. Otherwise, if the template-name names a function, or set |
18858 | of functions, returns a TEMPLATE_ID_EXPR. If the template-name |
18859 | names a class, returns a TYPE_DECL for the specialization. |
18860 | |
18861 | If CHECK_DEPENDENCY_P is FALSE, names are looked up in |
18862 | uninstantiated templates. */ |
18863 | |
18864 | static tree |
18865 | cp_parser_template_id (cp_parser *parser, |
18866 | bool template_keyword_p, |
18867 | bool check_dependency_p, |
18868 | enum tag_types tag_type, |
18869 | bool is_declaration) |
18870 | { |
18871 | tree templ; |
18872 | tree arguments; |
18873 | tree template_id; |
18874 | cp_token_position start_of_id = 0; |
18875 | cp_token *next_token = NULL, *next_token_2 = NULL; |
18876 | bool is_identifier; |
18877 | |
18878 | /* If the next token corresponds to a template-id, there is no need |
18879 | to reparse it. */ |
18880 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
18881 | |
18882 | if (token->type == CPP_TEMPLATE_ID) |
18883 | { |
18884 | cp_lexer_consume_token (lexer: parser->lexer); |
18885 | return saved_checks_value (check_value: token->u.tree_check_value); |
18886 | } |
18887 | |
18888 | /* Avoid performing name lookup if there is no possibility of |
18889 | finding a template-id. */ |
18890 | if ((token->type != CPP_NAME && token->keyword != RID_OPERATOR) |
18891 | || (token->type == CPP_NAME |
18892 | && !cp_parser_nth_token_starts_template_argument_list_p |
18893 | (parser, 2))) |
18894 | { |
18895 | cp_parser_error (parser, gmsgid: "expected template-id" ); |
18896 | return error_mark_node; |
18897 | } |
18898 | |
18899 | /* Remember where the template-id starts. */ |
18900 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
18901 | start_of_id = cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
18902 | |
18903 | push_deferring_access_checks (dk_deferred); |
18904 | |
18905 | /* Parse the template-name. */ |
18906 | is_identifier = false; |
18907 | templ = cp_parser_template_name (parser, template_keyword_p, |
18908 | check_dependency_p, |
18909 | is_declaration, |
18910 | tag_type, |
18911 | &is_identifier); |
18912 | |
18913 | /* Push any access checks inside the firewall we're about to create. */ |
18914 | vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks (); |
18915 | pop_deferring_access_checks (); |
18916 | if (templ == error_mark_node || is_identifier) |
18917 | return templ; |
18918 | |
18919 | /* Since we're going to preserve any side-effects from this parse, set up a |
18920 | firewall to protect our callers from cp_parser_commit_to_tentative_parse |
18921 | in the template arguments. */ |
18922 | tentative_firewall firewall (parser); |
18923 | reopen_deferring_access_checks (checks); |
18924 | |
18925 | /* If we find the sequence `[:' after a template-name, it's probably |
18926 | a digraph-typo for `< ::'. Substitute the tokens and check if we can |
18927 | parse correctly the argument list. */ |
18928 | if (((next_token = cp_lexer_peek_token (lexer: parser->lexer))->type |
18929 | == CPP_OPEN_SQUARE) |
18930 | && next_token->flags & DIGRAPH |
18931 | && ((next_token_2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))->type |
18932 | == CPP_COLON) |
18933 | && !(next_token_2->flags & PREV_WHITE)) |
18934 | { |
18935 | cp_parser_parse_tentatively (parser); |
18936 | /* Change `:' into `::'. */ |
18937 | next_token_2->type = CPP_SCOPE; |
18938 | /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is |
18939 | CPP_LESS. */ |
18940 | cp_lexer_consume_token (lexer: parser->lexer); |
18941 | |
18942 | /* Parse the arguments. */ |
18943 | arguments = cp_parser_enclosed_template_argument_list (parser); |
18944 | if (!cp_parser_parse_definitely (parser)) |
18945 | { |
18946 | /* If we couldn't parse an argument list, then we revert our changes |
18947 | and return simply an error. Maybe this is not a template-id |
18948 | after all. */ |
18949 | next_token_2->type = CPP_COLON; |
18950 | cp_parser_error (parser, gmsgid: "expected %<<%>" ); |
18951 | pop_deferring_access_checks (); |
18952 | return error_mark_node; |
18953 | } |
18954 | /* Otherwise, emit an error about the invalid digraph, but continue |
18955 | parsing because we got our argument list. */ |
18956 | if (permerror (next_token->location, |
18957 | "%<<::%> cannot begin a template-argument list" )) |
18958 | { |
18959 | static bool hint = false; |
18960 | inform (next_token->location, |
18961 | "%<<:%> is an alternate spelling for %<[%>." |
18962 | " Insert whitespace between %<<%> and %<::%>" ); |
18963 | if (!hint && !flag_permissive) |
18964 | { |
18965 | inform (next_token->location, "(if you use %<-fpermissive%> " |
18966 | "or %<-std=c++11%>, or %<-std=gnu++11%> G++ will " |
18967 | "accept your code)" ); |
18968 | hint = true; |
18969 | } |
18970 | } |
18971 | } |
18972 | else |
18973 | { |
18974 | /* Look for the `<' that starts the template-argument-list. */ |
18975 | if (!cp_parser_require (parser, CPP_LESS, RT_LESS)) |
18976 | { |
18977 | pop_deferring_access_checks (); |
18978 | return error_mark_node; |
18979 | } |
18980 | /* Parse the arguments. */ |
18981 | arguments = cp_parser_enclosed_template_argument_list (parser); |
18982 | |
18983 | if ((cxx_dialect > cxx17) |
18984 | && (TREE_CODE (templ) == FUNCTION_DECL || identifier_p (t: templ)) |
18985 | && !template_keyword_p |
18986 | && (cp_parser_error_occurred (parser) |
18987 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN))) |
18988 | { |
18989 | /* This didn't go well. */ |
18990 | if (TREE_CODE (templ) == FUNCTION_DECL) |
18991 | { |
18992 | /* C++20 says that "function-name < a;" is now ill-formed. */ |
18993 | if (cp_parser_error_occurred (parser)) |
18994 | { |
18995 | error_at (token->location, "invalid template-argument-list" ); |
18996 | inform (token->location, "function name as the left hand " |
18997 | "operand of %<<%> is ill-formed in C++20; wrap the " |
18998 | "function name in %<()%>" ); |
18999 | } |
19000 | else |
19001 | /* We expect "f<targs>" to be followed by "(args)". */ |
19002 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
19003 | "expected %<(%> after template-argument-list" ); |
19004 | if (start_of_id) |
19005 | /* Purge all subsequent tokens. */ |
19006 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_of_id); |
19007 | } |
19008 | else |
19009 | cp_parser_simulate_error (parser); |
19010 | pop_deferring_access_checks (); |
19011 | return error_mark_node; |
19012 | } |
19013 | } |
19014 | |
19015 | /* Set the location to be of the form: |
19016 | template-name < template-argument-list [opt] > |
19017 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
19018 | with caret == start at the start of the template-name, |
19019 | ranging until the closing '>'. */ |
19020 | location_t combined_loc |
19021 | = make_location (caret: token->location, start: token->location, lexer: parser->lexer); |
19022 | |
19023 | /* Check for concepts autos where they don't belong. We could |
19024 | identify types in some cases of identifier TEMPL, looking ahead |
19025 | for a CPP_SCOPE, but that would buy us nothing: we accept auto in |
19026 | types. We reject them in functions, but if what we have is an |
19027 | identifier, even with none_type we can't conclude it's NOT a |
19028 | type, we have to wait for template substitution. */ |
19029 | if (flag_concepts && check_auto_in_tmpl_args (templ, arguments)) |
19030 | template_id = error_mark_node; |
19031 | /* Build a representation of the specialization. */ |
19032 | else if (identifier_p (t: templ)) |
19033 | template_id = build_min_nt_loc (combined_loc, |
19034 | TEMPLATE_ID_EXPR, |
19035 | templ, arguments); |
19036 | else if (DECL_TYPE_TEMPLATE_P (templ) |
19037 | || DECL_TEMPLATE_TEMPLATE_PARM_P (templ)) |
19038 | { |
19039 | /* In "template <typename T> ... A<T>::", A<T> is the abstract A |
19040 | template (rather than some instantiation thereof) only if |
19041 | is not nested within some other construct. For example, in |
19042 | "template <typename T> void f(T) { A<T>::", A<T> is just an |
19043 | instantiation of A. */ |
19044 | bool entering_scope |
19045 | = (template_parm_scope_p () |
19046 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)); |
19047 | template_id |
19048 | = finish_template_type (templ, arguments, entering_scope); |
19049 | } |
19050 | else if (concept_definition_p (t: templ)) |
19051 | { |
19052 | /* The caller will decide whether this is a concept check or type |
19053 | constraint. */ |
19054 | template_id = build2_loc (loc: combined_loc, code: TEMPLATE_ID_EXPR, |
19055 | boolean_type_node, arg0: templ, arg1: arguments); |
19056 | } |
19057 | else if (variable_template_p (t: templ)) |
19058 | { |
19059 | template_id = lookup_template_variable (templ, arguments, tf_warning_or_error); |
19060 | if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR) |
19061 | SET_EXPR_LOCATION (template_id, combined_loc); |
19062 | } |
19063 | else if (TREE_CODE (templ) == TYPE_DECL |
19064 | && TREE_CODE (TREE_TYPE (templ)) == TYPENAME_TYPE) |
19065 | { |
19066 | /* Some type template in dependent scope. */ |
19067 | tree &name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (templ)); |
19068 | name = build_min_nt_loc (combined_loc, |
19069 | TEMPLATE_ID_EXPR, |
19070 | name, arguments); |
19071 | template_id = templ; |
19072 | } |
19073 | else |
19074 | { |
19075 | /* If it's not a class-template or a template-template, it should be |
19076 | a function-template. */ |
19077 | gcc_assert (OVL_P (templ) || BASELINK_P (templ)); |
19078 | |
19079 | template_id = lookup_template_function (templ, arguments); |
19080 | if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR) |
19081 | SET_EXPR_LOCATION (template_id, combined_loc); |
19082 | } |
19083 | |
19084 | /* If parsing tentatively, replace the sequence of tokens that makes |
19085 | up the template-id with a CPP_TEMPLATE_ID token. That way, |
19086 | should we re-parse the token stream, we will not have to repeat |
19087 | the effort required to do the parse, nor will we issue duplicate |
19088 | error messages about problems during instantiation of the |
19089 | template. */ |
19090 | if (start_of_id |
19091 | /* Don't do this if we had a parse error in a declarator; re-parsing |
19092 | might succeed if a name changes meaning (60361). */ |
19093 | && !(cp_parser_error_occurred (parser) |
19094 | && cp_parser_parsing_tentatively (parser) |
19095 | && parser->in_declarator_p)) |
19096 | { |
19097 | /* Reset the contents of the START_OF_ID token. */ |
19098 | token->type = CPP_TEMPLATE_ID; |
19099 | token->location = combined_loc; |
19100 | |
19101 | /* Retrieve any deferred checks. Do not pop this access checks yet |
19102 | so the memory will not be reclaimed during token replacing below. */ |
19103 | token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
19104 | token->tree_check_p = true; |
19105 | token->u.tree_check_value->value = template_id; |
19106 | token->u.tree_check_value->checks = get_deferred_access_checks (); |
19107 | token->keyword = RID_MAX; |
19108 | |
19109 | /* Purge all subsequent tokens. */ |
19110 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_of_id); |
19111 | |
19112 | /* ??? Can we actually assume that, if template_id == |
19113 | error_mark_node, we will have issued a diagnostic to the |
19114 | user, as opposed to simply marking the tentative parse as |
19115 | failed? */ |
19116 | if (cp_parser_error_occurred (parser) && template_id != error_mark_node) |
19117 | error_at (token->location, "parse error in template argument list" ); |
19118 | } |
19119 | |
19120 | pop_to_parent_deferring_access_checks (); |
19121 | return template_id; |
19122 | } |
19123 | |
19124 | /* Like cp_parser_template_id, called in non-type context. */ |
19125 | |
19126 | static tree |
19127 | cp_parser_template_id_expr (cp_parser *parser, |
19128 | bool template_keyword_p, |
19129 | bool check_dependency_p, |
19130 | bool is_declaration) |
19131 | { |
19132 | tree x = cp_parser_template_id (parser, template_keyword_p, check_dependency_p, |
19133 | tag_type: none_type, is_declaration); |
19134 | if (TREE_CODE (x) == TEMPLATE_ID_EXPR |
19135 | && concept_check_p (t: x)) |
19136 | /* We didn't check the arguments in cp_parser_template_id; do that now. */ |
19137 | return build_concept_id (x); |
19138 | return x; |
19139 | } |
19140 | |
19141 | /* Parse a template-name. |
19142 | |
19143 | template-name: |
19144 | identifier |
19145 | |
19146 | The standard should actually say: |
19147 | |
19148 | template-name: |
19149 | identifier |
19150 | operator-function-id |
19151 | |
19152 | A defect report has been filed about this issue. |
19153 | |
19154 | A conversion-function-id cannot be a template name because they cannot |
19155 | be part of a template-id. In fact, looking at this code: |
19156 | |
19157 | a.operator K<int>() |
19158 | |
19159 | the conversion-function-id is "operator K<int>", and K<int> is a type-id. |
19160 | It is impossible to call a templated conversion-function-id with an |
19161 | explicit argument list, since the only allowed template parameter is |
19162 | the type to which it is converting. |
19163 | |
19164 | If TEMPLATE_KEYWORD_P is true, then we have just seen the |
19165 | `template' keyword, in a construction like: |
19166 | |
19167 | T::template f<3>() |
19168 | |
19169 | In that case `f' is taken to be a template-name, even though there |
19170 | is no way of knowing for sure. |
19171 | |
19172 | Returns the TEMPLATE_DECL for the template, or an OVERLOAD if the |
19173 | name refers to a set of overloaded functions, at least one of which |
19174 | is a template, or an IDENTIFIER_NODE with the name of the template, |
19175 | if TEMPLATE_KEYWORD_P is true. If CHECK_DEPENDENCY_P is FALSE, |
19176 | names are looked up inside uninstantiated templates. */ |
19177 | |
19178 | static tree |
19179 | cp_parser_template_name (cp_parser* parser, |
19180 | bool template_keyword_p, |
19181 | bool check_dependency_p, |
19182 | bool is_declaration, |
19183 | enum tag_types tag_type, |
19184 | bool *is_identifier) |
19185 | { |
19186 | tree identifier; |
19187 | tree decl; |
19188 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
19189 | |
19190 | /* If the next token is `operator', then we have either an |
19191 | operator-function-id or a conversion-function-id. */ |
19192 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_OPERATOR)) |
19193 | { |
19194 | /* We don't know whether we're looking at an |
19195 | operator-function-id or a conversion-function-id. */ |
19196 | cp_parser_parse_tentatively (parser); |
19197 | /* Try an operator-function-id. */ |
19198 | identifier = cp_parser_operator_function_id (parser); |
19199 | /* If that didn't work, try a conversion-function-id. */ |
19200 | if (!cp_parser_parse_definitely (parser)) |
19201 | { |
19202 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
19203 | return error_mark_node; |
19204 | } |
19205 | } |
19206 | /* Look for the identifier. */ |
19207 | else |
19208 | identifier = cp_parser_identifier (parser); |
19209 | |
19210 | /* If we didn't find an identifier, we don't have a template-id. */ |
19211 | if (identifier == error_mark_node) |
19212 | return error_mark_node; |
19213 | |
19214 | /* If the name immediately followed the `template' keyword, then it |
19215 | is a template-name. However, if the next token is not `<', then |
19216 | we do not treat it as a template-name, since it is not being used |
19217 | as part of a template-id. This enables us to handle constructs |
19218 | like: |
19219 | |
19220 | template <typename T> struct S { S(); }; |
19221 | template <typename T> S<T>::S(); |
19222 | |
19223 | correctly. We would treat `S' as a template -- if it were `S<T>' |
19224 | -- but we do not if there is no `<'. */ |
19225 | |
19226 | if (processing_template_decl |
19227 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1)) |
19228 | { |
19229 | /* In a declaration, in a dependent context, we pretend that the |
19230 | "template" keyword was present in order to improve error |
19231 | recovery. For example, given: |
19232 | |
19233 | template <typename T> void f(T::X<int>); |
19234 | |
19235 | we want to treat "X<int>" as a template-id. */ |
19236 | if (is_declaration |
19237 | && !template_keyword_p |
19238 | && parser->scope && TYPE_P (parser->scope) |
19239 | && check_dependency_p |
19240 | && dependent_scope_p (parser->scope) |
19241 | /* Do not do this for dtors (or ctors), since they never |
19242 | need the template keyword before their name. */ |
19243 | && !constructor_name_p (identifier, parser->scope)) |
19244 | { |
19245 | cp_token_position start = 0; |
19246 | |
19247 | /* Explain what went wrong. */ |
19248 | error_at (token->location, "non-template %qD used as template" , |
19249 | identifier); |
19250 | inform (token->location, "use %<%T::template %D%> to indicate that it is a template" , |
19251 | parser->scope, identifier); |
19252 | /* If parsing tentatively, find the location of the "<" token. */ |
19253 | if (cp_parser_simulate_error (parser)) |
19254 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: true); |
19255 | /* Parse the template arguments so that we can issue error |
19256 | messages about them. */ |
19257 | cp_lexer_consume_token (lexer: parser->lexer); |
19258 | cp_parser_enclosed_template_argument_list (parser); |
19259 | /* Skip tokens until we find a good place from which to |
19260 | continue parsing. */ |
19261 | cp_parser_skip_to_closing_parenthesis (parser, |
19262 | /*recovering=*/true, |
19263 | /*or_comma=*/true, |
19264 | /*consume_paren=*/false); |
19265 | /* If parsing tentatively, permanently remove the |
19266 | template argument list. That will prevent duplicate |
19267 | error messages from being issued about the missing |
19268 | "template" keyword. */ |
19269 | if (start) |
19270 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
19271 | if (is_identifier) |
19272 | *is_identifier = true; |
19273 | parser->context->object_type = NULL_TREE; |
19274 | return identifier; |
19275 | } |
19276 | |
19277 | /* If the "template" keyword is present, then there is generally |
19278 | no point in doing name-lookup, so we just return IDENTIFIER. |
19279 | But, if the qualifying scope is non-dependent then we can |
19280 | (and must) do name-lookup normally. */ |
19281 | if (template_keyword_p) |
19282 | { |
19283 | tree scope = (parser->scope ? parser->scope |
19284 | : parser->context->object_type); |
19285 | if (scope && TYPE_P (scope) |
19286 | && (!CLASS_TYPE_P (scope) |
19287 | || (check_dependency_p && dependent_scope_p (scope)))) |
19288 | { |
19289 | /* We're optimizing away the call to cp_parser_lookup_name, but |
19290 | we still need to do this. */ |
19291 | parser->object_scope = parser->context->object_type; |
19292 | parser->context->object_type = NULL_TREE; |
19293 | return identifier; |
19294 | } |
19295 | } |
19296 | } |
19297 | |
19298 | /* cp_parser_lookup_name clears OBJECT_TYPE. */ |
19299 | tree scope = (parser->scope ? parser->scope |
19300 | : parser->context->object_type); |
19301 | |
19302 | /* Look up the name. */ |
19303 | decl = cp_parser_lookup_name (parser, identifier, |
19304 | tag_type, |
19305 | /*is_template=*/1 + template_keyword_p, |
19306 | /*is_namespace=*/false, |
19307 | check_dependency_p, |
19308 | /*ambiguous_decls=*/NULL, |
19309 | token->location); |
19310 | |
19311 | decl = strip_using_decl (decl); |
19312 | |
19313 | /* 13.3 [temp.names] A < is interpreted as the delimiter of a |
19314 | template-argument-list if it follows a name that is not a |
19315 | conversion-function-id and |
19316 | - that follows the keyword template or a ~ after a nested-name-specifier or |
19317 | in a class member access expression, or |
19318 | - for which name lookup finds the injected-class-name of a class template |
19319 | or finds any declaration of a template, or |
19320 | - that is an unqualified name for which name lookup either finds one or |
19321 | more functions or finds nothing, or |
19322 | - that is a terminal name in a using-declarator (9.9), in a declarator-id |
19323 | (9.3.4), or in a type-only context other than a nested-name-specifier |
19324 | (13.8). */ |
19325 | |
19326 | /* Handle injected-class-name. */ |
19327 | decl = maybe_get_template_decl_from_type_decl (decl); |
19328 | |
19329 | /* If DECL is a template, then the name was a template-name. */ |
19330 | if (TREE_CODE (decl) == TEMPLATE_DECL) |
19331 | { |
19332 | if ((TREE_DEPRECATED (decl) || TREE_UNAVAILABLE (decl)) |
19333 | && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) |
19334 | { |
19335 | tree d = DECL_TEMPLATE_RESULT (decl); |
19336 | tree attr; |
19337 | if (TREE_CODE (d) == TYPE_DECL) |
19338 | attr = TYPE_ATTRIBUTES (TREE_TYPE (d)); |
19339 | else |
19340 | attr = DECL_ATTRIBUTES (d); |
19341 | if (TREE_UNAVAILABLE (decl)) |
19342 | { |
19343 | attr = lookup_attribute (attr_name: "unavailable" , list: attr); |
19344 | error_unavailable_use (decl, attr); |
19345 | } |
19346 | else if (TREE_DEPRECATED (decl) |
19347 | && deprecated_state != DEPRECATED_SUPPRESS) |
19348 | { |
19349 | attr = lookup_attribute (attr_name: "deprecated" , list: attr); |
19350 | warn_deprecated_use (decl, attr); |
19351 | } |
19352 | } |
19353 | } |
19354 | else |
19355 | { |
19356 | /* Look through an overload set for any templates. */ |
19357 | bool found = false; |
19358 | |
19359 | for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (decl)); |
19360 | !found && iter; ++iter) |
19361 | if (TREE_CODE (*iter) == TEMPLATE_DECL) |
19362 | found = true; |
19363 | |
19364 | /* "an unqualified name for which name lookup either finds one or more |
19365 | functions or finds nothing". */ |
19366 | if (!found |
19367 | && (cxx_dialect > cxx17) |
19368 | && !scope |
19369 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS) |
19370 | && tag_type == none_type) |
19371 | { |
19372 | /* The "more functions" case. Just use the OVERLOAD as normally. |
19373 | We don't use is_overloaded_fn here to avoid considering |
19374 | BASELINKs. */ |
19375 | if (TREE_CODE (decl) == OVERLOAD |
19376 | /* Name lookup found one function. */ |
19377 | || TREE_CODE (decl) == FUNCTION_DECL |
19378 | /* Name lookup found nothing. */ |
19379 | || decl == error_mark_node) |
19380 | found = true; |
19381 | } |
19382 | |
19383 | /* "that follows the keyword template"..."in a type-only context" */ |
19384 | if (!found && scope |
19385 | && (template_keyword_p || tag_type != none_type) |
19386 | && dependentish_scope_p (scope) |
19387 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1)) |
19388 | found = true; |
19389 | |
19390 | if (!found) |
19391 | { |
19392 | /* The name does not name a template. */ |
19393 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
19394 | return error_mark_node; |
19395 | } |
19396 | else if ((!DECL_P (decl) && !is_overloaded_fn (decl)) |
19397 | || TREE_CODE (decl) == USING_DECL |
19398 | /* cp_parser_template_id can only handle some TYPE_DECLs. */ |
19399 | || (TREE_CODE (decl) == TYPE_DECL |
19400 | && TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)) |
19401 | /* Repeat the lookup at instantiation time. */ |
19402 | decl = identifier; |
19403 | } |
19404 | |
19405 | return decl; |
19406 | } |
19407 | |
19408 | /* Parse a template-argument-list. |
19409 | |
19410 | template-argument-list: |
19411 | template-argument ... [opt] |
19412 | template-argument-list , template-argument ... [opt] |
19413 | |
19414 | Returns a TREE_VEC containing the arguments. */ |
19415 | |
19416 | static tree |
19417 | cp_parser_template_argument_list (cp_parser* parser) |
19418 | { |
19419 | bool saved_in_template_argument_list_p; |
19420 | bool saved_ice_p; |
19421 | bool saved_non_ice_p; |
19422 | |
19423 | /* Don't create location wrapper nodes within a template-argument-list. */ |
19424 | auto_suppress_location_wrappers sentinel; |
19425 | |
19426 | saved_in_template_argument_list_p = parser->in_template_argument_list_p; |
19427 | parser->in_template_argument_list_p = true; |
19428 | /* Even if the template-id appears in an integral |
19429 | constant-expression, the contents of the argument list do |
19430 | not. */ |
19431 | saved_ice_p = parser->integral_constant_expression_p; |
19432 | parser->integral_constant_expression_p = false; |
19433 | saved_non_ice_p = parser->non_integral_constant_expression_p; |
19434 | parser->non_integral_constant_expression_p = false; |
19435 | |
19436 | /* Parse the arguments. */ |
19437 | auto_vec<tree, 10> args; |
19438 | do |
19439 | { |
19440 | if (!args.is_empty ()) |
19441 | /* Consume the comma. */ |
19442 | cp_lexer_consume_token (lexer: parser->lexer); |
19443 | |
19444 | /* Parse the template-argument. */ |
19445 | tree argument = cp_parser_template_argument (parser); |
19446 | |
19447 | /* If the next token is an ellipsis, we're expanding a template |
19448 | argument pack. */ |
19449 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
19450 | { |
19451 | if (argument == error_mark_node) |
19452 | { |
19453 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
19454 | error_at (token->location, |
19455 | "expected parameter pack before %<...%>" ); |
19456 | } |
19457 | /* Consume the `...' token. */ |
19458 | cp_lexer_consume_token (lexer: parser->lexer); |
19459 | |
19460 | /* Make the argument into a TYPE_PACK_EXPANSION or |
19461 | EXPR_PACK_EXPANSION. */ |
19462 | argument = make_pack_expansion (argument); |
19463 | } |
19464 | |
19465 | args.safe_push (obj: argument); |
19466 | } |
19467 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
19468 | |
19469 | int n_args = args.length (); |
19470 | tree vec = make_tree_vec (n_args); |
19471 | |
19472 | for (int i = 0; i < n_args; i++) |
19473 | TREE_VEC_ELT (vec, i) = args[i]; |
19474 | |
19475 | parser->non_integral_constant_expression_p = saved_non_ice_p; |
19476 | parser->integral_constant_expression_p = saved_ice_p; |
19477 | parser->in_template_argument_list_p = saved_in_template_argument_list_p; |
19478 | if (CHECKING_P) |
19479 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec)); |
19480 | return vec; |
19481 | } |
19482 | |
19483 | /* Parse a template-argument. |
19484 | |
19485 | template-argument: |
19486 | assignment-expression |
19487 | type-id |
19488 | id-expression |
19489 | |
19490 | The representation is that of an assignment-expression, type-id, or |
19491 | id-expression -- except that the qualified id-expression is |
19492 | evaluated, so that the value returned is either a DECL or an |
19493 | OVERLOAD. |
19494 | |
19495 | Although the standard says "assignment-expression", it forbids |
19496 | throw-expressions or assignments in the template argument. |
19497 | Therefore, we use "conditional-expression" instead. */ |
19498 | |
19499 | static tree |
19500 | cp_parser_template_argument (cp_parser* parser) |
19501 | { |
19502 | tree argument; |
19503 | bool template_p; |
19504 | bool address_p; |
19505 | bool maybe_type_id = false; |
19506 | cp_token *token = NULL, *argument_start_token = NULL; |
19507 | location_t loc = 0; |
19508 | cp_id_kind idk; |
19509 | |
19510 | /* There's really no way to know what we're looking at, so we just |
19511 | try each alternative in order. |
19512 | |
19513 | [temp.arg] |
19514 | |
19515 | In a template-argument, an ambiguity between a type-id and an |
19516 | expression is resolved to a type-id, regardless of the form of |
19517 | the corresponding template-parameter. |
19518 | |
19519 | Therefore, we try a type-id first. */ |
19520 | cp_parser_parse_tentatively (parser); |
19521 | argument = cp_parser_template_type_arg (parser); |
19522 | /* If there was no error parsing the type-id but the next token is a |
19523 | '>>', our behavior depends on which dialect of C++ we're |
19524 | parsing. In C++98, we probably found a typo for '> >'. But there |
19525 | are type-id which are also valid expressions. For instance: |
19526 | |
19527 | struct X { int operator >> (int); }; |
19528 | template <int V> struct Foo {}; |
19529 | Foo<X () >> 5> r; |
19530 | |
19531 | Here 'X()' is a valid type-id of a function type, but the user just |
19532 | wanted to write the expression "X() >> 5". Thus, we remember that we |
19533 | found a valid type-id, but we still try to parse the argument as an |
19534 | expression to see what happens. |
19535 | |
19536 | In C++0x, the '>>' will be considered two separate '>' |
19537 | tokens. */ |
19538 | if (!cp_parser_error_occurred (parser) |
19539 | && ((cxx_dialect == cxx98 |
19540 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT)) |
19541 | /* Similarly for >= which |
19542 | cp_parser_next_token_ends_template_argument_p treats for |
19543 | diagnostics purposes as mistyped > =, but can be valid |
19544 | after a type-id. */ |
19545 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ))) |
19546 | { |
19547 | maybe_type_id = true; |
19548 | cp_parser_abort_tentative_parse (parser); |
19549 | } |
19550 | else |
19551 | { |
19552 | /* If the next token isn't a `,' or a `>', then this argument wasn't |
19553 | really finished. This means that the argument is not a valid |
19554 | type-id. */ |
19555 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19556 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19557 | /* If that worked, we're done. */ |
19558 | if (cp_parser_parse_definitely (parser)) |
19559 | return argument; |
19560 | } |
19561 | /* We're still not sure what the argument will be. */ |
19562 | cp_parser_parse_tentatively (parser); |
19563 | /* Try a template. */ |
19564 | argument_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
19565 | argument = cp_parser_id_expression (parser, |
19566 | /*template_keyword_p=*/false, |
19567 | /*check_dependency_p=*/true, |
19568 | template_p: &template_p, |
19569 | /*declarator_p=*/false, |
19570 | /*optional_p=*/false); |
19571 | /* If the next token isn't a `,' or a `>', then this argument wasn't |
19572 | really finished. */ |
19573 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19574 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19575 | if (!cp_parser_error_occurred (parser)) |
19576 | { |
19577 | /* Figure out what is being referred to. If the id-expression |
19578 | was for a class template specialization, then we will have a |
19579 | TYPE_DECL at this point. There is no need to do name lookup |
19580 | at this point in that case. */ |
19581 | if (TREE_CODE (argument) != TYPE_DECL) |
19582 | argument = cp_parser_lookup_name (parser, argument, |
19583 | none_type, |
19584 | /*is_template=*/template_p, |
19585 | /*is_namespace=*/false, |
19586 | /*check_dependency=*/true, |
19587 | /*ambiguous_decls=*/NULL, |
19588 | argument_start_token->location); |
19589 | if (TREE_CODE (argument) != TEMPLATE_DECL |
19590 | && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) |
19591 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
19592 | } |
19593 | if (cp_parser_parse_definitely (parser)) |
19594 | { |
19595 | if (TREE_UNAVAILABLE (argument)) |
19596 | error_unavailable_use (argument, NULL_TREE); |
19597 | else if (TREE_DEPRECATED (argument)) |
19598 | warn_deprecated_use (argument, NULL_TREE); |
19599 | return argument; |
19600 | } |
19601 | /* It must be a non-type argument. In C++17 any constant-expression is |
19602 | allowed. */ |
19603 | if (cxx_dialect > cxx14) |
19604 | goto general_expr; |
19605 | |
19606 | /* Otherwise, the permitted cases are given in [temp.arg.nontype]: |
19607 | |
19608 | -- an integral constant-expression of integral or enumeration |
19609 | type; or |
19610 | |
19611 | -- the name of a non-type template-parameter; or |
19612 | |
19613 | -- the name of an object or function with external linkage... |
19614 | |
19615 | -- the address of an object or function with external linkage... |
19616 | |
19617 | -- a pointer to member... */ |
19618 | /* Look for a non-type template parameter. */ |
19619 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
19620 | { |
19621 | cp_parser_parse_tentatively (parser); |
19622 | argument = cp_parser_primary_expression (parser, |
19623 | /*address_p=*/false, |
19624 | /*cast_p=*/false, |
19625 | /*template_arg_p=*/true, |
19626 | idk: &idk); |
19627 | if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX |
19628 | || !cp_parser_next_token_ends_template_argument_p (parser)) |
19629 | cp_parser_simulate_error (parser); |
19630 | if (cp_parser_parse_definitely (parser)) |
19631 | return argument; |
19632 | } |
19633 | |
19634 | /* If the next token is "&", the argument must be the address of an |
19635 | object or function with external linkage. */ |
19636 | address_p = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND); |
19637 | if (address_p) |
19638 | { |
19639 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
19640 | cp_lexer_consume_token (lexer: parser->lexer); |
19641 | } |
19642 | /* See if we might have an id-expression. */ |
19643 | token = cp_lexer_peek_token (lexer: parser->lexer); |
19644 | if (token->type == CPP_NAME |
19645 | || token->keyword == RID_OPERATOR |
19646 | || token->type == CPP_SCOPE |
19647 | || token->type == CPP_TEMPLATE_ID |
19648 | || token->type == CPP_NESTED_NAME_SPECIFIER) |
19649 | { |
19650 | cp_parser_parse_tentatively (parser); |
19651 | argument = cp_parser_primary_expression (parser, |
19652 | address_p, |
19653 | /*cast_p=*/false, |
19654 | /*template_arg_p=*/true, |
19655 | idk: &idk); |
19656 | if (cp_parser_error_occurred (parser) |
19657 | || !cp_parser_next_token_ends_template_argument_p (parser)) |
19658 | cp_parser_abort_tentative_parse (parser); |
19659 | else |
19660 | { |
19661 | tree probe; |
19662 | |
19663 | if (INDIRECT_REF_P (argument)) |
19664 | { |
19665 | /* Strip the dereference temporarily. */ |
19666 | gcc_assert (REFERENCE_REF_P (argument)); |
19667 | argument = TREE_OPERAND (argument, 0); |
19668 | } |
19669 | |
19670 | /* If we're in a template, we represent a qualified-id referring |
19671 | to a static data member as a SCOPE_REF even if the scope isn't |
19672 | dependent so that we can check access control later. */ |
19673 | probe = argument; |
19674 | if (TREE_CODE (probe) == SCOPE_REF) |
19675 | probe = TREE_OPERAND (probe, 1); |
19676 | if (VAR_P (probe)) |
19677 | { |
19678 | /* A variable without external linkage might still be a |
19679 | valid constant-expression, so no error is issued here |
19680 | if the external-linkage check fails. */ |
19681 | if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe)) |
19682 | cp_parser_simulate_error (parser); |
19683 | } |
19684 | else if (is_overloaded_fn (argument)) |
19685 | /* All overloaded functions are allowed; if the external |
19686 | linkage test does not pass, an error will be issued |
19687 | later. */ |
19688 | ; |
19689 | else if (address_p |
19690 | && (TREE_CODE (argument) == OFFSET_REF |
19691 | || TREE_CODE (argument) == SCOPE_REF)) |
19692 | /* A pointer-to-member. */ |
19693 | ; |
19694 | else if (TREE_CODE (argument) == TEMPLATE_PARM_INDEX) |
19695 | ; |
19696 | else |
19697 | cp_parser_simulate_error (parser); |
19698 | |
19699 | if (cp_parser_parse_definitely (parser)) |
19700 | { |
19701 | if (address_p) |
19702 | argument = build_x_unary_op (loc, ADDR_EXPR, argument, |
19703 | NULL_TREE, tf_warning_or_error); |
19704 | else |
19705 | argument = convert_from_reference (argument); |
19706 | return argument; |
19707 | } |
19708 | } |
19709 | } |
19710 | /* If the argument started with "&", there are no other valid |
19711 | alternatives at this point. */ |
19712 | if (address_p) |
19713 | { |
19714 | cp_parser_error (parser, gmsgid: "invalid non-type template argument" ); |
19715 | return error_mark_node; |
19716 | } |
19717 | |
19718 | general_expr: |
19719 | /* If the argument wasn't successfully parsed as a type-id followed |
19720 | by '>>', the argument can only be a constant expression now. |
19721 | Otherwise, we try parsing the constant-expression tentatively, |
19722 | because the argument could really be a type-id. */ |
19723 | if (maybe_type_id) |
19724 | cp_parser_parse_tentatively (parser); |
19725 | |
19726 | if (cxx_dialect <= cxx14) |
19727 | argument = cp_parser_constant_expression (parser); |
19728 | else |
19729 | { |
19730 | /* In C++20, we can encounter a braced-init-list. */ |
19731 | if (cxx_dialect >= cxx20 |
19732 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
19733 | return cp_parser_braced_list (parser); |
19734 | |
19735 | /* With C++17 generalized non-type template arguments we need to handle |
19736 | lvalue constant expressions, too. */ |
19737 | argument = cp_parser_assignment_expression (parser); |
19738 | require_potential_constant_expression (argument); |
19739 | } |
19740 | |
19741 | if (!maybe_type_id) |
19742 | return argument; |
19743 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19744 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19745 | if (cp_parser_parse_definitely (parser)) |
19746 | return argument; |
19747 | /* We did our best to parse the argument as a non type-id, but that |
19748 | was the only alternative that matched (albeit with a '>' after |
19749 | it). We can assume it's just a typo from the user, and a |
19750 | diagnostic will then be issued. */ |
19751 | return cp_parser_template_type_arg (parser); |
19752 | } |
19753 | |
19754 | /* Parse an explicit-instantiation. |
19755 | |
19756 | explicit-instantiation: |
19757 | template declaration |
19758 | |
19759 | Although the standard says `declaration', what it really means is: |
19760 | |
19761 | explicit-instantiation: |
19762 | template decl-specifier-seq [opt] declarator [opt] ; |
19763 | |
19764 | Things like `template int S<int>::i = 5, int S<double>::j;' are not |
19765 | supposed to be allowed. A defect report has been filed about this |
19766 | issue. |
19767 | |
19768 | GNU Extension: |
19769 | |
19770 | explicit-instantiation: |
19771 | storage-class-specifier template |
19772 | decl-specifier-seq [opt] declarator [opt] ; |
19773 | function-specifier template |
19774 | decl-specifier-seq [opt] declarator [opt] ; */ |
19775 | |
19776 | static void |
19777 | cp_parser_explicit_instantiation (cp_parser* parser) |
19778 | { |
19779 | int declares_class_or_enum; |
19780 | cp_decl_specifier_seq decl_specifiers; |
19781 | tree extension_specifier = NULL_TREE; |
19782 | |
19783 | auto_timevar tv (TV_TEMPLATE_INST); |
19784 | |
19785 | /* Look for an (optional) storage-class-specifier or |
19786 | function-specifier. */ |
19787 | if (cp_parser_allow_gnu_extensions_p (parser)) |
19788 | { |
19789 | extension_specifier |
19790 | = cp_parser_storage_class_specifier_opt (parser); |
19791 | if (!extension_specifier) |
19792 | extension_specifier |
19793 | = cp_parser_function_specifier_opt (parser, |
19794 | /*decl_specs=*/NULL); |
19795 | } |
19796 | |
19797 | /* Look for the `template' keyword. */ |
19798 | cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE); |
19799 | /* Let the front end know that we are processing an explicit |
19800 | instantiation. */ |
19801 | begin_explicit_instantiation (); |
19802 | /* [temp.explicit] says that we are supposed to ignore access |
19803 | control while processing explicit instantiation directives. */ |
19804 | push_deferring_access_checks (dk_no_check); |
19805 | /* Parse a decl-specifier-seq. */ |
19806 | cp_parser_decl_specifier_seq (parser, |
19807 | flags: CP_PARSER_FLAGS_OPTIONAL, |
19808 | decl_specs: &decl_specifiers, |
19809 | declares_class_or_enum: &declares_class_or_enum); |
19810 | |
19811 | cp_omp_declare_simd_data odsd; |
19812 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
19813 | cp_parser_handle_directive_omp_attributes (parser, |
19814 | pattrs: &decl_specifiers.attributes, |
19815 | data: &odsd, start: true); |
19816 | |
19817 | /* If there was exactly one decl-specifier, and it declared a class, |
19818 | and there's no declarator, then we have an explicit type |
19819 | instantiation. */ |
19820 | if (declares_class_or_enum && cp_parser_declares_only_class_p (parser)) |
19821 | { |
19822 | tree type = check_tag_decl (&decl_specifiers, |
19823 | /*explicit_type_instantiation_p=*/true); |
19824 | /* Turn access control back on for names used during |
19825 | template instantiation. */ |
19826 | pop_deferring_access_checks (); |
19827 | if (type) |
19828 | do_type_instantiation (type, extension_specifier, |
19829 | /*complain=*/tf_error); |
19830 | } |
19831 | else |
19832 | { |
19833 | cp_declarator *declarator; |
19834 | tree decl; |
19835 | |
19836 | /* Parse the declarator. */ |
19837 | declarator |
19838 | = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
19839 | CP_PARSER_FLAGS_NONE, |
19840 | /*ctor_dtor_or_conv_p=*/NULL, |
19841 | /*parenthesized_p=*/NULL, |
19842 | /*member_p=*/false, |
19843 | /*friend_p=*/false, |
19844 | /*static_p=*/false); |
19845 | if (declares_class_or_enum & 2) |
19846 | cp_parser_check_for_definition_in_return_type (declarator, |
19847 | type: decl_specifiers.type, |
19848 | type_location: decl_specifiers.locations[ds_type_spec]); |
19849 | if (declarator != cp_error_declarator) |
19850 | { |
19851 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_inline)) |
19852 | permerror (decl_specifiers.locations[ds_inline], |
19853 | "explicit instantiation shall not use" |
19854 | " %<inline%> specifier" ); |
19855 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_constexpr)) |
19856 | permerror (decl_specifiers.locations[ds_constexpr], |
19857 | "explicit instantiation shall not use" |
19858 | " %<constexpr%> specifier" ); |
19859 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_consteval)) |
19860 | permerror (decl_specifiers.locations[ds_consteval], |
19861 | "explicit instantiation shall not use" |
19862 | " %<consteval%> specifier" ); |
19863 | |
19864 | decl = grokdeclarator (declarator, &decl_specifiers, |
19865 | NORMAL, 0, &decl_specifiers.attributes); |
19866 | /* Turn access control back on for names used during |
19867 | template instantiation. */ |
19868 | pop_deferring_access_checks (); |
19869 | /* Do the explicit instantiation. */ |
19870 | do_decl_instantiation (decl, extension_specifier); |
19871 | } |
19872 | else |
19873 | { |
19874 | pop_deferring_access_checks (); |
19875 | /* Skip the body of the explicit instantiation. */ |
19876 | cp_parser_skip_to_end_of_statement (parser); |
19877 | } |
19878 | } |
19879 | /* We're done with the instantiation. */ |
19880 | end_explicit_instantiation (); |
19881 | |
19882 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
19883 | |
19884 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
19885 | } |
19886 | |
19887 | /* Parse an explicit-specialization. |
19888 | |
19889 | explicit-specialization: |
19890 | template < > declaration |
19891 | |
19892 | Although the standard says `declaration', what it really means is: |
19893 | |
19894 | explicit-specialization: |
19895 | template <> decl-specifier [opt] init-declarator [opt] ; |
19896 | template <> function-definition |
19897 | template <> explicit-specialization |
19898 | template <> template-declaration */ |
19899 | |
19900 | static void |
19901 | cp_parser_explicit_specialization (cp_parser* parser) |
19902 | { |
19903 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
19904 | |
19905 | /* Look for the `template' keyword. */ |
19906 | cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE); |
19907 | /* Look for the `<'. */ |
19908 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
19909 | /* Look for the `>'. */ |
19910 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
19911 | /* We have processed another parameter list. */ |
19912 | ++parser->num_template_parameter_lists; |
19913 | |
19914 | /* [temp] |
19915 | |
19916 | A template ... explicit specialization ... shall not have C |
19917 | linkage. */ |
19918 | bool need_lang_pop = current_lang_name == lang_name_c; |
19919 | if (need_lang_pop) |
19920 | { |
19921 | error_at (token->location, "template specialization with C linkage" ); |
19922 | maybe_show_extern_c_location (); |
19923 | |
19924 | /* Give it C++ linkage to avoid confusing other parts of the |
19925 | front end. */ |
19926 | push_lang_context (lang_name_cplusplus); |
19927 | } |
19928 | |
19929 | /* Let the front end know that we are beginning a specialization. */ |
19930 | if (begin_specialization ()) |
19931 | { |
19932 | /* If the next keyword is `template', we need to figure out |
19933 | whether or not we're looking a template-declaration. */ |
19934 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
19935 | { |
19936 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_LESS |
19937 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type != CPP_GREATER) |
19938 | cp_parser_template_declaration_after_export (parser, |
19939 | /*member_p=*/false); |
19940 | else |
19941 | cp_parser_explicit_specialization (parser); |
19942 | } |
19943 | else |
19944 | /* Parse the dependent declaration. */ |
19945 | cp_parser_single_declaration (parser, |
19946 | /*checks=*/NULL, |
19947 | /*member_p=*/false, |
19948 | /*explicit_specialization_p=*/true, |
19949 | /*friend_p=*/NULL); |
19950 | } |
19951 | |
19952 | /* We're done with the specialization. */ |
19953 | end_specialization (); |
19954 | |
19955 | /* For the erroneous case of a template with C linkage, we pushed an |
19956 | implicit C++ linkage scope; exit that scope now. */ |
19957 | if (need_lang_pop) |
19958 | pop_lang_context (); |
19959 | |
19960 | /* We're done with this parameter list. */ |
19961 | --parser->num_template_parameter_lists; |
19962 | } |
19963 | |
19964 | /* Preserve the attributes across a garbage collect (by making it a GC |
19965 | root), which can occur when parsing a member function. */ |
19966 | |
19967 | static GTY(()) vec<tree, va_gc> *cp_parser_decl_specs_attrs; |
19968 | |
19969 | /* Parse a type-specifier. |
19970 | |
19971 | type-specifier: |
19972 | simple-type-specifier |
19973 | class-specifier |
19974 | enum-specifier |
19975 | elaborated-type-specifier |
19976 | cv-qualifier |
19977 | |
19978 | GNU Extension: |
19979 | |
19980 | type-specifier: |
19981 | __complex__ |
19982 | |
19983 | Returns a representation of the type-specifier. For a |
19984 | class-specifier, enum-specifier, or elaborated-type-specifier, a |
19985 | TREE_TYPE is returned; otherwise, a TYPE_DECL is returned. |
19986 | |
19987 | The parser flags FLAGS is used to control type-specifier parsing. |
19988 | |
19989 | If IS_DECLARATION is TRUE, then this type-specifier is appearing |
19990 | in a decl-specifier-seq. |
19991 | |
19992 | If DECLARES_CLASS_OR_ENUM is non-NULL, and the type-specifier is a |
19993 | class-specifier, enum-specifier, or elaborated-type-specifier, then |
19994 | *DECLARES_CLASS_OR_ENUM is set to a nonzero value. The value is 1 |
19995 | if a type is declared; 2 if it is defined. Otherwise, it is set to |
19996 | zero. |
19997 | |
19998 | If IS_CV_QUALIFIER is non-NULL, and the type-specifier is a |
19999 | cv-qualifier, then IS_CV_QUALIFIER is set to TRUE. Otherwise, it |
20000 | is set to FALSE. */ |
20001 | |
20002 | static tree |
20003 | cp_parser_type_specifier (cp_parser* parser, |
20004 | cp_parser_flags flags, |
20005 | cp_decl_specifier_seq *decl_specs, |
20006 | bool is_declaration, |
20007 | int* declares_class_or_enum, |
20008 | bool* is_cv_qualifier) |
20009 | { |
20010 | tree type_spec = NULL_TREE; |
20011 | cp_token *token; |
20012 | enum rid keyword; |
20013 | cp_decl_spec ds = ds_last; |
20014 | |
20015 | /* Assume this type-specifier does not declare a new type. */ |
20016 | if (declares_class_or_enum) |
20017 | *declares_class_or_enum = 0; |
20018 | /* And that it does not specify a cv-qualifier. */ |
20019 | if (is_cv_qualifier) |
20020 | *is_cv_qualifier = false; |
20021 | /* Peek at the next token. */ |
20022 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20023 | |
20024 | /* If we're looking at a keyword, we can use that to guide the |
20025 | production we choose. */ |
20026 | keyword = token->keyword; |
20027 | switch (keyword) |
20028 | { |
20029 | case RID_ENUM: |
20030 | if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS)) |
20031 | goto elaborated_type_specifier; |
20032 | |
20033 | /* Look for the enum-specifier. */ |
20034 | type_spec = cp_parser_enum_specifier (parser); |
20035 | /* If that worked, we're done. */ |
20036 | if (type_spec) |
20037 | { |
20038 | if (declares_class_or_enum) |
20039 | *declares_class_or_enum = 2; |
20040 | if (decl_specs) |
20041 | cp_parser_set_decl_spec_type (decl_specs, |
20042 | type_spec, |
20043 | token, |
20044 | /*type_definition_p=*/true); |
20045 | return type_spec; |
20046 | } |
20047 | else |
20048 | goto elaborated_type_specifier; |
20049 | |
20050 | /* Any of these indicate either a class-specifier, or an |
20051 | elaborated-type-specifier. */ |
20052 | case RID_CLASS: |
20053 | case RID_STRUCT: |
20054 | case RID_UNION: |
20055 | if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS)) |
20056 | goto elaborated_type_specifier; |
20057 | |
20058 | /* Parse tentatively so that we can back up if we don't find a |
20059 | class-specifier. */ |
20060 | cp_parser_parse_tentatively (parser); |
20061 | if (decl_specs->attributes) |
20062 | vec_safe_push (v&: cp_parser_decl_specs_attrs, obj: decl_specs->attributes); |
20063 | /* Look for the class-specifier. */ |
20064 | type_spec = cp_parser_class_specifier (parser); |
20065 | if (decl_specs->attributes) |
20066 | cp_parser_decl_specs_attrs->pop (); |
20067 | invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: type_spec); |
20068 | /* If that worked, we're done. */ |
20069 | if (cp_parser_parse_definitely (parser)) |
20070 | { |
20071 | if (declares_class_or_enum) |
20072 | *declares_class_or_enum = 2; |
20073 | if (decl_specs) |
20074 | cp_parser_set_decl_spec_type (decl_specs, |
20075 | type_spec, |
20076 | token, |
20077 | /*type_definition_p=*/true); |
20078 | return type_spec; |
20079 | } |
20080 | |
20081 | /* Fall through. */ |
20082 | elaborated_type_specifier: |
20083 | /* We're declaring (not defining) a class or enum. */ |
20084 | if (declares_class_or_enum) |
20085 | *declares_class_or_enum = 1; |
20086 | |
20087 | /* Fall through. */ |
20088 | case RID_TYPENAME: |
20089 | /* Look for an elaborated-type-specifier. */ |
20090 | type_spec |
20091 | = (cp_parser_elaborated_type_specifier |
20092 | (parser, |
20093 | decl_spec_seq_has_spec_p (decl_specs, ds_friend), |
20094 | is_declaration)); |
20095 | if (decl_specs) |
20096 | cp_parser_set_decl_spec_type (decl_specs, |
20097 | type_spec, |
20098 | token, |
20099 | /*type_definition_p=*/false); |
20100 | return type_spec; |
20101 | |
20102 | case RID_CONST: |
20103 | ds = ds_const; |
20104 | if (is_cv_qualifier) |
20105 | *is_cv_qualifier = true; |
20106 | break; |
20107 | |
20108 | case RID_VOLATILE: |
20109 | ds = ds_volatile; |
20110 | if (is_cv_qualifier) |
20111 | *is_cv_qualifier = true; |
20112 | break; |
20113 | |
20114 | case RID_RESTRICT: |
20115 | ds = ds_restrict; |
20116 | if (is_cv_qualifier) |
20117 | *is_cv_qualifier = true; |
20118 | break; |
20119 | |
20120 | case RID_COMPLEX: |
20121 | /* The `__complex__' keyword is a GNU extension. */ |
20122 | ds = ds_complex; |
20123 | break; |
20124 | |
20125 | default: |
20126 | break; |
20127 | } |
20128 | |
20129 | /* Handle simple keywords. */ |
20130 | if (ds != ds_last) |
20131 | { |
20132 | if (decl_specs) |
20133 | { |
20134 | set_and_check_decl_spec_loc (decl_specs, ds, token); |
20135 | decl_specs->any_specifiers_p = true; |
20136 | } |
20137 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
20138 | } |
20139 | |
20140 | /* If we do not already have a type-specifier, assume we are looking |
20141 | at a simple-type-specifier. */ |
20142 | type_spec = cp_parser_simple_type_specifier (parser, |
20143 | decl_specs, |
20144 | flags); |
20145 | |
20146 | /* If we didn't find a type-specifier, and a type-specifier was not |
20147 | optional in this context, issue an error message. */ |
20148 | if (!type_spec && !(flags & CP_PARSER_FLAGS_OPTIONAL)) |
20149 | { |
20150 | cp_parser_error (parser, gmsgid: "expected type specifier" ); |
20151 | return error_mark_node; |
20152 | } |
20153 | |
20154 | return type_spec; |
20155 | } |
20156 | |
20157 | /* Parse a simple-type-specifier. |
20158 | |
20159 | simple-type-specifier: |
20160 | :: [opt] nested-name-specifier [opt] type-name |
20161 | :: [opt] nested-name-specifier template template-id |
20162 | char |
20163 | wchar_t |
20164 | bool |
20165 | short |
20166 | int |
20167 | long |
20168 | signed |
20169 | unsigned |
20170 | float |
20171 | double |
20172 | void |
20173 | |
20174 | C++11 Extension: |
20175 | |
20176 | simple-type-specifier: |
20177 | auto |
20178 | decltype ( expression ) |
20179 | char16_t |
20180 | char32_t |
20181 | __underlying_type ( type-id ) |
20182 | |
20183 | C++17 extension: |
20184 | |
20185 | nested-name-specifier(opt) template-name |
20186 | |
20187 | GNU Extension: |
20188 | |
20189 | simple-type-specifier: |
20190 | __int128 |
20191 | __typeof__ unary-expression |
20192 | __typeof__ ( type-id ) |
20193 | __typeof__ ( type-id ) { initializer-list , [opt] } |
20194 | |
20195 | Concepts Extension: |
20196 | |
20197 | simple-type-specifier: |
20198 | constrained-type-specifier |
20199 | |
20200 | Returns the indicated TYPE_DECL. If DECL_SPECS is not NULL, it is |
20201 | appropriately updated. */ |
20202 | |
20203 | static tree |
20204 | cp_parser_simple_type_specifier (cp_parser* parser, |
20205 | cp_decl_specifier_seq *decl_specs, |
20206 | cp_parser_flags flags) |
20207 | { |
20208 | tree type = NULL_TREE; |
20209 | cp_token *token; |
20210 | int idx; |
20211 | |
20212 | /* Peek at the next token. */ |
20213 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20214 | |
20215 | /* If we're looking at a keyword, things are easy. */ |
20216 | switch (token->keyword) |
20217 | { |
20218 | case RID_CHAR: |
20219 | if (decl_specs) |
20220 | decl_specs->explicit_char_p = true; |
20221 | type = char_type_node; |
20222 | break; |
20223 | case RID_CHAR8: |
20224 | type = char8_type_node; |
20225 | break; |
20226 | case RID_CHAR16: |
20227 | type = char16_type_node; |
20228 | break; |
20229 | case RID_CHAR32: |
20230 | type = char32_type_node; |
20231 | break; |
20232 | case RID_WCHAR: |
20233 | type = wchar_type_node; |
20234 | break; |
20235 | case RID_BOOL: |
20236 | type = boolean_type_node; |
20237 | break; |
20238 | case RID_SHORT: |
20239 | set_and_check_decl_spec_loc (decl_specs, ds: ds_short, token); |
20240 | type = short_integer_type_node; |
20241 | break; |
20242 | case RID_INT: |
20243 | if (decl_specs) |
20244 | decl_specs->explicit_int_p = true; |
20245 | type = integer_type_node; |
20246 | break; |
20247 | case RID_INT_N_0: |
20248 | case RID_INT_N_1: |
20249 | case RID_INT_N_2: |
20250 | case RID_INT_N_3: |
20251 | idx = token->keyword - RID_INT_N_0; |
20252 | if (! int_n_enabled_p [idx]) |
20253 | break; |
20254 | if (decl_specs) |
20255 | { |
20256 | decl_specs->explicit_intN_p = true; |
20257 | decl_specs->int_n_idx = idx; |
20258 | /* Check if the alternate "__intN__" form has been used instead of |
20259 | "__intN". */ |
20260 | if (startswith (IDENTIFIER_POINTER (token->u.value) |
20261 | + (IDENTIFIER_LENGTH (token->u.value) - 2), prefix: "__" )) |
20262 | decl_specs->int_n_alt = true; |
20263 | } |
20264 | type = int_n_trees [idx].signed_type; |
20265 | break; |
20266 | case RID_LONG: |
20267 | if (decl_specs) |
20268 | set_and_check_decl_spec_loc (decl_specs, ds: ds_long, token); |
20269 | type = long_integer_type_node; |
20270 | break; |
20271 | case RID_SIGNED: |
20272 | set_and_check_decl_spec_loc (decl_specs, ds: ds_signed, token); |
20273 | type = integer_type_node; |
20274 | break; |
20275 | case RID_UNSIGNED: |
20276 | set_and_check_decl_spec_loc (decl_specs, ds: ds_unsigned, token); |
20277 | type = unsigned_type_node; |
20278 | break; |
20279 | case RID_FLOAT: |
20280 | type = float_type_node; |
20281 | break; |
20282 | case RID_DOUBLE: |
20283 | type = double_type_node; |
20284 | break; |
20285 | CASE_RID_FLOATN_NX: |
20286 | type = FLOATN_NX_TYPE_NODE (token->keyword - RID_FLOATN_NX_FIRST); |
20287 | if (type == NULL_TREE) |
20288 | error ("%<_Float%d%s%> is not supported on this target" , |
20289 | floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].n, |
20290 | floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].extended |
20291 | ? "x" : "" ); |
20292 | break; |
20293 | case RID_VOID: |
20294 | type = void_type_node; |
20295 | break; |
20296 | |
20297 | case RID_AUTO: |
20298 | maybe_warn_cpp0x (str: CPP0X_AUTO); |
20299 | if (parser->auto_is_implicit_function_template_parm_p) |
20300 | { |
20301 | /* The 'auto' might be the placeholder return type for a function decl |
20302 | with trailing return type. */ |
20303 | bool have_trailing_return_fn_decl = false; |
20304 | |
20305 | cp_parser_parse_tentatively (parser); |
20306 | cp_lexer_consume_token (lexer: parser->lexer); |
20307 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
20308 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
20309 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
20310 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EOF)) |
20311 | { |
20312 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
20313 | { |
20314 | cp_lexer_consume_token (lexer: parser->lexer); |
20315 | cp_parser_skip_to_closing_parenthesis (parser, |
20316 | /*recovering*/false, |
20317 | /*or_comma*/false, |
20318 | /*consume_paren*/true); |
20319 | continue; |
20320 | } |
20321 | |
20322 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
20323 | { |
20324 | have_trailing_return_fn_decl = true; |
20325 | break; |
20326 | } |
20327 | |
20328 | cp_lexer_consume_token (lexer: parser->lexer); |
20329 | } |
20330 | cp_parser_abort_tentative_parse (parser); |
20331 | |
20332 | if (have_trailing_return_fn_decl) |
20333 | { |
20334 | type = make_auto (); |
20335 | break; |
20336 | } |
20337 | |
20338 | if (cxx_dialect >= cxx14) |
20339 | { |
20340 | type = synthesize_implicit_template_parm (parser, NULL_TREE); |
20341 | type = TREE_TYPE (type); |
20342 | } |
20343 | else |
20344 | type = error_mark_node; |
20345 | |
20346 | if (current_class_type && LAMBDA_TYPE_P (current_class_type)) |
20347 | { |
20348 | if (cxx_dialect < cxx14) |
20349 | error_at (token->location, |
20350 | "use of %<auto%> in lambda parameter declaration " |
20351 | "only available with " |
20352 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
20353 | } |
20354 | else if (!flag_concepts_ts && parser->in_template_argument_list_p) |
20355 | pedwarn (token->location, 0, |
20356 | "use of %<auto%> in template argument " |
20357 | "only available with %<-fconcepts-ts%>" ); |
20358 | else if (!flag_concepts) |
20359 | pedwarn (token->location, 0, |
20360 | "use of %<auto%> in parameter declaration " |
20361 | "only available with %<-std=c++20%> or %<-fconcepts%>" ); |
20362 | else if (cxx_dialect < cxx14) |
20363 | error_at (token->location, |
20364 | "use of %<auto%> in parameter declaration " |
20365 | "only available with " |
20366 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
20367 | } |
20368 | else |
20369 | type = make_auto (); |
20370 | break; |
20371 | |
20372 | case RID_DECLTYPE: |
20373 | /* Since DR 743, decltype can either be a simple-type-specifier by |
20374 | itself or begin a nested-name-specifier. Parsing it will replace |
20375 | it with a CPP_DECLTYPE, so just rewind and let the CPP_DECLTYPE |
20376 | handling below decide what to do. */ |
20377 | cp_parser_decltype (parser); |
20378 | cp_lexer_set_token_position (lexer: parser->lexer, pos: token); |
20379 | break; |
20380 | |
20381 | case RID_TYPEOF: |
20382 | /* Consume the `typeof' token. */ |
20383 | cp_lexer_consume_token (lexer: parser->lexer); |
20384 | /* Parse the operand to `typeof'. */ |
20385 | type = cp_parser_sizeof_operand (parser, RID_TYPEOF); |
20386 | /* If it is not already a TYPE, take its type. */ |
20387 | if (!TYPE_P (type)) |
20388 | type = finish_typeof (type); |
20389 | |
20390 | if (decl_specs) |
20391 | cp_parser_set_decl_spec_type (decl_specs, type, |
20392 | token, |
20393 | /*type_definition_p=*/false); |
20394 | |
20395 | return type; |
20396 | |
20397 | default: |
20398 | /* If token is a type-yielding built-in traits, parse it. */ |
20399 | const cp_trait* trait = cp_lexer_peek_trait_type (lexer: parser->lexer); |
20400 | if (trait) |
20401 | { |
20402 | type = cp_parser_trait (parser, trait); |
20403 | if (decl_specs) |
20404 | cp_parser_set_decl_spec_type (decl_specs, type, |
20405 | token, |
20406 | /*type_definition_p=*/false); |
20407 | |
20408 | return type; |
20409 | } |
20410 | |
20411 | break; |
20412 | } |
20413 | |
20414 | /* If token is an already-parsed decltype not followed by ::, |
20415 | it's a simple-type-specifier. */ |
20416 | if (token->type == CPP_DECLTYPE |
20417 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE) |
20418 | { |
20419 | type = saved_checks_value (check_value: token->u.tree_check_value); |
20420 | if (decl_specs) |
20421 | { |
20422 | cp_parser_set_decl_spec_type (decl_specs, type, |
20423 | token, |
20424 | /*type_definition_p=*/false); |
20425 | /* Remember that we are handling a decltype in order to |
20426 | implement the resolution of DR 1510 when the argument |
20427 | isn't instantiation dependent. */ |
20428 | decl_specs->decltype_p = true; |
20429 | } |
20430 | cp_lexer_consume_token (lexer: parser->lexer); |
20431 | return type; |
20432 | } |
20433 | |
20434 | /* If the type-specifier was for a built-in type, we're done. */ |
20435 | if (type) |
20436 | { |
20437 | /* Record the type. */ |
20438 | if (decl_specs |
20439 | && (token->keyword != RID_SIGNED |
20440 | && token->keyword != RID_UNSIGNED |
20441 | && token->keyword != RID_SHORT |
20442 | && token->keyword != RID_LONG)) |
20443 | cp_parser_set_decl_spec_type (decl_specs, |
20444 | type, |
20445 | token, |
20446 | /*type_definition_p=*/false); |
20447 | if (decl_specs) |
20448 | decl_specs->any_specifiers_p = true; |
20449 | |
20450 | /* Consume the token. */ |
20451 | cp_lexer_consume_token (lexer: parser->lexer); |
20452 | |
20453 | if (type == error_mark_node) |
20454 | return error_mark_node; |
20455 | |
20456 | /* There is no valid C++ program where a non-template type is |
20457 | followed by a "<". That usually indicates that the user thought |
20458 | that the type was a template. */ |
20459 | cp_parser_check_for_invalid_template_id (parser, type, tag_type: none_type, |
20460 | location: token->location); |
20461 | |
20462 | return TYPE_NAME (type); |
20463 | } |
20464 | |
20465 | /* The type-specifier must be a user-defined type. */ |
20466 | if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES)) |
20467 | { |
20468 | bool qualified_p; |
20469 | bool global_p; |
20470 | const bool typename_p = (cxx_dialect >= cxx20 |
20471 | && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
20472 | |
20473 | /* Don't gobble tokens or issue error messages if this is an |
20474 | optional type-specifier. */ |
20475 | if (flags & CP_PARSER_FLAGS_OPTIONAL) |
20476 | cp_parser_parse_tentatively (parser); |
20477 | |
20478 | /* Remember current tentative parsing state -- if we know we need |
20479 | a type, we can give better diagnostics here. */ |
20480 | bool tent = cp_parser_parsing_tentatively (parser); |
20481 | |
20482 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20483 | |
20484 | /* Look for the optional `::' operator. */ |
20485 | global_p |
20486 | = (cp_parser_global_scope_opt (parser, |
20487 | /*current_scope_valid_p=*/false) |
20488 | != NULL_TREE); |
20489 | /* Look for the nested-name specifier. */ |
20490 | qualified_p |
20491 | = (cp_parser_nested_name_specifier_opt (parser, |
20492 | /*typename_keyword_p=*/false, |
20493 | /*check_dependency_p=*/true, |
20494 | /*type_p=*/false, |
20495 | /*is_declaration=*/false) |
20496 | != NULL_TREE); |
20497 | /* If we have seen a nested-name-specifier, and the next token |
20498 | is `template', then we are using the template-id production. */ |
20499 | if (parser->scope |
20500 | && cp_parser_optional_template_keyword (parser)) |
20501 | { |
20502 | /* Look for the template-id. */ |
20503 | type = cp_parser_template_id (parser, |
20504 | /*template_keyword_p=*/true, |
20505 | /*check_dependency_p=*/true, |
20506 | tag_type: none_type, |
20507 | /*is_declaration=*/false); |
20508 | /* If the template-id did not name a type, we are out of |
20509 | luck. */ |
20510 | if (TREE_CODE (type) != TYPE_DECL) |
20511 | { |
20512 | /* ...unless we pretend we have seen 'typename'. */ |
20513 | if (typename_p) |
20514 | type = cp_parser_make_typename_type (parser, id: type, |
20515 | id_location: token->location); |
20516 | else |
20517 | { |
20518 | cp_parser_error (parser, gmsgid: "expected template-id for type" ); |
20519 | type = error_mark_node; |
20520 | } |
20521 | } |
20522 | } |
20523 | /* DR 1812: A < following a qualified-id in a typename-specifier |
20524 | could safely be assumed to begin a template argument list, so |
20525 | the template keyword should be optional. */ |
20526 | else if (parser->scope |
20527 | && qualified_p |
20528 | && typename_p |
20529 | && cp_lexer_next_token_is (lexer: parser->lexer, CPP_TEMPLATE_ID)) |
20530 | { |
20531 | cp_parser_parse_tentatively (parser); |
20532 | |
20533 | type = cp_parser_template_id (parser, |
20534 | /*template_keyword_p=*/true, |
20535 | /*check_dependency_p=*/true, |
20536 | tag_type: none_type, |
20537 | /*is_declaration=*/false); |
20538 | /* This is handled below, so back off. */ |
20539 | if (type && concept_check_p (t: type)) |
20540 | cp_parser_simulate_error (parser); |
20541 | |
20542 | if (!cp_parser_parse_definitely (parser)) |
20543 | type = NULL_TREE; |
20544 | else if (TREE_CODE (type) == TEMPLATE_ID_EXPR) |
20545 | type = make_typename_type (parser->scope, type, typename_type, |
20546 | /*complain=*/tf_error); |
20547 | else if (TREE_CODE (type) != TYPE_DECL) |
20548 | type = NULL_TREE; |
20549 | } |
20550 | |
20551 | /* Otherwise, look for a type-name. */ |
20552 | if (!type) |
20553 | { |
20554 | if (cxx_dialect >= cxx17 || flag_concepts) |
20555 | cp_parser_parse_tentatively (parser); |
20556 | |
20557 | type = cp_parser_type_name (parser, (qualified_p && typename_p)); |
20558 | |
20559 | if ((cxx_dialect >= cxx17 || flag_concepts) |
20560 | && !cp_parser_parse_definitely (parser)) |
20561 | type = NULL_TREE; |
20562 | } |
20563 | |
20564 | if (!type && flag_concepts && decl_specs) |
20565 | { |
20566 | /* Try for a type-constraint with template arguments. We check |
20567 | decl_specs here to avoid trying this for a functional cast. */ |
20568 | |
20569 | cp_parser_parse_tentatively (parser); |
20570 | |
20571 | type = cp_parser_template_id (parser, |
20572 | /*template_keyword_p=*/false, |
20573 | /*check_dependency_p=*/true, |
20574 | tag_type: none_type, |
20575 | /*is_declaration=*/false); |
20576 | if (type && concept_check_p (t: type)) |
20577 | { |
20578 | location_t loc = EXPR_LOCATION (type); |
20579 | type = cp_parser_placeholder_type_specifier (parser, loc, |
20580 | type, tent); |
20581 | if (tent && type == error_mark_node) |
20582 | /* Perhaps it's a concept-check expression. */ |
20583 | cp_parser_simulate_error (parser); |
20584 | } |
20585 | else |
20586 | cp_parser_simulate_error (parser); |
20587 | |
20588 | if (!cp_parser_parse_definitely (parser)) |
20589 | type = NULL_TREE; |
20590 | } |
20591 | |
20592 | if (!type && cxx_dialect >= cxx17) |
20593 | { |
20594 | /* Try class template argument deduction or type-constraint without |
20595 | template arguments. */ |
20596 | tree name = cp_parser_identifier (parser); |
20597 | if (name && TREE_CODE (name) == IDENTIFIER_NODE |
20598 | && parser->scope != error_mark_node) |
20599 | { |
20600 | location_t loc |
20601 | = cp_lexer_previous_token (lexer: parser->lexer)->location; |
20602 | tree tmpl = cp_parser_lookup_name (parser, name, |
20603 | none_type, |
20604 | /*is_template=*/false, |
20605 | /*is_namespace=*/false, |
20606 | /*check_dependency=*/true, |
20607 | /*ambiguous_decls=*/NULL, |
20608 | token->location); |
20609 | if (tmpl && tmpl != error_mark_node |
20610 | && ctad_template_p (tmpl)) |
20611 | type = make_template_placeholder (tmpl); |
20612 | else if (flag_concepts && tmpl && concept_definition_p (t: tmpl)) |
20613 | type = cp_parser_placeholder_type_specifier (parser, loc, |
20614 | tmpl, tent); |
20615 | else |
20616 | { |
20617 | type = error_mark_node; |
20618 | if (!cp_parser_simulate_error (parser)) |
20619 | cp_parser_name_lookup_error (parser, name, decl: tmpl, |
20620 | desired: NLE_TYPE, location: token->location); |
20621 | } |
20622 | } |
20623 | else |
20624 | type = error_mark_node; |
20625 | } |
20626 | |
20627 | /* If it didn't work out, we don't have a TYPE. */ |
20628 | if ((flags & CP_PARSER_FLAGS_OPTIONAL) |
20629 | && !cp_parser_parse_definitely (parser)) |
20630 | type = NULL_TREE; |
20631 | |
20632 | /* Keep track of all name-lookups performed in class scopes. */ |
20633 | if (type |
20634 | && !global_p |
20635 | && !qualified_p |
20636 | && TREE_CODE (type) == TYPE_DECL |
20637 | && identifier_p (DECL_NAME (type))) |
20638 | maybe_note_name_used_in_class (DECL_NAME (type), type); |
20639 | |
20640 | if (type && decl_specs) |
20641 | cp_parser_set_decl_spec_type (decl_specs, type, |
20642 | token, |
20643 | /*type_definition_p=*/false); |
20644 | } |
20645 | |
20646 | /* If we didn't get a type-name, issue an error message. */ |
20647 | if (!type && !(flags & CP_PARSER_FLAGS_OPTIONAL)) |
20648 | { |
20649 | cp_parser_error (parser, gmsgid: "expected type-name" ); |
20650 | return error_mark_node; |
20651 | } |
20652 | |
20653 | if (type && type != error_mark_node) |
20654 | { |
20655 | /* See if TYPE is an Objective-C type, and if so, parse and |
20656 | accept any protocol references following it. Do this before |
20657 | the cp_parser_check_for_invalid_template_id() call, because |
20658 | Objective-C types can be followed by '<...>' which would |
20659 | enclose protocol names rather than template arguments, and so |
20660 | everything is fine. */ |
20661 | if (c_dialect_objc () && !parser->scope |
20662 | && (objc_is_id (type) || objc_is_class_name (type))) |
20663 | { |
20664 | tree protos = cp_parser_objc_protocol_refs_opt (parser); |
20665 | tree qual_type = objc_get_protocol_qualified_type (type, protos); |
20666 | |
20667 | /* Clobber the "unqualified" type previously entered into |
20668 | DECL_SPECS with the new, improved protocol-qualified version. */ |
20669 | if (decl_specs) |
20670 | decl_specs->type = qual_type; |
20671 | |
20672 | return qual_type; |
20673 | } |
20674 | |
20675 | /* There is no valid C++ program where a non-template type is |
20676 | followed by a "<". That usually indicates that the user |
20677 | thought that the type was a template. */ |
20678 | cp_parser_check_for_invalid_template_id (parser, type, |
20679 | tag_type: none_type, |
20680 | location: token->location); |
20681 | } |
20682 | |
20683 | return type; |
20684 | } |
20685 | |
20686 | /* Parse the remainder of a placholder-type-specifier. |
20687 | |
20688 | placeholder-type-specifier: |
20689 | type-constraint_opt auto |
20690 | type-constraint_opt decltype(auto) |
20691 | |
20692 | The raw form of the constraint is parsed in cp_parser_simple_type_specifier |
20693 | and passed as TMPL. This function converts TMPL to an actual type-constraint, |
20694 | parses the placeholder type, and performs some contextual syntactic analysis. |
20695 | |
20696 | LOC provides the location of the template name. |
20697 | |
20698 | TENTATIVE is true if the type-specifier parsing is tentative; in that case, |
20699 | don't give an error if TMPL isn't a valid type-constraint, as the template-id |
20700 | might actually be a concept-check, |
20701 | |
20702 | Note that the Concepts TS allows the auto or decltype(auto) to be |
20703 | omitted in a constrained-type-specifier. */ |
20704 | |
20705 | static tree |
20706 | cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, |
20707 | tree tmpl, bool tentative) |
20708 | { |
20709 | if (tmpl == error_mark_node) |
20710 | return error_mark_node; |
20711 | |
20712 | tree orig_tmpl = tmpl; |
20713 | |
20714 | /* Get the arguments as written for subsequent analysis. */ |
20715 | tree args = NULL_TREE; |
20716 | if (TREE_CODE (tmpl) == TEMPLATE_ID_EXPR) |
20717 | { |
20718 | args = TREE_OPERAND (tmpl, 1); |
20719 | tmpl = TREE_OPERAND (tmpl, 0); |
20720 | } |
20721 | else |
20722 | /* A concept-name with no arguments can't be an expression. */ |
20723 | tentative = false; |
20724 | |
20725 | tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error; |
20726 | |
20727 | /* Get the concept and prototype parameter for the constraint. */ |
20728 | tree_pair info = finish_type_constraints (tmpl, args, complain); |
20729 | tree con = info.first; |
20730 | tree proto = info.second; |
20731 | if (con == error_mark_node) |
20732 | return error_mark_node; |
20733 | |
20734 | /* As per the standard, require auto or decltype(auto), except in some |
20735 | cases (template parameter lists, -fconcepts-ts enabled). */ |
20736 | cp_token *placeholder = NULL, *close_paren = NULL; |
20737 | if (cxx_dialect >= cxx20) |
20738 | { |
20739 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
20740 | placeholder = cp_lexer_consume_token (lexer: parser->lexer); |
20741 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DECLTYPE)) |
20742 | { |
20743 | placeholder = cp_lexer_consume_token (lexer: parser->lexer); |
20744 | matching_parens parens; |
20745 | parens.require_open (parser); |
20746 | cp_parser_require_keyword (parser, RID_AUTO, RT_AUTO); |
20747 | close_paren = parens.require_close (parser); |
20748 | } |
20749 | } |
20750 | |
20751 | /* A type constraint constrains a contextually determined type or type |
20752 | parameter pack. However, the Concepts TS does allow concepts |
20753 | to introduce non-type and template template parameters. */ |
20754 | if (TREE_CODE (proto) != TYPE_DECL) |
20755 | { |
20756 | if (!flag_concepts_ts |
20757 | || !processing_template_parmlist) |
20758 | { |
20759 | if (!tentative) |
20760 | { |
20761 | error_at (loc, "%qE does not constrain a type" , DECL_NAME (con)); |
20762 | inform (DECL_SOURCE_LOCATION (con), "concept defined here" ); |
20763 | } |
20764 | return error_mark_node; |
20765 | } |
20766 | } |
20767 | |
20768 | /* In a template parameter list, a type-parameter can be introduced |
20769 | by type-constraints alone. */ |
20770 | if (processing_template_parmlist && !placeholder) |
20771 | { |
20772 | /* In a default argument we may not be creating new parameters. */ |
20773 | if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) |
20774 | { |
20775 | /* If this assert turns out to be false, do error() instead. */ |
20776 | gcc_assert (tentative); |
20777 | return error_mark_node; |
20778 | } |
20779 | return build_constrained_parameter (con, proto, args); |
20780 | } |
20781 | |
20782 | /* Diagnose issues placeholder issues. */ |
20783 | if (!flag_concepts_ts |
20784 | && !parser->in_result_type_constraint_p |
20785 | && !placeholder) |
20786 | { |
20787 | if (tentative) |
20788 | /* Perhaps it's a concept-check expression (c++/91073). */ |
20789 | return error_mark_node; |
20790 | |
20791 | tree id = build_nt (TEMPLATE_ID_EXPR, tmpl, args); |
20792 | tree expr = DECL_P (orig_tmpl) ? DECL_NAME (con) : id; |
20793 | error_at (input_location, |
20794 | "expected %<auto%> or %<decltype(auto)%> after %qE" , expr); |
20795 | /* Fall through. This is an error of omission. */ |
20796 | } |
20797 | else if (parser->in_result_type_constraint_p && placeholder) |
20798 | { |
20799 | /* A trailing return type only allows type-constraints. */ |
20800 | error_at (input_location, |
20801 | "unexpected placeholder in constrained result type" ); |
20802 | } |
20803 | |
20804 | /* In a parameter-declaration-clause, a placeholder-type-specifier |
20805 | results in an invented template parameter. */ |
20806 | if (parser->auto_is_implicit_function_template_parm_p) |
20807 | { |
20808 | if (close_paren) |
20809 | { |
20810 | location_t loc = make_location (caret: placeholder->location, |
20811 | start: placeholder->location, |
20812 | finish: close_paren->location); |
20813 | error_at (loc, "cannot declare a parameter with %<decltype(auto)%>" ); |
20814 | return error_mark_node; |
20815 | } |
20816 | tree parm = build_constrained_parameter (con, proto, args); |
20817 | return synthesize_implicit_template_parm (parser, parm); |
20818 | } |
20819 | |
20820 | /* Determine if the type should be deduced using template argument |
20821 | deduction or decltype deduction. Note that the latter is always |
20822 | used for type-constraints in trailing return types. */ |
20823 | bool decltype_p = placeholder |
20824 | ? placeholder->keyword == RID_DECLTYPE |
20825 | : parser->in_result_type_constraint_p; |
20826 | |
20827 | /* Otherwise, this is the type of a variable or return type. */ |
20828 | if (decltype_p) |
20829 | return make_constrained_decltype_auto (con, args); |
20830 | else |
20831 | return make_constrained_auto (con, args); |
20832 | } |
20833 | |
20834 | /* Parse a type-name. |
20835 | |
20836 | type-name: |
20837 | class-name |
20838 | enum-name |
20839 | typedef-name |
20840 | simple-template-id [in c++0x] |
20841 | |
20842 | enum-name: |
20843 | identifier |
20844 | |
20845 | typedef-name: |
20846 | identifier |
20847 | |
20848 | Concepts: |
20849 | |
20850 | type-name: |
20851 | concept-name |
20852 | partial-concept-id |
20853 | |
20854 | concept-name: |
20855 | identifier |
20856 | |
20857 | Returns a TYPE_DECL for the type. */ |
20858 | |
20859 | static tree |
20860 | cp_parser_type_name (cp_parser* parser, bool typename_keyword_p) |
20861 | { |
20862 | tree type_decl; |
20863 | |
20864 | /* We can't know yet whether it is a class-name or not. */ |
20865 | cp_parser_parse_tentatively (parser); |
20866 | /* Try a class-name. */ |
20867 | type_decl = cp_parser_class_name (parser, |
20868 | typename_keyword_p, |
20869 | /*template_keyword_p=*/false, |
20870 | none_type, |
20871 | /*check_dependency_p=*/true, |
20872 | /*class_head_p=*/false, |
20873 | /*is_declaration=*/false); |
20874 | /* If it's not a class-name, keep looking. */ |
20875 | if (!cp_parser_parse_definitely (parser)) |
20876 | { |
20877 | if (cxx_dialect < cxx11) |
20878 | /* It must be a typedef-name or an enum-name. */ |
20879 | return cp_parser_nonclass_name (parser); |
20880 | |
20881 | cp_parser_parse_tentatively (parser); |
20882 | /* It is either a simple-template-id representing an |
20883 | instantiation of an alias template... */ |
20884 | type_decl = cp_parser_template_id (parser, |
20885 | /*template_keyword_p=*/false, |
20886 | /*check_dependency_p=*/true, |
20887 | tag_type: none_type, |
20888 | /*is_declaration=*/false); |
20889 | /* Note that this must be an instantiation of an alias template |
20890 | because [temp.names]/6 says: |
20891 | |
20892 | A template-id that names an alias template specialization |
20893 | is a type-name. |
20894 | |
20895 | Whereas [temp.names]/7 says: |
20896 | |
20897 | A simple-template-id that names a class template |
20898 | specialization is a class-name. |
20899 | |
20900 | With concepts, this could also be a partial-concept-id that |
20901 | declares a non-type template parameter. */ |
20902 | if (type_decl != NULL_TREE |
20903 | && TREE_CODE (type_decl) == TYPE_DECL |
20904 | && TYPE_DECL_ALIAS_P (type_decl)) |
20905 | gcc_assert (DECL_TEMPLATE_INSTANTIATION (type_decl)); |
20906 | else |
20907 | cp_parser_simulate_error (parser); |
20908 | |
20909 | if (!cp_parser_parse_definitely (parser)) |
20910 | /* ... Or a typedef-name or an enum-name. */ |
20911 | return cp_parser_nonclass_name (parser); |
20912 | } |
20913 | |
20914 | return type_decl; |
20915 | } |
20916 | |
20917 | /* Parse a non-class type-name, that is, either an enum-name, a typedef-name, |
20918 | or a concept-name. |
20919 | |
20920 | enum-name: |
20921 | identifier |
20922 | |
20923 | typedef-name: |
20924 | identifier |
20925 | |
20926 | concept-name: |
20927 | identifier |
20928 | |
20929 | Returns a TYPE_DECL for the type. */ |
20930 | |
20931 | static tree |
20932 | cp_parser_nonclass_name (cp_parser* parser) |
20933 | { |
20934 | tree type_decl; |
20935 | tree identifier; |
20936 | |
20937 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
20938 | identifier = cp_parser_identifier (parser); |
20939 | if (identifier == error_mark_node) |
20940 | return error_mark_node; |
20941 | |
20942 | /* Look up the type-name. */ |
20943 | type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); |
20944 | |
20945 | type_decl = strip_using_decl (type_decl); |
20946 | |
20947 | if (TREE_CODE (type_decl) != TYPE_DECL |
20948 | && (objc_is_id (identifier) || objc_is_class_name (identifier))) |
20949 | { |
20950 | /* See if this is an Objective-C type. */ |
20951 | tree protos = cp_parser_objc_protocol_refs_opt (parser); |
20952 | tree type = objc_get_protocol_qualified_type (identifier, protos); |
20953 | if (type) |
20954 | type_decl = TYPE_NAME (type); |
20955 | } |
20956 | |
20957 | /* Issue an error if we did not find a type-name. */ |
20958 | if (TREE_CODE (type_decl) != TYPE_DECL |
20959 | /* In Objective-C, we have the complication that class names are |
20960 | normally type names and start declarations (eg, the |
20961 | "NSObject" in "NSObject *object;"), but can be used in an |
20962 | Objective-C 2.0 dot-syntax (as in "NSObject.version") which |
20963 | is an expression. So, a classname followed by a dot is not a |
20964 | valid type-name. */ |
20965 | || (objc_is_class_name (TREE_TYPE (type_decl)) |
20966 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT)) |
20967 | { |
20968 | if (!cp_parser_simulate_error (parser)) |
20969 | cp_parser_name_lookup_error (parser, name: identifier, decl: type_decl, |
20970 | desired: NLE_TYPE, location: token->location); |
20971 | return error_mark_node; |
20972 | } |
20973 | /* Remember that the name was used in the definition of the |
20974 | current class so that we can check later to see if the |
20975 | meaning would have been different after the class was |
20976 | entirely defined. */ |
20977 | else if (type_decl != error_mark_node |
20978 | && !parser->scope) |
20979 | maybe_note_name_used_in_class (identifier, type_decl); |
20980 | |
20981 | return type_decl; |
20982 | } |
20983 | |
20984 | /* Parse an elaborated-type-specifier. Note that the grammar given |
20985 | here incorporates the resolution to DR68. |
20986 | |
20987 | elaborated-type-specifier: |
20988 | class-key :: [opt] nested-name-specifier [opt] identifier |
20989 | class-key :: [opt] nested-name-specifier [opt] template [opt] template-id |
20990 | enum-key :: [opt] nested-name-specifier [opt] identifier |
20991 | typename :: [opt] nested-name-specifier identifier |
20992 | typename :: [opt] nested-name-specifier template [opt] |
20993 | template-id |
20994 | |
20995 | GNU extension: |
20996 | |
20997 | elaborated-type-specifier: |
20998 | class-key attributes :: [opt] nested-name-specifier [opt] identifier |
20999 | class-key attributes :: [opt] nested-name-specifier [opt] |
21000 | template [opt] template-id |
21001 | enum attributes :: [opt] nested-name-specifier [opt] identifier |
21002 | |
21003 | If IS_FRIEND is TRUE, then this elaborated-type-specifier is being |
21004 | declared `friend'. If IS_DECLARATION is TRUE, then this |
21005 | elaborated-type-specifier appears in a decl-specifiers-seq, i.e., |
21006 | something is being declared. |
21007 | |
21008 | Returns the TYPE specified. */ |
21009 | |
21010 | static tree |
21011 | cp_parser_elaborated_type_specifier (cp_parser* parser, |
21012 | bool is_friend, |
21013 | bool is_declaration) |
21014 | { |
21015 | enum tag_types tag_type; |
21016 | tree identifier; |
21017 | tree type = NULL_TREE; |
21018 | tree attributes = NULL_TREE; |
21019 | tree globalscope; |
21020 | cp_token *token = NULL; |
21021 | |
21022 | /* For class and enum types the location of the class-key or enum-key. */ |
21023 | location_t key_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21024 | /* For a scoped enum, the 'class' or 'struct' keyword id. */ |
21025 | rid scoped_key = RID_MAX; |
21026 | |
21027 | /* See if we're looking at the `enum' keyword. */ |
21028 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ENUM)) |
21029 | { |
21030 | /* Consume the `enum' token. */ |
21031 | cp_lexer_consume_token (lexer: parser->lexer); |
21032 | /* Remember that it's an enumeration type. */ |
21033 | tag_type = enum_type; |
21034 | /* Issue a warning if the `struct' or `class' key (for C++0x scoped |
21035 | enums) is used here. */ |
21036 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
21037 | if (cp_parser_is_keyword (token, keyword: scoped_key = RID_CLASS) |
21038 | || cp_parser_is_keyword (token, keyword: scoped_key = RID_STRUCT)) |
21039 | { |
21040 | location_t loc = token->location; |
21041 | gcc_rich_location richloc (loc); |
21042 | richloc.add_range (loc: input_location); |
21043 | richloc.add_fixit_remove (); |
21044 | pedwarn (&richloc, 0, "elaborated-type-specifier for " |
21045 | "a scoped enum must not use the %qD keyword" , |
21046 | token->u.value); |
21047 | /* Consume the `struct' or `class' and parse it anyway. */ |
21048 | cp_lexer_consume_token (lexer: parser->lexer); |
21049 | /* Create a combined location for the whole scoped-enum-key. */ |
21050 | key_loc = make_location (caret: key_loc, start: key_loc, finish: loc); |
21051 | } |
21052 | else |
21053 | scoped_key = RID_MAX; |
21054 | |
21055 | /* Parse the attributes. */ |
21056 | attributes = cp_parser_attributes_opt (parser); |
21057 | } |
21058 | /* Or, it might be `typename'. */ |
21059 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
21060 | keyword: RID_TYPENAME)) |
21061 | { |
21062 | /* Consume the `typename' token. */ |
21063 | cp_lexer_consume_token (lexer: parser->lexer); |
21064 | /* Remember that it's a `typename' type. */ |
21065 | tag_type = typename_type; |
21066 | } |
21067 | /* Otherwise it must be a class-key. */ |
21068 | else |
21069 | { |
21070 | key_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21071 | tag_type = cp_parser_class_key (parser); |
21072 | if (tag_type == none_type) |
21073 | return error_mark_node; |
21074 | /* Parse the attributes. */ |
21075 | attributes = cp_parser_attributes_opt (parser); |
21076 | } |
21077 | |
21078 | /* Look for the `::' operator. */ |
21079 | globalscope = cp_parser_global_scope_opt (parser, |
21080 | /*current_scope_valid_p=*/false); |
21081 | /* Look for the nested-name-specifier. */ |
21082 | tree nested_name_specifier; |
21083 | if (tag_type == typename_type && !globalscope) |
21084 | { |
21085 | nested_name_specifier |
21086 | = cp_parser_nested_name_specifier (parser, |
21087 | /*typename_keyword_p=*/true, |
21088 | /*check_dependency_p=*/true, |
21089 | /*type_p=*/true, |
21090 | is_declaration); |
21091 | if (!nested_name_specifier) |
21092 | return error_mark_node; |
21093 | } |
21094 | else |
21095 | /* Even though `typename' is not present, the proposed resolution |
21096 | to Core Issue 180 says that in `class A<T>::B', `B' should be |
21097 | considered a type-name, even if `A<T>' is dependent. */ |
21098 | nested_name_specifier |
21099 | = cp_parser_nested_name_specifier_opt (parser, |
21100 | /*typename_keyword_p=*/true, |
21101 | /*check_dependency_p=*/true, |
21102 | /*type_p=*/true, |
21103 | is_declaration); |
21104 | /* For everything but enumeration types, consider a template-id. |
21105 | For an enumeration type, consider only a plain identifier. */ |
21106 | if (tag_type != enum_type) |
21107 | { |
21108 | bool template_p = false; |
21109 | tree decl; |
21110 | |
21111 | /* Allow the `template' keyword. */ |
21112 | template_p = cp_parser_optional_template_keyword (parser); |
21113 | /* If we didn't see `template', we don't know if there's a |
21114 | template-id or not. */ |
21115 | if (!template_p) |
21116 | cp_parser_parse_tentatively (parser); |
21117 | /* The `template' keyword must follow a nested-name-specifier. */ |
21118 | else if (!nested_name_specifier && !globalscope) |
21119 | { |
21120 | cp_parser_error (parser, gmsgid: "%<template%> must follow a nested-" |
21121 | "name-specifier" ); |
21122 | return error_mark_node; |
21123 | } |
21124 | |
21125 | /* Parse the template-id. */ |
21126 | token = cp_lexer_peek_token (lexer: parser->lexer); |
21127 | decl = cp_parser_template_id (parser, template_keyword_p: template_p, |
21128 | /*check_dependency_p=*/true, |
21129 | tag_type, |
21130 | is_declaration); |
21131 | /* If we didn't find a template-id, look for an ordinary |
21132 | identifier. */ |
21133 | if (!template_p && !cp_parser_parse_definitely (parser)) |
21134 | ; |
21135 | /* We can get here when cp_parser_template_id, called by |
21136 | cp_parser_class_name with tag_type == none_type, succeeds |
21137 | and caches a BASELINK. Then, when called again here, |
21138 | instead of failing and returning an error_mark_node |
21139 | returns it (see template/typename17.C in C++11). |
21140 | ??? Could we diagnose this earlier? */ |
21141 | else if (tag_type == typename_type && BASELINK_P (decl)) |
21142 | { |
21143 | cp_parser_diagnose_invalid_type_name (parser, id: decl, location: token->location); |
21144 | type = error_mark_node; |
21145 | } |
21146 | /* If DECL is a TEMPLATE_ID_EXPR, and the `typename' keyword is |
21147 | in effect, then we must assume that, upon instantiation, the |
21148 | template will correspond to a class. */ |
21149 | else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR |
21150 | && tag_type == typename_type) |
21151 | type = make_typename_type (parser->scope, decl, |
21152 | typename_type, |
21153 | /*complain=*/tf_error); |
21154 | /* If the `typename' keyword is in effect and DECL is not a type |
21155 | decl, then type is non existent. */ |
21156 | else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL) |
21157 | ; |
21158 | else if (TREE_CODE (decl) == TYPE_DECL) |
21159 | { |
21160 | type = check_elaborated_type_specifier (tag_type, decl, |
21161 | /*allow_template_p=*/true); |
21162 | |
21163 | /* If the next token is a semicolon, this must be a specialization, |
21164 | instantiation, or friend declaration. Check the scope while we |
21165 | still know whether or not we had a nested-name-specifier. */ |
21166 | if (type != error_mark_node |
21167 | && !nested_name_specifier && !is_friend |
21168 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
21169 | check_unqualified_spec_or_inst (type, token->location); |
21170 | } |
21171 | else if (decl == error_mark_node) |
21172 | type = error_mark_node; |
21173 | } |
21174 | |
21175 | if (!type) |
21176 | { |
21177 | token = cp_lexer_peek_token (lexer: parser->lexer); |
21178 | identifier = cp_parser_identifier (parser); |
21179 | |
21180 | if (identifier == error_mark_node) |
21181 | { |
21182 | parser->scope = NULL_TREE; |
21183 | return error_mark_node; |
21184 | } |
21185 | |
21186 | /* For a `typename', we needn't call xref_tag. */ |
21187 | if (tag_type == typename_type |
21188 | && TREE_CODE (parser->scope) != NAMESPACE_DECL) |
21189 | return cp_parser_make_typename_type (parser, id: identifier, |
21190 | id_location: token->location); |
21191 | |
21192 | /* Template parameter lists apply only if we are not within a |
21193 | function parameter list. */ |
21194 | bool template_parm_lists_apply |
21195 | = parser->num_template_parameter_lists; |
21196 | if (template_parm_lists_apply) |
21197 | for (cp_binding_level *s = current_binding_level; |
21198 | s && s->kind != sk_template_parms; |
21199 | s = s->level_chain) |
21200 | if (s->kind == sk_function_parms) |
21201 | template_parm_lists_apply = false; |
21202 | |
21203 | /* Look up a qualified name in the usual way. */ |
21204 | if (parser->scope) |
21205 | { |
21206 | tree decl; |
21207 | tree ambiguous_decls; |
21208 | |
21209 | decl = cp_parser_lookup_name (parser, identifier, |
21210 | tag_type, |
21211 | /*is_template=*/false, |
21212 | /*is_namespace=*/false, |
21213 | /*check_dependency=*/true, |
21214 | &ambiguous_decls, |
21215 | token->location); |
21216 | |
21217 | /* If the lookup was ambiguous, an error will already have been |
21218 | issued. */ |
21219 | if (ambiguous_decls) |
21220 | return error_mark_node; |
21221 | |
21222 | /* If we are parsing friend declaration, DECL may be a |
21223 | TEMPLATE_DECL tree node here. However, we need to check |
21224 | whether this TEMPLATE_DECL results in valid code. Consider |
21225 | the following example: |
21226 | |
21227 | namespace N { |
21228 | template <class T> class C {}; |
21229 | } |
21230 | class X { |
21231 | template <class T> friend class N::C; // #1, valid code |
21232 | }; |
21233 | template <class T> class Y { |
21234 | friend class N::C; // #2, invalid code |
21235 | }; |
21236 | |
21237 | For both case #1 and #2, we arrive at a TEMPLATE_DECL after |
21238 | name lookup of `N::C'. We see that friend declaration must |
21239 | be template for the code to be valid. Note that |
21240 | processing_template_decl does not work here since it is |
21241 | always 1 for the above two cases. */ |
21242 | |
21243 | decl = (cp_parser_maybe_treat_template_as_class |
21244 | (decl, /*tag_name_p=*/is_friend |
21245 | && template_parm_lists_apply)); |
21246 | |
21247 | if (TREE_CODE (decl) != TYPE_DECL) |
21248 | { |
21249 | cp_parser_diagnose_invalid_type_name (parser, |
21250 | id: identifier, |
21251 | location: token->location); |
21252 | return error_mark_node; |
21253 | } |
21254 | |
21255 | if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE) |
21256 | { |
21257 | bool allow_template = (template_parm_lists_apply |
21258 | || DECL_SELF_REFERENCE_P (decl)); |
21259 | type = check_elaborated_type_specifier (tag_type, decl, |
21260 | allow_template); |
21261 | |
21262 | if (type == error_mark_node) |
21263 | return error_mark_node; |
21264 | } |
21265 | |
21266 | /* Forward declarations of nested types, such as |
21267 | |
21268 | class C1::C2; |
21269 | class C1::C2::C3; |
21270 | |
21271 | are invalid unless all components preceding the final '::' |
21272 | are complete. If all enclosing types are complete, these |
21273 | declarations become merely pointless. |
21274 | |
21275 | Invalid forward declarations of nested types are errors |
21276 | caught elsewhere in parsing. Those that are pointless arrive |
21277 | here. */ |
21278 | |
21279 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
21280 | && !is_friend && is_declaration |
21281 | && !processing_explicit_instantiation) |
21282 | warning (0, "declaration %qD does not declare anything" , decl); |
21283 | |
21284 | type = TREE_TYPE (decl); |
21285 | } |
21286 | else |
21287 | { |
21288 | /* An elaborated-type-specifier sometimes introduces a new type and |
21289 | sometimes names an existing type. Normally, the rule is that it |
21290 | introduces a new type only if there is not an existing type of |
21291 | the same name already in scope. For example, given: |
21292 | |
21293 | struct S {}; |
21294 | void f() { struct S s; } |
21295 | |
21296 | the `struct S' in the body of `f' is the same `struct S' as in |
21297 | the global scope; the existing definition is used. However, if |
21298 | there were no global declaration, this would introduce a new |
21299 | local class named `S'. |
21300 | |
21301 | An exception to this rule applies to the following code: |
21302 | |
21303 | namespace N { struct S; } |
21304 | |
21305 | Here, the elaborated-type-specifier names a new type |
21306 | unconditionally; even if there is already an `S' in the |
21307 | containing scope this declaration names a new type. |
21308 | This exception only applies if the elaborated-type-specifier |
21309 | forms the complete declaration: |
21310 | |
21311 | [class.name] |
21312 | |
21313 | A declaration consisting solely of `class-key identifier ;' is |
21314 | either a redeclaration of the name in the current scope or a |
21315 | forward declaration of the identifier as a class name. It |
21316 | introduces the name into the current scope. |
21317 | |
21318 | We are in this situation precisely when the next token is a `;'. |
21319 | |
21320 | An exception to the exception is that a `friend' declaration does |
21321 | *not* name a new type; i.e., given: |
21322 | |
21323 | struct S { friend struct T; }; |
21324 | |
21325 | `T' is not a new type in the scope of `S'. |
21326 | |
21327 | Also, `new struct S' or `sizeof (struct S)' never results in the |
21328 | definition of a new type; a new type can only be declared in a |
21329 | declaration context. */ |
21330 | |
21331 | TAG_how how; |
21332 | |
21333 | if (is_friend) |
21334 | /* Friends have special name lookup rules. */ |
21335 | how = TAG_how::HIDDEN_FRIEND; |
21336 | else if (is_declaration |
21337 | && cp_lexer_next_token_is (lexer: parser->lexer, |
21338 | type: CPP_SEMICOLON)) |
21339 | /* This is a `class-key identifier ;' */ |
21340 | how = TAG_how::CURRENT_ONLY; |
21341 | else |
21342 | how = TAG_how::GLOBAL; |
21343 | |
21344 | bool template_p = |
21345 | (template_parm_lists_apply |
21346 | && (cp_parser_next_token_starts_class_definition_p (parser) |
21347 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON))); |
21348 | /* An unqualified name was used to reference this type, so |
21349 | there were no qualifying templates. */ |
21350 | if (template_parm_lists_apply |
21351 | && !cp_parser_check_template_parameters (parser, |
21352 | /*num_templates=*/0, |
21353 | /*template_id*/false, |
21354 | token->location, |
21355 | /*declarator=*/NULL)) |
21356 | return error_mark_node; |
21357 | |
21358 | type = xref_tag (tag_type, identifier, how, tpl_header_p: template_p); |
21359 | } |
21360 | } |
21361 | |
21362 | if (type == error_mark_node) |
21363 | return error_mark_node; |
21364 | |
21365 | /* Allow attributes on forward declarations of classes. */ |
21366 | if (attributes) |
21367 | { |
21368 | if (TREE_CODE (type) == TYPENAME_TYPE) |
21369 | warning (OPT_Wattributes, |
21370 | "attributes ignored on uninstantiated type" ); |
21371 | else if (tag_type != enum_type |
21372 | && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM |
21373 | && CLASSTYPE_TEMPLATE_INSTANTIATION (type) |
21374 | && ! processing_explicit_instantiation) |
21375 | warning (OPT_Wattributes, |
21376 | "attributes ignored on template instantiation" ); |
21377 | else if (is_friend && cxx11_attribute_p (attributes)) |
21378 | { |
21379 | if (warning (OPT_Wattributes, "attribute ignored" )) |
21380 | inform (input_location, "an attribute that appertains to a friend " |
21381 | "declaration that is not a definition is ignored" ); |
21382 | } |
21383 | else if (is_declaration && cp_parser_declares_only_class_p (parser)) |
21384 | cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); |
21385 | else |
21386 | warning (OPT_Wattributes, |
21387 | "attributes ignored on elaborated-type-specifier that is " |
21388 | "not a forward declaration" ); |
21389 | } |
21390 | |
21391 | if (tag_type == enum_type) |
21392 | cp_parser_maybe_warn_enum_key (parser, key_loc, type, scoped_key); |
21393 | else |
21394 | { |
21395 | /* Diagnose class/struct/union mismatches. IS_DECLARATION is false |
21396 | for alias definition. */ |
21397 | bool decl_class = (is_declaration |
21398 | && cp_parser_declares_only_class_p (parser)); |
21399 | cp_parser_check_class_key (parser, key_loc, tag_type, type, false, |
21400 | decl_class); |
21401 | |
21402 | /* Indicate whether this class was declared as a `class' or as a |
21403 | `struct'. */ |
21404 | if (CLASS_TYPE_P (type) && !currently_open_class (type)) |
21405 | CLASSTYPE_DECLARED_CLASS (type) = (tag_type == class_type); |
21406 | } |
21407 | |
21408 | /* A "<" cannot follow an elaborated type specifier. If that |
21409 | happens, the user was probably trying to form a template-id. */ |
21410 | cp_parser_check_for_invalid_template_id (parser, type, tag_type, |
21411 | location: token->location); |
21412 | |
21413 | return type; |
21414 | } |
21415 | |
21416 | /* Parse an enum-specifier. |
21417 | |
21418 | enum-specifier: |
21419 | enum-head { enumerator-list [opt] } |
21420 | enum-head { enumerator-list , } [C++0x] |
21421 | |
21422 | enum-head: |
21423 | enum-key identifier [opt] enum-base [opt] |
21424 | enum-key nested-name-specifier identifier enum-base [opt] |
21425 | |
21426 | enum-key: |
21427 | enum |
21428 | enum class [C++0x] |
21429 | enum struct [C++0x] |
21430 | |
21431 | enum-base: [C++0x] |
21432 | : type-specifier-seq |
21433 | |
21434 | opaque-enum-specifier: |
21435 | enum-key identifier enum-base [opt] ; |
21436 | |
21437 | GNU Extensions: |
21438 | enum-key attributes[opt] identifier [opt] enum-base [opt] |
21439 | { enumerator-list [opt] }attributes[opt] |
21440 | enum-key attributes[opt] identifier [opt] enum-base [opt] |
21441 | { enumerator-list, }attributes[opt] [C++0x] |
21442 | |
21443 | Returns an ENUM_TYPE representing the enumeration, or NULL_TREE |
21444 | if the token stream isn't an enum-specifier after all. */ |
21445 | |
21446 | static tree |
21447 | cp_parser_enum_specifier (cp_parser* parser) |
21448 | { |
21449 | tree identifier; |
21450 | tree type = NULL_TREE; |
21451 | tree prev_scope; |
21452 | tree nested_name_specifier = NULL_TREE; |
21453 | tree attributes; |
21454 | bool scoped_enum_p = false; |
21455 | bool has_underlying_type = false; |
21456 | bool nested_being_defined = false; |
21457 | bool new_value_list = false; |
21458 | bool is_new_type = false; |
21459 | bool is_unnamed = false; |
21460 | tree underlying_type = NULL_TREE; |
21461 | cp_token *type_start_token = NULL; |
21462 | auto cleanup = make_temp_override (var&: parser->colon_corrects_to_scope_p, overrider: false); |
21463 | |
21464 | /* Parse tentatively so that we can back up if we don't find a |
21465 | enum-specifier. */ |
21466 | cp_parser_parse_tentatively (parser); |
21467 | |
21468 | /* Caller guarantees that the current token is 'enum', an identifier |
21469 | possibly follows, and the token after that is an opening brace. |
21470 | If we don't have an identifier, fabricate an anonymous name for |
21471 | the enumeration being defined. */ |
21472 | cp_lexer_consume_token (lexer: parser->lexer); |
21473 | |
21474 | /* Parse the "class" or "struct", which indicates a scoped |
21475 | enumeration type in C++0x. */ |
21476 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CLASS) |
21477 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STRUCT)) |
21478 | { |
21479 | if (cxx_dialect < cxx11) |
21480 | maybe_warn_cpp0x (str: CPP0X_SCOPED_ENUMS); |
21481 | |
21482 | /* Consume the `struct' or `class' token. */ |
21483 | cp_lexer_consume_token (lexer: parser->lexer); |
21484 | |
21485 | scoped_enum_p = true; |
21486 | } |
21487 | |
21488 | attributes = cp_parser_attributes_opt (parser); |
21489 | |
21490 | /* Clear the qualification. */ |
21491 | parser->scope = NULL_TREE; |
21492 | parser->qualifying_scope = NULL_TREE; |
21493 | parser->object_scope = NULL_TREE; |
21494 | |
21495 | /* Figure out in what scope the declaration is being placed. */ |
21496 | prev_scope = current_scope (); |
21497 | |
21498 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
21499 | |
21500 | push_deferring_access_checks (dk_no_check); |
21501 | nested_name_specifier |
21502 | = cp_parser_nested_name_specifier_opt (parser, |
21503 | /*typename_keyword_p=*/true, |
21504 | /*check_dependency_p=*/false, |
21505 | /*type_p=*/false, |
21506 | /*is_declaration=*/false); |
21507 | |
21508 | if (nested_name_specifier) |
21509 | { |
21510 | tree name; |
21511 | |
21512 | identifier = cp_parser_identifier (parser); |
21513 | name = cp_parser_lookup_name (parser, identifier, |
21514 | enum_type, |
21515 | /*is_template=*/false, |
21516 | /*is_namespace=*/false, |
21517 | /*check_dependency=*/true, |
21518 | /*ambiguous_decls=*/NULL, |
21519 | input_location); |
21520 | if (name && name != error_mark_node) |
21521 | { |
21522 | type = TREE_TYPE (name); |
21523 | if (TREE_CODE (type) == TYPENAME_TYPE) |
21524 | { |
21525 | /* Are template enums allowed in ISO? */ |
21526 | if (template_parm_scope_p ()) |
21527 | pedwarn (type_start_token->location, OPT_Wpedantic, |
21528 | "%qD is an enumeration template" , name); |
21529 | /* ignore a typename reference, for it will be solved by name |
21530 | in start_enum. */ |
21531 | type = NULL_TREE; |
21532 | } |
21533 | } |
21534 | else if (nested_name_specifier == error_mark_node) |
21535 | /* We already issued an error. */; |
21536 | else |
21537 | { |
21538 | error_at (type_start_token->location, |
21539 | "%qD does not name an enumeration in %qT" , |
21540 | identifier, nested_name_specifier); |
21541 | nested_name_specifier = error_mark_node; |
21542 | } |
21543 | } |
21544 | else |
21545 | { |
21546 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
21547 | identifier = cp_parser_identifier (parser); |
21548 | else |
21549 | { |
21550 | identifier = make_anon_name (); |
21551 | is_unnamed = true; |
21552 | if (scoped_enum_p) |
21553 | error_at (type_start_token->location, |
21554 | "unnamed scoped enum is not allowed" ); |
21555 | } |
21556 | } |
21557 | pop_deferring_access_checks (); |
21558 | |
21559 | /* Check for the `:' that denotes a specified underlying type in C++0x. |
21560 | Note that a ':' could also indicate a bitfield width, however. */ |
21561 | location_t colon_loc = UNKNOWN_LOCATION; |
21562 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
21563 | { |
21564 | cp_decl_specifier_seq type_specifiers; |
21565 | |
21566 | /* Consume the `:'. */ |
21567 | colon_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21568 | cp_lexer_consume_token (lexer: parser->lexer); |
21569 | |
21570 | auto tdf |
21571 | = make_temp_override (var&: parser->type_definition_forbidden_message, |
21572 | G_("types may not be defined in enum-base" )); |
21573 | |
21574 | /* Parse the type-specifier-seq. */ |
21575 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE, |
21576 | /*is_declaration=*/false, |
21577 | /*is_trailing_return=*/false, |
21578 | &type_specifiers); |
21579 | |
21580 | /* At this point this is surely not elaborated type specifier. */ |
21581 | if (!cp_parser_parse_definitely (parser)) |
21582 | return NULL_TREE; |
21583 | |
21584 | if (cxx_dialect < cxx11) |
21585 | maybe_warn_cpp0x (str: CPP0X_SCOPED_ENUMS); |
21586 | |
21587 | has_underlying_type = true; |
21588 | |
21589 | /* If that didn't work, stop. */ |
21590 | if (type_specifiers.type != error_mark_node) |
21591 | { |
21592 | underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME, |
21593 | /*initialized=*/0, NULL); |
21594 | if (underlying_type == error_mark_node |
21595 | || check_for_bare_parameter_packs (underlying_type)) |
21596 | underlying_type = NULL_TREE; |
21597 | } |
21598 | } |
21599 | |
21600 | /* Look for the `{' but don't consume it yet. */ |
21601 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
21602 | { |
21603 | if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type)) |
21604 | { |
21605 | if (has_underlying_type) |
21606 | cp_parser_commit_to_tentative_parse (parser); |
21607 | cp_parser_error (parser, gmsgid: "expected %<{%>" ); |
21608 | if (has_underlying_type) |
21609 | return error_mark_node; |
21610 | } |
21611 | /* An opaque-enum-specifier must have a ';' here. */ |
21612 | if ((scoped_enum_p || underlying_type) |
21613 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
21614 | { |
21615 | if (has_underlying_type) |
21616 | pedwarn (colon_loc, |
21617 | OPT_Welaborated_enum_base, |
21618 | "declaration of enumeration with " |
21619 | "fixed underlying type and no enumerator list is " |
21620 | "only permitted as a standalone declaration" ); |
21621 | else |
21622 | cp_parser_error (parser, gmsgid: "expected %<;%> or %<{%>" ); |
21623 | } |
21624 | } |
21625 | |
21626 | if (!has_underlying_type && !cp_parser_parse_definitely (parser)) |
21627 | return NULL_TREE; |
21628 | |
21629 | if (nested_name_specifier) |
21630 | { |
21631 | if (CLASS_TYPE_P (nested_name_specifier)) |
21632 | { |
21633 | nested_being_defined = TYPE_BEING_DEFINED (nested_name_specifier); |
21634 | TYPE_BEING_DEFINED (nested_name_specifier) = 1; |
21635 | push_scope (nested_name_specifier); |
21636 | } |
21637 | else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL) |
21638 | push_nested_namespace (nested_name_specifier); |
21639 | } |
21640 | |
21641 | /* Issue an error message if type-definitions are forbidden here. */ |
21642 | if (!cp_parser_check_type_definition (parser)) |
21643 | type = error_mark_node; |
21644 | else |
21645 | /* Create the new type. We do this before consuming the opening |
21646 | brace so the enum will be recorded as being on the line of its |
21647 | tag (or the 'enum' keyword, if there is no tag). */ |
21648 | type = start_enum (identifier, type, underlying_type, |
21649 | attributes, scoped_enum_p, &is_new_type); |
21650 | |
21651 | /* If the next token is not '{' it is an opaque-enum-specifier or an |
21652 | elaborated-type-specifier. */ |
21653 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
21654 | { |
21655 | auto_timevar tv (TV_PARSE_ENUM); |
21656 | |
21657 | if (nested_name_specifier |
21658 | && nested_name_specifier != error_mark_node) |
21659 | { |
21660 | /* The following catches invalid code such as: |
21661 | enum class S<int>::E { A, B, C }; */ |
21662 | if (!processing_specialization |
21663 | && CLASS_TYPE_P (nested_name_specifier) |
21664 | && CLASSTYPE_USE_TEMPLATE (nested_name_specifier)) |
21665 | error_at (type_start_token->location, "cannot add an enumerator " |
21666 | "list to a template instantiation" ); |
21667 | |
21668 | if (TREE_CODE (nested_name_specifier) == TYPENAME_TYPE) |
21669 | { |
21670 | error_at (type_start_token->location, |
21671 | "%<%T::%E%> has not been declared" , |
21672 | TYPE_CONTEXT (nested_name_specifier), |
21673 | nested_name_specifier); |
21674 | type = error_mark_node; |
21675 | } |
21676 | else if (TREE_CODE (nested_name_specifier) != NAMESPACE_DECL |
21677 | && !CLASS_TYPE_P (nested_name_specifier)) |
21678 | { |
21679 | error_at (type_start_token->location, "nested name specifier " |
21680 | "%qT for enum declaration does not name a class " |
21681 | "or namespace" , nested_name_specifier); |
21682 | type = error_mark_node; |
21683 | } |
21684 | /* If that scope does not contain the scope in which the |
21685 | class was originally declared, the program is invalid. */ |
21686 | else if (prev_scope && !is_ancestor (ancestor: prev_scope, |
21687 | descendant: nested_name_specifier)) |
21688 | { |
21689 | if (at_namespace_scope_p ()) |
21690 | error_at (type_start_token->location, |
21691 | "declaration of %qD in namespace %qD which does not " |
21692 | "enclose %qD" , |
21693 | type, prev_scope, nested_name_specifier); |
21694 | else |
21695 | error_at (type_start_token->location, |
21696 | "declaration of %qD in %qD which does not " |
21697 | "enclose %qD" , |
21698 | type, prev_scope, nested_name_specifier); |
21699 | type = error_mark_node; |
21700 | } |
21701 | /* If that scope is the scope where the declaration is being placed |
21702 | the program is invalid. */ |
21703 | else if (CLASS_TYPE_P (nested_name_specifier) |
21704 | && CLASS_TYPE_P (prev_scope) |
21705 | && same_type_p (nested_name_specifier, prev_scope)) |
21706 | { |
21707 | permerror (type_start_token->location, |
21708 | "extra qualification not allowed" ); |
21709 | nested_name_specifier = NULL_TREE; |
21710 | } |
21711 | } |
21712 | |
21713 | if (scoped_enum_p) |
21714 | begin_scope (sk_scoped_enum, type); |
21715 | |
21716 | /* Consume the opening brace. */ |
21717 | matching_braces braces; |
21718 | braces.consume_open (parser); |
21719 | |
21720 | if (type == error_mark_node) |
21721 | ; /* Nothing to add */ |
21722 | else if (OPAQUE_ENUM_P (type) |
21723 | || (cxx_dialect > cxx98 && processing_specialization)) |
21724 | { |
21725 | new_value_list = true; |
21726 | SET_OPAQUE_ENUM_P (type, false); |
21727 | DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; |
21728 | } |
21729 | else |
21730 | { |
21731 | error_at (type_start_token->location, |
21732 | "multiple definition of %q#T" , type); |
21733 | inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)), |
21734 | "previous definition here" ); |
21735 | type = error_mark_node; |
21736 | } |
21737 | |
21738 | if (type == error_mark_node) |
21739 | cp_parser_skip_to_end_of_block_or_statement (parser); |
21740 | /* If the next token is not '}', then there are some enumerators. */ |
21741 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
21742 | { |
21743 | if (is_unnamed && !scoped_enum_p |
21744 | /* Don't warn for enum {} a; here. */ |
21745 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SEMICOLON)) |
21746 | pedwarn (type_start_token->location, OPT_Wpedantic, |
21747 | "ISO C++ forbids empty unnamed enum" ); |
21748 | } |
21749 | else |
21750 | { |
21751 | /* We've seen a '{' so we know we're in an enum-specifier. |
21752 | Commit to any tentative parse to get syntax errors. */ |
21753 | cp_parser_commit_to_tentative_parse (parser); |
21754 | cp_parser_enumerator_list (parser, type); |
21755 | } |
21756 | |
21757 | /* Consume the final '}'. */ |
21758 | braces.require_close (parser); |
21759 | |
21760 | if (scoped_enum_p) |
21761 | finish_scope (); |
21762 | } |
21763 | else |
21764 | { |
21765 | /* If a ';' follows, then it is an opaque-enum-specifier |
21766 | and additional restrictions apply. */ |
21767 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
21768 | { |
21769 | if (is_unnamed) |
21770 | error_at (type_start_token->location, |
21771 | "opaque-enum-specifier without name" ); |
21772 | else if (nested_name_specifier) |
21773 | error_at (type_start_token->location, |
21774 | "opaque-enum-specifier must use a simple identifier" ); |
21775 | } |
21776 | } |
21777 | |
21778 | /* Look for trailing attributes to apply to this enumeration, and |
21779 | apply them if appropriate. */ |
21780 | if (cp_parser_allow_gnu_extensions_p (parser)) |
21781 | { |
21782 | tree trailing_attr = cp_parser_gnu_attributes_opt (parser); |
21783 | cplus_decl_attributes (&type, |
21784 | trailing_attr, |
21785 | (int) ATTR_FLAG_TYPE_IN_PLACE); |
21786 | } |
21787 | |
21788 | /* Finish up the enumeration. */ |
21789 | if (type != error_mark_node) |
21790 | { |
21791 | if (new_value_list) |
21792 | finish_enum_value_list (type); |
21793 | if (is_new_type) |
21794 | finish_enum (type); |
21795 | } |
21796 | |
21797 | if (nested_name_specifier) |
21798 | { |
21799 | if (CLASS_TYPE_P (nested_name_specifier)) |
21800 | { |
21801 | TYPE_BEING_DEFINED (nested_name_specifier) = nested_being_defined; |
21802 | pop_scope (nested_name_specifier); |
21803 | } |
21804 | else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL) |
21805 | pop_nested_namespace (nested_name_specifier); |
21806 | } |
21807 | return type; |
21808 | } |
21809 | |
21810 | /* Parse an enumerator-list. The enumerators all have the indicated |
21811 | TYPE. |
21812 | |
21813 | enumerator-list: |
21814 | enumerator-definition |
21815 | enumerator-list , enumerator-definition */ |
21816 | |
21817 | static void |
21818 | cp_parser_enumerator_list (cp_parser* parser, tree type) |
21819 | { |
21820 | while (true) |
21821 | { |
21822 | /* Parse an enumerator-definition. */ |
21823 | cp_parser_enumerator_definition (parser, type); |
21824 | |
21825 | /* If the next token is not a ',', we've reached the end of |
21826 | the list. */ |
21827 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
21828 | break; |
21829 | /* Otherwise, consume the `,' and keep going. */ |
21830 | cp_lexer_consume_token (lexer: parser->lexer); |
21831 | /* If the next token is a `}', there is a trailing comma. */ |
21832 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
21833 | { |
21834 | if (cxx_dialect < cxx11) |
21835 | pedwarn (input_location, OPT_Wpedantic, |
21836 | "comma at end of enumerator list" ); |
21837 | break; |
21838 | } |
21839 | } |
21840 | } |
21841 | |
21842 | /* Parse an enumerator-definition. The enumerator has the indicated |
21843 | TYPE. |
21844 | |
21845 | enumerator-definition: |
21846 | enumerator |
21847 | enumerator = constant-expression |
21848 | |
21849 | enumerator: |
21850 | identifier |
21851 | |
21852 | GNU Extensions: |
21853 | |
21854 | enumerator-definition: |
21855 | enumerator attributes [opt] |
21856 | enumerator attributes [opt] = constant-expression */ |
21857 | |
21858 | static void |
21859 | cp_parser_enumerator_definition (cp_parser* parser, tree type) |
21860 | { |
21861 | tree identifier; |
21862 | tree value; |
21863 | location_t loc; |
21864 | |
21865 | /* Save the input location because we are interested in the location |
21866 | of the identifier and not the location of the explicit value. */ |
21867 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21868 | |
21869 | /* Look for the identifier. */ |
21870 | identifier = cp_parser_identifier (parser); |
21871 | if (identifier == error_mark_node) |
21872 | return; |
21873 | |
21874 | /* Parse any specified attributes. */ |
21875 | tree attrs = cp_parser_attributes_opt (parser); |
21876 | |
21877 | /* If the next token is an '=', then there is an explicit value. */ |
21878 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
21879 | { |
21880 | /* Consume the `=' token. */ |
21881 | cp_lexer_consume_token (lexer: parser->lexer); |
21882 | /* Parse the value. */ |
21883 | value = cp_parser_constant_expression (parser); |
21884 | } |
21885 | else |
21886 | value = NULL_TREE; |
21887 | |
21888 | /* If we are processing a template, make sure the initializer of the |
21889 | enumerator doesn't contain any bare template parameter pack. */ |
21890 | if (current_lambda_expr ()) |
21891 | { |
21892 | /* In a lambda it should work, but doesn't currently. */ |
21893 | if (uses_parameter_packs (value)) |
21894 | { |
21895 | sorry ("unexpanded parameter pack in enumerator in lambda" ); |
21896 | value = error_mark_node; |
21897 | } |
21898 | } |
21899 | else if (check_for_bare_parameter_packs (value)) |
21900 | value = error_mark_node; |
21901 | |
21902 | /* Create the enumerator. */ |
21903 | build_enumerator (identifier, value, type, attrs, loc); |
21904 | } |
21905 | |
21906 | /* Parse a namespace-name. |
21907 | |
21908 | namespace-name: |
21909 | original-namespace-name |
21910 | namespace-alias |
21911 | |
21912 | Returns the NAMESPACE_DECL for the namespace. */ |
21913 | |
21914 | static tree |
21915 | cp_parser_namespace_name (cp_parser* parser) |
21916 | { |
21917 | tree identifier; |
21918 | tree namespace_decl; |
21919 | |
21920 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
21921 | |
21922 | /* Get the name of the namespace. */ |
21923 | identifier = cp_parser_identifier (parser); |
21924 | if (identifier == error_mark_node) |
21925 | return error_mark_node; |
21926 | |
21927 | /* Look up the identifier in the currently active scope. Look only |
21928 | for namespaces, due to: |
21929 | |
21930 | [basic.lookup.udir] |
21931 | |
21932 | When looking up a namespace-name in a using-directive or alias |
21933 | definition, only namespace names are considered. |
21934 | |
21935 | And: |
21936 | |
21937 | [basic.lookup.qual] |
21938 | |
21939 | During the lookup of a name preceding the :: scope resolution |
21940 | operator, object, function, and enumerator names are ignored. |
21941 | |
21942 | (Note that cp_parser_qualifying_entity only calls this |
21943 | function if the token after the name is the scope resolution |
21944 | operator.) */ |
21945 | namespace_decl = cp_parser_lookup_name (parser, identifier, |
21946 | none_type, |
21947 | /*is_template=*/false, |
21948 | /*is_namespace=*/true, |
21949 | /*check_dependency=*/true, |
21950 | /*ambiguous_decls=*/NULL, |
21951 | token->location); |
21952 | /* If it's not a namespace, issue an error. */ |
21953 | if (namespace_decl == error_mark_node |
21954 | || TREE_CODE (namespace_decl) != NAMESPACE_DECL) |
21955 | { |
21956 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
21957 | { |
21958 | auto_diagnostic_group d; |
21959 | name_hint hint; |
21960 | if (namespace_decl == error_mark_node |
21961 | && parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL) |
21962 | hint = suggest_alternative_in_explicit_scope (token->location, |
21963 | identifier, |
21964 | parser->scope); |
21965 | if (const char *suggestion = hint.suggestion ()) |
21966 | { |
21967 | gcc_rich_location richloc (token->location); |
21968 | richloc.add_fixit_replace (new_content: suggestion); |
21969 | error_at (&richloc, |
21970 | "%qD is not a namespace-name; did you mean %qs?" , |
21971 | identifier, suggestion); |
21972 | } |
21973 | else |
21974 | error_at (token->location, "%qD is not a namespace-name" , |
21975 | identifier); |
21976 | } |
21977 | else |
21978 | cp_parser_error (parser, gmsgid: "expected namespace-name" ); |
21979 | namespace_decl = error_mark_node; |
21980 | } |
21981 | |
21982 | return namespace_decl; |
21983 | } |
21984 | |
21985 | /* Parse a namespace-definition. |
21986 | |
21987 | namespace-definition: |
21988 | named-namespace-definition |
21989 | unnamed-namespace-definition |
21990 | |
21991 | named-namespace-definition: |
21992 | original-namespace-definition |
21993 | extension-namespace-definition |
21994 | |
21995 | original-namespace-definition: |
21996 | namespace identifier { namespace-body } |
21997 | |
21998 | extension-namespace-definition: |
21999 | namespace original-namespace-name { namespace-body } |
22000 | |
22001 | unnamed-namespace-definition: |
22002 | namespace { namespace-body } */ |
22003 | |
22004 | static void |
22005 | cp_parser_namespace_definition (cp_parser* parser) |
22006 | { |
22007 | tree identifier; |
22008 | int nested_definition_count = 0; |
22009 | |
22010 | cp_ensure_no_omp_declare_simd (parser); |
22011 | cp_ensure_no_oacc_routine (parser); |
22012 | |
22013 | bool is_inline = cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_INLINE); |
22014 | const bool topmost_inline_p = is_inline; |
22015 | |
22016 | if (is_inline) |
22017 | { |
22018 | maybe_warn_cpp0x (str: CPP0X_INLINE_NAMESPACES); |
22019 | cp_lexer_consume_token (lexer: parser->lexer); |
22020 | } |
22021 | |
22022 | /* Look for the `namespace' keyword. */ |
22023 | cp_token* token |
22024 | = cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
22025 | |
22026 | /* Parse any specified attributes before the identifier. */ |
22027 | tree attribs = cp_parser_attributes_opt (parser); |
22028 | |
22029 | for (;;) |
22030 | { |
22031 | identifier = NULL_TREE; |
22032 | |
22033 | bool nested_inline_p = cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
22034 | keyword: RID_INLINE); |
22035 | if (nested_inline_p && nested_definition_count != 0) |
22036 | { |
22037 | if (pedantic && cxx_dialect < cxx20) |
22038 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
22039 | OPT_Wc__20_extensions, "nested inline namespace " |
22040 | "definitions only available with %<-std=c++20%> or " |
22041 | "%<-std=gnu++20%>" ); |
22042 | cp_lexer_consume_token (lexer: parser->lexer); |
22043 | } |
22044 | |
22045 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
22046 | { |
22047 | identifier = cp_parser_identifier (parser); |
22048 | |
22049 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
22050 | pedwarn (input_location, OPT_Wpedantic, |
22051 | "standard attributes on namespaces must precede " |
22052 | "the namespace name" ); |
22053 | |
22054 | /* Parse any attributes specified after the identifier. */ |
22055 | attribs = attr_chainon (attrs: attribs, attr: cp_parser_attributes_opt (parser)); |
22056 | } |
22057 | |
22058 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SCOPE)) |
22059 | { |
22060 | /* Don't forget that the innermost namespace might have been |
22061 | marked as inline. Use |= because we cannot overwrite |
22062 | IS_INLINE in case the outermost namespace is inline, but |
22063 | there are no nested inlines. */ |
22064 | is_inline |= nested_inline_p; |
22065 | break; |
22066 | } |
22067 | |
22068 | if (!nested_definition_count && pedantic && cxx_dialect < cxx17) |
22069 | pedwarn (input_location, OPT_Wc__17_extensions, |
22070 | "nested namespace definitions only available with " |
22071 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
22072 | |
22073 | /* Nested namespace names can create new namespaces (unlike |
22074 | other qualified-ids). */ |
22075 | if (int count = (identifier |
22076 | ? push_namespace (identifier, make_inline: nested_inline_p) |
22077 | : 0)) |
22078 | nested_definition_count += count; |
22079 | else |
22080 | cp_parser_error (parser, gmsgid: "nested namespace name required" ); |
22081 | cp_lexer_consume_token (lexer: parser->lexer); |
22082 | } |
22083 | |
22084 | if (nested_definition_count && !identifier) |
22085 | cp_parser_error (parser, gmsgid: "namespace name required" ); |
22086 | |
22087 | if (nested_definition_count && attribs) |
22088 | error_at (token->location, |
22089 | "a nested namespace definition cannot have attributes" ); |
22090 | if (nested_definition_count && topmost_inline_p) |
22091 | error_at (token->location, |
22092 | "a nested namespace definition cannot be inline" ); |
22093 | |
22094 | /* Start the namespace. */ |
22095 | nested_definition_count += push_namespace (identifier, make_inline: is_inline); |
22096 | |
22097 | bool has_visibility = handle_namespace_attrs (current_namespace, attribs); |
22098 | |
22099 | warning (OPT_Wnamespaces, "namespace %qD entered" , current_namespace); |
22100 | |
22101 | /* Look for the `{' to validate starting the namespace. */ |
22102 | matching_braces braces; |
22103 | if (braces.require_open (parser)) |
22104 | { |
22105 | /* Parse the body of the namespace. */ |
22106 | cp_parser_namespace_body (parser); |
22107 | |
22108 | /* Look for the final `}'. */ |
22109 | braces.require_close (parser); |
22110 | } |
22111 | |
22112 | if (has_visibility) |
22113 | pop_visibility (1); |
22114 | |
22115 | /* Pop the nested namespace definitions. */ |
22116 | while (nested_definition_count--) |
22117 | pop_namespace (); |
22118 | } |
22119 | |
22120 | /* Parse a namespace-body. |
22121 | |
22122 | namespace-body: |
22123 | declaration-seq [opt] */ |
22124 | |
22125 | static void |
22126 | cp_parser_namespace_body (cp_parser* parser) |
22127 | { |
22128 | cp_parser_declaration_seq_opt (parser); |
22129 | } |
22130 | |
22131 | /* Parse a namespace-alias-definition. |
22132 | |
22133 | namespace-alias-definition: |
22134 | namespace identifier = qualified-namespace-specifier ; */ |
22135 | |
22136 | static void |
22137 | cp_parser_namespace_alias_definition (cp_parser* parser) |
22138 | { |
22139 | tree identifier; |
22140 | tree namespace_specifier; |
22141 | |
22142 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
22143 | |
22144 | /* Look for the `namespace' keyword. */ |
22145 | cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
22146 | /* Look for the identifier. */ |
22147 | identifier = cp_parser_identifier (parser); |
22148 | if (identifier == error_mark_node) |
22149 | return; |
22150 | /* Look for the `=' token. */ |
22151 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser) |
22152 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
22153 | { |
22154 | error_at (token->location, "%<namespace%> definition is not allowed here" ); |
22155 | /* Skip the definition. */ |
22156 | cp_lexer_consume_token (lexer: parser->lexer); |
22157 | if (cp_parser_skip_to_closing_brace (parser)) |
22158 | cp_lexer_consume_token (lexer: parser->lexer); |
22159 | return; |
22160 | } |
22161 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
22162 | /* Look for the qualified-namespace-specifier. */ |
22163 | namespace_specifier |
22164 | = cp_parser_qualified_namespace_specifier (parser); |
22165 | cp_warn_deprecated_use_scopes (namespace_specifier); |
22166 | /* Look for the `;' token. */ |
22167 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22168 | |
22169 | /* Register the alias in the symbol table. */ |
22170 | do_namespace_alias (identifier, namespace_specifier); |
22171 | } |
22172 | |
22173 | /* Parse a qualified-namespace-specifier. |
22174 | |
22175 | qualified-namespace-specifier: |
22176 | :: [opt] nested-name-specifier [opt] namespace-name |
22177 | |
22178 | Returns a NAMESPACE_DECL corresponding to the specified |
22179 | namespace. */ |
22180 | |
22181 | static tree |
22182 | cp_parser_qualified_namespace_specifier (cp_parser* parser) |
22183 | { |
22184 | /* Look for the optional `::'. */ |
22185 | cp_parser_global_scope_opt (parser, |
22186 | /*current_scope_valid_p=*/false); |
22187 | |
22188 | /* Look for the optional nested-name-specifier. */ |
22189 | cp_parser_nested_name_specifier_opt (parser, |
22190 | /*typename_keyword_p=*/false, |
22191 | /*check_dependency_p=*/true, |
22192 | /*type_p=*/false, |
22193 | /*is_declaration=*/true); |
22194 | |
22195 | return cp_parser_namespace_name (parser); |
22196 | } |
22197 | |
22198 | /* Subroutine of cp_parser_using_declaration. */ |
22199 | |
22200 | static tree |
22201 | finish_using_decl (tree qscope, tree identifier, bool typename_p = false) |
22202 | { |
22203 | tree decl = NULL_TREE; |
22204 | if (at_class_scope_p ()) |
22205 | { |
22206 | /* Create the USING_DECL. */ |
22207 | decl = do_class_using_decl (qscope, identifier); |
22208 | |
22209 | if (check_for_bare_parameter_packs (decl)) |
22210 | return error_mark_node; |
22211 | |
22212 | if (decl && typename_p) |
22213 | USING_DECL_TYPENAME_P (decl) = 1; |
22214 | |
22215 | /* Add it to the list of members in this class. */ |
22216 | finish_member_declaration (decl); |
22217 | } |
22218 | else |
22219 | finish_nonmember_using_decl (scope: qscope, name: identifier); |
22220 | return decl; |
22221 | } |
22222 | |
22223 | /* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an |
22224 | access declaration. |
22225 | |
22226 | using-declaration: |
22227 | using typename [opt] :: [opt] nested-name-specifier unqualified-id ; |
22228 | using :: unqualified-id ; |
22229 | |
22230 | access-declaration: |
22231 | qualified-id ; |
22232 | |
22233 | */ |
22234 | |
22235 | static bool |
22236 | cp_parser_using_declaration (cp_parser* parser, |
22237 | bool access_declaration_p) |
22238 | { |
22239 | cp_token *token; |
22240 | bool typename_p = false; |
22241 | bool global_scope_p; |
22242 | tree identifier; |
22243 | tree qscope; |
22244 | int oldcount = errorcount; |
22245 | cp_token *diag_token = NULL; |
22246 | |
22247 | if (access_declaration_p) |
22248 | { |
22249 | diag_token = cp_lexer_peek_token (lexer: parser->lexer); |
22250 | cp_parser_parse_tentatively (parser); |
22251 | } |
22252 | else |
22253 | { |
22254 | /* Look for the `using' keyword. */ |
22255 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22256 | |
22257 | again: |
22258 | /* Peek at the next token. */ |
22259 | token = cp_lexer_peek_token (lexer: parser->lexer); |
22260 | /* See if it's `typename'. */ |
22261 | if (token->keyword == RID_TYPENAME) |
22262 | { |
22263 | /* Remember that we've seen it. */ |
22264 | typename_p = true; |
22265 | /* Consume the `typename' token. */ |
22266 | cp_lexer_consume_token (lexer: parser->lexer); |
22267 | } |
22268 | } |
22269 | |
22270 | /* Look for the optional global scope qualification. */ |
22271 | global_scope_p |
22272 | = (cp_parser_global_scope_opt (parser, |
22273 | /*current_scope_valid_p=*/false) |
22274 | != NULL_TREE); |
22275 | |
22276 | /* If we saw `typename', or didn't see `::', then there must be a |
22277 | nested-name-specifier present. */ |
22278 | if (typename_p || !global_scope_p) |
22279 | { |
22280 | qscope = cp_parser_nested_name_specifier (parser, typename_keyword_p: typename_p, |
22281 | /*check_dependency_p=*/true, |
22282 | /*type_p=*/false, |
22283 | /*is_declaration=*/true); |
22284 | if (!qscope && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
22285 | { |
22286 | cp_parser_skip_to_end_of_block_or_statement (parser); |
22287 | return false; |
22288 | } |
22289 | } |
22290 | /* Otherwise, we could be in either of the two productions. In that |
22291 | case, treat the nested-name-specifier as optional. */ |
22292 | else |
22293 | qscope = cp_parser_nested_name_specifier_opt (parser, |
22294 | /*typename_keyword_p=*/false, |
22295 | /*check_dependency_p=*/true, |
22296 | /*type_p=*/false, |
22297 | /*is_declaration=*/true); |
22298 | if (!qscope) |
22299 | qscope = global_namespace; |
22300 | |
22301 | cp_warn_deprecated_use_scopes (qscope); |
22302 | |
22303 | if (access_declaration_p |
22304 | && !MAYBE_CLASS_TYPE_P (qscope) |
22305 | && TREE_CODE (qscope) != ENUMERAL_TYPE) |
22306 | /* If the qualifying scope of an access-declaration isn't a class |
22307 | or enumeration type then it can't be valid. */ |
22308 | cp_parser_simulate_error (parser); |
22309 | |
22310 | if (access_declaration_p && cp_parser_error_occurred (parser)) |
22311 | /* Something has already gone wrong; there's no need to parse |
22312 | further. Since an error has occurred, the return value of |
22313 | cp_parser_parse_definitely will be false, as required. */ |
22314 | return cp_parser_parse_definitely (parser); |
22315 | |
22316 | token = cp_lexer_peek_token (lexer: parser->lexer); |
22317 | /* Parse the unqualified-id. */ |
22318 | identifier = cp_parser_unqualified_id (parser, |
22319 | /*template_keyword_p=*/false, |
22320 | /*check_dependency_p=*/true, |
22321 | /*declarator_p=*/true, |
22322 | /*optional_p=*/false); |
22323 | |
22324 | if (access_declaration_p) |
22325 | { |
22326 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
22327 | cp_parser_simulate_error (parser); |
22328 | if (!cp_parser_parse_definitely (parser)) |
22329 | return false; |
22330 | } |
22331 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
22332 | { |
22333 | cp_token *ell = cp_lexer_consume_token (lexer: parser->lexer); |
22334 | if (cxx_dialect < cxx17) |
22335 | pedwarn (ell->location, OPT_Wc__17_extensions, |
22336 | "pack expansion in using-declaration only available " |
22337 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
22338 | |
22339 | /* A parameter pack can appear in the qualifying scope, and/or in the |
22340 | terminal name (if naming a conversion function). Logically they're |
22341 | part of a single pack expansion of the overall USING_DECL, but we |
22342 | express them as separate pack expansions within the USING_DECL since |
22343 | we can't create a pack expansion over a USING_DECL. */ |
22344 | bool saw_parm_pack = false; |
22345 | if (uses_parameter_packs (qscope)) |
22346 | { |
22347 | qscope = make_pack_expansion (qscope); |
22348 | saw_parm_pack = true; |
22349 | } |
22350 | if (identifier_p (t: identifier) |
22351 | && IDENTIFIER_CONV_OP_P (identifier) |
22352 | && uses_parameter_packs (TREE_TYPE (identifier))) |
22353 | { |
22354 | identifier = make_conv_op_name (make_pack_expansion |
22355 | (TREE_TYPE (identifier))); |
22356 | saw_parm_pack = true; |
22357 | } |
22358 | if (!saw_parm_pack) |
22359 | { |
22360 | /* Issue an error in terms using a SCOPE_REF that includes both |
22361 | components. */ |
22362 | tree name |
22363 | = build_qualified_name (NULL_TREE, qscope, identifier, false); |
22364 | make_pack_expansion (name); |
22365 | gcc_assert (seen_error ()); |
22366 | qscope = identifier = error_mark_node; |
22367 | } |
22368 | } |
22369 | |
22370 | /* The function we call to handle a using-declaration is different |
22371 | depending on what scope we are in. */ |
22372 | if (qscope == error_mark_node || identifier == error_mark_node) |
22373 | ; |
22374 | else if (!identifier_p (t: identifier) |
22375 | && TREE_CODE (identifier) != BIT_NOT_EXPR) |
22376 | /* [namespace.udecl] |
22377 | |
22378 | A using declaration shall not name a template-id. */ |
22379 | error_at (token->location, |
22380 | "a template-id may not appear in a using-declaration" ); |
22381 | else |
22382 | { |
22383 | tree decl = finish_using_decl (qscope, identifier, typename_p); |
22384 | |
22385 | if (decl == error_mark_node) |
22386 | { |
22387 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22388 | return false; |
22389 | } |
22390 | } |
22391 | |
22392 | if (!access_declaration_p |
22393 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
22394 | { |
22395 | cp_token *comma = cp_lexer_consume_token (lexer: parser->lexer); |
22396 | if (cxx_dialect < cxx17) |
22397 | pedwarn (comma->location, OPT_Wc__17_extensions, |
22398 | "comma-separated list in using-declaration only available " |
22399 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
22400 | goto again; |
22401 | } |
22402 | |
22403 | /* Look for the final `;'. */ |
22404 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22405 | |
22406 | if (access_declaration_p && errorcount == oldcount) |
22407 | warning_at (diag_token->location, OPT_Wdeprecated, |
22408 | "access declarations are deprecated " |
22409 | "in favor of using-declarations; " |
22410 | "suggestion: add the %<using%> keyword" ); |
22411 | |
22412 | return true; |
22413 | } |
22414 | |
22415 | /* C++20 using enum declaration. |
22416 | |
22417 | using-enum-declaration : |
22418 | using elaborated-enum-specifier ; */ |
22419 | |
22420 | static void |
22421 | cp_parser_using_enum (cp_parser *parser) |
22422 | { |
22423 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22424 | |
22425 | /* Using cp_parser_elaborated_type_specifier rejects typedef-names, which |
22426 | breaks one of the motivating examples in using-enum-5.C. |
22427 | cp_parser_simple_type_specifier seems to be closer to what we actually |
22428 | want, though that hasn't been properly specified yet. */ |
22429 | |
22430 | /* Consume 'enum'. */ |
22431 | gcc_checking_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM)); |
22432 | cp_lexer_consume_token (lexer: parser->lexer); |
22433 | |
22434 | cp_token *start = cp_lexer_peek_token (lexer: parser->lexer); |
22435 | |
22436 | tree type = (cp_parser_simple_type_specifier |
22437 | (parser, NULL, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
22438 | |
22439 | cp_token *end = cp_lexer_previous_token (lexer: parser->lexer); |
22440 | |
22441 | if (type == error_mark_node |
22442 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
22443 | { |
22444 | cp_parser_skip_to_end_of_block_or_statement (parser); |
22445 | return; |
22446 | } |
22447 | if (TREE_CODE (type) == TYPE_DECL) |
22448 | type = TREE_TYPE (type); |
22449 | |
22450 | /* The elaborated-enum-specifier shall not name a dependent type and the type |
22451 | shall have a reachable enum-specifier. */ |
22452 | const char *msg = nullptr; |
22453 | if (cxx_dialect < cxx20) |
22454 | msg = G_("%<using enum%> " |
22455 | "only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
22456 | else if (dependent_type_p (type)) |
22457 | msg = G_("%<using enum%> of dependent type %qT" ); |
22458 | else if (TREE_CODE (type) != ENUMERAL_TYPE) |
22459 | msg = G_("%<using enum%> of non-enumeration type %q#T" ); |
22460 | else if (!COMPLETE_TYPE_P (type)) |
22461 | msg = G_("%<using enum%> of incomplete type %qT" ); |
22462 | else if (OPAQUE_ENUM_P (type)) |
22463 | msg = G_("%<using enum%> of %qT before its enum-specifier" ); |
22464 | if (msg) |
22465 | { |
22466 | location_t loc = make_location (caret: start, start, end); |
22467 | auto_diagnostic_group g; |
22468 | error_at (loc, msg, type); |
22469 | loc = location_of (type); |
22470 | if (cxx_dialect < cxx20 || loc == input_location) |
22471 | ; |
22472 | else if (OPAQUE_ENUM_P (type)) |
22473 | inform (loc, "opaque-enum-declaration here" ); |
22474 | else |
22475 | inform (loc, "declared here" ); |
22476 | } |
22477 | |
22478 | /* A using-enum-declaration introduces the enumerator names of the named |
22479 | enumeration as if by a using-declaration for each enumerator. */ |
22480 | if (TREE_CODE (type) == ENUMERAL_TYPE) |
22481 | for (tree v = TYPE_VALUES (type); v; v = TREE_CHAIN (v)) |
22482 | finish_using_decl (qscope: type, DECL_NAME (TREE_VALUE (v))); |
22483 | } |
22484 | |
22485 | /* Parse an alias-declaration. |
22486 | |
22487 | alias-declaration: |
22488 | using identifier attribute-specifier-seq [opt] = type-id */ |
22489 | |
22490 | static tree |
22491 | cp_parser_alias_declaration (cp_parser* parser) |
22492 | { |
22493 | tree id, type, decl, pushed_scope = NULL_TREE, attributes; |
22494 | location_t id_location, type_location; |
22495 | cp_declarator *declarator; |
22496 | cp_decl_specifier_seq decl_specs; |
22497 | bool member_p; |
22498 | const char *saved_message = NULL; |
22499 | |
22500 | /* Look for the `using' keyword. */ |
22501 | cp_token *using_token |
22502 | = cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22503 | if (using_token == NULL) |
22504 | return error_mark_node; |
22505 | |
22506 | id_location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
22507 | id = cp_parser_identifier (parser); |
22508 | if (id == error_mark_node) |
22509 | return error_mark_node; |
22510 | |
22511 | cp_token *attrs_token = cp_lexer_peek_token (lexer: parser->lexer); |
22512 | attributes = cp_parser_attributes_opt (parser); |
22513 | if (attributes == error_mark_node) |
22514 | return error_mark_node; |
22515 | |
22516 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
22517 | |
22518 | if (cp_parser_error_occurred (parser)) |
22519 | return error_mark_node; |
22520 | |
22521 | cp_parser_commit_to_tentative_parse (parser); |
22522 | |
22523 | /* Now we are going to parse the type-id of the declaration. */ |
22524 | |
22525 | /* |
22526 | [dcl.type]/3 says: |
22527 | |
22528 | "A type-specifier-seq shall not define a class or enumeration |
22529 | unless it appears in the type-id of an alias-declaration (7.1.3) that |
22530 | is not the declaration of a template-declaration." |
22531 | |
22532 | In other words, if we currently are in an alias template, the |
22533 | type-id should not define a type. |
22534 | |
22535 | So let's set parser->type_definition_forbidden_message in that |
22536 | case; cp_parser_check_type_definition (called by |
22537 | cp_parser_class_specifier) will then emit an error if a type is |
22538 | defined in the type-id. */ |
22539 | if (parser->num_template_parameter_lists) |
22540 | { |
22541 | saved_message = parser->type_definition_forbidden_message; |
22542 | parser->type_definition_forbidden_message = |
22543 | G_("types may not be defined in alias template declarations" ); |
22544 | } |
22545 | |
22546 | type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
22547 | &type_location); |
22548 | |
22549 | /* Restore the error message if need be. */ |
22550 | if (parser->num_template_parameter_lists) |
22551 | parser->type_definition_forbidden_message = saved_message; |
22552 | |
22553 | if (type == error_mark_node |
22554 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
22555 | { |
22556 | cp_parser_skip_to_end_of_block_or_statement (parser); |
22557 | return error_mark_node; |
22558 | } |
22559 | |
22560 | /* A typedef-name can also be introduced by an alias-declaration. The |
22561 | identifier following the using keyword becomes a typedef-name. It has |
22562 | the same semantics as if it were introduced by the typedef |
22563 | specifier. In particular, it does not define a new type and it shall |
22564 | not appear in the type-id. */ |
22565 | |
22566 | clear_decl_specs (decl_specs: &decl_specs); |
22567 | decl_specs.type = type; |
22568 | if (attributes != NULL_TREE) |
22569 | { |
22570 | decl_specs.attributes = attributes; |
22571 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22572 | ds: ds_attribute, |
22573 | attrs_token); |
22574 | } |
22575 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22576 | ds: ds_typedef, |
22577 | using_token); |
22578 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22579 | ds: ds_alias, |
22580 | using_token); |
22581 | decl_specs.locations[ds_type_spec] = type_location; |
22582 | |
22583 | if (parser->num_template_parameter_lists |
22584 | && !cp_parser_check_template_parameters (parser, |
22585 | /*num_templates=*/0, |
22586 | /*template_id*/false, |
22587 | id_location, |
22588 | /*declarator=*/NULL)) |
22589 | return error_mark_node; |
22590 | |
22591 | declarator = make_id_declarator (NULL_TREE, unqualified_name: id, sfk: sfk_none, id_location); |
22592 | |
22593 | member_p = at_class_scope_p (); |
22594 | if (member_p) |
22595 | decl = grokfield (declarator, &decl_specs, NULL_TREE, false, |
22596 | NULL_TREE, attributes); |
22597 | else |
22598 | decl = start_decl (declarator, &decl_specs, 0, |
22599 | attributes, NULL_TREE, &pushed_scope); |
22600 | if (decl == error_mark_node) |
22601 | return decl; |
22602 | |
22603 | cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0); |
22604 | |
22605 | if (pushed_scope) |
22606 | pop_scope (pushed_scope); |
22607 | |
22608 | /* If decl is a template, return its TEMPLATE_DECL so that it gets |
22609 | added into the symbol table; otherwise, return the TYPE_DECL. */ |
22610 | if (DECL_LANG_SPECIFIC (decl) |
22611 | && DECL_TEMPLATE_INFO (decl) |
22612 | && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) |
22613 | { |
22614 | decl = DECL_TI_TEMPLATE (decl); |
22615 | if (member_p) |
22616 | check_member_template (decl); |
22617 | } |
22618 | |
22619 | return decl; |
22620 | } |
22621 | |
22622 | /* Parse a using-directive. |
22623 | |
22624 | using-directive: |
22625 | attribute-specifier-seq [opt] using namespace :: [opt] |
22626 | nested-name-specifier [opt] namespace-name ; */ |
22627 | |
22628 | static void |
22629 | cp_parser_using_directive (cp_parser* parser) |
22630 | { |
22631 | tree namespace_decl; |
22632 | tree attribs = cp_parser_std_attribute_spec_seq (parser); |
22633 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
22634 | { |
22635 | /* Error during attribute parsing that resulted in skipping |
22636 | to next semicolon. */ |
22637 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22638 | return; |
22639 | } |
22640 | |
22641 | /* Look for the `using' keyword. */ |
22642 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22643 | /* And the `namespace' keyword. */ |
22644 | cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
22645 | /* Look for the optional `::' operator. */ |
22646 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
22647 | /* And the optional nested-name-specifier. */ |
22648 | cp_parser_nested_name_specifier_opt (parser, |
22649 | /*typename_keyword_p=*/false, |
22650 | /*check_dependency_p=*/true, |
22651 | /*type_p=*/false, |
22652 | /*is_declaration=*/true); |
22653 | /* Get the namespace being used. */ |
22654 | namespace_decl = cp_parser_namespace_name (parser); |
22655 | cp_warn_deprecated_use_scopes (namespace_decl); |
22656 | /* And any specified GNU attributes. */ |
22657 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
22658 | attribs = chainon (attribs, cp_parser_gnu_attributes_opt (parser)); |
22659 | |
22660 | /* Update the symbol table. */ |
22661 | finish_using_directive (target: namespace_decl, attribs); |
22662 | |
22663 | /* Look for the final `;'. */ |
22664 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22665 | } |
22666 | |
22667 | /* Parse an asm-definition. |
22668 | |
22669 | asm-qualifier: |
22670 | volatile |
22671 | inline |
22672 | goto |
22673 | |
22674 | asm-qualifier-list: |
22675 | asm-qualifier |
22676 | asm-qualifier-list asm-qualifier |
22677 | |
22678 | asm-definition: |
22679 | asm ( string-literal ) ; |
22680 | |
22681 | GNU Extension: |
22682 | |
22683 | asm-definition: |
22684 | asm asm-qualifier-list [opt] ( string-literal ) ; |
22685 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] ) ; |
22686 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] |
22687 | : asm-operand-list [opt] ) ; |
22688 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] |
22689 | : asm-operand-list [opt] |
22690 | : asm-clobber-list [opt] ) ; |
22691 | asm asm-qualifier-list [opt] ( string-literal : : asm-operand-list [opt] |
22692 | : asm-clobber-list [opt] |
22693 | : asm-goto-list ) ; |
22694 | |
22695 | The form with asm-goto-list is valid if and only if the asm-qualifier-list |
22696 | contains goto, and is the only allowed form in that case. No duplicates are |
22697 | allowed in an asm-qualifier-list. */ |
22698 | |
22699 | static void |
22700 | cp_parser_asm_definition (cp_parser* parser) |
22701 | { |
22702 | tree outputs = NULL_TREE; |
22703 | tree inputs = NULL_TREE; |
22704 | tree clobbers = NULL_TREE; |
22705 | tree labels = NULL_TREE; |
22706 | tree asm_stmt; |
22707 | bool extended_p = false; |
22708 | bool invalid_inputs_p = false; |
22709 | bool invalid_outputs_p = false; |
22710 | required_token missing = RT_NONE; |
22711 | tree std_attrs = cp_parser_std_attribute_spec_seq (parser); |
22712 | location_t asm_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
22713 | |
22714 | /* Look for the `asm' keyword. */ |
22715 | cp_parser_require_keyword (parser, RID_ASM, RT_ASM); |
22716 | |
22717 | /* In C++20, unevaluated inline assembly is permitted in constexpr |
22718 | functions. */ |
22719 | if (parser->in_function_body |
22720 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
22721 | && cxx_dialect < cxx20) |
22722 | pedwarn (asm_loc, OPT_Wc__20_extensions, "%<asm%> in %<constexpr%> " |
22723 | "function only available with %<-std=c++20%> or " |
22724 | "%<-std=gnu++20%>" ); |
22725 | |
22726 | /* Handle the asm-qualifier-list. */ |
22727 | location_t volatile_loc = UNKNOWN_LOCATION; |
22728 | location_t inline_loc = UNKNOWN_LOCATION; |
22729 | location_t goto_loc = UNKNOWN_LOCATION; |
22730 | location_t first_loc = UNKNOWN_LOCATION; |
22731 | |
22732 | if (cp_parser_allow_gnu_extensions_p (parser)) |
22733 | for (;;) |
22734 | { |
22735 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
22736 | location_t loc = token->location; |
22737 | switch (cp_lexer_peek_token (lexer: parser->lexer)->keyword) |
22738 | { |
22739 | case RID_VOLATILE: |
22740 | if (volatile_loc) |
22741 | { |
22742 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22743 | token->u.value); |
22744 | inform (volatile_loc, "first seen here" ); |
22745 | } |
22746 | else |
22747 | { |
22748 | if (!parser->in_function_body) |
22749 | warning_at (loc, 0, "%<asm%> qualifier %qT ignored " |
22750 | "outside of function body" , token->u.value); |
22751 | volatile_loc = loc; |
22752 | } |
22753 | cp_lexer_consume_token (lexer: parser->lexer); |
22754 | continue; |
22755 | |
22756 | case RID_INLINE: |
22757 | if (inline_loc) |
22758 | { |
22759 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22760 | token->u.value); |
22761 | inform (inline_loc, "first seen here" ); |
22762 | } |
22763 | else |
22764 | inline_loc = loc; |
22765 | if (!first_loc) |
22766 | first_loc = loc; |
22767 | cp_lexer_consume_token (lexer: parser->lexer); |
22768 | continue; |
22769 | |
22770 | case RID_GOTO: |
22771 | if (goto_loc) |
22772 | { |
22773 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22774 | token->u.value); |
22775 | inform (goto_loc, "first seen here" ); |
22776 | } |
22777 | else |
22778 | goto_loc = loc; |
22779 | if (!first_loc) |
22780 | first_loc = loc; |
22781 | cp_lexer_consume_token (lexer: parser->lexer); |
22782 | continue; |
22783 | |
22784 | case RID_CONST: |
22785 | case RID_RESTRICT: |
22786 | error_at (loc, "%qT is not an %<asm%> qualifier" , token->u.value); |
22787 | cp_lexer_consume_token (lexer: parser->lexer); |
22788 | continue; |
22789 | |
22790 | default: |
22791 | break; |
22792 | } |
22793 | break; |
22794 | } |
22795 | |
22796 | bool volatile_p = (volatile_loc != UNKNOWN_LOCATION); |
22797 | bool inline_p = (inline_loc != UNKNOWN_LOCATION); |
22798 | bool goto_p = (goto_loc != UNKNOWN_LOCATION); |
22799 | |
22800 | if (!parser->in_function_body && (inline_p || goto_p)) |
22801 | { |
22802 | error_at (first_loc, "%<asm%> qualifier outside of function body" ); |
22803 | inline_p = goto_p = false; |
22804 | } |
22805 | |
22806 | /* Look for the opening `('. */ |
22807 | if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) |
22808 | return; |
22809 | /* Look for the string. */ |
22810 | tree string = cp_parser_string_literal (parser, /*translate=*/false, |
22811 | /*wide_ok=*/false); |
22812 | if (string == error_mark_node) |
22813 | { |
22814 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
22815 | /*consume_paren=*/true); |
22816 | return; |
22817 | } |
22818 | |
22819 | /* If we're allowing GNU extensions, check for the extended assembly |
22820 | syntax. Unfortunately, the `:' tokens need not be separated by |
22821 | a space in C, and so, for compatibility, we tolerate that here |
22822 | too. Doing that means that we have to treat the `::' operator as |
22823 | two `:' tokens. */ |
22824 | if (cp_parser_allow_gnu_extensions_p (parser) |
22825 | && parser->in_function_body |
22826 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
22827 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE))) |
22828 | { |
22829 | bool inputs_p = false; |
22830 | bool clobbers_p = false; |
22831 | bool labels_p = false; |
22832 | |
22833 | /* The extended syntax was used. */ |
22834 | extended_p = true; |
22835 | |
22836 | /* Look for outputs. */ |
22837 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22838 | { |
22839 | /* Consume the `:'. */ |
22840 | cp_lexer_consume_token (lexer: parser->lexer); |
22841 | /* Parse the output-operands. */ |
22842 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22843 | type: CPP_COLON) |
22844 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22845 | type: CPP_SCOPE) |
22846 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22847 | type: CPP_CLOSE_PAREN)) |
22848 | { |
22849 | outputs = cp_parser_asm_operand_list (parser); |
22850 | if (outputs == error_mark_node) |
22851 | invalid_outputs_p = true; |
22852 | } |
22853 | } |
22854 | /* If the next token is `::', there are no outputs, and the |
22855 | next token is the beginning of the inputs. */ |
22856 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22857 | /* The inputs are coming next. */ |
22858 | inputs_p = true; |
22859 | |
22860 | /* Look for inputs. */ |
22861 | if (inputs_p |
22862 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22863 | { |
22864 | /* Consume the `:' or `::'. */ |
22865 | cp_lexer_consume_token (lexer: parser->lexer); |
22866 | /* Parse the output-operands. */ |
22867 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22868 | type: CPP_COLON) |
22869 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22870 | type: CPP_SCOPE) |
22871 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22872 | type: CPP_CLOSE_PAREN)) |
22873 | { |
22874 | inputs = cp_parser_asm_operand_list (parser); |
22875 | if (inputs == error_mark_node) |
22876 | invalid_inputs_p = true; |
22877 | } |
22878 | } |
22879 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22880 | /* The clobbers are coming next. */ |
22881 | clobbers_p = true; |
22882 | |
22883 | /* Look for clobbers. */ |
22884 | if (clobbers_p |
22885 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22886 | { |
22887 | clobbers_p = true; |
22888 | /* Consume the `:' or `::'. */ |
22889 | cp_lexer_consume_token (lexer: parser->lexer); |
22890 | /* Parse the clobbers. */ |
22891 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22892 | type: CPP_COLON) |
22893 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22894 | type: CPP_CLOSE_PAREN)) |
22895 | clobbers = cp_parser_asm_clobber_list (parser); |
22896 | } |
22897 | else if (goto_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22898 | /* The labels are coming next. */ |
22899 | labels_p = true; |
22900 | |
22901 | /* Look for labels. */ |
22902 | if (labels_p |
22903 | || (goto_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON))) |
22904 | { |
22905 | labels_p = true; |
22906 | /* Consume the `:' or `::'. */ |
22907 | cp_lexer_consume_token (lexer: parser->lexer); |
22908 | /* Parse the labels. */ |
22909 | labels = cp_parser_asm_label_list (parser); |
22910 | } |
22911 | |
22912 | if (goto_p && !labels_p) |
22913 | missing = clobbers_p ? RT_COLON : RT_COLON_SCOPE; |
22914 | } |
22915 | else if (goto_p) |
22916 | missing = RT_COLON_SCOPE; |
22917 | |
22918 | /* Look for the closing `)'. */ |
22919 | if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN, |
22920 | missing ? missing : RT_CLOSE_PAREN)) |
22921 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
22922 | /*consume_paren=*/true); |
22923 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22924 | |
22925 | if (!invalid_inputs_p && !invalid_outputs_p) |
22926 | { |
22927 | /* Create the ASM_EXPR. */ |
22928 | if (parser->in_function_body) |
22929 | { |
22930 | asm_stmt = finish_asm_stmt (asm_loc, volatile_p, string, outputs, |
22931 | inputs, clobbers, labels, inline_p); |
22932 | /* If the extended syntax was not used, mark the ASM_EXPR. */ |
22933 | if (!extended_p) |
22934 | { |
22935 | tree temp = asm_stmt; |
22936 | if (TREE_CODE (temp) == CLEANUP_POINT_EXPR) |
22937 | temp = TREE_OPERAND (temp, 0); |
22938 | |
22939 | ASM_INPUT_P (temp) = 1; |
22940 | } |
22941 | } |
22942 | else |
22943 | symtab->finalize_toplevel_asm (asm_str: string); |
22944 | } |
22945 | |
22946 | if (std_attrs && any_nonignored_attribute_p (std_attrs)) |
22947 | warning_at (asm_loc, OPT_Wattributes, |
22948 | "attributes ignored on %<asm%> declaration" ); |
22949 | } |
22950 | |
22951 | /* Given the type TYPE of a declaration with declarator DECLARATOR, return the |
22952 | type that comes from the decl-specifier-seq. */ |
22953 | |
22954 | static tree |
22955 | strip_declarator_types (tree type, cp_declarator *declarator) |
22956 | { |
22957 | for (cp_declarator *d = declarator; d;) |
22958 | switch (d->kind) |
22959 | { |
22960 | case cdk_id: |
22961 | case cdk_decomp: |
22962 | case cdk_error: |
22963 | d = NULL; |
22964 | break; |
22965 | |
22966 | default: |
22967 | if (TYPE_PTRMEMFUNC_P (type)) |
22968 | type = TYPE_PTRMEMFUNC_FN_TYPE (type); |
22969 | type = TREE_TYPE (type); |
22970 | d = d->declarator; |
22971 | break; |
22972 | } |
22973 | |
22974 | return type; |
22975 | } |
22976 | |
22977 | /* Warn about the most vexing parse syntactic ambiguity, i.e., warn when |
22978 | a construct looks like a variable definition but is actually a function |
22979 | declaration. DECL_SPECIFIERS is the decl-specifier-seq and DECLARATOR |
22980 | is the declarator for this function declaration. */ |
22981 | |
22982 | static void |
22983 | warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers, |
22984 | const cp_declarator *declarator) |
22985 | { |
22986 | /* Only warn if we are declaring a function at block scope. */ |
22987 | if (!at_function_scope_p ()) |
22988 | return; |
22989 | |
22990 | /* And only if there is no storage class specified. */ |
22991 | if (decl_specifiers->storage_class != sc_none |
22992 | || decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef)) |
22993 | return; |
22994 | |
22995 | if (declarator->kind != cdk_function |
22996 | || !declarator->declarator |
22997 | || declarator->declarator->kind != cdk_id |
22998 | || !identifier_p (t: get_unqualified_id |
22999 | (declarator: const_cast<cp_declarator *>(declarator)))) |
23000 | return; |
23001 | |
23002 | /* Don't warn when the whole declarator (not just the declarator-id!) |
23003 | was parenthesized. That is, don't warn for int(n()) but do warn |
23004 | for int(f)(). */ |
23005 | if (declarator->parenthesized != UNKNOWN_LOCATION) |
23006 | return; |
23007 | |
23008 | tree type; |
23009 | if (decl_specifiers->type) |
23010 | { |
23011 | type = decl_specifiers->type; |
23012 | if (TREE_CODE (type) == TYPE_DECL) |
23013 | type = TREE_TYPE (type); |
23014 | |
23015 | /* If the return type is void there is no ambiguity. */ |
23016 | if (same_type_p (type, void_type_node)) |
23017 | return; |
23018 | } |
23019 | else if (decl_specifiers->any_type_specifiers_p) |
23020 | /* Code like long f(); will have null ->type. If we have any |
23021 | type-specifiers, pretend we've seen int. */ |
23022 | type = integer_type_node; |
23023 | else |
23024 | return; |
23025 | |
23026 | auto_diagnostic_group d; |
23027 | location_t loc = declarator->u.function.parens_loc; |
23028 | tree params = declarator->u.function.parameters; |
23029 | const bool has_list_ctor_p = CLASS_TYPE_P (type) && TYPE_HAS_LIST_CTOR (type); |
23030 | |
23031 | /* The T t() case. */ |
23032 | if (params == void_list_node) |
23033 | { |
23034 | if (warning_at (loc, OPT_Wvexing_parse, |
23035 | "empty parentheses were disambiguated as a function " |
23036 | "declaration" )) |
23037 | { |
23038 | /* () means value-initialization (C++03 and up); {} (C++11 and up) |
23039 | means value-initialization or aggregate-initialization, nothing |
23040 | means default-initialization. We can only suggest removing the |
23041 | parentheses/adding {} if T has a default constructor. */ |
23042 | if (!CLASS_TYPE_P (type) || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) |
23043 | { |
23044 | gcc_rich_location iloc (loc); |
23045 | iloc.add_fixit_remove (); |
23046 | inform (&iloc, "remove parentheses to default-initialize " |
23047 | "a variable" ); |
23048 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
23049 | { |
23050 | if (CP_AGGREGATE_TYPE_P (type)) |
23051 | inform (loc, "or replace parentheses with braces to " |
23052 | "aggregate-initialize a variable" ); |
23053 | else |
23054 | inform (loc, "or replace parentheses with braces to " |
23055 | "value-initialize a variable" ); |
23056 | } |
23057 | } |
23058 | } |
23059 | return; |
23060 | } |
23061 | |
23062 | /* If we had (...) or the parameter-list wasn't parenthesized, |
23063 | we're done. */ |
23064 | if (params == NULL_TREE || !PARENTHESIZED_LIST_P (params)) |
23065 | return; |
23066 | |
23067 | /* The T t(X()) case. */ |
23068 | if (list_length (params) == 2) |
23069 | { |
23070 | if (warning_at (loc, OPT_Wvexing_parse, |
23071 | "parentheses were disambiguated as a function " |
23072 | "declaration" )) |
23073 | { |
23074 | gcc_rich_location iloc (loc); |
23075 | /* {}-initialization means that we can use an initializer-list |
23076 | constructor if no default constructor is available, so don't |
23077 | suggest using {} for classes that have an initializer_list |
23078 | constructor. */ |
23079 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
23080 | { |
23081 | iloc.add_fixit_replace (where: get_start (loc), new_content: "{" ); |
23082 | iloc.add_fixit_replace (where: get_finish (loc), new_content: "}" ); |
23083 | inform (&iloc, "replace parentheses with braces to declare a " |
23084 | "variable" ); |
23085 | } |
23086 | else |
23087 | { |
23088 | iloc.add_fixit_insert_after (where: get_start (loc), new_content: "(" ); |
23089 | iloc.add_fixit_insert_before (where: get_finish (loc), new_content: ")" ); |
23090 | inform (&iloc, "add parentheses to declare a variable" ); |
23091 | } |
23092 | } |
23093 | } |
23094 | /* The T t(X(), X()) case. */ |
23095 | else if (warning_at (loc, OPT_Wvexing_parse, |
23096 | "parentheses were disambiguated as a function " |
23097 | "declaration" )) |
23098 | { |
23099 | gcc_rich_location iloc (loc); |
23100 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
23101 | { |
23102 | iloc.add_fixit_replace (where: get_start (loc), new_content: "{" ); |
23103 | iloc.add_fixit_replace (where: get_finish (loc), new_content: "}" ); |
23104 | inform (&iloc, "replace parentheses with braces to declare a " |
23105 | "variable" ); |
23106 | } |
23107 | } |
23108 | } |
23109 | |
23110 | /* If DECLARATOR with DECL_SPECS is a function declarator that has |
23111 | the form of a deduction guide, tag it as such. CTOR_DTOR_OR_CONV_P |
23112 | has the same meaning as in cp_parser_declarator. */ |
23113 | |
23114 | static void |
23115 | cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser, |
23116 | cp_decl_specifier_seq *decl_specs, |
23117 | cp_declarator *declarator, |
23118 | int *ctor_dtor_or_conv_p) |
23119 | { |
23120 | if (cxx_dialect >= cxx17 |
23121 | && *ctor_dtor_or_conv_p <= 0 |
23122 | && !decl_specs->type |
23123 | && !decl_specs->any_type_specifiers_p |
23124 | && function_declarator_p (declarator)) |
23125 | { |
23126 | cp_declarator *id = get_id_declarator (declarator); |
23127 | tree name = id->u.id.unqualified_name; |
23128 | parser->scope = id->u.id.qualifying_scope; |
23129 | tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc); |
23130 | if (tmpl |
23131 | && (DECL_CLASS_TEMPLATE_P (tmpl) |
23132 | || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))) |
23133 | { |
23134 | id->u.id.unqualified_name = dguide_name (tmpl); |
23135 | id->u.id.sfk = sfk_deduction_guide; |
23136 | *ctor_dtor_or_conv_p = 1; |
23137 | } |
23138 | } |
23139 | } |
23140 | |
23141 | /* Declarators [gram.dcl.decl] */ |
23142 | |
23143 | /* Parse an init-declarator. |
23144 | |
23145 | init-declarator: |
23146 | declarator initializer [opt] |
23147 | |
23148 | GNU Extension: |
23149 | |
23150 | init-declarator: |
23151 | declarator asm-specification [opt] attributes [opt] initializer [opt] |
23152 | |
23153 | function-definition: |
23154 | decl-specifier-seq [opt] declarator ctor-initializer [opt] |
23155 | function-body |
23156 | decl-specifier-seq [opt] declarator function-try-block |
23157 | |
23158 | GNU Extension: |
23159 | |
23160 | function-definition: |
23161 | __extension__ function-definition |
23162 | |
23163 | TM Extension: |
23164 | |
23165 | function-definition: |
23166 | decl-specifier-seq [opt] declarator function-transaction-block |
23167 | |
23168 | The parser flags FLAGS is used to control type-specifier parsing. |
23169 | |
23170 | The DECL_SPECIFIERS apply to this declarator. Returns a |
23171 | representation of the entity declared. If MEMBER_P is TRUE, then |
23172 | this declarator appears in a class scope. The new DECL created by |
23173 | this declarator is returned. |
23174 | |
23175 | The CHECKS are access checks that should be performed once we know |
23176 | what entity is being declared (and, therefore, what classes have |
23177 | befriended it). |
23178 | |
23179 | If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and |
23180 | for a function-definition here as well. If the declarator is a |
23181 | declarator for a function-definition, *FUNCTION_DEFINITION_P will |
23182 | be TRUE upon return. By that point, the function-definition will |
23183 | have been completely parsed. |
23184 | |
23185 | FUNCTION_DEFINITION_P may be NULL if FUNCTION_DEFINITION_ALLOWED_P |
23186 | is FALSE. |
23187 | |
23188 | If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the |
23189 | parsed declaration if it is an uninitialized single declarator not followed |
23190 | by a `;', or to error_mark_node otherwise. Either way, the trailing `;', |
23191 | if present, will not be consumed. If returned, this declarator will be |
23192 | created with SD_INITIALIZED but will not call cp_finish_decl. |
23193 | |
23194 | If INIT_LOC is not NULL, and *INIT_LOC is equal to UNKNOWN_LOCATION, |
23195 | and there is an initializer, the pointed location_t is set to the |
23196 | location of the '=' or `(', or '{' in C++11 token introducing the |
23197 | initializer. */ |
23198 | |
23199 | static tree |
23200 | cp_parser_init_declarator (cp_parser* parser, |
23201 | cp_parser_flags flags, |
23202 | cp_decl_specifier_seq *decl_specifiers, |
23203 | vec<deferred_access_check, va_gc> *checks, |
23204 | bool function_definition_allowed_p, |
23205 | bool member_p, |
23206 | int declares_class_or_enum, |
23207 | bool* function_definition_p, |
23208 | tree* maybe_range_for_decl, |
23209 | location_t* init_loc, |
23210 | tree* auto_result) |
23211 | { |
23212 | cp_token *token = NULL, *asm_spec_start_token = NULL, |
23213 | *attributes_start_token = NULL; |
23214 | cp_declarator *declarator; |
23215 | tree prefix_attributes; |
23216 | tree attributes = NULL; |
23217 | tree asm_specification; |
23218 | tree initializer; |
23219 | tree decl = NULL_TREE; |
23220 | tree scope; |
23221 | int is_initialized; |
23222 | /* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if |
23223 | initialized with "= ..", CPP_OPEN_PAREN if initialized with |
23224 | "(...)". */ |
23225 | enum cpp_ttype initialization_kind; |
23226 | bool is_direct_init = false; |
23227 | bool is_non_constant_init; |
23228 | int ctor_dtor_or_conv_p; |
23229 | bool friend_p = cp_parser_friend_p (decl_specifiers); |
23230 | bool static_p = decl_specifiers->storage_class == sc_static; |
23231 | tree pushed_scope = NULL_TREE; |
23232 | bool range_for_decl_p = false; |
23233 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
23234 | location_t tmp_init_loc = UNKNOWN_LOCATION; |
23235 | |
23236 | if (decl_spec_seq_has_spec_p (decl_specifiers, ds_consteval)) |
23237 | flags |= CP_PARSER_FLAGS_CONSTEVAL; |
23238 | |
23239 | /* Assume that this is not the declarator for a function |
23240 | definition. */ |
23241 | if (function_definition_p) |
23242 | *function_definition_p = false; |
23243 | |
23244 | /* Default arguments are only permitted for function parameters. */ |
23245 | if (decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef)) |
23246 | parser->default_arg_ok_p = false; |
23247 | |
23248 | /* Defer access checks while parsing the declarator; we cannot know |
23249 | what names are accessible until we know what is being |
23250 | declared. */ |
23251 | resume_deferring_access_checks (); |
23252 | |
23253 | token = cp_lexer_peek_token (lexer: parser->lexer); |
23254 | |
23255 | /* Parse the declarator. */ |
23256 | declarator |
23257 | = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
23258 | flags, &ctor_dtor_or_conv_p, |
23259 | /*parenthesized_p=*/NULL, |
23260 | member_p, friend_p, static_p); |
23261 | /* Gather up the deferred checks. */ |
23262 | stop_deferring_access_checks (); |
23263 | |
23264 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
23265 | |
23266 | /* If the DECLARATOR was erroneous, there's no need to go |
23267 | further. */ |
23268 | if (declarator == cp_error_declarator) |
23269 | return error_mark_node; |
23270 | |
23271 | /* Check that the number of template-parameter-lists is OK. */ |
23272 | if (!cp_parser_check_declarator_template_parameters (parser, declarator, |
23273 | token->location)) |
23274 | return error_mark_node; |
23275 | |
23276 | if (declares_class_or_enum & 2) |
23277 | cp_parser_check_for_definition_in_return_type (declarator, |
23278 | type: decl_specifiers->type, |
23279 | type_location: decl_specifiers->locations[ds_type_spec]); |
23280 | |
23281 | /* Figure out what scope the entity declared by the DECLARATOR is |
23282 | located in. `grokdeclarator' sometimes changes the scope, so |
23283 | we compute it now. */ |
23284 | scope = get_scope_of_declarator (declarator); |
23285 | |
23286 | /* Perform any lookups in the declared type which were thought to be |
23287 | dependent, but are not in the scope of the declarator. */ |
23288 | decl_specifiers->type |
23289 | = maybe_update_decl_type (decl_specifiers->type, scope); |
23290 | |
23291 | /* If we're allowing GNU extensions, look for an |
23292 | asm-specification. */ |
23293 | if (cp_parser_allow_gnu_extensions_p (parser)) |
23294 | { |
23295 | /* Look for an asm-specification. */ |
23296 | asm_spec_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
23297 | asm_specification = cp_parser_asm_specification_opt (parser); |
23298 | } |
23299 | else |
23300 | asm_specification = NULL_TREE; |
23301 | |
23302 | /* Gather the attributes that were provided with the |
23303 | decl-specifiers. */ |
23304 | prefix_attributes = decl_specifiers->attributes; |
23305 | |
23306 | /* Look for attributes. */ |
23307 | attributes_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
23308 | attributes = cp_parser_attributes_opt (parser); |
23309 | |
23310 | /* Peek at the next token. */ |
23311 | token = cp_lexer_peek_token (lexer: parser->lexer); |
23312 | |
23313 | bool bogus_implicit_tmpl = false; |
23314 | |
23315 | if (function_declarator_p (declarator)) |
23316 | { |
23317 | /* Handle C++17 deduction guides. Note that class-scope |
23318 | non-template deduction guides are instead handled in |
23319 | cp_parser_member_declaration. */ |
23320 | cp_parser_maybe_adjust_declarator_for_dguide (parser, |
23321 | decl_specs: decl_specifiers, |
23322 | declarator, |
23323 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p); |
23324 | |
23325 | if (!member_p && !cp_parser_error_occurred (parser)) |
23326 | warn_about_ambiguous_parse (decl_specifiers, declarator); |
23327 | |
23328 | /* Check to see if the token indicates the start of a |
23329 | function-definition. */ |
23330 | if (cp_parser_token_starts_function_definition_p (token)) |
23331 | { |
23332 | if (!function_definition_allowed_p) |
23333 | { |
23334 | /* If a function-definition should not appear here, issue an |
23335 | error message. */ |
23336 | cp_parser_error (parser, |
23337 | gmsgid: "a function-definition is not allowed here" ); |
23338 | return error_mark_node; |
23339 | } |
23340 | |
23341 | location_t func_brace_location |
23342 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
23343 | |
23344 | /* Neither attributes nor an asm-specification are allowed |
23345 | on a function-definition. */ |
23346 | if (asm_specification) |
23347 | error_at (asm_spec_start_token->location, |
23348 | "an %<asm%> specification is not allowed " |
23349 | "on a function-definition" ); |
23350 | if (attributes) |
23351 | error_at (attributes_start_token->location, |
23352 | "attributes are not allowed " |
23353 | "on a function-definition" ); |
23354 | /* This is a function-definition. */ |
23355 | *function_definition_p = true; |
23356 | |
23357 | /* Parse the function definition. */ |
23358 | if (member_p) |
23359 | decl = cp_parser_save_member_function_body (parser, |
23360 | decl_specifiers, |
23361 | declarator, |
23362 | prefix_attributes); |
23363 | else |
23364 | decl = |
23365 | (cp_parser_function_definition_from_specifiers_and_declarator |
23366 | (parser, decl_specifiers, prefix_attributes, declarator)); |
23367 | |
23368 | if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl)) |
23369 | { |
23370 | /* This is where the prologue starts... */ |
23371 | DECL_STRUCT_FUNCTION (decl)->function_start_locus |
23372 | = func_brace_location; |
23373 | } |
23374 | |
23375 | return decl; |
23376 | } |
23377 | } |
23378 | else if (parser->fully_implicit_function_template_p) |
23379 | { |
23380 | /* A non-template declaration involving a function parameter list |
23381 | containing an implicit template parameter will be made into a |
23382 | template. If the resulting declaration is not going to be an |
23383 | actual function then finish the template scope here to prevent it. |
23384 | An error message will be issued once we have a decl to talk about. |
23385 | |
23386 | FIXME probably we should do type deduction rather than create an |
23387 | implicit template, but the standard currently doesn't allow it. */ |
23388 | bogus_implicit_tmpl = true; |
23389 | finish_fully_implicit_template (parser, NULL_TREE); |
23390 | } |
23391 | |
23392 | /* [dcl.dcl] |
23393 | |
23394 | Only in function declarations for constructors, destructors, type |
23395 | conversions, and deduction guides can the decl-specifier-seq be omitted. |
23396 | |
23397 | We explicitly postpone this check past the point where we handle |
23398 | function-definitions because we tolerate function-definitions |
23399 | that are missing their return types in some modes. */ |
23400 | if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0) |
23401 | { |
23402 | cp_parser_error (parser, |
23403 | gmsgid: "expected constructor, destructor, or type conversion" ); |
23404 | return error_mark_node; |
23405 | } |
23406 | |
23407 | /* An `=' or an '{' in C++11, indicate an initializer. An '(' may indicate |
23408 | an initializer as well. */ |
23409 | if (token->type == CPP_EQ |
23410 | || token->type == CPP_OPEN_PAREN |
23411 | || token->type == CPP_OPEN_BRACE) |
23412 | { |
23413 | /* Don't get fooled into thinking that F(i)(1)(2) is an initializer. |
23414 | It isn't; it's an expression. (Here '(i)' would have already been |
23415 | parsed as a declarator.) */ |
23416 | if (token->type == CPP_OPEN_PAREN |
23417 | && cp_parser_uncommitted_to_tentative_parse_p (parser)) |
23418 | { |
23419 | cp_lexer_save_tokens (lexer: parser->lexer); |
23420 | cp_lexer_consume_token (lexer: parser->lexer); |
23421 | cp_parser_skip_to_closing_parenthesis (parser, |
23422 | /*recovering*/false, |
23423 | /*or_comma*/false, |
23424 | /*consume_paren*/true); |
23425 | /* If this is an initializer, only a ',' or ';' can follow: either |
23426 | we have another init-declarator, or we're at the end of an |
23427 | init-declarator-list which can only be followed by a ';'. */ |
23428 | bool ok = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
23429 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
23430 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
23431 | if (UNLIKELY (!ok)) |
23432 | /* Not an init-declarator. */ |
23433 | return error_mark_node; |
23434 | } |
23435 | is_initialized = SD_INITIALIZED; |
23436 | initialization_kind = token->type; |
23437 | declarator->init_loc = token->location; |
23438 | if (maybe_range_for_decl) |
23439 | *maybe_range_for_decl = error_mark_node; |
23440 | tmp_init_loc = token->location; |
23441 | if (init_loc && *init_loc == UNKNOWN_LOCATION) |
23442 | *init_loc = tmp_init_loc; |
23443 | |
23444 | if (token->type == CPP_EQ |
23445 | && function_declarator_p (declarator)) |
23446 | { |
23447 | cp_token *t2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
23448 | if (t2->keyword == RID_DEFAULT) |
23449 | is_initialized = SD_DEFAULTED; |
23450 | else if (t2->keyword == RID_DELETE) |
23451 | is_initialized = SD_DELETED; |
23452 | } |
23453 | } |
23454 | else |
23455 | { |
23456 | /* If the init-declarator isn't initialized and isn't followed by a |
23457 | `,' or `;', it's not a valid init-declarator. */ |
23458 | if (token->type != CPP_COMMA |
23459 | && token->type != CPP_SEMICOLON) |
23460 | { |
23461 | if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node) |
23462 | range_for_decl_p = true; |
23463 | else |
23464 | { |
23465 | if (!maybe_range_for_decl) |
23466 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
23467 | return error_mark_node; |
23468 | } |
23469 | } |
23470 | is_initialized = SD_UNINITIALIZED; |
23471 | initialization_kind = CPP_EOF; |
23472 | } |
23473 | |
23474 | /* Because start_decl has side-effects, we should only call it if we |
23475 | know we're going ahead. By this point, we know that we cannot |
23476 | possibly be looking at any other construct. */ |
23477 | cp_parser_commit_to_tentative_parse (parser); |
23478 | |
23479 | /* Enter the newly declared entry in the symbol table. If we're |
23480 | processing a declaration in a class-specifier, we wait until |
23481 | after processing the initializer. */ |
23482 | if (!member_p) |
23483 | { |
23484 | if (parser->in_unbraced_linkage_specification_p) |
23485 | decl_specifiers->storage_class = sc_extern; |
23486 | decl = start_decl (declarator, decl_specifiers, |
23487 | range_for_decl_p? SD_INITIALIZED : is_initialized, |
23488 | attributes, prefix_attributes, &pushed_scope); |
23489 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
23490 | cp_finalize_oacc_routine (parser, decl, false); |
23491 | /* Adjust location of decl if declarator->id_loc is more appropriate: |
23492 | set, and decl wasn't merged with another decl, in which case its |
23493 | location would be different from input_location, and more accurate. */ |
23494 | if (DECL_P (decl) |
23495 | && declarator->id_loc != UNKNOWN_LOCATION |
23496 | && DECL_SOURCE_LOCATION (decl) == input_location) |
23497 | DECL_SOURCE_LOCATION (decl) = declarator->id_loc; |
23498 | } |
23499 | else if (scope) |
23500 | /* Enter the SCOPE. That way unqualified names appearing in the |
23501 | initializer will be looked up in SCOPE. */ |
23502 | pushed_scope = push_scope (scope); |
23503 | |
23504 | /* Perform deferred access control checks, now that we know in which |
23505 | SCOPE the declared entity resides. */ |
23506 | if (!member_p && decl) |
23507 | { |
23508 | tree saved_current_function_decl = NULL_TREE; |
23509 | |
23510 | /* If the entity being declared is a function, pretend that we |
23511 | are in its scope. If it is a `friend', it may have access to |
23512 | things that would not otherwise be accessible. */ |
23513 | if (TREE_CODE (decl) == FUNCTION_DECL) |
23514 | { |
23515 | saved_current_function_decl = current_function_decl; |
23516 | current_function_decl = decl; |
23517 | } |
23518 | |
23519 | /* Perform access checks for template parameters. */ |
23520 | cp_parser_perform_template_parameter_access_checks (checks); |
23521 | |
23522 | /* Perform the access control checks for the declarator and the |
23523 | decl-specifiers. */ |
23524 | perform_deferred_access_checks (tf_warning_or_error); |
23525 | |
23526 | /* Restore the saved value. */ |
23527 | if (TREE_CODE (decl) == FUNCTION_DECL) |
23528 | current_function_decl = saved_current_function_decl; |
23529 | } |
23530 | |
23531 | /* Parse the initializer. */ |
23532 | initializer = NULL_TREE; |
23533 | is_direct_init = false; |
23534 | is_non_constant_init = true; |
23535 | if (is_initialized) |
23536 | { |
23537 | if (function_declarator_p (declarator)) |
23538 | { |
23539 | if (initialization_kind == CPP_EQ) |
23540 | initializer = cp_parser_pure_specifier (parser); |
23541 | else |
23542 | { |
23543 | /* If the declaration was erroneous, we don't really |
23544 | know what the user intended, so just silently |
23545 | consume the initializer. */ |
23546 | if (decl != error_mark_node) |
23547 | error_at (tmp_init_loc, "initializer provided for function" ); |
23548 | cp_parser_skip_to_closing_parenthesis (parser, |
23549 | /*recovering=*/true, |
23550 | /*or_comma=*/false, |
23551 | /*consume_paren=*/true); |
23552 | } |
23553 | } |
23554 | else |
23555 | { |
23556 | /* We want to record the extra mangling scope for in-class |
23557 | initializers of class members and initializers of static |
23558 | data member templates and namespace-scope initializers. |
23559 | The former involves deferring parsing of the initializer |
23560 | until end of class as with default arguments. So right |
23561 | here we only handle the latter two. */ |
23562 | bool has_lambda_scope = false; |
23563 | |
23564 | if (decl != error_mark_node |
23565 | && !member_p |
23566 | && (processing_template_decl || DECL_NAMESPACE_SCOPE_P (decl))) |
23567 | has_lambda_scope = true; |
23568 | |
23569 | if (has_lambda_scope) |
23570 | start_lambda_scope (decl); |
23571 | initializer = cp_parser_initializer (parser, |
23572 | &is_direct_init, |
23573 | &is_non_constant_init); |
23574 | if (has_lambda_scope) |
23575 | finish_lambda_scope (); |
23576 | if (initializer == error_mark_node) |
23577 | cp_parser_skip_to_end_of_statement (parser); |
23578 | } |
23579 | } |
23580 | |
23581 | /* The old parser allows attributes to appear after a parenthesized |
23582 | initializer. Mark Mitchell proposed removing this functionality |
23583 | on the GCC mailing lists on 2002-08-13. This parser accepts the |
23584 | attributes -- but ignores them. Made a permerror in GCC 8. */ |
23585 | if (cp_parser_allow_gnu_extensions_p (parser) |
23586 | && initialization_kind == CPP_OPEN_PAREN |
23587 | && cp_parser_attributes_opt (parser) |
23588 | && permerror (input_location, |
23589 | "attributes after parenthesized initializer ignored" )) |
23590 | { |
23591 | static bool hint; |
23592 | if (flag_permissive && !hint) |
23593 | { |
23594 | hint = true; |
23595 | inform (input_location, |
23596 | "this flexibility is deprecated and will be removed" ); |
23597 | } |
23598 | } |
23599 | |
23600 | /* And now complain about a non-function implicit template. */ |
23601 | if (bogus_implicit_tmpl && decl != error_mark_node) |
23602 | error_at (DECL_SOURCE_LOCATION (decl), |
23603 | "non-function %qD declared as implicit template" , decl); |
23604 | |
23605 | /* For an in-class declaration, use `grokfield' to create the |
23606 | declaration. */ |
23607 | if (member_p) |
23608 | { |
23609 | if (pushed_scope) |
23610 | { |
23611 | pop_scope (pushed_scope); |
23612 | pushed_scope = NULL_TREE; |
23613 | } |
23614 | decl = grokfield (declarator, decl_specifiers, |
23615 | initializer, !is_non_constant_init, |
23616 | /*asmspec=*/NULL_TREE, |
23617 | attr_chainon (attrs: attributes, attr: prefix_attributes)); |
23618 | if (decl && TREE_CODE (decl) == FUNCTION_DECL) |
23619 | cp_parser_save_default_args (parser, decl); |
23620 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
23621 | cp_finalize_oacc_routine (parser, decl, false); |
23622 | } |
23623 | |
23624 | /* Finish processing the declaration. But, skip member |
23625 | declarations. */ |
23626 | if (!member_p && decl && decl != error_mark_node && !range_for_decl_p) |
23627 | { |
23628 | cp_finish_decl (decl, |
23629 | initializer, !is_non_constant_init, |
23630 | asm_specification, |
23631 | /* If the initializer is in parentheses, then this is |
23632 | a direct-initialization, which means that an |
23633 | `explicit' constructor is OK. Otherwise, an |
23634 | `explicit' constructor cannot be used. */ |
23635 | ((is_direct_init || !is_initialized) |
23636 | ? LOOKUP_NORMAL : LOOKUP_IMPLICIT)); |
23637 | } |
23638 | else if ((cxx_dialect != cxx98) && friend_p |
23639 | && decl && TREE_CODE (decl) == FUNCTION_DECL) |
23640 | /* Core issue #226 (C++0x only): A default template-argument |
23641 | shall not be specified in a friend class template |
23642 | declaration. */ |
23643 | check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true, |
23644 | /*is_partial=*/false, /*is_friend_decl=*/1); |
23645 | |
23646 | if (!friend_p && pushed_scope) |
23647 | pop_scope (pushed_scope); |
23648 | |
23649 | if (function_declarator_p (declarator) |
23650 | && parser->fully_implicit_function_template_p) |
23651 | { |
23652 | if (member_p) |
23653 | decl = finish_fully_implicit_template (parser, decl); |
23654 | else |
23655 | finish_fully_implicit_template (parser, /*member_decl_opt=*/0); |
23656 | } |
23657 | |
23658 | if (auto_result && is_initialized && decl_specifiers->type |
23659 | && type_uses_auto (decl_specifiers->type)) |
23660 | *auto_result = strip_declarator_types (TREE_TYPE (decl), declarator); |
23661 | |
23662 | return decl; |
23663 | } |
23664 | |
23665 | /* Parse a declarator. |
23666 | |
23667 | declarator: |
23668 | direct-declarator |
23669 | ptr-operator declarator |
23670 | |
23671 | abstract-declarator: |
23672 | ptr-operator abstract-declarator [opt] |
23673 | direct-abstract-declarator |
23674 | |
23675 | GNU Extensions: |
23676 | |
23677 | declarator: |
23678 | attributes [opt] direct-declarator |
23679 | attributes [opt] ptr-operator declarator |
23680 | |
23681 | abstract-declarator: |
23682 | attributes [opt] ptr-operator abstract-declarator [opt] |
23683 | attributes [opt] direct-abstract-declarator |
23684 | |
23685 | The parser flags FLAGS is used to control type-specifier parsing. |
23686 | |
23687 | If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to |
23688 | detect constructors, destructors, deduction guides, or conversion operators. |
23689 | It is set to -1 if the declarator is a name, and +1 if it is a |
23690 | function. Otherwise it is set to zero. Usually you just want to |
23691 | test for >0, but internally the negative value is used. |
23692 | |
23693 | (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have |
23694 | a decl-specifier-seq unless it declares a constructor, destructor, |
23695 | or conversion. It might seem that we could check this condition in |
23696 | semantic analysis, rather than parsing, but that makes it difficult |
23697 | to handle something like `f()'. We want to notice that there are |
23698 | no decl-specifiers, and therefore realize that this is an |
23699 | expression, not a declaration.) |
23700 | |
23701 | If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff |
23702 | the declarator is a direct-declarator of the form "(...)". |
23703 | |
23704 | MEMBER_P is true iff this declarator is a member-declarator. |
23705 | |
23706 | FRIEND_P is true iff this declarator is a friend. |
23707 | |
23708 | STATIC_P is true iff the keyword static was seen. */ |
23709 | |
23710 | static cp_declarator * |
23711 | cp_parser_declarator (cp_parser* parser, |
23712 | cp_parser_declarator_kind dcl_kind, |
23713 | cp_parser_flags flags, |
23714 | int* ctor_dtor_or_conv_p, |
23715 | bool* parenthesized_p, |
23716 | bool member_p, bool friend_p, bool static_p) |
23717 | { |
23718 | cp_declarator *declarator; |
23719 | enum tree_code code; |
23720 | cp_cv_quals cv_quals; |
23721 | tree class_type; |
23722 | tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE; |
23723 | |
23724 | /* Assume this is not a constructor, destructor, or type-conversion |
23725 | operator. */ |
23726 | if (ctor_dtor_or_conv_p) |
23727 | *ctor_dtor_or_conv_p = 0; |
23728 | |
23729 | if (cp_parser_allow_gnu_extensions_p (parser)) |
23730 | gnu_attributes = cp_parser_gnu_attributes_opt (parser); |
23731 | |
23732 | /* Check for the ptr-operator production. */ |
23733 | cp_parser_parse_tentatively (parser); |
23734 | /* Parse the ptr-operator. */ |
23735 | code = cp_parser_ptr_operator (parser, |
23736 | &class_type, |
23737 | &cv_quals, |
23738 | &std_attributes); |
23739 | |
23740 | /* If that worked, then we have a ptr-operator. */ |
23741 | if (cp_parser_parse_definitely (parser)) |
23742 | { |
23743 | /* If a ptr-operator was found, then this declarator was not |
23744 | parenthesized. */ |
23745 | if (parenthesized_p) |
23746 | *parenthesized_p = false; |
23747 | /* The dependent declarator is optional if we are parsing an |
23748 | abstract-declarator. */ |
23749 | if (dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
23750 | cp_parser_parse_tentatively (parser); |
23751 | |
23752 | /* Parse the dependent declarator. */ |
23753 | declarator = cp_parser_declarator (parser, dcl_kind, flags, |
23754 | /*ctor_dtor_or_conv_p=*/NULL, |
23755 | /*parenthesized_p=*/NULL, |
23756 | member_p, friend_p, static_p); |
23757 | |
23758 | /* If we are parsing an abstract-declarator, we must handle the |
23759 | case where the dependent declarator is absent. */ |
23760 | if (dcl_kind != CP_PARSER_DECLARATOR_NAMED |
23761 | && !cp_parser_parse_definitely (parser)) |
23762 | declarator = NULL; |
23763 | |
23764 | declarator = cp_parser_make_indirect_declarator |
23765 | (code, class_type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
23766 | } |
23767 | /* Everything else is a direct-declarator. */ |
23768 | else |
23769 | { |
23770 | if (parenthesized_p) |
23771 | *parenthesized_p = cp_lexer_next_token_is (lexer: parser->lexer, |
23772 | type: CPP_OPEN_PAREN); |
23773 | declarator = cp_parser_direct_declarator (parser, dcl_kind, |
23774 | flags, ctor_dtor_or_conv_p, |
23775 | member_p, friend_p, static_p); |
23776 | } |
23777 | |
23778 | if (gnu_attributes && declarator && declarator != cp_error_declarator) |
23779 | declarator->attributes = gnu_attributes; |
23780 | return declarator; |
23781 | } |
23782 | |
23783 | /* Parse a direct-declarator or direct-abstract-declarator. |
23784 | |
23785 | direct-declarator: |
23786 | declarator-id |
23787 | direct-declarator ( parameter-declaration-clause ) |
23788 | cv-qualifier-seq [opt] |
23789 | ref-qualifier [opt] |
23790 | exception-specification [opt] |
23791 | direct-declarator [ constant-expression [opt] ] |
23792 | ( declarator ) |
23793 | |
23794 | direct-abstract-declarator: |
23795 | direct-abstract-declarator [opt] |
23796 | ( parameter-declaration-clause ) |
23797 | cv-qualifier-seq [opt] |
23798 | ref-qualifier [opt] |
23799 | exception-specification [opt] |
23800 | direct-abstract-declarator [opt] [ constant-expression [opt] ] |
23801 | ( abstract-declarator ) |
23802 | |
23803 | Returns a representation of the declarator. DCL_KIND is |
23804 | CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a |
23805 | direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if |
23806 | we are parsing a direct-declarator. It is |
23807 | CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case |
23808 | of ambiguity we prefer an abstract declarator, as per |
23809 | [dcl.ambig.res]. |
23810 | The parser flags FLAGS is used to control type-specifier parsing. |
23811 | CTOR_DTOR_OR_CONV_P, MEMBER_P, FRIEND_P, and STATIC_P are |
23812 | as for cp_parser_declarator. */ |
23813 | |
23814 | static cp_declarator * |
23815 | cp_parser_direct_declarator (cp_parser* parser, |
23816 | cp_parser_declarator_kind dcl_kind, |
23817 | cp_parser_flags flags, |
23818 | int* ctor_dtor_or_conv_p, |
23819 | bool member_p, bool friend_p, bool static_p) |
23820 | { |
23821 | cp_token *token; |
23822 | cp_declarator *declarator = NULL; |
23823 | tree scope = NULL_TREE; |
23824 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
23825 | bool saved_in_declarator_p = parser->in_declarator_p; |
23826 | bool first = true; |
23827 | tree pushed_scope = NULL_TREE; |
23828 | cp_token *open_paren = NULL, *close_paren = NULL; |
23829 | |
23830 | while (true) |
23831 | { |
23832 | /* Peek at the next token. */ |
23833 | token = cp_lexer_peek_token (lexer: parser->lexer); |
23834 | if (token->type == CPP_OPEN_PAREN) |
23835 | { |
23836 | /* This is either a parameter-declaration-clause, or a |
23837 | parenthesized declarator. When we know we are parsing a |
23838 | named declarator, it must be a parenthesized declarator |
23839 | if FIRST is true. For instance, `(int)' is a |
23840 | parameter-declaration-clause, with an omitted |
23841 | direct-abstract-declarator. But `((*))', is a |
23842 | parenthesized abstract declarator. Finally, when T is a |
23843 | template parameter `(T)' is a |
23844 | parameter-declaration-clause, and not a parenthesized |
23845 | named declarator. |
23846 | |
23847 | We first try and parse a parameter-declaration-clause, |
23848 | and then try a nested declarator (if FIRST is true). |
23849 | |
23850 | It is not an error for it not to be a |
23851 | parameter-declaration-clause, even when FIRST is |
23852 | false. Consider, |
23853 | |
23854 | int i (int); |
23855 | int i (3); |
23856 | |
23857 | The first is the declaration of a function while the |
23858 | second is the definition of a variable, including its |
23859 | initializer. |
23860 | |
23861 | Having seen only the parenthesis, we cannot know which of |
23862 | these two alternatives should be selected. Even more |
23863 | complex are examples like: |
23864 | |
23865 | int i (int (a)); |
23866 | int i (int (3)); |
23867 | |
23868 | The former is a function-declaration; the latter is a |
23869 | variable initialization. |
23870 | |
23871 | Thus again, we try a parameter-declaration-clause, and if |
23872 | that fails, we back out and return. */ |
23873 | |
23874 | if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
23875 | { |
23876 | tree params; |
23877 | bool is_declarator = false; |
23878 | |
23879 | open_paren = NULL; |
23880 | |
23881 | /* In a member-declarator, the only valid interpretation |
23882 | of a parenthesis is the start of a |
23883 | parameter-declaration-clause. (It is invalid to |
23884 | initialize a static data member with a parenthesized |
23885 | initializer; only the "=" form of initialization is |
23886 | permitted.) */ |
23887 | if (!member_p) |
23888 | cp_parser_parse_tentatively (parser); |
23889 | |
23890 | /* Consume the `('. */ |
23891 | const location_t parens_start = token->location; |
23892 | matching_parens parens; |
23893 | parens.consume_open (parser); |
23894 | if (first) |
23895 | { |
23896 | /* If this is going to be an abstract declarator, we're |
23897 | in a declarator and we can't have default args. */ |
23898 | parser->default_arg_ok_p = false; |
23899 | parser->in_declarator_p = true; |
23900 | } |
23901 | |
23902 | begin_scope (sk_function_parms, NULL_TREE); |
23903 | |
23904 | /* Parse the parameter-declaration-clause. */ |
23905 | params |
23906 | = cp_parser_parameter_declaration_clause (parser, flags); |
23907 | const location_t parens_end |
23908 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
23909 | |
23910 | /* Consume the `)'. */ |
23911 | parens.require_close (parser); |
23912 | |
23913 | /* For code like |
23914 | int x(auto(42)); |
23915 | A a(auto(i), 42); |
23916 | we have synthesized an implicit template parameter and marked |
23917 | what we thought was a function as an implicit function template. |
23918 | But now, having seen the whole parameter list, we know it's not |
23919 | a function declaration, so undo that. */ |
23920 | if (cp_parser_error_occurred (parser) |
23921 | && parser->fully_implicit_function_template_p |
23922 | /* Don't do this for the inner (). */ |
23923 | && parser->default_arg_ok_p) |
23924 | abort_fully_implicit_template (parser); |
23925 | |
23926 | /* If all went well, parse the cv-qualifier-seq, |
23927 | ref-qualifier and the exception-specification. */ |
23928 | if (member_p || cp_parser_parse_definitely (parser)) |
23929 | { |
23930 | cp_cv_quals cv_quals; |
23931 | cp_virt_specifiers virt_specifiers; |
23932 | cp_ref_qualifier ref_qual; |
23933 | tree exception_specification; |
23934 | tree late_return; |
23935 | tree attrs; |
23936 | bool memfn = (member_p || (pushed_scope |
23937 | && CLASS_TYPE_P (pushed_scope))); |
23938 | unsigned char local_variables_forbidden_p |
23939 | = parser->local_variables_forbidden_p; |
23940 | /* 'this' is not allowed in static member functions. */ |
23941 | if (static_p || friend_p) |
23942 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
23943 | |
23944 | is_declarator = true; |
23945 | |
23946 | if (ctor_dtor_or_conv_p) |
23947 | *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; |
23948 | first = false; |
23949 | |
23950 | /* Parse the cv-qualifier-seq. */ |
23951 | cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
23952 | /* Parse the ref-qualifier. */ |
23953 | ref_qual = cp_parser_ref_qualifier_opt (parser); |
23954 | /* Parse the tx-qualifier. */ |
23955 | tree tx_qual = cp_parser_tx_qualifier_opt (parser); |
23956 | |
23957 | tree save_ccp = current_class_ptr; |
23958 | tree save_ccr = current_class_ref; |
23959 | if (memfn && !friend_p && !static_p) |
23960 | /* DR 1207: 'this' is in scope after the cv-quals. */ |
23961 | inject_this_parameter (current_class_type, cv_quals); |
23962 | |
23963 | /* If it turned out that this is e.g. a pointer to a |
23964 | function, we don't want to delay noexcept parsing. */ |
23965 | if (declarator == NULL || declarator->kind != cdk_id) |
23966 | flags &= ~CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
23967 | |
23968 | /* Parse the exception-specification. */ |
23969 | exception_specification |
23970 | = cp_parser_exception_specification_opt (parser, |
23971 | flags); |
23972 | |
23973 | attrs = cp_parser_std_attribute_spec_seq (parser); |
23974 | |
23975 | cp_omp_declare_simd_data odsd; |
23976 | if ((flag_openmp || flag_openmp_simd) |
23977 | && declarator |
23978 | && declarator->std_attributes |
23979 | && declarator->kind == cdk_id) |
23980 | { |
23981 | tree *pa = &declarator->std_attributes; |
23982 | cp_parser_handle_directive_omp_attributes (parser, pattrs: pa, |
23983 | data: &odsd, start: false); |
23984 | } |
23985 | |
23986 | /* In here, we handle cases where attribute is used after |
23987 | the function declaration. For example: |
23988 | void func (int x) __attribute__((vector(..))); */ |
23989 | tree gnu_attrs = NULL_TREE; |
23990 | tree requires_clause = NULL_TREE; |
23991 | late_return |
23992 | = cp_parser_late_return_type_opt (parser, declarator, |
23993 | requires_clause); |
23994 | |
23995 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
23996 | |
23997 | /* Parse the virt-specifier-seq. */ |
23998 | virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); |
23999 | |
24000 | location_t parens_loc = make_location (caret: parens_start, |
24001 | start: parens_start, |
24002 | finish: parens_end); |
24003 | /* Create the function-declarator. */ |
24004 | declarator = make_call_declarator (target: declarator, |
24005 | parms: params, |
24006 | cv_qualifiers: cv_quals, |
24007 | virt_specifiers, |
24008 | ref_qualifier: ref_qual, |
24009 | tx_qualifier: tx_qual, |
24010 | exception_specification, |
24011 | late_return_type: late_return, |
24012 | requires_clause, |
24013 | std_attrs: attrs, |
24014 | parens_loc); |
24015 | declarator->attributes = gnu_attrs; |
24016 | /* Any subsequent parameter lists are to do with |
24017 | return type, so are not those of the declared |
24018 | function. */ |
24019 | parser->default_arg_ok_p = false; |
24020 | |
24021 | current_class_ptr = save_ccp; |
24022 | current_class_ref = save_ccr; |
24023 | |
24024 | /* Restore the state of local_variables_forbidden_p. */ |
24025 | parser->local_variables_forbidden_p |
24026 | = local_variables_forbidden_p; |
24027 | } |
24028 | |
24029 | /* Remove the function parms from scope. */ |
24030 | pop_bindings_and_leave_scope (); |
24031 | |
24032 | if (is_declarator) |
24033 | /* Repeat the main loop. */ |
24034 | continue; |
24035 | } |
24036 | |
24037 | /* If this is the first, we can try a parenthesized |
24038 | declarator. */ |
24039 | if (first) |
24040 | { |
24041 | bool saved_in_type_id_in_expr_p; |
24042 | |
24043 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
24044 | parser->in_declarator_p = saved_in_declarator_p; |
24045 | |
24046 | open_paren = token; |
24047 | /* Consume the `('. */ |
24048 | matching_parens parens; |
24049 | parens.consume_open (parser); |
24050 | /* Parse the nested declarator. */ |
24051 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
24052 | parser->in_type_id_in_expr_p = true; |
24053 | declarator |
24054 | = cp_parser_declarator (parser, dcl_kind, flags, |
24055 | ctor_dtor_or_conv_p, |
24056 | /*parenthesized_p=*/NULL, |
24057 | member_p, friend_p, |
24058 | /*static_p=*/false); |
24059 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
24060 | first = false; |
24061 | /* Expect a `)'. */ |
24062 | close_paren = cp_lexer_peek_token (lexer: parser->lexer); |
24063 | if (!parens.require_close (parser)) |
24064 | declarator = cp_error_declarator; |
24065 | if (declarator == cp_error_declarator) |
24066 | break; |
24067 | |
24068 | goto handle_declarator; |
24069 | } |
24070 | /* Otherwise, we must be done. */ |
24071 | else |
24072 | break; |
24073 | } |
24074 | else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
24075 | && token->type == CPP_OPEN_SQUARE |
24076 | && !cp_next_tokens_can_be_attribute_p (parser)) |
24077 | { |
24078 | /* Parse an array-declarator. */ |
24079 | tree bounds, attrs; |
24080 | |
24081 | if (ctor_dtor_or_conv_p) |
24082 | *ctor_dtor_or_conv_p = 0; |
24083 | |
24084 | open_paren = NULL; |
24085 | first = false; |
24086 | parser->default_arg_ok_p = false; |
24087 | parser->in_declarator_p = true; |
24088 | /* Consume the `['. */ |
24089 | cp_lexer_consume_token (lexer: parser->lexer); |
24090 | /* Peek at the next token. */ |
24091 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24092 | /* If the next token is `]', then there is no |
24093 | constant-expression. */ |
24094 | if (token->type != CPP_CLOSE_SQUARE) |
24095 | { |
24096 | bool non_constant_p; |
24097 | bounds |
24098 | = cp_parser_constant_expression (parser, |
24099 | /*allow_non_constant=*/allow_non_constant_p: true, |
24100 | non_constant_p: &non_constant_p); |
24101 | if (!non_constant_p) |
24102 | /* OK */; |
24103 | else if (error_operand_p (t: bounds)) |
24104 | /* Already gave an error. */; |
24105 | else if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
24106 | /* Let compute_array_index_type diagnose this. */; |
24107 | else if (!parser->in_function_body |
24108 | || parsing_function_declarator ()) |
24109 | { |
24110 | /* Normally, the array bound must be an integral constant |
24111 | expression. However, as an extension, we allow VLAs |
24112 | in function scopes as long as they aren't part of a |
24113 | parameter declaration. */ |
24114 | cp_parser_error (parser, |
24115 | gmsgid: "array bound is not an integer constant" ); |
24116 | bounds = error_mark_node; |
24117 | } |
24118 | else if (processing_template_decl |
24119 | && !type_dependent_expression_p (bounds)) |
24120 | { |
24121 | /* Remember this wasn't a constant-expression. */ |
24122 | bounds = build_nop (TREE_TYPE (bounds), bounds); |
24123 | TREE_SIDE_EFFECTS (bounds) = 1; |
24124 | } |
24125 | } |
24126 | else |
24127 | bounds = NULL_TREE; |
24128 | /* Look for the closing `]'. */ |
24129 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
24130 | { |
24131 | declarator = cp_error_declarator; |
24132 | break; |
24133 | } |
24134 | |
24135 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24136 | declarator = make_array_declarator (element: declarator, bounds); |
24137 | declarator->std_attributes = attrs; |
24138 | } |
24139 | else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) |
24140 | { |
24141 | { |
24142 | tree qualifying_scope; |
24143 | tree unqualified_name; |
24144 | tree attrs; |
24145 | special_function_kind sfk; |
24146 | bool abstract_ok; |
24147 | bool pack_expansion_p = false; |
24148 | cp_token *declarator_id_start_token; |
24149 | |
24150 | /* Parse a declarator-id */ |
24151 | abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER); |
24152 | if (abstract_ok) |
24153 | { |
24154 | cp_parser_parse_tentatively (parser); |
24155 | |
24156 | /* If we see an ellipsis, we should be looking at a |
24157 | parameter pack. */ |
24158 | if (token->type == CPP_ELLIPSIS) |
24159 | { |
24160 | /* Consume the `...' */ |
24161 | cp_lexer_consume_token (lexer: parser->lexer); |
24162 | |
24163 | pack_expansion_p = true; |
24164 | } |
24165 | } |
24166 | |
24167 | declarator_id_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
24168 | unqualified_name |
24169 | = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok); |
24170 | qualifying_scope = parser->scope; |
24171 | if (abstract_ok) |
24172 | { |
24173 | bool okay = false; |
24174 | |
24175 | if (!unqualified_name && pack_expansion_p) |
24176 | { |
24177 | /* Check whether an error occurred. */ |
24178 | okay = !cp_parser_error_occurred (parser); |
24179 | |
24180 | /* We already consumed the ellipsis to mark a |
24181 | parameter pack, but we have no way to report it, |
24182 | so abort the tentative parse. We will be exiting |
24183 | immediately anyway. */ |
24184 | cp_parser_abort_tentative_parse (parser); |
24185 | } |
24186 | else |
24187 | okay = cp_parser_parse_definitely (parser); |
24188 | |
24189 | if (!okay) |
24190 | unqualified_name = error_mark_node; |
24191 | else if (unqualified_name |
24192 | && (qualifying_scope |
24193 | || (!identifier_p (t: unqualified_name)))) |
24194 | { |
24195 | cp_parser_error (parser, gmsgid: "expected unqualified-id" ); |
24196 | unqualified_name = error_mark_node; |
24197 | } |
24198 | } |
24199 | |
24200 | if (!unqualified_name) |
24201 | return NULL; |
24202 | if (unqualified_name == error_mark_node) |
24203 | { |
24204 | declarator = cp_error_declarator; |
24205 | pack_expansion_p = false; |
24206 | declarator->parameter_pack_p = false; |
24207 | break; |
24208 | } |
24209 | |
24210 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24211 | |
24212 | if (qualifying_scope && at_namespace_scope_p () |
24213 | && TREE_CODE (qualifying_scope) == TYPENAME_TYPE) |
24214 | { |
24215 | /* In the declaration of a member of a template class |
24216 | outside of the class itself, the SCOPE will sometimes |
24217 | be a TYPENAME_TYPE. For example, given: |
24218 | |
24219 | template <typename T> |
24220 | int S<T>::R::i = 3; |
24221 | |
24222 | the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In |
24223 | this context, we must resolve S<T>::R to an ordinary |
24224 | type, rather than a typename type. |
24225 | |
24226 | The reason we normally avoid resolving TYPENAME_TYPEs |
24227 | is that a specialization of `S' might render |
24228 | `S<T>::R' not a type. However, if `S' is |
24229 | specialized, then this `i' will not be used, so there |
24230 | is no harm in resolving the types here. */ |
24231 | tree type; |
24232 | |
24233 | /* Resolve the TYPENAME_TYPE. */ |
24234 | type = resolve_typename_type (qualifying_scope, |
24235 | /*only_current_p=*/false); |
24236 | /* If that failed, the declarator is invalid. */ |
24237 | if (TREE_CODE (type) == TYPENAME_TYPE) |
24238 | { |
24239 | if (typedef_variant_p (type)) |
24240 | error_at (declarator_id_start_token->location, |
24241 | "cannot define member of dependent typedef " |
24242 | "%qT" , type); |
24243 | else |
24244 | error_at (declarator_id_start_token->location, |
24245 | "%<%T::%E%> is not a type" , |
24246 | TYPE_CONTEXT (qualifying_scope), |
24247 | TYPE_IDENTIFIER (qualifying_scope)); |
24248 | } |
24249 | qualifying_scope = type; |
24250 | } |
24251 | |
24252 | sfk = sfk_none; |
24253 | |
24254 | if (unqualified_name) |
24255 | { |
24256 | tree class_type; |
24257 | |
24258 | if (qualifying_scope |
24259 | && CLASS_TYPE_P (qualifying_scope)) |
24260 | class_type = qualifying_scope; |
24261 | else |
24262 | class_type = current_class_type; |
24263 | |
24264 | if (TREE_CODE (unqualified_name) == TYPE_DECL) |
24265 | { |
24266 | tree name_type = TREE_TYPE (unqualified_name); |
24267 | |
24268 | if (!class_type || !same_type_p (name_type, class_type)) |
24269 | { |
24270 | /* We do not attempt to print the declarator |
24271 | here because we do not have enough |
24272 | information about its original syntactic |
24273 | form. */ |
24274 | cp_parser_error (parser, gmsgid: "invalid declarator" ); |
24275 | declarator = cp_error_declarator; |
24276 | break; |
24277 | } |
24278 | else if (qualifying_scope |
24279 | && CLASSTYPE_USE_TEMPLATE (name_type)) |
24280 | { |
24281 | error_at (declarator_id_start_token->location, |
24282 | "invalid use of constructor as a template" ); |
24283 | inform (declarator_id_start_token->location, |
24284 | "use %<%T::%D%> instead of %<%T::%D%> to " |
24285 | "name the constructor in a qualified name" , |
24286 | class_type, |
24287 | DECL_NAME (TYPE_TI_TEMPLATE (class_type)), |
24288 | class_type, name_type); |
24289 | declarator = cp_error_declarator; |
24290 | break; |
24291 | } |
24292 | unqualified_name = constructor_name (class_type); |
24293 | } |
24294 | |
24295 | if (class_type) |
24296 | { |
24297 | if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR) |
24298 | sfk = sfk_destructor; |
24299 | else if (identifier_p (t: unqualified_name) |
24300 | && IDENTIFIER_CONV_OP_P (unqualified_name)) |
24301 | sfk = sfk_conversion; |
24302 | else if (/* There's no way to declare a constructor |
24303 | for an unnamed type, even if the type |
24304 | got a name for linkage purposes. */ |
24305 | !TYPE_WAS_UNNAMED (class_type) |
24306 | /* Handle correctly (c++/19200): |
24307 | |
24308 | struct S { |
24309 | struct T{}; |
24310 | friend void S(T); |
24311 | }; |
24312 | |
24313 | and also: |
24314 | |
24315 | namespace N { |
24316 | void S(); |
24317 | } |
24318 | |
24319 | struct S { |
24320 | friend void N::S(); |
24321 | }; */ |
24322 | && (!friend_p || class_type == qualifying_scope) |
24323 | && constructor_name_p (unqualified_name, |
24324 | class_type)) |
24325 | sfk = sfk_constructor; |
24326 | else if (is_overloaded_fn (unqualified_name) |
24327 | && DECL_CONSTRUCTOR_P (get_first_fn |
24328 | (unqualified_name))) |
24329 | sfk = sfk_constructor; |
24330 | |
24331 | if (ctor_dtor_or_conv_p && sfk != sfk_none) |
24332 | *ctor_dtor_or_conv_p = -1; |
24333 | } |
24334 | } |
24335 | declarator = make_id_declarator (qualifying_scope, |
24336 | unqualified_name, |
24337 | sfk, id_location: token->location); |
24338 | declarator->std_attributes = attrs; |
24339 | declarator->parameter_pack_p = pack_expansion_p; |
24340 | |
24341 | if (pack_expansion_p) |
24342 | maybe_warn_variadic_templates (); |
24343 | |
24344 | /* We're looking for this case in [temp.res]: |
24345 | A qualified-id is assumed to name a type if [...] |
24346 | - it is a decl-specifier of the decl-specifier-seq of a |
24347 | parameter-declaration in a declarator of a function or |
24348 | function template declaration, ... */ |
24349 | if (cxx_dialect >= cxx20 |
24350 | && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL) |
24351 | && declarator->kind == cdk_id |
24352 | && !at_class_scope_p () |
24353 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
24354 | { |
24355 | /* ...whose declarator-id is qualified. If it isn't, never |
24356 | assume the parameters to refer to types. */ |
24357 | if (qualifying_scope == NULL_TREE) |
24358 | flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
24359 | else |
24360 | { |
24361 | /* Now we have something like |
24362 | template <typename T> int C::x(S::p); |
24363 | which can be a function template declaration or a |
24364 | variable template definition. If name lookup for |
24365 | the declarator-id C::x finds one or more function |
24366 | templates, assume S::p to name a type. Otherwise, |
24367 | don't. */ |
24368 | tree decl |
24369 | = cp_parser_lookup_name (parser, unqualified_name, |
24370 | none_type, |
24371 | /*is_template=*/false, |
24372 | /*is_namespace=*/false, |
24373 | /*check_dependency=*/false, |
24374 | /*ambiguous_decls=*/NULL, |
24375 | token->location); |
24376 | |
24377 | if (!is_overloaded_fn (decl) |
24378 | /* Allow |
24379 | template<typename T> |
24380 | A<T>::A(T::type) { } */ |
24381 | && !(MAYBE_CLASS_TYPE_P (qualifying_scope) |
24382 | && constructor_name_p (unqualified_name, |
24383 | qualifying_scope))) |
24384 | flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
24385 | } |
24386 | } |
24387 | } |
24388 | |
24389 | handle_declarator:; |
24390 | scope = get_scope_of_declarator (declarator); |
24391 | if (scope) |
24392 | { |
24393 | /* Any names that appear after the declarator-id for a |
24394 | member are looked up in the containing scope. */ |
24395 | if (at_function_scope_p ()) |
24396 | { |
24397 | /* But declarations with qualified-ids can't appear in a |
24398 | function. */ |
24399 | cp_parser_error (parser, gmsgid: "qualified-id in declaration" ); |
24400 | declarator = cp_error_declarator; |
24401 | break; |
24402 | } |
24403 | pushed_scope = push_scope (scope); |
24404 | } |
24405 | parser->in_declarator_p = true; |
24406 | if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) |
24407 | || (declarator && declarator->kind == cdk_id)) |
24408 | /* Default args are only allowed on function |
24409 | declarations. */ |
24410 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
24411 | else |
24412 | parser->default_arg_ok_p = false; |
24413 | |
24414 | first = false; |
24415 | } |
24416 | /* We're done. */ |
24417 | else |
24418 | break; |
24419 | } |
24420 | |
24421 | /* For an abstract declarator, we might wind up with nothing at this |
24422 | point. That's an error; the declarator is not optional. */ |
24423 | if (!declarator) |
24424 | cp_parser_error (parser, gmsgid: "expected declarator" ); |
24425 | else if (open_paren) |
24426 | { |
24427 | /* Record overly parenthesized declarator so we can give a |
24428 | diagnostic about confusing decl/expr disambiguation. */ |
24429 | if (declarator->kind == cdk_array) |
24430 | { |
24431 | /* If the open and close parens are on different lines, this |
24432 | is probably a formatting thing, so ignore. */ |
24433 | expanded_location open = expand_location (open_paren->location); |
24434 | expanded_location close = expand_location (close_paren->location); |
24435 | if (open.line != close.line || open.file != close.file) |
24436 | open_paren = NULL; |
24437 | } |
24438 | if (open_paren) |
24439 | declarator->parenthesized = make_location (caret: open_paren->location, |
24440 | start: open_paren->location, |
24441 | finish: close_paren->location); |
24442 | } |
24443 | |
24444 | /* If we entered a scope, we must exit it now. */ |
24445 | if (pushed_scope) |
24446 | pop_scope (pushed_scope); |
24447 | |
24448 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
24449 | parser->in_declarator_p = saved_in_declarator_p; |
24450 | |
24451 | return declarator; |
24452 | } |
24453 | |
24454 | /* Parse a ptr-operator. |
24455 | |
24456 | ptr-operator: |
24457 | * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) |
24458 | * cv-qualifier-seq [opt] |
24459 | & |
24460 | :: [opt] nested-name-specifier * cv-qualifier-seq [opt] |
24461 | nested-name-specifier * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) |
24462 | |
24463 | GNU Extension: |
24464 | |
24465 | ptr-operator: |
24466 | & cv-qualifier-seq [opt] |
24467 | |
24468 | Returns INDIRECT_REF if a pointer, or pointer-to-member, was used. |
24469 | Returns ADDR_EXPR if a reference was used, or NON_LVALUE_EXPR for |
24470 | an rvalue reference. In the case of a pointer-to-member, *TYPE is |
24471 | filled in with the TYPE containing the member. *CV_QUALS is |
24472 | filled in with the cv-qualifier-seq, or TYPE_UNQUALIFIED, if there |
24473 | are no cv-qualifiers. Returns ERROR_MARK if an error occurred. |
24474 | Note that the tree codes returned by this function have nothing |
24475 | to do with the types of trees that will be eventually be created |
24476 | to represent the pointer or reference type being parsed. They are |
24477 | just constants with suggestive names. */ |
24478 | static enum tree_code |
24479 | cp_parser_ptr_operator (cp_parser* parser, |
24480 | tree* type, |
24481 | cp_cv_quals *cv_quals, |
24482 | tree *attributes) |
24483 | { |
24484 | enum tree_code code = ERROR_MARK; |
24485 | cp_token *token; |
24486 | tree attrs = NULL_TREE; |
24487 | |
24488 | /* Assume that it's not a pointer-to-member. */ |
24489 | *type = NULL_TREE; |
24490 | /* And that there are no cv-qualifiers. */ |
24491 | *cv_quals = TYPE_UNQUALIFIED; |
24492 | |
24493 | /* Peek at the next token. */ |
24494 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24495 | |
24496 | /* If it's a `*', `&' or `&&' we have a pointer or reference. */ |
24497 | if (token->type == CPP_MULT) |
24498 | code = INDIRECT_REF; |
24499 | else if (token->type == CPP_AND) |
24500 | code = ADDR_EXPR; |
24501 | else if ((cxx_dialect != cxx98) && |
24502 | token->type == CPP_AND_AND) /* C++0x only */ |
24503 | code = NON_LVALUE_EXPR; |
24504 | |
24505 | if (code != ERROR_MARK) |
24506 | { |
24507 | /* Consume the `*', `&' or `&&'. */ |
24508 | cp_lexer_consume_token (lexer: parser->lexer); |
24509 | |
24510 | /* A `*' can be followed by a cv-qualifier-seq, and so can a |
24511 | `&', if we are allowing GNU extensions. (The only qualifier |
24512 | that can legally appear after `&' is `restrict', but that is |
24513 | enforced during semantic analysis. */ |
24514 | if (code == INDIRECT_REF |
24515 | || cp_parser_allow_gnu_extensions_p (parser)) |
24516 | *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
24517 | |
24518 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24519 | if (attributes != NULL) |
24520 | *attributes = attrs; |
24521 | } |
24522 | else |
24523 | { |
24524 | /* Try the pointer-to-member case. */ |
24525 | cp_parser_parse_tentatively (parser); |
24526 | /* Look for the optional `::' operator. */ |
24527 | cp_parser_global_scope_opt (parser, |
24528 | /*current_scope_valid_p=*/false); |
24529 | /* Look for the nested-name specifier. */ |
24530 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24531 | cp_parser_nested_name_specifier (parser, |
24532 | /*typename_keyword_p=*/false, |
24533 | /*check_dependency_p=*/true, |
24534 | /*type_p=*/false, |
24535 | /*is_declaration=*/false); |
24536 | /* If we found it, and the next token is a `*', then we are |
24537 | indeed looking at a pointer-to-member operator. */ |
24538 | if (!cp_parser_error_occurred (parser) |
24539 | && cp_parser_require (parser, CPP_MULT, RT_MULT)) |
24540 | { |
24541 | /* Indicate that the `*' operator was used. */ |
24542 | code = INDIRECT_REF; |
24543 | |
24544 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
24545 | error_at (token->location, "%qD is a namespace" , parser->scope); |
24546 | else if (TREE_CODE (parser->scope) == ENUMERAL_TYPE) |
24547 | error_at (token->location, "cannot form pointer to member of " |
24548 | "non-class %q#T" , parser->scope); |
24549 | else |
24550 | { |
24551 | /* The type of which the member is a member is given by the |
24552 | current SCOPE. */ |
24553 | *type = parser->scope; |
24554 | /* The next name will not be qualified. */ |
24555 | parser->scope = NULL_TREE; |
24556 | parser->qualifying_scope = NULL_TREE; |
24557 | parser->object_scope = NULL_TREE; |
24558 | /* Look for optional c++11 attributes. */ |
24559 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24560 | if (attributes != NULL) |
24561 | *attributes = attrs; |
24562 | /* Look for the optional cv-qualifier-seq. */ |
24563 | *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
24564 | } |
24565 | } |
24566 | /* If that didn't work we don't have a ptr-operator. */ |
24567 | if (!cp_parser_parse_definitely (parser)) |
24568 | cp_parser_error (parser, gmsgid: "expected ptr-operator" ); |
24569 | } |
24570 | |
24571 | return code; |
24572 | } |
24573 | |
24574 | /* Parse an (optional) cv-qualifier-seq. |
24575 | |
24576 | cv-qualifier-seq: |
24577 | cv-qualifier cv-qualifier-seq [opt] |
24578 | |
24579 | cv-qualifier: |
24580 | const |
24581 | volatile |
24582 | |
24583 | GNU Extension: |
24584 | |
24585 | cv-qualifier: |
24586 | __restrict__ |
24587 | |
24588 | Returns a bitmask representing the cv-qualifiers. */ |
24589 | |
24590 | static cp_cv_quals |
24591 | cp_parser_cv_qualifier_seq_opt (cp_parser* parser) |
24592 | { |
24593 | cp_cv_quals cv_quals = TYPE_UNQUALIFIED; |
24594 | |
24595 | while (true) |
24596 | { |
24597 | cp_token *token; |
24598 | cp_cv_quals cv_qualifier; |
24599 | |
24600 | /* Peek at the next token. */ |
24601 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24602 | /* See if it's a cv-qualifier. */ |
24603 | switch (token->keyword) |
24604 | { |
24605 | case RID_CONST: |
24606 | cv_qualifier = TYPE_QUAL_CONST; |
24607 | break; |
24608 | |
24609 | case RID_VOLATILE: |
24610 | cv_qualifier = TYPE_QUAL_VOLATILE; |
24611 | break; |
24612 | |
24613 | case RID_RESTRICT: |
24614 | cv_qualifier = TYPE_QUAL_RESTRICT; |
24615 | break; |
24616 | |
24617 | default: |
24618 | cv_qualifier = TYPE_UNQUALIFIED; |
24619 | break; |
24620 | } |
24621 | |
24622 | if (!cv_qualifier) |
24623 | break; |
24624 | |
24625 | if (cv_quals & cv_qualifier) |
24626 | { |
24627 | gcc_rich_location richloc (token->location); |
24628 | richloc.add_fixit_remove (); |
24629 | error_at (&richloc, "duplicate cv-qualifier" ); |
24630 | cp_lexer_purge_token (lexer: parser->lexer); |
24631 | } |
24632 | else |
24633 | { |
24634 | cp_lexer_consume_token (lexer: parser->lexer); |
24635 | cv_quals |= cv_qualifier; |
24636 | } |
24637 | } |
24638 | |
24639 | return cv_quals; |
24640 | } |
24641 | |
24642 | /* Parse an (optional) ref-qualifier |
24643 | |
24644 | ref-qualifier: |
24645 | & |
24646 | && |
24647 | |
24648 | Returns cp_ref_qualifier representing ref-qualifier. */ |
24649 | |
24650 | static cp_ref_qualifier |
24651 | cp_parser_ref_qualifier_opt (cp_parser* parser) |
24652 | { |
24653 | cp_ref_qualifier ref_qual = REF_QUAL_NONE; |
24654 | |
24655 | /* Don't try to parse bitwise '&' as a ref-qualifier (c++/57532). */ |
24656 | if (cxx_dialect < cxx11 && cp_parser_parsing_tentatively (parser)) |
24657 | return ref_qual; |
24658 | |
24659 | while (true) |
24660 | { |
24661 | cp_ref_qualifier curr_ref_qual = REF_QUAL_NONE; |
24662 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
24663 | |
24664 | switch (token->type) |
24665 | { |
24666 | case CPP_AND: |
24667 | curr_ref_qual = REF_QUAL_LVALUE; |
24668 | break; |
24669 | |
24670 | case CPP_AND_AND: |
24671 | curr_ref_qual = REF_QUAL_RVALUE; |
24672 | break; |
24673 | |
24674 | default: |
24675 | curr_ref_qual = REF_QUAL_NONE; |
24676 | break; |
24677 | } |
24678 | |
24679 | if (!curr_ref_qual) |
24680 | break; |
24681 | else if (ref_qual) |
24682 | { |
24683 | error_at (token->location, "multiple ref-qualifiers" ); |
24684 | cp_lexer_purge_token (lexer: parser->lexer); |
24685 | } |
24686 | else |
24687 | { |
24688 | ref_qual = curr_ref_qual; |
24689 | cp_lexer_consume_token (lexer: parser->lexer); |
24690 | } |
24691 | } |
24692 | |
24693 | return ref_qual; |
24694 | } |
24695 | |
24696 | /* Parse an optional tx-qualifier. |
24697 | |
24698 | tx-qualifier: |
24699 | transaction_safe |
24700 | transaction_safe_dynamic */ |
24701 | |
24702 | static tree |
24703 | cp_parser_tx_qualifier_opt (cp_parser *parser) |
24704 | { |
24705 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
24706 | if (token->type == CPP_NAME) |
24707 | { |
24708 | tree name = token->u.value; |
24709 | const char *p = IDENTIFIER_POINTER (name); |
24710 | const int len = strlen (s: "transaction_safe" ); |
24711 | if (startswith (str: p, prefix: "transaction_safe" )) |
24712 | { |
24713 | p += len; |
24714 | if (*p == '\0' |
24715 | || !strcmp (s1: p, s2: "_dynamic" )) |
24716 | { |
24717 | cp_lexer_consume_token (lexer: parser->lexer); |
24718 | if (!flag_tm) |
24719 | { |
24720 | error ("%qE requires %<-fgnu-tm%>" , name); |
24721 | return NULL_TREE; |
24722 | } |
24723 | else |
24724 | return name; |
24725 | } |
24726 | } |
24727 | } |
24728 | return NULL_TREE; |
24729 | } |
24730 | |
24731 | /* Parse an (optional) virt-specifier-seq. |
24732 | |
24733 | virt-specifier-seq: |
24734 | virt-specifier virt-specifier-seq [opt] |
24735 | |
24736 | virt-specifier: |
24737 | override |
24738 | final |
24739 | |
24740 | Returns a bitmask representing the virt-specifiers. */ |
24741 | |
24742 | static cp_virt_specifiers |
24743 | cp_parser_virt_specifier_seq_opt (cp_parser* parser) |
24744 | { |
24745 | cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; |
24746 | |
24747 | while (true) |
24748 | { |
24749 | cp_token *token; |
24750 | cp_virt_specifiers virt_specifier; |
24751 | |
24752 | /* Peek at the next token. */ |
24753 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24754 | /* See if it's a virt-specifier-qualifier. */ |
24755 | if (token->type != CPP_NAME) |
24756 | break; |
24757 | if (id_equal (id: token->u.value, str: "override" )) |
24758 | { |
24759 | maybe_warn_cpp0x (str: CPP0X_OVERRIDE_CONTROLS); |
24760 | virt_specifier = VIRT_SPEC_OVERRIDE; |
24761 | } |
24762 | else if (id_equal (id: token->u.value, str: "final" )) |
24763 | { |
24764 | maybe_warn_cpp0x (str: CPP0X_OVERRIDE_CONTROLS); |
24765 | virt_specifier = VIRT_SPEC_FINAL; |
24766 | } |
24767 | else if (id_equal (id: token->u.value, str: "__final" )) |
24768 | { |
24769 | virt_specifier = VIRT_SPEC_FINAL; |
24770 | } |
24771 | else |
24772 | break; |
24773 | |
24774 | if (virt_specifiers & virt_specifier) |
24775 | { |
24776 | gcc_rich_location richloc (token->location); |
24777 | richloc.add_fixit_remove (); |
24778 | error_at (&richloc, "duplicate virt-specifier" ); |
24779 | cp_lexer_purge_token (lexer: parser->lexer); |
24780 | } |
24781 | else |
24782 | { |
24783 | cp_lexer_consume_token (lexer: parser->lexer); |
24784 | virt_specifiers |= virt_specifier; |
24785 | } |
24786 | } |
24787 | return virt_specifiers; |
24788 | } |
24789 | |
24790 | /* Used by handling of trailing-return-types and NSDMI, in which 'this' |
24791 | is in scope even though it isn't real. */ |
24792 | |
24793 | void |
24794 | inject_this_parameter (tree ctype, cp_cv_quals quals) |
24795 | { |
24796 | tree this_parm; |
24797 | |
24798 | if (current_class_ptr) |
24799 | { |
24800 | /* We don't clear this between NSDMIs. Is it already what we want? */ |
24801 | tree type = TREE_TYPE (TREE_TYPE (current_class_ptr)); |
24802 | if (DECL_P (current_class_ptr) |
24803 | && DECL_CONTEXT (current_class_ptr) == NULL_TREE |
24804 | && same_type_ignoring_top_level_qualifiers_p (ctype, type) |
24805 | && cp_type_quals (type) == quals) |
24806 | return; |
24807 | } |
24808 | |
24809 | this_parm = build_this_parm (NULL_TREE, ctype, quals); |
24810 | /* Clear this first to avoid shortcut in cp_build_indirect_ref. */ |
24811 | current_class_ptr = NULL_TREE; |
24812 | current_class_ref |
24813 | = cp_build_fold_indirect_ref (this_parm); |
24814 | current_class_ptr = this_parm; |
24815 | } |
24816 | |
24817 | /* Return true iff our current scope is a non-static data member |
24818 | initializer. */ |
24819 | |
24820 | bool |
24821 | parsing_nsdmi (void) |
24822 | { |
24823 | /* We recognize NSDMI context by the context-less 'this' pointer set up |
24824 | by the function above. */ |
24825 | if (current_class_ptr |
24826 | && TREE_CODE (current_class_ptr) == PARM_DECL |
24827 | && DECL_CONTEXT (current_class_ptr) == NULL_TREE) |
24828 | return true; |
24829 | return false; |
24830 | } |
24831 | |
24832 | /* True if we're parsing a function declarator. */ |
24833 | |
24834 | bool |
24835 | parsing_function_declarator () |
24836 | { |
24837 | /* this_entity is NULL for a function parameter scope while parsing the |
24838 | declarator; it is set when parsing the body of the function. */ |
24839 | return (current_binding_level->kind == sk_function_parms |
24840 | && !current_binding_level->this_entity); |
24841 | } |
24842 | |
24843 | /* Parse a late-specified return type, if any. This is not a separate |
24844 | non-terminal, but part of a function declarator, which looks like |
24845 | |
24846 | -> trailing-type-specifier-seq abstract-declarator(opt) |
24847 | |
24848 | Returns the type indicated by the type-id. |
24849 | |
24850 | In addition to this, parse any queued up #pragma omp declare simd |
24851 | clauses, and #pragma acc routine clauses. |
24852 | |
24853 | QUALS is either a bitmask of cv_qualifiers or -1 for a non-member |
24854 | function. */ |
24855 | |
24856 | static tree |
24857 | cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator, |
24858 | tree& requires_clause) |
24859 | { |
24860 | cp_token *token; |
24861 | tree type = NULL_TREE; |
24862 | bool declare_simd_p = (parser->omp_declare_simd |
24863 | && declarator |
24864 | && declarator->kind == cdk_id); |
24865 | |
24866 | bool oacc_routine_p = (parser->oacc_routine |
24867 | && declarator |
24868 | && declarator->kind == cdk_id); |
24869 | |
24870 | /* Peek at the next token. */ |
24871 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24872 | /* A late-specified return type is indicated by an initial '->'. */ |
24873 | if (token->type != CPP_DEREF |
24874 | && token->keyword != RID_REQUIRES |
24875 | && !(token->type == CPP_NAME |
24876 | && token->u.value == ridpointers[RID_REQUIRES]) |
24877 | && !(declare_simd_p || oacc_routine_p)) |
24878 | return NULL_TREE; |
24879 | |
24880 | if (token->type == CPP_DEREF) |
24881 | { |
24882 | /* Consume the ->. */ |
24883 | cp_lexer_consume_token (lexer: parser->lexer); |
24884 | |
24885 | type = cp_parser_trailing_type_id (parser); |
24886 | } |
24887 | |
24888 | /* Function declarations may be followed by a trailing |
24889 | requires-clause. */ |
24890 | requires_clause = cp_parser_requires_clause_opt (parser, false); |
24891 | |
24892 | if (declare_simd_p) |
24893 | declarator->attributes |
24894 | = cp_parser_late_parsing_omp_declare_simd (parser, |
24895 | declarator->attributes); |
24896 | if (oacc_routine_p) |
24897 | declarator->attributes |
24898 | = cp_parser_late_parsing_oacc_routine (parser, |
24899 | declarator->attributes); |
24900 | |
24901 | return type; |
24902 | } |
24903 | |
24904 | /* Parse a declarator-id. |
24905 | |
24906 | declarator-id: |
24907 | id-expression |
24908 | :: [opt] nested-name-specifier [opt] type-name |
24909 | |
24910 | In the `id-expression' case, the value returned is as for |
24911 | cp_parser_id_expression if the id-expression was an unqualified-id. |
24912 | If the id-expression was a qualified-id, then a SCOPE_REF is |
24913 | returned. The first operand is the scope (either a NAMESPACE_DECL |
24914 | or TREE_TYPE), but the second is still just a representation of an |
24915 | unqualified-id. */ |
24916 | |
24917 | static tree |
24918 | cp_parser_declarator_id (cp_parser* parser, bool optional_p) |
24919 | { |
24920 | tree id; |
24921 | /* The expression must be an id-expression. Assume that qualified |
24922 | names are the names of types so that: |
24923 | |
24924 | template <class T> |
24925 | int S<T>::R::i = 3; |
24926 | |
24927 | will work; we must treat `S<T>::R' as the name of a type. |
24928 | Similarly, assume that qualified names are templates, where |
24929 | required, so that: |
24930 | |
24931 | template <class T> |
24932 | int S<T>::R<T>::i = 3; |
24933 | |
24934 | will work, too. */ |
24935 | id = cp_parser_id_expression (parser, |
24936 | /*template_keyword_p=*/false, |
24937 | /*check_dependency_p=*/false, |
24938 | /*template_p=*/NULL, |
24939 | /*declarator_p=*/true, |
24940 | optional_p); |
24941 | if (id && BASELINK_P (id)) |
24942 | id = BASELINK_FUNCTIONS (id); |
24943 | return id; |
24944 | } |
24945 | |
24946 | /* Parse a type-id. |
24947 | |
24948 | type-id: |
24949 | type-specifier-seq abstract-declarator [opt] |
24950 | |
24951 | The parser flags FLAGS is used to control type-specifier parsing. |
24952 | |
24953 | If IS_TEMPLATE_ARG is true, we are parsing a template argument. |
24954 | |
24955 | If IS_TRAILING_RETURN is true, we are in a trailing-return-type, |
24956 | i.e. we've just seen "->". |
24957 | |
24958 | Returns the TYPE specified. */ |
24959 | |
24960 | static tree |
24961 | cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags, |
24962 | bool is_template_arg, bool is_trailing_return, |
24963 | location_t *type_location) |
24964 | { |
24965 | cp_decl_specifier_seq type_specifier_seq; |
24966 | cp_declarator *abstract_declarator; |
24967 | |
24968 | /* Parse the type-specifier-seq. */ |
24969 | cp_parser_type_specifier_seq (parser, flags, |
24970 | /*is_declaration=*/false, |
24971 | is_trailing_return, |
24972 | &type_specifier_seq); |
24973 | if (type_location) |
24974 | *type_location = type_specifier_seq.locations[ds_type_spec]; |
24975 | |
24976 | if (is_template_arg && type_specifier_seq.type |
24977 | && TREE_CODE (type_specifier_seq.type) == TEMPLATE_TYPE_PARM |
24978 | && CLASS_PLACEHOLDER_TEMPLATE (type_specifier_seq.type)) |
24979 | /* A bare template name as a template argument is a template template |
24980 | argument, not a placeholder, so fail parsing it as a type argument. */ |
24981 | { |
24982 | gcc_assert (cp_parser_uncommitted_to_tentative_parse_p (parser)); |
24983 | cp_parser_simulate_error (parser); |
24984 | return error_mark_node; |
24985 | } |
24986 | if (type_specifier_seq.type == error_mark_node) |
24987 | return error_mark_node; |
24988 | |
24989 | /* There might or might not be an abstract declarator. */ |
24990 | cp_parser_parse_tentatively (parser); |
24991 | /* Look for the declarator. */ |
24992 | abstract_declarator |
24993 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_ABSTRACT, |
24994 | flags: CP_PARSER_FLAGS_NONE, NULL, |
24995 | /*parenthesized_p=*/NULL, |
24996 | /*member_p=*/false, |
24997 | /*friend_p=*/false, |
24998 | /*static_p=*/false); |
24999 | /* Check to see if there really was a declarator. */ |
25000 | if (!cp_parser_parse_definitely (parser)) |
25001 | abstract_declarator = NULL; |
25002 | |
25003 | bool auto_typeid_ok = false; |
25004 | /* The concepts TS allows 'auto' as a type-id. */ |
25005 | if (flag_concepts_ts) |
25006 | auto_typeid_ok = !parser->in_type_id_in_expr_p; |
25007 | /* DR 625 prohibits use of auto as a template-argument. We allow 'auto' |
25008 | outside the template-argument-list context here only for the sake of |
25009 | diagnostic: grokdeclarator then can emit a better error message for |
25010 | e.g. using T = auto. */ |
25011 | else if (flag_concepts) |
25012 | auto_typeid_ok = (!parser->in_type_id_in_expr_p |
25013 | && !parser->in_template_argument_list_p); |
25014 | |
25015 | if (type_specifier_seq.type |
25016 | && !auto_typeid_ok |
25017 | /* None of the valid uses of 'auto' in C++14 involve the type-id |
25018 | nonterminal, but it is valid in a trailing-return-type. */ |
25019 | && !(cxx_dialect >= cxx14 && is_trailing_return)) |
25020 | if (tree auto_node = type_uses_auto (type_specifier_seq.type)) |
25021 | { |
25022 | /* A type-id with type 'auto' is only ok if the abstract declarator |
25023 | is a function declarator with a late-specified return type. |
25024 | |
25025 | A type-id with 'auto' is also valid in a trailing-return-type |
25026 | in a compound-requirement. */ |
25027 | if (abstract_declarator |
25028 | && abstract_declarator->kind == cdk_function |
25029 | && abstract_declarator->u.function.late_return_type) |
25030 | /* OK */; |
25031 | else if (parser->in_result_type_constraint_p) |
25032 | /* OK */; |
25033 | else |
25034 | { |
25035 | if (!cp_parser_simulate_error (parser)) |
25036 | { |
25037 | location_t loc = type_specifier_seq.locations[ds_type_spec]; |
25038 | if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) |
25039 | { |
25040 | auto_diagnostic_group g; |
25041 | gcc_rich_location richloc (loc); |
25042 | richloc.add_fixit_insert_after (new_content: "<>" ); |
25043 | error_at (&richloc, "missing template arguments after %qE" , |
25044 | tmpl); |
25045 | inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here" , |
25046 | tmpl); |
25047 | } |
25048 | else if (parser->in_template_argument_list_p) |
25049 | error_at (loc, "%qT not permitted in template argument" , |
25050 | auto_node); |
25051 | else |
25052 | error_at (loc, "invalid use of %qT" , auto_node); |
25053 | } |
25054 | return error_mark_node; |
25055 | } |
25056 | } |
25057 | |
25058 | return groktypename (&type_specifier_seq, abstract_declarator, |
25059 | is_template_arg); |
25060 | } |
25061 | |
25062 | /* Wrapper for cp_parser_type_id_1. */ |
25063 | |
25064 | static tree |
25065 | cp_parser_type_id (cp_parser *parser, cp_parser_flags flags, |
25066 | location_t *type_location) |
25067 | { |
25068 | return cp_parser_type_id_1 (parser, flags, is_template_arg: false, is_trailing_return: false, type_location); |
25069 | } |
25070 | |
25071 | /* Wrapper for cp_parser_type_id_1. */ |
25072 | |
25073 | static tree |
25074 | cp_parser_template_type_arg (cp_parser *parser) |
25075 | { |
25076 | const char *saved_message = parser->type_definition_forbidden_message; |
25077 | parser->type_definition_forbidden_message |
25078 | = G_("types may not be defined in template arguments" ); |
25079 | tree r = cp_parser_type_id_1 (parser, flags: CP_PARSER_FLAGS_NONE, |
25080 | /*is_template_arg=*/true, |
25081 | /*is_trailing_return=*/false, type_location: nullptr); |
25082 | parser->type_definition_forbidden_message = saved_message; |
25083 | /* cp_parser_type_id_1 checks for auto, but only for |
25084 | ->auto_is_implicit_function_template_parm_p. */ |
25085 | if (cxx_dialect >= cxx14 && !flag_concepts_ts && type_uses_auto (r)) |
25086 | { |
25087 | error ("invalid use of %<auto%> in template argument" ); |
25088 | r = error_mark_node; |
25089 | } |
25090 | return r; |
25091 | } |
25092 | |
25093 | /* Wrapper for cp_parser_type_id_1. */ |
25094 | |
25095 | static tree |
25096 | cp_parser_trailing_type_id (cp_parser *parser) |
25097 | { |
25098 | return cp_parser_type_id_1 (parser, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
25099 | is_template_arg: false, is_trailing_return: true, NULL); |
25100 | } |
25101 | |
25102 | /* Parse a type-specifier-seq. |
25103 | |
25104 | type-specifier-seq: |
25105 | type-specifier type-specifier-seq [opt] |
25106 | |
25107 | GNU extension: |
25108 | |
25109 | type-specifier-seq: |
25110 | attributes type-specifier-seq [opt] |
25111 | |
25112 | The parser flags FLAGS is used to control type-specifier parsing. |
25113 | |
25114 | If IS_DECLARATION is true, we are at the start of a "condition" or |
25115 | exception-declaration, so we might be followed by a declarator-id. |
25116 | |
25117 | If IS_TRAILING_RETURN is true, we are in a trailing-return-type, |
25118 | i.e. we've just seen "->". |
25119 | |
25120 | Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */ |
25121 | |
25122 | static void |
25123 | cp_parser_type_specifier_seq (cp_parser* parser, |
25124 | cp_parser_flags flags, |
25125 | bool is_declaration, |
25126 | bool is_trailing_return, |
25127 | cp_decl_specifier_seq *type_specifier_seq) |
25128 | { |
25129 | bool seen_type_specifier = false; |
25130 | cp_token *start_token = NULL; |
25131 | |
25132 | /* Clear the TYPE_SPECIFIER_SEQ. */ |
25133 | clear_decl_specs (decl_specs: type_specifier_seq); |
25134 | |
25135 | flags |= CP_PARSER_FLAGS_OPTIONAL; |
25136 | /* In the context of a trailing return type, enum E { } is an |
25137 | elaborated-type-specifier followed by a function-body, not an |
25138 | enum-specifier. */ |
25139 | if (is_trailing_return) |
25140 | flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS; |
25141 | |
25142 | /* Parse the type-specifiers and attributes. */ |
25143 | while (true) |
25144 | { |
25145 | tree type_specifier; |
25146 | bool is_cv_qualifier; |
25147 | |
25148 | /* Check for attributes first. */ |
25149 | if (cp_next_tokens_can_be_attribute_p (parser)) |
25150 | { |
25151 | /* GNU attributes at the end of a declaration apply to the |
25152 | declaration as a whole, not to the trailing return type. So look |
25153 | ahead to see if these attributes are at the end. */ |
25154 | if (seen_type_specifier && is_trailing_return |
25155 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
25156 | { |
25157 | size_t n = cp_parser_skip_attributes_opt (parser, 1); |
25158 | cp_token *tok = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
25159 | if (tok->type == CPP_SEMICOLON || tok->type == CPP_COMMA |
25160 | || tok->type == CPP_EQ || tok->type == CPP_OPEN_BRACE) |
25161 | break; |
25162 | } |
25163 | type_specifier_seq->attributes |
25164 | = attr_chainon (attrs: type_specifier_seq->attributes, |
25165 | attr: cp_parser_attributes_opt (parser)); |
25166 | continue; |
25167 | } |
25168 | |
25169 | /* record the token of the beginning of the type specifier seq, |
25170 | for error reporting purposes*/ |
25171 | if (!start_token) |
25172 | start_token = cp_lexer_peek_token (lexer: parser->lexer); |
25173 | |
25174 | /* Look for the type-specifier. */ |
25175 | type_specifier = cp_parser_type_specifier (parser, |
25176 | flags, |
25177 | decl_specs: type_specifier_seq, |
25178 | /*is_declaration=*/false, |
25179 | NULL, |
25180 | is_cv_qualifier: &is_cv_qualifier); |
25181 | if (!type_specifier) |
25182 | { |
25183 | /* If the first type-specifier could not be found, this is not a |
25184 | type-specifier-seq at all. */ |
25185 | if (!seen_type_specifier) |
25186 | { |
25187 | /* Set in_declarator_p to avoid skipping to the semicolon. */ |
25188 | int in_decl = parser->in_declarator_p; |
25189 | parser->in_declarator_p = true; |
25190 | |
25191 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
25192 | || !cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
25193 | cp_parser_error (parser, gmsgid: "expected type-specifier" ); |
25194 | |
25195 | parser->in_declarator_p = in_decl; |
25196 | |
25197 | type_specifier_seq->type = error_mark_node; |
25198 | return; |
25199 | } |
25200 | /* If subsequent type-specifiers could not be found, the |
25201 | type-specifier-seq is complete. */ |
25202 | break; |
25203 | } |
25204 | |
25205 | seen_type_specifier = true; |
25206 | /* The standard says that a condition can be: |
25207 | |
25208 | type-specifier-seq declarator = assignment-expression |
25209 | |
25210 | However, given: |
25211 | |
25212 | struct S {}; |
25213 | if (int S = ...) |
25214 | |
25215 | we should treat the "S" as a declarator, not as a |
25216 | type-specifier. The standard doesn't say that explicitly for |
25217 | type-specifier-seq, but it does say that for |
25218 | decl-specifier-seq in an ordinary declaration. Perhaps it |
25219 | would be clearer just to allow a decl-specifier-seq here, and |
25220 | then add a semantic restriction that if any decl-specifiers |
25221 | that are not type-specifiers appear, the program is invalid. */ |
25222 | if (is_declaration && !is_cv_qualifier) |
25223 | flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; |
25224 | } |
25225 | } |
25226 | |
25227 | /* Return whether the function currently being declared has an associated |
25228 | template parameter list. */ |
25229 | |
25230 | static bool |
25231 | function_being_declared_is_template_p (cp_parser* parser) |
25232 | { |
25233 | if (!current_template_parms || processing_template_parmlist) |
25234 | return false; |
25235 | |
25236 | if (parser->implicit_template_scope) |
25237 | return true; |
25238 | |
25239 | if (at_class_scope_p () |
25240 | && TYPE_BEING_DEFINED (current_class_type)) |
25241 | return parser->num_template_parameter_lists != 0; |
25242 | |
25243 | return ((int) parser->num_template_parameter_lists > template_class_depth |
25244 | (current_class_type)); |
25245 | } |
25246 | |
25247 | /* Parse a parameter-declaration-clause. |
25248 | |
25249 | parameter-declaration-clause: |
25250 | parameter-declaration-list [opt] ... [opt] |
25251 | parameter-declaration-list , ... |
25252 | |
25253 | The parser flags FLAGS is used to control type-specifier parsing. |
25254 | |
25255 | Returns a representation for the parameter declarations. A return |
25256 | value of NULL indicates a parameter-declaration-clause consisting |
25257 | only of an ellipsis. */ |
25258 | |
25259 | static tree |
25260 | cp_parser_parameter_declaration_clause (cp_parser* parser, |
25261 | cp_parser_flags flags) |
25262 | { |
25263 | tree parameters; |
25264 | cp_token *token; |
25265 | bool ellipsis_p; |
25266 | |
25267 | auto cleanup = make_temp_override |
25268 | (var&: parser->auto_is_implicit_function_template_parm_p); |
25269 | |
25270 | if (!processing_specialization |
25271 | && !processing_template_parmlist |
25272 | && !processing_explicit_instantiation |
25273 | /* default_arg_ok_p tracks whether this is a parameter-clause for an |
25274 | actual function or a random abstract declarator. */ |
25275 | && parser->default_arg_ok_p) |
25276 | if (!current_function_decl |
25277 | || (current_class_type && LAMBDA_TYPE_P (current_class_type))) |
25278 | parser->auto_is_implicit_function_template_parm_p = true; |
25279 | |
25280 | /* Peek at the next token. */ |
25281 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25282 | /* Check for trivial parameter-declaration-clauses. */ |
25283 | if (token->type == CPP_ELLIPSIS) |
25284 | { |
25285 | /* Consume the `...' token. */ |
25286 | cp_lexer_consume_token (lexer: parser->lexer); |
25287 | return NULL_TREE; |
25288 | } |
25289 | else if (token->type == CPP_CLOSE_PAREN) |
25290 | /* There are no parameters. */ |
25291 | return void_list_node; |
25292 | /* Check for `(void)', too, which is a special case. */ |
25293 | else if (token->keyword == RID_VOID |
25294 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
25295 | == CPP_CLOSE_PAREN)) |
25296 | { |
25297 | /* Consume the `void' token. */ |
25298 | cp_lexer_consume_token (lexer: parser->lexer); |
25299 | /* There are no parameters. */ |
25300 | return explicit_void_list_node; |
25301 | } |
25302 | |
25303 | /* A vector of parameters that haven't been pushed yet. */ |
25304 | auto_vec<tree> pending_decls; |
25305 | |
25306 | /* Parse the parameter-declaration-list. */ |
25307 | parameters = cp_parser_parameter_declaration_list (parser, flags, |
25308 | &pending_decls); |
25309 | /* If a parse error occurred while parsing the |
25310 | parameter-declaration-list, then the entire |
25311 | parameter-declaration-clause is erroneous. */ |
25312 | if (parameters == error_mark_node) |
25313 | return NULL_TREE; |
25314 | |
25315 | /* Peek at the next token. */ |
25316 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25317 | /* If it's a `,', the clause should terminate with an ellipsis. */ |
25318 | if (token->type == CPP_COMMA) |
25319 | { |
25320 | /* Consume the `,'. */ |
25321 | cp_lexer_consume_token (lexer: parser->lexer); |
25322 | /* Expect an ellipsis. */ |
25323 | ellipsis_p |
25324 | = (cp_parser_require (parser, CPP_ELLIPSIS, RT_ELLIPSIS) != NULL); |
25325 | } |
25326 | /* It might also be `...' if the optional trailing `,' was |
25327 | omitted. */ |
25328 | else if (token->type == CPP_ELLIPSIS) |
25329 | { |
25330 | /* Consume the `...' token. */ |
25331 | cp_lexer_consume_token (lexer: parser->lexer); |
25332 | /* And remember that we saw it. */ |
25333 | ellipsis_p = true; |
25334 | } |
25335 | else |
25336 | ellipsis_p = false; |
25337 | |
25338 | /* A valid parameter-declaration-clause can only be followed by a ')'. |
25339 | So it's time to push all the parameters we have seen now that we |
25340 | know we have a valid declaration. Note that here we may not have |
25341 | committed yet, nor should we. Pushing here will detect the error |
25342 | of redefining a parameter. */ |
25343 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
25344 | { |
25345 | for (tree p : pending_decls) |
25346 | pushdecl (p); |
25347 | |
25348 | /* Delayed checking of auto parameters. */ |
25349 | if (!parser->auto_is_implicit_function_template_parm_p |
25350 | && cxx_dialect >= cxx14) |
25351 | for (tree p = parameters; p; p = TREE_CHAIN (p)) |
25352 | if (type_uses_auto (TREE_TYPE (TREE_VALUE (p)))) |
25353 | { |
25354 | error_at (location_of (TREE_VALUE (p)), |
25355 | "%<auto%> parameter not permitted in this context" ); |
25356 | TREE_TYPE (TREE_VALUE (p)) = error_mark_node; |
25357 | } |
25358 | } |
25359 | |
25360 | /* Finish the parameter list. */ |
25361 | if (!ellipsis_p) |
25362 | parameters = chainon (parameters, void_list_node); |
25363 | |
25364 | return parameters; |
25365 | } |
25366 | |
25367 | /* Parse a parameter-declaration-list. |
25368 | |
25369 | parameter-declaration-list: |
25370 | parameter-declaration |
25371 | parameter-declaration-list , parameter-declaration |
25372 | |
25373 | The parser flags FLAGS is used to control type-specifier parsing. |
25374 | PENDING_DECLS is a vector of parameters that haven't been pushed yet. |
25375 | |
25376 | Returns a representation of the parameter-declaration-list, as for |
25377 | cp_parser_parameter_declaration_clause. However, the |
25378 | `void_list_node' is never appended to the list. */ |
25379 | |
25380 | static tree |
25381 | cp_parser_parameter_declaration_list (cp_parser* parser, |
25382 | cp_parser_flags flags, |
25383 | auto_vec<tree> *pending_decls) |
25384 | { |
25385 | tree parameters = NULL_TREE; |
25386 | tree *tail = ¶meters; |
25387 | bool saved_in_unbraced_linkage_specification_p; |
25388 | int index = 0; |
25389 | |
25390 | /* The special considerations that apply to a function within an |
25391 | unbraced linkage specifications do not apply to the parameters |
25392 | to the function. */ |
25393 | saved_in_unbraced_linkage_specification_p |
25394 | = parser->in_unbraced_linkage_specification_p; |
25395 | parser->in_unbraced_linkage_specification_p = false; |
25396 | |
25397 | /* Look for more parameters. */ |
25398 | while (true) |
25399 | { |
25400 | cp_parameter_declarator *parameter; |
25401 | tree decl = error_mark_node; |
25402 | bool parenthesized_p = false; |
25403 | |
25404 | /* Parse the parameter. */ |
25405 | parameter |
25406 | = cp_parser_parameter_declaration (parser, flags, |
25407 | /*template_parm_p=*/false, |
25408 | &parenthesized_p); |
25409 | |
25410 | /* We don't know yet if the enclosing context is unavailable or deprecated, |
25411 | so wait and deal with it in grokparms if appropriate. */ |
25412 | deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; |
25413 | |
25414 | if (parameter && !cp_parser_error_occurred (parser)) |
25415 | { |
25416 | decl = grokdeclarator (parameter->declarator, |
25417 | ¶meter->decl_specifiers, |
25418 | PARM, |
25419 | parameter->default_argument != NULL_TREE, |
25420 | ¶meter->decl_specifiers.attributes); |
25421 | if (decl != error_mark_node && parameter->loc != UNKNOWN_LOCATION) |
25422 | DECL_SOURCE_LOCATION (decl) = parameter->loc; |
25423 | } |
25424 | |
25425 | deprecated_state = DEPRECATED_NORMAL; |
25426 | |
25427 | /* If a parse error occurred parsing the parameter declaration, |
25428 | then the entire parameter-declaration-list is erroneous. */ |
25429 | if (decl == error_mark_node) |
25430 | { |
25431 | parameters = error_mark_node; |
25432 | break; |
25433 | } |
25434 | |
25435 | if (parameter->decl_specifiers.attributes) |
25436 | cplus_decl_attributes (&decl, |
25437 | parameter->decl_specifiers.attributes, |
25438 | 0); |
25439 | if (DECL_NAME (decl)) |
25440 | { |
25441 | /* We cannot always pushdecl while parsing tentatively because |
25442 | it may have side effects and we can't be sure yet if we're |
25443 | parsing a declaration, e.g.: |
25444 | |
25445 | S foo(int(x), int(x), int{x}); |
25446 | |
25447 | where it's not clear if we're dealing with a constructor call |
25448 | or a function declaration until we've seen the last argument |
25449 | which breaks it up. |
25450 | It's safe to pushdecl so long as it doesn't result in a clash |
25451 | with an already-pushed parameter. But we don't delay pushing |
25452 | different parameters to handle |
25453 | |
25454 | S foo(int(i), decltype(i) j = 42); |
25455 | |
25456 | which is valid. */ |
25457 | if (pending_decls |
25458 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25459 | /* See if PARAMETERS already contains a parameter with the same |
25460 | DECL_NAME as DECL. */ |
25461 | && [parameters, decl] { |
25462 | for (tree p = parameters; p; p = TREE_CHAIN (p)) |
25463 | if (DECL_NAME (decl) == DECL_NAME (TREE_VALUE (p))) |
25464 | return true; |
25465 | return false; |
25466 | }()) |
25467 | pending_decls->safe_push (obj: decl); |
25468 | else |
25469 | decl = pushdecl (decl); |
25470 | } |
25471 | |
25472 | if (decl != error_mark_node) |
25473 | { |
25474 | retrofit_lang_decl (decl); |
25475 | DECL_PARM_INDEX (decl) = ++index; |
25476 | DECL_PARM_LEVEL (decl) = function_parm_depth (); |
25477 | } |
25478 | |
25479 | /* Add the new parameter to the list. */ |
25480 | *tail = build_tree_list (parameter->default_argument, decl); |
25481 | tail = &TREE_CHAIN (*tail); |
25482 | |
25483 | /* If the parameters were parenthesized, it's the case of |
25484 | T foo(X(x)) which looks like a variable definition but |
25485 | is a function declaration. */ |
25486 | if (index == 1 || PARENTHESIZED_LIST_P (parameters)) |
25487 | PARENTHESIZED_LIST_P (parameters) = parenthesized_p; |
25488 | |
25489 | /* Peek at the next token. */ |
25490 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
25491 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS) |
25492 | /* These are for Objective-C++ */ |
25493 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
25494 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
25495 | /* The parameter-declaration-list is complete. */ |
25496 | break; |
25497 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
25498 | { |
25499 | cp_token *token; |
25500 | |
25501 | /* Peek at the next token. */ |
25502 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
25503 | /* If it's an ellipsis, then the list is complete. */ |
25504 | if (token->type == CPP_ELLIPSIS) |
25505 | break; |
25506 | /* Otherwise, there must be more parameters. Consume the |
25507 | `,'. */ |
25508 | cp_lexer_consume_token (lexer: parser->lexer); |
25509 | /* When parsing something like: |
25510 | |
25511 | int i(float f, double d) |
25512 | |
25513 | we can tell after seeing the declaration for "f" that we |
25514 | are not looking at an initialization of a variable "i", |
25515 | but rather at the declaration of a function "i". |
25516 | |
25517 | Due to the fact that the parsing of template arguments |
25518 | (as specified to a template-id) requires backtracking we |
25519 | cannot use this technique when inside a template argument |
25520 | list. */ |
25521 | if (!parser->in_template_argument_list_p |
25522 | && !parser->in_type_id_in_expr_p |
25523 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25524 | /* However, a parameter-declaration of the form |
25525 | "float(f)" (which is a valid declaration of a |
25526 | parameter "f") can also be interpreted as an |
25527 | expression (the conversion of "f" to "float"). */ |
25528 | && !parenthesized_p) |
25529 | cp_parser_commit_to_tentative_parse (parser); |
25530 | } |
25531 | else |
25532 | { |
25533 | cp_parser_error (parser, gmsgid: "expected %<,%> or %<...%>" ); |
25534 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
25535 | cp_parser_skip_to_closing_parenthesis (parser, |
25536 | /*recovering=*/true, |
25537 | /*or_comma=*/false, |
25538 | /*consume_paren=*/false); |
25539 | break; |
25540 | } |
25541 | } |
25542 | |
25543 | parser->in_unbraced_linkage_specification_p |
25544 | = saved_in_unbraced_linkage_specification_p; |
25545 | |
25546 | /* Reset implicit_template_scope if we are about to leave the function |
25547 | parameter list that introduced it. Note that for out-of-line member |
25548 | definitions, there will be one or more class scopes before we get to |
25549 | the template parameter scope. */ |
25550 | |
25551 | if (cp_binding_level *its = parser->implicit_template_scope) |
25552 | if (cp_binding_level *maybe_its = current_binding_level->level_chain) |
25553 | { |
25554 | while (maybe_its->kind == sk_class) |
25555 | maybe_its = maybe_its->level_chain; |
25556 | if (maybe_its == its) |
25557 | { |
25558 | parser->implicit_template_parms = 0; |
25559 | parser->implicit_template_scope = 0; |
25560 | } |
25561 | } |
25562 | |
25563 | return parameters; |
25564 | } |
25565 | |
25566 | /* Parse a parameter declaration. |
25567 | |
25568 | parameter-declaration: |
25569 | decl-specifier-seq ... [opt] declarator |
25570 | decl-specifier-seq declarator = assignment-expression |
25571 | decl-specifier-seq ... [opt] abstract-declarator [opt] |
25572 | decl-specifier-seq abstract-declarator [opt] = assignment-expression |
25573 | |
25574 | The parser flags FLAGS is used to control type-specifier parsing. |
25575 | |
25576 | If TEMPLATE_PARM_P is TRUE, then this parameter-declaration |
25577 | declares a template parameter. (In that case, a non-nested `>' |
25578 | token encountered during the parsing of the assignment-expression |
25579 | is not interpreted as a greater-than operator.) |
25580 | |
25581 | Returns a representation of the parameter, or NULL if an error |
25582 | occurs. If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to |
25583 | true iff the declarator is of the form "(p)". */ |
25584 | |
25585 | static cp_parameter_declarator * |
25586 | cp_parser_parameter_declaration (cp_parser *parser, |
25587 | cp_parser_flags flags, |
25588 | bool template_parm_p, |
25589 | bool *parenthesized_p) |
25590 | { |
25591 | int declares_class_or_enum; |
25592 | cp_decl_specifier_seq decl_specifiers; |
25593 | cp_declarator *declarator; |
25594 | tree default_argument; |
25595 | cp_token *token = NULL, *declarator_token_start = NULL; |
25596 | const char *saved_message; |
25597 | bool template_parameter_pack_p = false; |
25598 | |
25599 | /* In a template parameter, `>' is not an operator. |
25600 | |
25601 | [temp.param] |
25602 | |
25603 | When parsing a default template-argument for a non-type |
25604 | template-parameter, the first non-nested `>' is taken as the end |
25605 | of the template parameter-list rather than a greater-than |
25606 | operator. */ |
25607 | |
25608 | /* Type definitions may not appear in parameter types. */ |
25609 | saved_message = parser->type_definition_forbidden_message; |
25610 | parser->type_definition_forbidden_message |
25611 | = G_("types may not be defined in parameter types" ); |
25612 | |
25613 | int template_parm_idx = (function_being_declared_is_template_p (parser) ? |
25614 | TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS |
25615 | (current_template_parms)) : 0); |
25616 | |
25617 | /* Parse the declaration-specifiers. */ |
25618 | cp_token *decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
25619 | cp_parser_decl_specifier_seq (parser, |
25620 | flags: flags | CP_PARSER_FLAGS_PARAMETER, |
25621 | decl_specs: &decl_specifiers, |
25622 | declares_class_or_enum: &declares_class_or_enum); |
25623 | |
25624 | /* [dcl.spec.auto.general]: "A placeholder-type-specifier of the form |
25625 | type-constraint opt auto can be used as a decl-specifier of the |
25626 | decl-specifier-seq of a parameter-declaration of a function declaration |
25627 | or lambda-expression..." but we must not synthesize an implicit template |
25628 | type parameter in its declarator. That is, in "void f(auto[auto{10}]);" |
25629 | we want to synthesize only the first auto. */ |
25630 | auto cleanup = make_temp_override |
25631 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
25632 | |
25633 | /* Complain about missing 'typename' or other invalid type names. */ |
25634 | if (!decl_specifiers.any_type_specifiers_p |
25635 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
25636 | decl_specifiers.type = error_mark_node; |
25637 | |
25638 | /* If an error occurred, there's no reason to attempt to parse the |
25639 | rest of the declaration. */ |
25640 | if (cp_parser_error_occurred (parser)) |
25641 | { |
25642 | parser->type_definition_forbidden_message = saved_message; |
25643 | return NULL; |
25644 | } |
25645 | |
25646 | /* Peek at the next token. */ |
25647 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25648 | |
25649 | /* If the next token is a `)', `,', `=', `>', or `...', then there |
25650 | is no declarator. However, when variadic templates are enabled, |
25651 | there may be a declarator following `...'. */ |
25652 | if (token->type == CPP_CLOSE_PAREN |
25653 | || token->type == CPP_COMMA |
25654 | || token->type == CPP_EQ |
25655 | || token->type == CPP_GREATER) |
25656 | { |
25657 | declarator = NULL; |
25658 | if (parenthesized_p) |
25659 | *parenthesized_p = false; |
25660 | } |
25661 | /* Otherwise, there should be a declarator. */ |
25662 | else |
25663 | { |
25664 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
25665 | parser->default_arg_ok_p = false; |
25666 | |
25667 | /* After seeing a decl-specifier-seq, if the next token is not a |
25668 | "(" or "{", there is no possibility that the code is a valid |
25669 | expression. Therefore, if parsing tentatively, we commit at |
25670 | this point. */ |
25671 | if (!parser->in_template_argument_list_p |
25672 | /* In an expression context, having seen: |
25673 | |
25674 | (int((char ... |
25675 | |
25676 | we cannot be sure whether we are looking at a |
25677 | function-type (taking a "char" as a parameter) or a cast |
25678 | of some object of type "char" to "int". */ |
25679 | && !parser->in_type_id_in_expr_p |
25680 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25681 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
25682 | { |
25683 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
25684 | { |
25685 | if (decl_specifiers.type |
25686 | && template_placeholder_p (decl_specifiers.type)) |
25687 | /* This is a CTAD expression, not a parameter declaration. */ |
25688 | cp_parser_simulate_error (parser); |
25689 | } |
25690 | else |
25691 | cp_parser_commit_to_tentative_parse (parser); |
25692 | } |
25693 | /* Parse the declarator. */ |
25694 | declarator_token_start = token; |
25695 | declarator = cp_parser_declarator (parser, |
25696 | dcl_kind: CP_PARSER_DECLARATOR_EITHER, |
25697 | flags: CP_PARSER_FLAGS_NONE, |
25698 | /*ctor_dtor_or_conv_p=*/NULL, |
25699 | parenthesized_p, |
25700 | /*member_p=*/false, |
25701 | /*friend_p=*/false, |
25702 | /*static_p=*/false); |
25703 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
25704 | /* After the declarator, allow more attributes. */ |
25705 | decl_specifiers.attributes |
25706 | = attr_chainon (attrs: decl_specifiers.attributes, |
25707 | attr: cp_parser_attributes_opt (parser)); |
25708 | |
25709 | /* If the declarator is a template parameter pack, remember that and |
25710 | clear the flag in the declarator itself so we don't get errors |
25711 | from grokdeclarator. */ |
25712 | if (template_parm_p && declarator && declarator->parameter_pack_p) |
25713 | { |
25714 | declarator->parameter_pack_p = false; |
25715 | template_parameter_pack_p = true; |
25716 | } |
25717 | } |
25718 | |
25719 | /* If the next token is an ellipsis, and we have not seen a declarator |
25720 | name, and if either the type of the declarator contains parameter |
25721 | packs but it is not a TYPE_PACK_EXPANSION or is null (this happens |
25722 | for, eg, abbreviated integral type names), then we actually have a |
25723 | parameter pack expansion expression. Otherwise, leave the ellipsis |
25724 | for a C-style variadic function. */ |
25725 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25726 | |
25727 | bool xobj_param_p |
25728 | = decl_spec_seq_has_spec_p (&decl_specifiers, ds_this); |
25729 | if (xobj_param_p && template_parm_p) |
25730 | { |
25731 | error_at (decl_specifiers.locations[ds_this], |
25732 | "%<this%> specifier in template parameter declaration" ); |
25733 | xobj_param_p = false; |
25734 | decl_specifiers.locations[ds_this] = 0; |
25735 | } |
25736 | |
25737 | /* If a function parameter pack was specified and an implicit template |
25738 | parameter was introduced during cp_parser_parameter_declaration, |
25739 | change any implicit parameters introduced into packs. */ |
25740 | if (parser->implicit_template_parms |
25741 | && ((token->type == CPP_ELLIPSIS |
25742 | && declarator_can_be_parameter_pack (declarator)) |
25743 | || (declarator && declarator->parameter_pack_p))) |
25744 | { |
25745 | int latest_template_parm_idx = TREE_VEC_LENGTH |
25746 | (INNERMOST_TEMPLATE_PARMS (current_template_parms)); |
25747 | |
25748 | if (latest_template_parm_idx != template_parm_idx) |
25749 | decl_specifiers.type |
25750 | = convert_generic_types_to_packs (decl_specifiers.type, |
25751 | template_parm_idx, |
25752 | latest_template_parm_idx); |
25753 | } |
25754 | |
25755 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
25756 | { |
25757 | tree type = decl_specifiers.type; |
25758 | |
25759 | if (type && DECL_P (type)) |
25760 | type = TREE_TYPE (type); |
25761 | |
25762 | if (((type |
25763 | && TREE_CODE (type) != TYPE_PACK_EXPANSION |
25764 | && (template_parm_p || uses_parameter_packs (type))) |
25765 | || (!type && template_parm_p)) |
25766 | && declarator_can_be_parameter_pack (declarator)) |
25767 | { |
25768 | /* Consume the `...'. */ |
25769 | cp_lexer_consume_token (lexer: parser->lexer); |
25770 | maybe_warn_variadic_templates (); |
25771 | |
25772 | /* Build a pack expansion type */ |
25773 | if (template_parm_p) |
25774 | template_parameter_pack_p = true; |
25775 | else if (declarator) |
25776 | declarator->parameter_pack_p = true; |
25777 | else |
25778 | decl_specifiers.type = make_pack_expansion (type); |
25779 | } |
25780 | } |
25781 | |
25782 | if (xobj_param_p |
25783 | && ((declarator && declarator->parameter_pack_p) |
25784 | || (decl_specifiers.type |
25785 | && PACK_EXPANSION_P (decl_specifiers.type)))) |
25786 | { |
25787 | location_t xobj_param |
25788 | = make_location (caret: decl_specifiers.locations[ds_this], |
25789 | start: decl_spec_token_start->location, |
25790 | finish: input_location); |
25791 | error_at (xobj_param, |
25792 | "an explicit object parameter cannot " |
25793 | "be a function parameter pack" ); |
25794 | xobj_param_p = false; |
25795 | decl_specifiers.locations[ds_this] = 0; |
25796 | } |
25797 | |
25798 | /* The restriction on defining new types applies only to the type |
25799 | of the parameter, not to the default argument. */ |
25800 | parser->type_definition_forbidden_message = saved_message; |
25801 | cp_token *eq_token = NULL; |
25802 | /* If the next token is `=', then process a default argument. */ |
25803 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
25804 | { |
25805 | tree type = decl_specifiers.type; |
25806 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25807 | /* Used for diagnostics with an xobj parameter. */ |
25808 | eq_token = token; |
25809 | if (declarator) |
25810 | declarator->init_loc = token->location; |
25811 | /* If we are defining a class, then the tokens that make up the |
25812 | default argument must be saved and processed later. */ |
25813 | if (!template_parm_p && at_class_scope_p () |
25814 | && TYPE_BEING_DEFINED (current_class_type) |
25815 | && !LAMBDA_TYPE_P (current_class_type)) |
25816 | default_argument = cp_parser_cache_defarg (parser, /*nsdmi=*/false); |
25817 | |
25818 | /* A constrained-type-specifier may declare a type |
25819 | template-parameter. */ |
25820 | else if (declares_constrained_type_template_parameter (type)) |
25821 | default_argument |
25822 | = cp_parser_default_type_template_argument (parser); |
25823 | |
25824 | /* A constrained-type-specifier may declare a |
25825 | template-template-parameter. */ |
25826 | else if (declares_constrained_template_template_parameter (type)) |
25827 | default_argument |
25828 | = cp_parser_default_template_template_argument (parser); |
25829 | |
25830 | /* Outside of a class definition, we can just parse the |
25831 | assignment-expression. */ |
25832 | else |
25833 | default_argument |
25834 | = cp_parser_default_argument (parser, template_parm_p); |
25835 | |
25836 | if (!parser->default_arg_ok_p) |
25837 | { |
25838 | permerror (token->location, |
25839 | "default arguments are only " |
25840 | "permitted for function parameters" ); |
25841 | } |
25842 | else if ((declarator && declarator->parameter_pack_p) |
25843 | || template_parameter_pack_p |
25844 | || (decl_specifiers.type |
25845 | && PACK_EXPANSION_P (decl_specifiers.type))) |
25846 | { |
25847 | /* Find the name of the parameter pack. */ |
25848 | cp_declarator *id_declarator = declarator; |
25849 | while (id_declarator && id_declarator->kind != cdk_id) |
25850 | id_declarator = id_declarator->declarator; |
25851 | |
25852 | if (id_declarator && id_declarator->kind == cdk_id) |
25853 | error_at (declarator_token_start->location, |
25854 | template_parm_p |
25855 | ? G_("template parameter pack %qD " |
25856 | "cannot have a default argument" ) |
25857 | : G_("parameter pack %qD cannot have " |
25858 | "a default argument" ), |
25859 | id_declarator->u.id.unqualified_name); |
25860 | else |
25861 | error_at (declarator_token_start->location, |
25862 | template_parm_p |
25863 | ? G_("template parameter pack cannot have " |
25864 | "a default argument" ) |
25865 | : G_("parameter pack cannot have a " |
25866 | "default argument" )); |
25867 | |
25868 | default_argument = NULL_TREE; |
25869 | } |
25870 | } |
25871 | else |
25872 | default_argument = NULL_TREE; |
25873 | |
25874 | if (default_argument) |
25875 | STRIP_ANY_LOCATION_WRAPPER (default_argument); |
25876 | |
25877 | if (xobj_param_p) |
25878 | { |
25879 | if (default_argument) |
25880 | { |
25881 | /* If there is a default_argument, eq_token should always be set. */ |
25882 | gcc_assert (eq_token); |
25883 | location_t param_with_init_loc |
25884 | = make_location (caret: eq_token->location, |
25885 | start: decl_spec_token_start->location, |
25886 | finish: input_location); |
25887 | error_at (param_with_init_loc, |
25888 | "an explicit object parameter " |
25889 | "may not have a default argument" ); |
25890 | } |
25891 | /* Xobj parameters can not have default arguments, thus |
25892 | we can reuse the default argument field to flag the param as such. */ |
25893 | default_argument = this_identifier; |
25894 | } |
25895 | |
25896 | /* Generate a location for the parameter, ranging from the start of the |
25897 | initial token to the end of the final token (using input_location for |
25898 | the latter, set up by cp_lexer_set_source_position_from_token when |
25899 | consuming tokens). |
25900 | |
25901 | If we have a identifier, then use it for the caret location, e.g. |
25902 | |
25903 | extern int callee (int one, int (*two)(int, int), float three); |
25904 | ~~~~~~^~~~~~~~~~~~~~ |
25905 | |
25906 | otherwise, reuse the start location for the caret location e.g.: |
25907 | |
25908 | extern int callee (int one, int (*)(int, int), float three); |
25909 | ^~~~~~~~~~~~~~~~~ |
25910 | |
25911 | */ |
25912 | location_t caret_loc = (declarator && declarator->id_loc != UNKNOWN_LOCATION |
25913 | ? declarator->id_loc |
25914 | : decl_spec_token_start->location); |
25915 | location_t param_loc = make_location (caret: caret_loc, |
25916 | start: decl_spec_token_start->location, |
25917 | finish: input_location); |
25918 | |
25919 | return make_parameter_declarator (decl_specifiers: &decl_specifiers, |
25920 | declarator, |
25921 | default_argument, |
25922 | loc: param_loc, |
25923 | template_parameter_pack_p); |
25924 | } |
25925 | |
25926 | /* Parse a default argument and return it. |
25927 | |
25928 | TEMPLATE_PARM_P is true if this is a default argument for a |
25929 | non-type template parameter. */ |
25930 | static tree |
25931 | cp_parser_default_argument (cp_parser *parser, bool template_parm_p) |
25932 | { |
25933 | tree default_argument = NULL_TREE; |
25934 | bool saved_greater_than_is_operator_p; |
25935 | unsigned char saved_local_variables_forbidden_p; |
25936 | |
25937 | /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is |
25938 | set correctly. */ |
25939 | saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; |
25940 | parser->greater_than_is_operator_p = !template_parm_p; |
25941 | auto odsd = make_temp_override (var&: parser->omp_declare_simd, NULL); |
25942 | auto ord = make_temp_override (var&: parser->oacc_routine, NULL); |
25943 | auto oafp = make_temp_override (var&: parser->omp_attrs_forbidden_p, overrider: false); |
25944 | |
25945 | /* Local variable names (and the `this' keyword) may not |
25946 | appear in a default argument. */ |
25947 | saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; |
25948 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
25949 | /* Parse the assignment-expression. */ |
25950 | if (template_parm_p) |
25951 | push_deferring_access_checks (dk_no_deferred); |
25952 | tree saved_class_ptr = NULL_TREE; |
25953 | tree saved_class_ref = NULL_TREE; |
25954 | /* The "this" pointer is not valid in a default argument. */ |
25955 | if (cfun) |
25956 | { |
25957 | saved_class_ptr = current_class_ptr; |
25958 | cp_function_chain->x_current_class_ptr = NULL_TREE; |
25959 | saved_class_ref = current_class_ref; |
25960 | cp_function_chain->x_current_class_ref = NULL_TREE; |
25961 | } |
25962 | default_argument = cp_parser_initializer (parser); |
25963 | /* Restore the "this" pointer. */ |
25964 | if (cfun) |
25965 | { |
25966 | cp_function_chain->x_current_class_ptr = saved_class_ptr; |
25967 | cp_function_chain->x_current_class_ref = saved_class_ref; |
25968 | } |
25969 | if (BRACE_ENCLOSED_INITIALIZER_P (default_argument)) |
25970 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
25971 | if (template_parm_p) |
25972 | pop_deferring_access_checks (); |
25973 | parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; |
25974 | parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; |
25975 | |
25976 | return default_argument; |
25977 | } |
25978 | |
25979 | /* Parse a function-body. |
25980 | |
25981 | function-body: |
25982 | compound_statement */ |
25983 | |
25984 | static void |
25985 | cp_parser_function_body (cp_parser *parser, bool in_function_try_block) |
25986 | { |
25987 | cp_parser_compound_statement (parser, NULL, bcs_flags: (in_function_try_block |
25988 | ? BCS_TRY_BLOCK : BCS_NORMAL), |
25989 | function_body: true); |
25990 | } |
25991 | |
25992 | /* Parse a ctor-initializer-opt followed by a function-body. Return |
25993 | true if a ctor-initializer was present. When IN_FUNCTION_TRY_BLOCK |
25994 | is true we are parsing a function-try-block. */ |
25995 | |
25996 | static void |
25997 | cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, |
25998 | bool in_function_try_block) |
25999 | { |
26000 | tree body, list; |
26001 | const bool check_body_p |
26002 | = (DECL_CONSTRUCTOR_P (current_function_decl) |
26003 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl)); |
26004 | tree last = NULL; |
26005 | |
26006 | if (in_function_try_block |
26007 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
26008 | && cxx_dialect < cxx20) |
26009 | { |
26010 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
26011 | pedwarn (input_location, OPT_Wc__20_extensions, |
26012 | "function-try-block body of %<constexpr%> constructor only " |
26013 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
26014 | else |
26015 | pedwarn (input_location, OPT_Wc__20_extensions, |
26016 | "function-try-block body of %<constexpr%> function only " |
26017 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
26018 | } |
26019 | |
26020 | /* Begin the function body. */ |
26021 | body = begin_function_body (); |
26022 | /* Parse the optional ctor-initializer. */ |
26023 | cp_parser_ctor_initializer_opt (parser); |
26024 | |
26025 | /* If we're parsing a constexpr constructor definition, we need |
26026 | to check that the constructor body is indeed empty. However, |
26027 | before we get to cp_parser_function_body lot of junk has been |
26028 | generated, so we can't just check that we have an empty block. |
26029 | Rather we take a snapshot of the outermost block, and check whether |
26030 | cp_parser_function_body changed its state. */ |
26031 | if (check_body_p) |
26032 | { |
26033 | list = cur_stmt_list; |
26034 | if (STATEMENT_LIST_TAIL (list)) |
26035 | last = STATEMENT_LIST_TAIL (list)->stmt; |
26036 | } |
26037 | /* Parse the function-body. */ |
26038 | cp_parser_function_body (parser, in_function_try_block); |
26039 | if (check_body_p) |
26040 | check_constexpr_ctor_body (last, list, /*complain=*/true); |
26041 | /* Finish the function body. */ |
26042 | finish_function_body (body); |
26043 | } |
26044 | |
26045 | /* Parse an initializer. |
26046 | |
26047 | initializer: |
26048 | = initializer-clause |
26049 | ( expression-list ) |
26050 | |
26051 | Returns an expression representing the initializer. If no |
26052 | initializer is present, NULL_TREE is returned. |
26053 | |
26054 | *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause' |
26055 | production is used, and TRUE otherwise. *IS_DIRECT_INIT is |
26056 | set to TRUE if there is no initializer present. If there is an |
26057 | initializer, and it is not a constant-expression, *NON_CONSTANT_P |
26058 | is set to true; otherwise it is set to false. */ |
26059 | |
26060 | static tree |
26061 | cp_parser_initializer (cp_parser *parser, bool *is_direct_init /*=nullptr*/, |
26062 | bool *non_constant_p /*=nullptr*/, bool subexpression_p) |
26063 | { |
26064 | cp_token *token; |
26065 | tree init; |
26066 | |
26067 | /* Peek at the next token. */ |
26068 | token = cp_lexer_peek_token (lexer: parser->lexer); |
26069 | |
26070 | /* Let our caller know whether or not this initializer was |
26071 | parenthesized. */ |
26072 | if (is_direct_init) |
26073 | *is_direct_init = (token->type != CPP_EQ); |
26074 | /* Assume that the initializer is constant. */ |
26075 | if (non_constant_p) |
26076 | *non_constant_p = false; |
26077 | |
26078 | if (token->type == CPP_EQ) |
26079 | { |
26080 | /* Consume the `='. */ |
26081 | cp_lexer_consume_token (lexer: parser->lexer); |
26082 | /* Parse the initializer-clause. */ |
26083 | init = cp_parser_initializer_clause (parser, non_constant_p); |
26084 | } |
26085 | else if (token->type == CPP_OPEN_PAREN) |
26086 | { |
26087 | vec<tree, va_gc> *vec; |
26088 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
26089 | /*cast_p=*/false, |
26090 | /*allow_expansion_p=*/true, |
26091 | non_constant_p); |
26092 | if (vec == NULL) |
26093 | return error_mark_node; |
26094 | init = build_tree_list_vec (vec); |
26095 | release_tree_vector (vec); |
26096 | } |
26097 | else if (token->type == CPP_OPEN_BRACE) |
26098 | { |
26099 | cp_lexer_set_source_position (lexer: parser->lexer); |
26100 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
26101 | init = cp_parser_braced_list (parser, non_constant_p); |
26102 | CONSTRUCTOR_IS_DIRECT_INIT (init) = 1; |
26103 | } |
26104 | else |
26105 | { |
26106 | /* Anything else is an error. */ |
26107 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
26108 | init = error_mark_node; |
26109 | } |
26110 | |
26111 | if (!subexpression_p && check_for_bare_parameter_packs (init)) |
26112 | init = error_mark_node; |
26113 | |
26114 | return init; |
26115 | } |
26116 | |
26117 | /* Parse an initializer-clause. |
26118 | |
26119 | initializer-clause: |
26120 | assignment-expression |
26121 | braced-init-list |
26122 | |
26123 | Returns an expression representing the initializer. |
26124 | |
26125 | If the `assignment-expression' production is used the value |
26126 | returned is simply a representation for the expression. |
26127 | |
26128 | Otherwise, calls cp_parser_braced_list. */ |
26129 | |
26130 | static cp_expr |
26131 | cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) |
26132 | { |
26133 | cp_expr initializer; |
26134 | |
26135 | /* Assume the expression is constant. */ |
26136 | if (non_constant_p) |
26137 | *non_constant_p = false; |
26138 | |
26139 | /* If it is not a `{', then we are looking at an |
26140 | assignment-expression. */ |
26141 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
26142 | { |
26143 | initializer |
26144 | = cp_parser_constant_expression (parser, |
26145 | /*allow_non_constant_p=*/2, |
26146 | non_constant_p); |
26147 | } |
26148 | else |
26149 | initializer = cp_parser_braced_list (parser, non_constant_p); |
26150 | |
26151 | return initializer; |
26152 | } |
26153 | |
26154 | /* Parse a brace-enclosed initializer list. |
26155 | |
26156 | braced-init-list: |
26157 | { initializer-list , [opt] } |
26158 | { designated-initializer-list , [opt] } |
26159 | { } |
26160 | |
26161 | Returns a CONSTRUCTOR. The CONSTRUCTOR_ELTS will be |
26162 | the elements of the initializer-list (or NULL, if the last |
26163 | production is used). The TREE_TYPE for the CONSTRUCTOR will be |
26164 | NULL_TREE. There is no way to detect whether or not the optional |
26165 | trailing `,' was provided. NON_CONSTANT_P is as for |
26166 | cp_parser_initializer. */ |
26167 | |
26168 | static cp_expr |
26169 | cp_parser_braced_list (cp_parser *parser, bool *non_constant_p /*=nullptr*/) |
26170 | { |
26171 | tree initializer; |
26172 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
26173 | auto oas = make_temp_override (var&: parser->omp_array_section_p, overrider: false); |
26174 | |
26175 | /* Consume the `{' token. */ |
26176 | matching_braces braces; |
26177 | braces.require_open (parser); |
26178 | /* Create a CONSTRUCTOR to represent the braced-initializer. */ |
26179 | initializer = make_node (CONSTRUCTOR); |
26180 | /* If it's not a `}', then there is a non-trivial initializer. */ |
26181 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
26182 | { |
26183 | bool designated; |
26184 | /* Parse the initializer list. */ |
26185 | CONSTRUCTOR_ELTS (initializer) |
26186 | = cp_parser_initializer_list (parser, non_constant_p, &designated); |
26187 | CONSTRUCTOR_IS_DESIGNATED_INIT (initializer) = designated; |
26188 | /* A trailing `,' token is allowed. */ |
26189 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
26190 | cp_lexer_consume_token (lexer: parser->lexer); |
26191 | } |
26192 | else if (non_constant_p) |
26193 | *non_constant_p = false; |
26194 | /* Now, there should be a trailing `}'. */ |
26195 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
26196 | braces.require_close (parser); |
26197 | TREE_TYPE (initializer) = init_list_type_node; |
26198 | recompute_constructor_flags (initializer); |
26199 | |
26200 | cp_expr result (initializer); |
26201 | /* Build a location of the form: |
26202 | { ... } |
26203 | ^~~~~~~ |
26204 | with caret==start at the open brace, finish at the close brace. */ |
26205 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
26206 | result.set_location (combined_loc); |
26207 | return result; |
26208 | } |
26209 | |
26210 | /* Consume tokens up to, but not including, the next non-nested closing `]'. |
26211 | Returns true iff we found a closing `]'. */ |
26212 | |
26213 | static bool |
26214 | cp_parser_skip_up_to_closing_square_bracket (cp_parser *parser) |
26215 | { |
26216 | unsigned square_depth = 0; |
26217 | |
26218 | while (true) |
26219 | { |
26220 | cp_token * token = cp_lexer_peek_token (lexer: parser->lexer); |
26221 | |
26222 | switch (token->type) |
26223 | { |
26224 | case CPP_PRAGMA_EOL: |
26225 | if (!parser->lexer->in_pragma) |
26226 | break; |
26227 | /* FALLTHRU */ |
26228 | |
26229 | case CPP_EOF: |
26230 | /* If we've run out of tokens, then there is no closing `]'. */ |
26231 | return false; |
26232 | |
26233 | case CPP_OPEN_SQUARE: |
26234 | ++square_depth; |
26235 | break; |
26236 | |
26237 | case CPP_CLOSE_SQUARE: |
26238 | if (!square_depth--) |
26239 | return true; |
26240 | break; |
26241 | |
26242 | default: |
26243 | break; |
26244 | } |
26245 | |
26246 | /* Consume the current token, skipping it. */ |
26247 | cp_lexer_consume_token (lexer: parser->lexer); |
26248 | } |
26249 | } |
26250 | |
26251 | /* Consume tokens up to, and including, the next non-nested closing `]'. |
26252 | Returns true iff we found a closing `]'. */ |
26253 | |
26254 | static bool |
26255 | cp_parser_skip_to_closing_square_bracket (cp_parser *parser) |
26256 | { |
26257 | bool found = cp_parser_skip_up_to_closing_square_bracket (parser); |
26258 | if (found) |
26259 | cp_lexer_consume_token (lexer: parser->lexer); |
26260 | return found; |
26261 | } |
26262 | |
26263 | /* Return true if we are looking at an array-designator, false otherwise. */ |
26264 | |
26265 | static bool |
26266 | cp_parser_array_designator_p (cp_parser *parser) |
26267 | { |
26268 | /* Consume the `['. */ |
26269 | cp_lexer_consume_token (lexer: parser->lexer); |
26270 | |
26271 | cp_lexer_save_tokens (lexer: parser->lexer); |
26272 | |
26273 | /* Skip tokens until the next token is a closing square bracket. |
26274 | If we find the closing `]', and the next token is a `=', then |
26275 | we are looking at an array designator. */ |
26276 | bool array_designator_p |
26277 | = (cp_parser_skip_to_closing_square_bracket (parser) |
26278 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)); |
26279 | |
26280 | /* Roll back the tokens we skipped. */ |
26281 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
26282 | |
26283 | return array_designator_p; |
26284 | } |
26285 | |
26286 | /* Parse an initializer-list. |
26287 | |
26288 | initializer-list: |
26289 | initializer-clause ... [opt] |
26290 | initializer-list , initializer-clause ... [opt] |
26291 | |
26292 | C++20 Extension: |
26293 | |
26294 | designated-initializer-list: |
26295 | designated-initializer-clause |
26296 | designated-initializer-list , designated-initializer-clause |
26297 | |
26298 | designated-initializer-clause: |
26299 | designator brace-or-equal-initializer |
26300 | |
26301 | designator: |
26302 | . identifier |
26303 | |
26304 | GNU Extension: |
26305 | |
26306 | initializer-list: |
26307 | designation initializer-clause ...[opt] |
26308 | initializer-list , designation initializer-clause ...[opt] |
26309 | |
26310 | designation: |
26311 | . identifier = |
26312 | identifier : |
26313 | [ constant-expression ] = |
26314 | |
26315 | Returns a vec of constructor_elt. The VALUE of each elt is an expression |
26316 | for the initializer. If the INDEX of the elt is non-NULL, it is the |
26317 | IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is |
26318 | as for cp_parser_initializer. Set *DESIGNATED to a boolean whether there |
26319 | are any designators. */ |
26320 | |
26321 | static vec<constructor_elt, va_gc> * |
26322 | cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p, |
26323 | bool *designated) |
26324 | { |
26325 | vec<constructor_elt, va_gc> *v = NULL; |
26326 | bool first_p = true; |
26327 | tree first_designator = NULL_TREE; |
26328 | |
26329 | /* Assume all of the expressions are constant. */ |
26330 | if (non_constant_p) |
26331 | *non_constant_p = false; |
26332 | |
26333 | unsigned nelts = 0; |
26334 | int suppress = suppress_location_wrappers; |
26335 | |
26336 | /* Parse the rest of the list. */ |
26337 | while (true) |
26338 | { |
26339 | cp_token *token; |
26340 | tree designator; |
26341 | tree initializer; |
26342 | bool clause_non_constant_p; |
26343 | bool direct_p = false; |
26344 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
26345 | |
26346 | /* Handle the C++20 syntax, '. id ='. */ |
26347 | if ((cxx_dialect >= cxx20 |
26348 | || cp_parser_allow_gnu_extensions_p (parser)) |
26349 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
26350 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_NAME |
26351 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_EQ |
26352 | || (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
26353 | == CPP_OPEN_BRACE))) |
26354 | { |
26355 | if (pedantic && cxx_dialect < cxx20) |
26356 | pedwarn (loc, OPT_Wc__20_extensions, |
26357 | "C++ designated initializers only available with " |
26358 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
26359 | /* Consume the `.'. */ |
26360 | cp_lexer_consume_token (lexer: parser->lexer); |
26361 | /* Consume the identifier. */ |
26362 | designator = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
26363 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
26364 | /* Consume the `='. */ |
26365 | cp_lexer_consume_token (lexer: parser->lexer); |
26366 | else |
26367 | direct_p = true; |
26368 | } |
26369 | /* Also, if the next token is an identifier and the following one is a |
26370 | colon, we are looking at the GNU designated-initializer |
26371 | syntax. */ |
26372 | else if (cp_parser_allow_gnu_extensions_p (parser) |
26373 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
26374 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
26375 | == CPP_COLON)) |
26376 | { |
26377 | /* Warn the user that they are using an extension. */ |
26378 | pedwarn (loc, OPT_Wpedantic, |
26379 | "ISO C++ does not allow GNU designated initializers" ); |
26380 | /* Consume the identifier. */ |
26381 | designator = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
26382 | /* Consume the `:'. */ |
26383 | cp_lexer_consume_token (lexer: parser->lexer); |
26384 | } |
26385 | /* Also handle C99 array designators, '[ const ] ='. */ |
26386 | else if (cp_parser_allow_gnu_extensions_p (parser) |
26387 | && !c_dialect_objc () |
26388 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
26389 | { |
26390 | /* In C++11, [ could start a lambda-introducer. */ |
26391 | bool non_const = false; |
26392 | |
26393 | cp_parser_parse_tentatively (parser); |
26394 | |
26395 | if (!cp_parser_array_designator_p (parser)) |
26396 | { |
26397 | cp_parser_simulate_error (parser); |
26398 | designator = NULL_TREE; |
26399 | } |
26400 | else |
26401 | { |
26402 | designator = cp_parser_constant_expression (parser, allow_non_constant_p: true, |
26403 | non_constant_p: &non_const); |
26404 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
26405 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
26406 | } |
26407 | |
26408 | if (!cp_parser_parse_definitely (parser)) |
26409 | designator = NULL_TREE; |
26410 | else if (non_const |
26411 | && (!require_potential_rvalue_constant_expression |
26412 | (designator))) |
26413 | designator = NULL_TREE; |
26414 | if (designator) |
26415 | /* Warn the user that they are using an extension. */ |
26416 | pedwarn (loc, OPT_Wpedantic, |
26417 | "ISO C++ does not allow C99 designated initializers" ); |
26418 | } |
26419 | else |
26420 | designator = NULL_TREE; |
26421 | |
26422 | if (first_p) |
26423 | { |
26424 | first_designator = designator; |
26425 | first_p = false; |
26426 | } |
26427 | else if (cxx_dialect >= cxx20 |
26428 | && first_designator != error_mark_node |
26429 | && (!first_designator != !designator)) |
26430 | { |
26431 | error_at (loc, "either all initializer clauses should be designated " |
26432 | "or none of them should be" ); |
26433 | first_designator = error_mark_node; |
26434 | } |
26435 | else if (cxx_dialect < cxx20 && !first_designator) |
26436 | first_designator = designator; |
26437 | |
26438 | /* Parse the initializer. */ |
26439 | initializer = cp_parser_initializer_clause (parser, |
26440 | non_constant_p: (non_constant_p != nullptr |
26441 | ? &clause_non_constant_p |
26442 | : nullptr)); |
26443 | /* If any clause is non-constant, so is the entire initializer. */ |
26444 | if (non_constant_p && clause_non_constant_p) |
26445 | *non_constant_p = true; |
26446 | |
26447 | if (TREE_CODE (initializer) == CONSTRUCTOR) |
26448 | /* This uses |= rather than = because C_I_D_I could have been set in |
26449 | cp_parser_functional_cast so we must be careful not to clear the |
26450 | flag. */ |
26451 | CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p; |
26452 | |
26453 | /* If we have an ellipsis, this is an initializer pack |
26454 | expansion. */ |
26455 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
26456 | { |
26457 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
26458 | |
26459 | /* Consume the `...'. */ |
26460 | cp_lexer_consume_token (lexer: parser->lexer); |
26461 | |
26462 | if (designator && cxx_dialect >= cxx20) |
26463 | error_at (loc, |
26464 | "%<...%> not allowed in designated initializer list" ); |
26465 | |
26466 | /* Turn the initializer into an initializer expansion. */ |
26467 | initializer = make_pack_expansion (initializer); |
26468 | } |
26469 | |
26470 | /* Add it to the vector. */ |
26471 | CONSTRUCTOR_APPEND_ELT (v, designator, initializer); |
26472 | |
26473 | /* If the next token is not a comma, we have reached the end of |
26474 | the list. */ |
26475 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
26476 | break; |
26477 | |
26478 | /* Peek at the next token. */ |
26479 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
26480 | /* If the next token is a `}', then we're still done. An |
26481 | initializer-clause can have a trailing `,' after the |
26482 | initializer-list and before the closing `}'. */ |
26483 | if (token->type == CPP_CLOSE_BRACE) |
26484 | break; |
26485 | |
26486 | /* Suppress location wrappers in a long initializer to save memory |
26487 | (14179). The cutoff is chosen arbitrarily. */ |
26488 | const unsigned loc_max = 256; |
26489 | unsigned incr = 1; |
26490 | if (TREE_CODE (initializer) == CONSTRUCTOR) |
26491 | /* Look one level down because it's easy. Looking deeper would require |
26492 | passing down a nelts pointer, and I don't think multi-level massive |
26493 | initializers are common enough to justify this. */ |
26494 | incr = CONSTRUCTOR_NELTS (initializer); |
26495 | nelts += incr; |
26496 | if (nelts >= loc_max && (nelts - incr) < loc_max) |
26497 | ++suppress_location_wrappers; |
26498 | |
26499 | /* Consume the `,' token. */ |
26500 | cp_lexer_consume_token (lexer: parser->lexer); |
26501 | } |
26502 | |
26503 | /* The same identifier shall not appear in multiple designators |
26504 | of a designated-initializer-list. */ |
26505 | if (first_designator) |
26506 | { |
26507 | unsigned int i; |
26508 | tree designator, val; |
26509 | FOR_EACH_CONSTRUCTOR_ELT (v, i, designator, val) |
26510 | if (designator && TREE_CODE (designator) == IDENTIFIER_NODE) |
26511 | { |
26512 | if (IDENTIFIER_MARKED (designator)) |
26513 | { |
26514 | error_at (cp_expr_loc_or_input_loc (t: val), |
26515 | "%<.%s%> designator used multiple times in " |
26516 | "the same initializer list" , |
26517 | IDENTIFIER_POINTER (designator)); |
26518 | (*v)[i].index = error_mark_node; |
26519 | } |
26520 | else |
26521 | IDENTIFIER_MARKED (designator) = 1; |
26522 | } |
26523 | FOR_EACH_CONSTRUCTOR_ELT (v, i, designator, val) |
26524 | if (designator && TREE_CODE (designator) == IDENTIFIER_NODE) |
26525 | IDENTIFIER_MARKED (designator) = 0; |
26526 | } |
26527 | |
26528 | suppress_location_wrappers = suppress; |
26529 | |
26530 | *designated = first_designator != NULL_TREE; |
26531 | return v; |
26532 | } |
26533 | |
26534 | /* Classes [gram.class] */ |
26535 | |
26536 | /* Parse a class-name. |
26537 | |
26538 | class-name: |
26539 | identifier |
26540 | template-id |
26541 | |
26542 | TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used |
26543 | to indicate that names looked up in dependent types should be |
26544 | assumed to be types. TEMPLATE_KEYWORD_P is true iff the `template' |
26545 | keyword has been used to indicate that the name that appears next |
26546 | is a template. TAG_TYPE indicates the explicit tag given before |
26547 | the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are |
26548 | looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class |
26549 | is the class being defined in a class-head. If ENUM_OK is TRUE, |
26550 | enum-names are also accepted. |
26551 | |
26552 | Returns the TYPE_DECL representing the class. */ |
26553 | |
26554 | static tree |
26555 | cp_parser_class_name (cp_parser *parser, |
26556 | bool typename_keyword_p, |
26557 | bool template_keyword_p, |
26558 | enum tag_types tag_type, |
26559 | bool check_dependency_p, |
26560 | bool class_head_p, |
26561 | bool is_declaration, |
26562 | bool enum_ok) |
26563 | { |
26564 | tree decl; |
26565 | tree identifier = NULL_TREE; |
26566 | |
26567 | /* All class-names start with an identifier. */ |
26568 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
26569 | if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID) |
26570 | { |
26571 | cp_parser_error (parser, gmsgid: "expected class-name" ); |
26572 | return error_mark_node; |
26573 | } |
26574 | |
26575 | /* PARSER->SCOPE can be cleared when parsing the template-arguments |
26576 | to a template-id, so we save it here. Consider object scope too, |
26577 | so that make_typename_type below can use it (cp_parser_template_name |
26578 | considers object scope also). This may happen with code like |
26579 | |
26580 | p->template A<T>::a() |
26581 | |
26582 | where we first want to look up A<T>::a in the class of the object |
26583 | expression, as per [basic.lookup.classref]. */ |
26584 | tree scope = parser->scope ? parser->scope : parser->context->object_type; |
26585 | /* This only checks parser->scope to avoid duplicate errors; if |
26586 | ->object_type is erroneous, go on to give a parse error. */ |
26587 | if (parser->scope == error_mark_node) |
26588 | return error_mark_node; |
26589 | |
26590 | /* Any name names a type if we're following the `typename' keyword |
26591 | in a qualified name where the enclosing scope is type-dependent. */ |
26592 | const bool typename_p = (typename_keyword_p |
26593 | && parser->scope |
26594 | && TYPE_P (parser->scope) |
26595 | && dependent_scope_p (parser->scope)); |
26596 | /* Handle the common case (an identifier, but not a template-id) |
26597 | efficiently. */ |
26598 | if (token->type == CPP_NAME |
26599 | && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) |
26600 | { |
26601 | cp_token *identifier_token; |
26602 | bool ambiguous_p; |
26603 | |
26604 | /* Look for the identifier. */ |
26605 | identifier_token = cp_lexer_peek_token (lexer: parser->lexer); |
26606 | ambiguous_p = identifier_token->error_reported; |
26607 | identifier = cp_parser_identifier (parser); |
26608 | /* If the next token isn't an identifier, we are certainly not |
26609 | looking at a class-name. */ |
26610 | if (identifier == error_mark_node) |
26611 | decl = error_mark_node; |
26612 | /* If we know this is a type-name, there's no need to look it |
26613 | up. */ |
26614 | else if (typename_p) |
26615 | decl = identifier; |
26616 | else |
26617 | { |
26618 | tree ambiguous_decls; |
26619 | /* If we already know that this lookup is ambiguous, then |
26620 | we've already issued an error message; there's no reason |
26621 | to check again. */ |
26622 | if (ambiguous_p) |
26623 | { |
26624 | cp_parser_simulate_error (parser); |
26625 | return error_mark_node; |
26626 | } |
26627 | /* If the next token is a `::', then the name must be a type |
26628 | name. |
26629 | |
26630 | [basic.lookup.qual] |
26631 | |
26632 | During the lookup for a name preceding the :: scope |
26633 | resolution operator, object, function, and enumerator |
26634 | names are ignored. */ |
26635 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
26636 | tag_type = scope_type; |
26637 | /* Look up the name. */ |
26638 | decl = cp_parser_lookup_name (parser, identifier, |
26639 | tag_type, |
26640 | /*is_template=*/false, |
26641 | /*is_namespace=*/false, |
26642 | check_dependency_p, |
26643 | &ambiguous_decls, |
26644 | identifier_token->location); |
26645 | if (ambiguous_decls) |
26646 | { |
26647 | if (cp_parser_parsing_tentatively (parser)) |
26648 | cp_parser_simulate_error (parser); |
26649 | return error_mark_node; |
26650 | } |
26651 | } |
26652 | } |
26653 | else |
26654 | { |
26655 | /* Try a template-id. */ |
26656 | decl = cp_parser_template_id (parser, template_keyword_p, |
26657 | check_dependency_p, |
26658 | tag_type, |
26659 | is_declaration); |
26660 | if (decl == error_mark_node) |
26661 | return error_mark_node; |
26662 | } |
26663 | |
26664 | decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p); |
26665 | |
26666 | /* If this is a typename, create a TYPENAME_TYPE. */ |
26667 | if (typename_p && decl != error_mark_node) |
26668 | { |
26669 | decl = make_typename_type (scope, decl, typename_type, |
26670 | /*complain=*/tf_error); |
26671 | if (decl != error_mark_node) |
26672 | decl = TYPE_NAME (decl); |
26673 | } |
26674 | |
26675 | decl = strip_using_decl (decl); |
26676 | |
26677 | /* Check to see that it is really the name of a class. */ |
26678 | if (TREE_CODE (decl) == TEMPLATE_ID_EXPR |
26679 | && identifier_p (TREE_OPERAND (decl, 0)) |
26680 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
26681 | /* Situations like this: |
26682 | |
26683 | template <typename T> struct A { |
26684 | typename T::template X<int>::I i; |
26685 | }; |
26686 | |
26687 | are problematic. Is `T::template X<int>' a class-name? The |
26688 | standard does not seem to be definitive, but there is no other |
26689 | valid interpretation of the following `::'. Therefore, those |
26690 | names are considered class-names. */ |
26691 | { |
26692 | decl = make_typename_type (scope, decl, tag_type, tf_error); |
26693 | if (decl != error_mark_node) |
26694 | decl = TYPE_NAME (decl); |
26695 | } |
26696 | else if (TREE_CODE (decl) != TYPE_DECL |
26697 | || TREE_TYPE (decl) == error_mark_node |
26698 | || !(MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)) |
26699 | || (enum_ok && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)) |
26700 | /* In Objective-C 2.0, a classname followed by '.' starts a |
26701 | dot-syntax expression, and it's not a type-name. */ |
26702 | || (c_dialect_objc () |
26703 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT |
26704 | && objc_is_class_name (decl))) |
26705 | decl = error_mark_node; |
26706 | |
26707 | if (decl == error_mark_node) |
26708 | cp_parser_error (parser, gmsgid: "expected class-name" ); |
26709 | else if (identifier && !parser->scope) |
26710 | maybe_note_name_used_in_class (identifier, decl); |
26711 | |
26712 | return decl; |
26713 | } |
26714 | |
26715 | /* Make sure that any member-function parameters are in scope. |
26716 | For instance, a function's noexcept-specifier can use the function's |
26717 | parameters: |
26718 | |
26719 | struct S { |
26720 | void fn (int p) noexcept(noexcept(p)); |
26721 | }; |
26722 | |
26723 | so we need to make sure name lookup can find them. This is used |
26724 | when we delay parsing of the noexcept-specifier. */ |
26725 | |
26726 | static void |
26727 | inject_parm_decls (tree decl) |
26728 | { |
26729 | begin_scope (sk_function_parms, decl); |
26730 | tree args = DECL_ARGUMENTS (decl); |
26731 | |
26732 | do_push_parm_decls (decl, args, /*nonparms=*/NULL); |
26733 | |
26734 | if (args && is_this_parameter (args)) |
26735 | { |
26736 | gcc_checking_assert (current_class_ptr == NULL_TREE); |
26737 | current_class_ref = cp_build_fold_indirect_ref (args); |
26738 | current_class_ptr = args; |
26739 | } |
26740 | } |
26741 | |
26742 | /* Undo the effects of inject_parm_decls. */ |
26743 | |
26744 | static void |
26745 | pop_injected_parms (void) |
26746 | { |
26747 | pop_bindings_and_leave_scope (); |
26748 | current_class_ptr = current_class_ref = NULL_TREE; |
26749 | } |
26750 | |
26751 | /* Parse a class-specifier. |
26752 | |
26753 | class-specifier: |
26754 | class-head { member-specification [opt] } |
26755 | |
26756 | Returns the TREE_TYPE representing the class. */ |
26757 | |
26758 | tree |
26759 | cp_parser_class_specifier (cp_parser* parser) |
26760 | { |
26761 | auto_timevar tv (TV_PARSE_STRUCT); |
26762 | |
26763 | tree type; |
26764 | tree attributes = NULL_TREE; |
26765 | bool nested_name_specifier_p; |
26766 | unsigned saved_num_template_parameter_lists; |
26767 | bool saved_in_function_body; |
26768 | unsigned char in_statement; |
26769 | bool in_switch_statement_p; |
26770 | bool saved_in_unbraced_linkage_specification_p; |
26771 | tree old_scope = NULL_TREE; |
26772 | tree scope = NULL_TREE; |
26773 | cp_token *closing_brace; |
26774 | |
26775 | push_deferring_access_checks (dk_no_deferred); |
26776 | |
26777 | /* Parse the class-head. */ |
26778 | type = cp_parser_class_head (parser, |
26779 | &nested_name_specifier_p); |
26780 | /* If the class-head was a semantic disaster, skip the entire body |
26781 | of the class. */ |
26782 | if (!type) |
26783 | { |
26784 | cp_parser_skip_to_end_of_block_or_statement (parser); |
26785 | pop_deferring_access_checks (); |
26786 | return error_mark_node; |
26787 | } |
26788 | |
26789 | /* Look for the `{'. */ |
26790 | matching_braces braces; |
26791 | if (!braces.require_open (parser)) |
26792 | { |
26793 | pop_deferring_access_checks (); |
26794 | return error_mark_node; |
26795 | } |
26796 | |
26797 | cp_ensure_no_omp_declare_simd (parser); |
26798 | cp_ensure_no_oacc_routine (parser); |
26799 | |
26800 | /* Issue an error message if type-definitions are forbidden here. */ |
26801 | bool type_definition_ok_p = cp_parser_check_type_definition (parser); |
26802 | /* Remember that we are defining one more class. */ |
26803 | ++parser->num_classes_being_defined; |
26804 | /* Inside the class, surrounding template-parameter-lists do not |
26805 | apply. */ |
26806 | saved_num_template_parameter_lists |
26807 | = parser->num_template_parameter_lists; |
26808 | parser->num_template_parameter_lists = 0; |
26809 | /* We are not in a function body. */ |
26810 | saved_in_function_body = parser->in_function_body; |
26811 | parser->in_function_body = false; |
26812 | /* Or in a loop. */ |
26813 | in_statement = parser->in_statement; |
26814 | parser->in_statement = 0; |
26815 | /* Or in a switch. */ |
26816 | in_switch_statement_p = parser->in_switch_statement_p; |
26817 | parser->in_switch_statement_p = false; |
26818 | /* We are not immediately inside an extern "lang" block. */ |
26819 | saved_in_unbraced_linkage_specification_p |
26820 | = parser->in_unbraced_linkage_specification_p; |
26821 | parser->in_unbraced_linkage_specification_p = false; |
26822 | /* 'this' from an enclosing non-static member function is unavailable. */ |
26823 | tree saved_ccp = current_class_ptr; |
26824 | tree saved_ccr = current_class_ref; |
26825 | current_class_ptr = NULL_TREE; |
26826 | current_class_ref = NULL_TREE; |
26827 | |
26828 | /* Start the class. */ |
26829 | if (nested_name_specifier_p) |
26830 | { |
26831 | scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); |
26832 | /* SCOPE must be a scope nested inside current scope. */ |
26833 | if (is_nested_namespace (current_namespace, |
26834 | descendant: decl_namespace_context (scope))) |
26835 | old_scope = push_inner_scope (scope); |
26836 | else |
26837 | nested_name_specifier_p = false; |
26838 | } |
26839 | type = begin_class_definition (type); |
26840 | |
26841 | if (type == error_mark_node) |
26842 | /* If the type is erroneous, skip the entire body of the class. */ |
26843 | cp_parser_skip_to_closing_brace (parser); |
26844 | else |
26845 | /* Parse the member-specification. */ |
26846 | cp_parser_member_specification_opt (parser); |
26847 | |
26848 | /* Look for the trailing `}'. */ |
26849 | closing_brace = braces.require_close (parser); |
26850 | /* Look for trailing attributes to apply to this class. */ |
26851 | if (cp_parser_allow_gnu_extensions_p (parser)) |
26852 | attributes = cp_parser_gnu_attributes_opt (parser); |
26853 | if (type != error_mark_node) |
26854 | type = finish_struct (type, attributes); |
26855 | if (nested_name_specifier_p) |
26856 | pop_inner_scope (old_scope, scope); |
26857 | |
26858 | /* We've finished a type definition. Check for the common syntax |
26859 | error of forgetting a semicolon after the definition. We need to |
26860 | be careful, as we can't just check for not-a-semicolon and be done |
26861 | with it; the user might have typed: |
26862 | |
26863 | class X { } c = ...; |
26864 | class X { } *p = ...; |
26865 | |
26866 | and so forth. Instead, enumerate all the possible tokens that |
26867 | might follow this production; if we don't see one of them, then |
26868 | complain and silently insert the semicolon. */ |
26869 | { |
26870 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
26871 | bool want_semicolon = true; |
26872 | |
26873 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
26874 | /* Don't try to parse c++11 attributes here. As per the |
26875 | grammar, that should be a task for |
26876 | cp_parser_decl_specifier_seq. */ |
26877 | want_semicolon = false; |
26878 | |
26879 | switch (token->type) |
26880 | { |
26881 | case CPP_NAME: |
26882 | case CPP_SEMICOLON: |
26883 | case CPP_MULT: |
26884 | case CPP_AND: |
26885 | case CPP_OPEN_PAREN: |
26886 | case CPP_CLOSE_PAREN: |
26887 | case CPP_COMMA: |
26888 | case CPP_SCOPE: |
26889 | want_semicolon = false; |
26890 | break; |
26891 | |
26892 | /* While it's legal for type qualifiers and storage class |
26893 | specifiers to follow type definitions in the grammar, only |
26894 | compiler testsuites contain code like that. Assume that if |
26895 | we see such code, then what we're really seeing is a case |
26896 | like: |
26897 | |
26898 | class X { } |
26899 | const <type> var = ...; |
26900 | |
26901 | or |
26902 | |
26903 | class Y { } |
26904 | static <type> func (...) ... |
26905 | |
26906 | i.e. the qualifier or specifier applies to the next |
26907 | declaration. To do so, however, we need to look ahead one |
26908 | more token to see if *that* token is a type specifier. |
26909 | |
26910 | This code could be improved to handle: |
26911 | |
26912 | class Z { } |
26913 | static const <type> var = ...; */ |
26914 | case CPP_KEYWORD: |
26915 | if (keyword_is_decl_specifier (token->keyword)) |
26916 | { |
26917 | cp_token *lookahead = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
26918 | |
26919 | /* Handling user-defined types here would be nice, but very |
26920 | tricky. */ |
26921 | want_semicolon |
26922 | = (lookahead->type == CPP_KEYWORD |
26923 | && keyword_begins_type_specifier (lookahead->keyword)); |
26924 | } |
26925 | break; |
26926 | default: |
26927 | break; |
26928 | } |
26929 | |
26930 | /* If we don't have a type, then something is very wrong and we |
26931 | shouldn't try to do anything clever. Likewise for not seeing the |
26932 | closing brace. */ |
26933 | if (closing_brace && TYPE_P (type) && want_semicolon) |
26934 | { |
26935 | /* Locate the closing brace. */ |
26936 | cp_token_position prev |
26937 | = cp_lexer_previous_token_position (lexer: parser->lexer); |
26938 | cp_token *prev_token = cp_lexer_token_at (parser->lexer, pos: prev); |
26939 | location_t loc = prev_token->location; |
26940 | |
26941 | /* We want to suggest insertion of a ';' immediately *after* the |
26942 | closing brace, so, if we can, offset the location by 1 column. */ |
26943 | location_t next_loc = loc; |
26944 | if (!linemap_location_from_macro_expansion_p (line_table, loc)) |
26945 | next_loc = linemap_position_for_loc_and_offset (set: line_table, loc, offset: 1); |
26946 | |
26947 | rich_location richloc (line_table, next_loc); |
26948 | |
26949 | /* If we successfully offset the location, suggest the fix-it. */ |
26950 | if (next_loc != loc) |
26951 | richloc.add_fixit_insert_before (where: next_loc, new_content: ";" ); |
26952 | |
26953 | if (CLASSTYPE_DECLARED_CLASS (type)) |
26954 | error_at (&richloc, |
26955 | "expected %<;%> after class definition" ); |
26956 | else if (TREE_CODE (type) == RECORD_TYPE) |
26957 | error_at (&richloc, |
26958 | "expected %<;%> after struct definition" ); |
26959 | else if (TREE_CODE (type) == UNION_TYPE) |
26960 | error_at (&richloc, |
26961 | "expected %<;%> after union definition" ); |
26962 | else |
26963 | gcc_unreachable (); |
26964 | |
26965 | /* Unget one token and smash it to look as though we encountered |
26966 | a semicolon in the input stream. */ |
26967 | cp_lexer_set_token_position (lexer: parser->lexer, pos: prev); |
26968 | token = cp_lexer_peek_token (lexer: parser->lexer); |
26969 | token->type = CPP_SEMICOLON; |
26970 | token->keyword = RID_MAX; |
26971 | } |
26972 | } |
26973 | |
26974 | /* If this class is not itself within the scope of another class, |
26975 | then we need to parse the bodies of all of the queued function |
26976 | definitions. Note that the queued functions defined in a class |
26977 | are not always processed immediately following the |
26978 | class-specifier for that class. Consider: |
26979 | |
26980 | struct A { |
26981 | struct B { void f() { sizeof (A); } }; |
26982 | }; |
26983 | |
26984 | If `f' were processed before the processing of `A' were |
26985 | completed, there would be no way to compute the size of `A'. |
26986 | Note that the nesting we are interested in here is lexical -- |
26987 | not the semantic nesting given by TYPE_CONTEXT. In particular, |
26988 | for: |
26989 | |
26990 | struct A { struct B; }; |
26991 | struct A::B { void f() { } }; |
26992 | |
26993 | there is no need to delay the parsing of `A::B::f'. */ |
26994 | if (--parser->num_classes_being_defined == 0) |
26995 | { |
26996 | tree decl; |
26997 | tree class_type = NULL_TREE; |
26998 | tree pushed_scope = NULL_TREE; |
26999 | unsigned ix; |
27000 | cp_default_arg_entry *e; |
27001 | |
27002 | if (!type_definition_ok_p || any_erroneous_template_args_p (type)) |
27003 | { |
27004 | /* Skip default arguments, NSDMIs, etc, in order to improve |
27005 | error recovery (c++/71169, c++/71832). */ |
27006 | vec_safe_truncate (unparsed_funs_with_default_args, size: 0); |
27007 | vec_safe_truncate (unparsed_nsdmis, size: 0); |
27008 | vec_safe_truncate (unparsed_funs_with_definitions, size: 0); |
27009 | } |
27010 | |
27011 | /* In a first pass, parse default arguments to the functions. |
27012 | Then, in a second pass, parse the bodies of the functions. |
27013 | This two-phased approach handles cases like: |
27014 | |
27015 | struct S { |
27016 | void f() { g(); } |
27017 | void g(int i = 3); |
27018 | }; |
27019 | |
27020 | */ |
27021 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_default_args, ix, e) |
27022 | { |
27023 | decl = e->decl; |
27024 | /* If there are default arguments that have not yet been processed, |
27025 | take care of them now. */ |
27026 | if (class_type != e->class_type) |
27027 | { |
27028 | if (pushed_scope) |
27029 | pop_scope (pushed_scope); |
27030 | class_type = e->class_type; |
27031 | pushed_scope = push_scope (class_type); |
27032 | } |
27033 | /* Make sure that any template parameters are in scope. */ |
27034 | maybe_begin_member_template_processing (decl); |
27035 | /* Parse the default argument expressions. */ |
27036 | cp_parser_late_parsing_default_args (parser, decl); |
27037 | /* Remove any template parameters from the symbol table. */ |
27038 | maybe_end_member_template_processing (); |
27039 | } |
27040 | vec_safe_truncate (unparsed_funs_with_default_args, size: 0); |
27041 | |
27042 | /* If there are noexcept-specifiers that have not yet been processed, |
27043 | take care of them now. Do this before processing NSDMIs as they |
27044 | may depend on noexcept-specifiers already having been processed. */ |
27045 | FOR_EACH_VEC_SAFE_ELT (unparsed_noexcepts, ix, decl) |
27046 | { |
27047 | tree ctx = DECL_CONTEXT (decl); |
27048 | if (class_type != ctx) |
27049 | { |
27050 | if (pushed_scope) |
27051 | pop_scope (pushed_scope); |
27052 | class_type = ctx; |
27053 | pushed_scope = push_scope (class_type); |
27054 | } |
27055 | |
27056 | tree def_parse = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); |
27057 | def_parse = TREE_PURPOSE (def_parse); |
27058 | |
27059 | /* Make sure that any template parameters are in scope. */ |
27060 | maybe_begin_member_template_processing (decl); |
27061 | |
27062 | /* Make sure that any member-function parameters are in scope. |
27063 | This function doesn't expect ccp to be set. */ |
27064 | current_class_ptr = current_class_ref = NULL_TREE; |
27065 | inject_parm_decls (decl); |
27066 | |
27067 | /* 'this' is not allowed in static member functions. */ |
27068 | unsigned char local_variables_forbidden_p |
27069 | = parser->local_variables_forbidden_p; |
27070 | if (DECL_THIS_STATIC (decl)) |
27071 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
27072 | |
27073 | /* Now we can parse the noexcept-specifier. */ |
27074 | tree spec = cp_parser_late_noexcept_specifier (parser, def_parse); |
27075 | |
27076 | if (spec == error_mark_node) |
27077 | spec = NULL_TREE; |
27078 | |
27079 | /* Update the fn's type directly -- it might have escaped |
27080 | beyond this decl :( */ |
27081 | fixup_deferred_exception_variants (TREE_TYPE (decl), spec); |
27082 | /* Update any instantiations we've already created. We must |
27083 | keep the new noexcept-specifier wrapped in a DEFERRED_NOEXCEPT |
27084 | so that maybe_instantiate_noexcept can tsubst the NOEXCEPT_EXPR |
27085 | in the pattern. */ |
27086 | for (tree i : DEFPARSE_INSTANTIATIONS (def_parse)) |
27087 | DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i)) |
27088 | = spec ? TREE_PURPOSE (spec) : error_mark_node; |
27089 | |
27090 | /* Restore the state of local_variables_forbidden_p. */ |
27091 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
27092 | |
27093 | /* The finish_struct call above performed various override checking, |
27094 | but it skipped unparsed noexcept-specifier operands. Now that we |
27095 | have resolved them, check again. */ |
27096 | noexcept_override_late_checks (decl); |
27097 | |
27098 | /* Remove any member-function parameters from the symbol table. */ |
27099 | pop_injected_parms (); |
27100 | |
27101 | /* Remove any template parameters from the symbol table. */ |
27102 | maybe_end_member_template_processing (); |
27103 | } |
27104 | vec_safe_truncate (unparsed_noexcepts, size: 0); |
27105 | |
27106 | /* Now parse any NSDMIs. */ |
27107 | FOR_EACH_VEC_SAFE_ELT (unparsed_nsdmis, ix, decl) |
27108 | { |
27109 | tree ctx = type_context_for_name_lookup (decl); |
27110 | if (class_type != ctx) |
27111 | { |
27112 | if (pushed_scope) |
27113 | pop_scope (pushed_scope); |
27114 | class_type = ctx; |
27115 | pushed_scope = push_scope (class_type); |
27116 | } |
27117 | inject_this_parameter (ctype: class_type, quals: TYPE_UNQUALIFIED); |
27118 | cp_parser_late_parsing_nsdmi (parser, decl); |
27119 | } |
27120 | vec_safe_truncate (unparsed_nsdmis, size: 0); |
27121 | |
27122 | /* Now contract attributes. */ |
27123 | FOR_EACH_VEC_SAFE_ELT (unparsed_contracts, ix, decl) |
27124 | { |
27125 | tree ctx = DECL_CONTEXT (decl); |
27126 | if (class_type != ctx) |
27127 | { |
27128 | if (pushed_scope) |
27129 | pop_scope (pushed_scope); |
27130 | class_type = ctx; |
27131 | pushed_scope = push_scope (class_type); |
27132 | } |
27133 | |
27134 | temp_override<tree> cfd(current_function_decl, decl); |
27135 | |
27136 | /* Make sure that any template parameters are in scope. */ |
27137 | maybe_begin_member_template_processing (decl); |
27138 | |
27139 | /* Make sure that any member-function parameters are in scope. |
27140 | This function doesn't expect ccp to be set. */ |
27141 | current_class_ptr = current_class_ref = NULL_TREE; |
27142 | inject_parm_decls (decl); |
27143 | |
27144 | /* 'this' is not allowed in static member functions. */ |
27145 | unsigned char local_variables_forbidden_p |
27146 | = parser->local_variables_forbidden_p; |
27147 | if (DECL_THIS_STATIC (decl)) |
27148 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
27149 | |
27150 | /* Now we can parse contract conditions. */ |
27151 | for (tree a = DECL_ATTRIBUTES (decl); a; a = TREE_CHAIN (a)) |
27152 | { |
27153 | if (cxx_contract_attribute_p (a)) |
27154 | cp_parser_late_contract_condition (parser, decl, a); |
27155 | } |
27156 | |
27157 | /* Restore the state of local_variables_forbidden_p. */ |
27158 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
27159 | |
27160 | /* Remove any member-function parameters from the symbol table. */ |
27161 | pop_injected_parms (); |
27162 | |
27163 | /* Remove any template parameters from the symbol table. */ |
27164 | maybe_end_member_template_processing (); |
27165 | |
27166 | /* Perform any deferred contract matching. */ |
27167 | match_deferred_contracts (decl); |
27168 | } |
27169 | vec_safe_truncate (unparsed_contracts, size: 0); |
27170 | |
27171 | current_class_ptr = NULL_TREE; |
27172 | current_class_ref = NULL_TREE; |
27173 | if (pushed_scope) |
27174 | pop_scope (pushed_scope); |
27175 | |
27176 | /* Now parse the body of the functions. */ |
27177 | if (flag_openmp) |
27178 | { |
27179 | /* OpenMP UDRs need to be parsed before all other functions. */ |
27180 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
27181 | if (DECL_OMP_DECLARE_REDUCTION_P (decl)) |
27182 | cp_parser_late_parsing_for_member (parser, decl); |
27183 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
27184 | if (!DECL_OMP_DECLARE_REDUCTION_P (decl)) |
27185 | cp_parser_late_parsing_for_member (parser, decl); |
27186 | } |
27187 | else |
27188 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
27189 | cp_parser_late_parsing_for_member (parser, decl); |
27190 | vec_safe_truncate (unparsed_funs_with_definitions, size: 0); |
27191 | } |
27192 | |
27193 | /* Put back any saved access checks. */ |
27194 | pop_deferring_access_checks (); |
27195 | |
27196 | /* Restore saved state. */ |
27197 | parser->in_switch_statement_p = in_switch_statement_p; |
27198 | parser->in_statement = in_statement; |
27199 | parser->in_function_body = saved_in_function_body; |
27200 | parser->num_template_parameter_lists |
27201 | = saved_num_template_parameter_lists; |
27202 | parser->in_unbraced_linkage_specification_p |
27203 | = saved_in_unbraced_linkage_specification_p; |
27204 | current_class_ptr = saved_ccp; |
27205 | current_class_ref = saved_ccr; |
27206 | |
27207 | return type; |
27208 | } |
27209 | |
27210 | /* Parse a class-head. |
27211 | |
27212 | class-head: |
27213 | class-key identifier [opt] base-clause [opt] |
27214 | class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt] |
27215 | class-key nested-name-specifier [opt] template-id |
27216 | base-clause [opt] |
27217 | |
27218 | class-virt-specifier: |
27219 | final |
27220 | |
27221 | GNU Extensions: |
27222 | class-key attributes identifier [opt] base-clause [opt] |
27223 | class-key attributes nested-name-specifier identifier base-clause [opt] |
27224 | class-key attributes nested-name-specifier [opt] template-id |
27225 | base-clause [opt] |
27226 | |
27227 | Upon return BASES is initialized to the list of base classes (or |
27228 | NULL, if there are none) in the same form returned by |
27229 | cp_parser_base_clause. |
27230 | |
27231 | Returns the TYPE of the indicated class. Sets |
27232 | *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions |
27233 | involving a nested-name-specifier was used, and FALSE otherwise. |
27234 | |
27235 | Returns error_mark_node if this is not a class-head. |
27236 | |
27237 | Returns NULL_TREE if the class-head is syntactically valid, but |
27238 | semantically invalid in a way that means we should skip the entire |
27239 | body of the class. */ |
27240 | |
27241 | static tree |
27242 | cp_parser_class_head (cp_parser* parser, |
27243 | bool* nested_name_specifier_p) |
27244 | { |
27245 | tree nested_name_specifier; |
27246 | enum tag_types class_key; |
27247 | tree id = NULL_TREE; |
27248 | tree type = NULL_TREE; |
27249 | tree attributes; |
27250 | tree bases; |
27251 | cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; |
27252 | bool template_id_p = false; |
27253 | bool qualified_p = false; |
27254 | bool invalid_nested_name_p = false; |
27255 | bool invalid_explicit_specialization_p = false; |
27256 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
27257 | tree pushed_scope = NULL_TREE; |
27258 | unsigned num_templates; |
27259 | cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL; |
27260 | /* Assume no nested-name-specifier will be present. */ |
27261 | *nested_name_specifier_p = false; |
27262 | /* Assume no template parameter lists will be used in defining the |
27263 | type. */ |
27264 | num_templates = 0; |
27265 | parser->colon_corrects_to_scope_p = false; |
27266 | |
27267 | /* Look for the class-key. */ |
27268 | class_key = cp_parser_class_key (parser); |
27269 | if (class_key == none_type) |
27270 | return error_mark_node; |
27271 | |
27272 | location_t class_head_start_location = input_location; |
27273 | |
27274 | /* Parse the attributes. */ |
27275 | attributes = cp_parser_attributes_opt (parser); |
27276 | if (find_contract (attrs: attributes)) |
27277 | diagnose_misapplied_contracts (attributes); |
27278 | |
27279 | /* If the next token is `::', that is invalid -- but sometimes |
27280 | people do try to write: |
27281 | |
27282 | struct ::S {}; |
27283 | |
27284 | Handle this gracefully by accepting the extra qualifier, and then |
27285 | issuing an error about it later if this really is a |
27286 | class-head. If it turns out just to be an elaborated type |
27287 | specifier, remain silent. */ |
27288 | if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)) |
27289 | qualified_p = true; |
27290 | |
27291 | /* It is OK to define an inaccessible class; for example: |
27292 | |
27293 | class A { class B; }; |
27294 | class A::B {}; |
27295 | |
27296 | So we want to ignore access when parsing the class name. |
27297 | However, we might be tentatively parsing what is really an |
27298 | elaborated-type-specifier naming a template-id, e.g. |
27299 | |
27300 | struct C<&D::m> c; |
27301 | |
27302 | In this case the tentative parse as a class-head will fail, but not |
27303 | before cp_parser_template_id splices in a CPP_TEMPLATE_ID token. |
27304 | Since dk_no_check is sticky, we must instead use dk_deferred so that |
27305 | any such CPP_TEMPLATE_ID token created during this tentative parse |
27306 | will correctly capture the access checks imposed by the template-id . */ |
27307 | push_deferring_access_checks (dk_deferred); |
27308 | |
27309 | /* Determine the name of the class. Begin by looking for an |
27310 | optional nested-name-specifier. */ |
27311 | nested_name_specifier_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
27312 | nested_name_specifier |
27313 | = cp_parser_nested_name_specifier_opt (parser, |
27314 | /*typename_keyword_p=*/false, |
27315 | /*check_dependency_p=*/false, |
27316 | /*type_p=*/true, |
27317 | /*is_declaration=*/false); |
27318 | /* If there was a nested-name-specifier, then there *must* be an |
27319 | identifier. */ |
27320 | |
27321 | cp_token *bad_template_keyword = NULL; |
27322 | |
27323 | if (nested_name_specifier) |
27324 | { |
27325 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
27326 | /* Although the grammar says `identifier', it really means |
27327 | `class-name' or `template-name'. You are only allowed to |
27328 | define a class that has already been declared with this |
27329 | syntax. |
27330 | |
27331 | The proposed resolution for Core Issue 180 says that wherever |
27332 | you see `class T::X' you should treat `X' as a type-name. |
27333 | |
27334 | We do not know if we will see a class-name, or a |
27335 | template-name. We look for a class-name first, in case the |
27336 | class-name is a template-id; if we looked for the |
27337 | template-name first we would stop after the template-name. */ |
27338 | cp_parser_parse_tentatively (parser); |
27339 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
27340 | bad_template_keyword = cp_lexer_consume_token (lexer: parser->lexer); |
27341 | type = cp_parser_class_name (parser, |
27342 | /*typename_keyword_p=*/false, |
27343 | /*template_keyword_p=*/false, |
27344 | tag_type: class_type, |
27345 | /*check_dependency_p=*/false, |
27346 | /*class_head_p=*/true, |
27347 | /*is_declaration=*/false); |
27348 | /* If that didn't work, ignore the nested-name-specifier. */ |
27349 | if (!cp_parser_parse_definitely (parser)) |
27350 | { |
27351 | invalid_nested_name_p = true; |
27352 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
27353 | id = cp_parser_identifier (parser); |
27354 | if (id == error_mark_node) |
27355 | id = NULL_TREE; |
27356 | } |
27357 | /* If we could not find a corresponding TYPE, treat this |
27358 | declaration like an unqualified declaration. */ |
27359 | if (type == error_mark_node) |
27360 | nested_name_specifier = NULL_TREE; |
27361 | /* Otherwise, count the number of templates used in TYPE and its |
27362 | containing scopes. */ |
27363 | else |
27364 | num_templates = num_template_headers_for_class (TREE_TYPE (type)); |
27365 | } |
27366 | /* Otherwise, the identifier is optional. */ |
27367 | else |
27368 | { |
27369 | /* We don't know whether what comes next is a template-id, |
27370 | an identifier, or nothing at all. */ |
27371 | cp_parser_parse_tentatively (parser); |
27372 | /* Check for a template-id. */ |
27373 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
27374 | id = cp_parser_template_id (parser, |
27375 | /*template_keyword_p=*/false, |
27376 | /*check_dependency_p=*/true, |
27377 | tag_type: class_key, |
27378 | /*is_declaration=*/true); |
27379 | /* If that didn't work, it could still be an identifier. */ |
27380 | if (!cp_parser_parse_definitely (parser)) |
27381 | { |
27382 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
27383 | { |
27384 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
27385 | id = cp_parser_identifier (parser); |
27386 | } |
27387 | else |
27388 | id = NULL_TREE; |
27389 | } |
27390 | else |
27391 | { |
27392 | template_id_p = true; |
27393 | ++num_templates; |
27394 | } |
27395 | } |
27396 | |
27397 | pop_deferring_access_checks (); |
27398 | |
27399 | if (id) |
27400 | { |
27401 | cp_parser_check_for_invalid_template_id (parser, type: id, |
27402 | tag_type: class_key, |
27403 | location: type_start_token->location); |
27404 | } |
27405 | virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); |
27406 | |
27407 | /* If it's not a `:' or a `{' then we can't really be looking at a |
27408 | class-head, since a class-head only appears as part of a |
27409 | class-specifier. We have to detect this situation before calling |
27410 | xref_tag, since that has irreversible side-effects. */ |
27411 | if (!cp_parser_next_token_starts_class_definition_p (parser)) |
27412 | { |
27413 | cp_parser_error (parser, gmsgid: "expected %<{%> or %<:%>" ); |
27414 | type = error_mark_node; |
27415 | goto out; |
27416 | } |
27417 | |
27418 | /* At this point, we're going ahead with the class-specifier, even |
27419 | if some other problem occurs. */ |
27420 | cp_parser_commit_to_tentative_parse (parser); |
27421 | if (virt_specifiers & VIRT_SPEC_OVERRIDE) |
27422 | { |
27423 | cp_parser_error (parser, |
27424 | gmsgid: "cannot specify %<override%> for a class" ); |
27425 | type = error_mark_node; |
27426 | goto out; |
27427 | } |
27428 | /* Issue the error about the overly-qualified name now. */ |
27429 | if (qualified_p) |
27430 | { |
27431 | cp_parser_error (parser, |
27432 | gmsgid: "global qualification of class name is invalid" ); |
27433 | type = error_mark_node; |
27434 | goto out; |
27435 | } |
27436 | else if (invalid_nested_name_p) |
27437 | { |
27438 | cp_parser_error (parser, |
27439 | gmsgid: "qualified name does not name a class" ); |
27440 | type = error_mark_node; |
27441 | goto out; |
27442 | } |
27443 | else if (nested_name_specifier) |
27444 | { |
27445 | tree scope; |
27446 | |
27447 | if (bad_template_keyword) |
27448 | /* [temp.names]: in a qualified-id formed by a class-head-name, the |
27449 | keyword template shall not appear at the top level. */ |
27450 | pedwarn (bad_template_keyword->location, OPT_Wpedantic, |
27451 | "keyword %<template%> not allowed in class-head-name" ); |
27452 | |
27453 | /* Reject typedef-names in class heads. */ |
27454 | if (!DECL_IMPLICIT_TYPEDEF_P (type)) |
27455 | { |
27456 | error_at (type_start_token->location, |
27457 | "invalid class name in declaration of %qD" , |
27458 | type); |
27459 | type = NULL_TREE; |
27460 | goto done; |
27461 | } |
27462 | |
27463 | /* Figure out in what scope the declaration is being placed. */ |
27464 | scope = current_scope (); |
27465 | /* If that scope does not contain the scope in which the |
27466 | class was originally declared, the program is invalid. */ |
27467 | if (scope && !is_ancestor (ancestor: scope, descendant: nested_name_specifier)) |
27468 | { |
27469 | if (at_namespace_scope_p ()) |
27470 | error_at (type_start_token->location, |
27471 | "declaration of %qD in namespace %qD which does not " |
27472 | "enclose %qD" , |
27473 | type, scope, nested_name_specifier); |
27474 | else |
27475 | error_at (type_start_token->location, |
27476 | "declaration of %qD in %qD which does not enclose %qD" , |
27477 | type, scope, nested_name_specifier); |
27478 | type = NULL_TREE; |
27479 | goto done; |
27480 | } |
27481 | /* [dcl.meaning] |
27482 | |
27483 | A declarator-id shall not be qualified except for the |
27484 | definition of a ... nested class outside of its class |
27485 | ... [or] the definition or explicit instantiation of a |
27486 | class member of a namespace outside of its namespace. */ |
27487 | if (scope == nested_name_specifier) |
27488 | permerror (nested_name_specifier_token_start->location, |
27489 | "extra qualification not allowed" ); |
27490 | } |
27491 | /* An explicit-specialization must be preceded by "template <>". If |
27492 | it is not, try to recover gracefully. */ |
27493 | if (at_namespace_scope_p () |
27494 | && parser->num_template_parameter_lists == 0 |
27495 | && !processing_template_parmlist |
27496 | && template_id_p) |
27497 | { |
27498 | /* Build a location of this form: |
27499 | struct typename <ARGS> |
27500 | ^~~~~~~~~~~~~~~~~~~~~~ |
27501 | with caret==start at the start token, and |
27502 | finishing at the end of the type. */ |
27503 | location_t reported_loc |
27504 | = make_location (caret: class_head_start_location, |
27505 | start: class_head_start_location, |
27506 | finish: get_finish (loc: type_start_token->location)); |
27507 | rich_location richloc (line_table, reported_loc); |
27508 | richloc.add_fixit_insert_before (where: class_head_start_location, |
27509 | new_content: "template <> " ); |
27510 | error_at (&richloc, |
27511 | "an explicit specialization must be preceded by" |
27512 | " %<template <>%>" ); |
27513 | invalid_explicit_specialization_p = true; |
27514 | /* Take the same action that would have been taken by |
27515 | cp_parser_explicit_specialization. */ |
27516 | ++parser->num_template_parameter_lists; |
27517 | begin_specialization (); |
27518 | } |
27519 | /* There must be no "return" statements between this point and the |
27520 | end of this function; set "type "to the correct return value and |
27521 | use "goto done;" to return. */ |
27522 | /* Make sure that the right number of template parameters were |
27523 | present. */ |
27524 | if (!cp_parser_check_template_parameters (parser, num_templates, |
27525 | template_id_p, |
27526 | type_start_token->location, |
27527 | /*declarator=*/NULL)) |
27528 | { |
27529 | /* If something went wrong, there is no point in even trying to |
27530 | process the class-definition. */ |
27531 | type = NULL_TREE; |
27532 | goto done; |
27533 | } |
27534 | |
27535 | /* Look up the type. */ |
27536 | if (template_id_p) |
27537 | { |
27538 | if (TREE_CODE (id) == TEMPLATE_ID_EXPR |
27539 | && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0)) |
27540 | || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD)) |
27541 | { |
27542 | error_at (type_start_token->location, |
27543 | "function template %qD redeclared as a class template" , id); |
27544 | type = error_mark_node; |
27545 | } |
27546 | else |
27547 | { |
27548 | type = TREE_TYPE (id); |
27549 | type = maybe_process_partial_specialization (type); |
27550 | |
27551 | /* Check the scope while we still know whether or not we had a |
27552 | nested-name-specifier. */ |
27553 | if (type != error_mark_node) |
27554 | check_unqualified_spec_or_inst (type, type_start_token->location); |
27555 | } |
27556 | if (nested_name_specifier) |
27557 | pushed_scope = push_scope (nested_name_specifier); |
27558 | } |
27559 | else if (nested_name_specifier) |
27560 | { |
27561 | type = TREE_TYPE (type); |
27562 | |
27563 | /* Given: |
27564 | |
27565 | template <typename T> struct S { struct T }; |
27566 | template <typename T> struct S<T>::T { }; |
27567 | |
27568 | we will get a TYPENAME_TYPE when processing the definition of |
27569 | `S::T'. We need to resolve it to the actual type before we |
27570 | try to define it. */ |
27571 | if (TREE_CODE (type) == TYPENAME_TYPE) |
27572 | { |
27573 | type = resolve_typename_type (type, /*only_current_p=*/false); |
27574 | if (TREE_CODE (type) == TYPENAME_TYPE) |
27575 | { |
27576 | cp_parser_error (parser, gmsgid: "could not resolve typename type" ); |
27577 | type = error_mark_node; |
27578 | } |
27579 | } |
27580 | |
27581 | type = maybe_process_partial_specialization (type); |
27582 | if (type == error_mark_node) |
27583 | { |
27584 | type = NULL_TREE; |
27585 | goto done; |
27586 | } |
27587 | |
27588 | /* Enter the scope indicated by the nested-name-specifier. */ |
27589 | pushed_scope = push_scope (nested_name_specifier); |
27590 | /* Get the canonical version of this type. */ |
27591 | type = TYPE_MAIN_DECL (type); |
27592 | /* Call push_template_decl if it seems like we should be defining a |
27593 | template either from the template headers or the type we're |
27594 | defining, so that we diagnose both extra and missing headers. */ |
27595 | if ((PROCESSING_REAL_TEMPLATE_DECL_P () |
27596 | || CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (type))) |
27597 | && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (type))) |
27598 | { |
27599 | type = push_template_decl (type); |
27600 | if (type == error_mark_node) |
27601 | { |
27602 | type = NULL_TREE; |
27603 | goto done; |
27604 | } |
27605 | } |
27606 | |
27607 | type = TREE_TYPE (type); |
27608 | *nested_name_specifier_p = true; |
27609 | } |
27610 | else /* The name is not a nested name. */ |
27611 | { |
27612 | /* If the class was unnamed, create a dummy name. */ |
27613 | if (!id) |
27614 | id = make_anon_name (); |
27615 | TAG_how how = (parser->in_type_id_in_expr_p |
27616 | ? TAG_how::INNERMOST_NON_CLASS |
27617 | : TAG_how::CURRENT_ONLY); |
27618 | type = xref_tag (class_key, id, how, |
27619 | tpl_header_p: parser->num_template_parameter_lists); |
27620 | } |
27621 | |
27622 | /* Diagnose class/struct/union mismatches. */ |
27623 | cp_parser_check_class_key (parser, UNKNOWN_LOCATION, class_key, type, |
27624 | true, true); |
27625 | |
27626 | /* Indicate whether this class was declared as a `class' or as a |
27627 | `struct'. */ |
27628 | if (TREE_CODE (type) == RECORD_TYPE) |
27629 | CLASSTYPE_DECLARED_CLASS (type) = class_key == class_type; |
27630 | |
27631 | /* If this type was already complete, and we see another definition, |
27632 | that's an error. Likewise if the type is already being defined: |
27633 | this can happen, eg, when it's defined from within an expression |
27634 | (c++/84605). */ |
27635 | if (type != error_mark_node |
27636 | && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type))) |
27637 | { |
27638 | error_at (type_start_token->location, "redefinition of %q#T" , |
27639 | type); |
27640 | inform (location_of (type), "previous definition of %q#T" , |
27641 | type); |
27642 | type = NULL_TREE; |
27643 | goto done; |
27644 | } |
27645 | else if (type == error_mark_node) |
27646 | type = NULL_TREE; |
27647 | |
27648 | if (type) |
27649 | { |
27650 | if (current_lambda_expr () |
27651 | && uses_parameter_packs (attributes)) |
27652 | { |
27653 | /* In a lambda this should work, but doesn't currently. */ |
27654 | sorry ("unexpanded parameter pack in local class in lambda" ); |
27655 | attributes = NULL_TREE; |
27656 | } |
27657 | |
27658 | /* Apply attributes now, before any use of the class as a template |
27659 | argument in its base list. */ |
27660 | cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); |
27661 | fixup_attribute_variants (type); |
27662 | } |
27663 | |
27664 | /* Associate constraints with the type. */ |
27665 | if (flag_concepts) |
27666 | type = associate_classtype_constraints (type); |
27667 | |
27668 | /* We will have entered the scope containing the class; the names of |
27669 | base classes should be looked up in that context. For example: |
27670 | |
27671 | struct A { struct B {}; struct C; }; |
27672 | struct A::C : B {}; |
27673 | |
27674 | is valid. */ |
27675 | |
27676 | /* Get the list of base-classes, if there is one. Defer access checking |
27677 | until the entire list has been seen, as per [class.access.general]. */ |
27678 | push_deferring_access_checks (dk_deferred); |
27679 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
27680 | { |
27681 | if (type) |
27682 | { |
27683 | pushclass (type); |
27684 | start_lambda_scope (TYPE_NAME (type)); |
27685 | } |
27686 | bases = cp_parser_base_clause (parser); |
27687 | if (type) |
27688 | { |
27689 | finish_lambda_scope (); |
27690 | popclass (); |
27691 | } |
27692 | } |
27693 | else |
27694 | bases = NULL_TREE; |
27695 | |
27696 | /* If we're really defining a class, process the base classes. |
27697 | If they're invalid, fail. */ |
27698 | if (type && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
27699 | xref_basetypes (type, bases); |
27700 | |
27701 | /* Now that all bases have been seen and attached to the class, check |
27702 | accessibility of the types named in the base-clause. This must be |
27703 | done relative to the class scope, so that we accept e.g. |
27704 | |
27705 | struct A { protected: struct B {}; }; |
27706 | struct C : A::B, A {}; // OK: A::B is accessible via base A |
27707 | |
27708 | as per [class.access.general]. */ |
27709 | if (type) |
27710 | pushclass (type); |
27711 | pop_to_parent_deferring_access_checks (); |
27712 | if (type) |
27713 | popclass (); |
27714 | |
27715 | done: |
27716 | /* Leave the scope given by the nested-name-specifier. We will |
27717 | enter the class scope itself while processing the members. */ |
27718 | if (pushed_scope) |
27719 | pop_scope (pushed_scope); |
27720 | |
27721 | if (invalid_explicit_specialization_p) |
27722 | { |
27723 | end_specialization (); |
27724 | --parser->num_template_parameter_lists; |
27725 | } |
27726 | |
27727 | if (type) |
27728 | DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; |
27729 | if (type && (virt_specifiers & VIRT_SPEC_FINAL)) |
27730 | CLASSTYPE_FINAL (type) = 1; |
27731 | out: |
27732 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
27733 | return type; |
27734 | } |
27735 | |
27736 | /* Parse a class-key. |
27737 | |
27738 | class-key: |
27739 | class |
27740 | struct |
27741 | union |
27742 | |
27743 | Returns the kind of class-key specified, or none_type to indicate |
27744 | error. */ |
27745 | |
27746 | static enum tag_types |
27747 | cp_parser_class_key (cp_parser* parser) |
27748 | { |
27749 | cp_token *token; |
27750 | enum tag_types tag_type; |
27751 | |
27752 | /* Look for the class-key. */ |
27753 | token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_KEY); |
27754 | if (!token) |
27755 | return none_type; |
27756 | |
27757 | /* Check to see if the TOKEN is a class-key. */ |
27758 | tag_type = cp_parser_token_is_class_key (token); |
27759 | if (!tag_type) |
27760 | cp_parser_error (parser, gmsgid: "expected class-key" ); |
27761 | return tag_type; |
27762 | } |
27763 | |
27764 | /* Parse a type-parameter-key. |
27765 | |
27766 | type-parameter-key: |
27767 | class |
27768 | typename |
27769 | */ |
27770 | |
27771 | static void |
27772 | cp_parser_type_parameter_key (cp_parser* parser) |
27773 | { |
27774 | /* Look for the type-parameter-key. */ |
27775 | enum tag_types tag_type = none_type; |
27776 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
27777 | if ((tag_type = cp_parser_token_is_type_parameter_key (token)) != none_type) |
27778 | { |
27779 | cp_lexer_consume_token (lexer: parser->lexer); |
27780 | if (pedantic && tag_type == typename_type |
27781 | && cxx_dialect < cxx17) |
27782 | /* typename is not allowed in a template template parameter |
27783 | by the standard until C++17. */ |
27784 | pedwarn (token->location, OPT_Wc__17_extensions, |
27785 | "ISO C++ forbids typename key in template template parameter;" |
27786 | " use %<-std=c++17%> or %<-std=gnu++17%>" ); |
27787 | } |
27788 | else |
27789 | cp_parser_error (parser, gmsgid: "expected %<class%> or %<typename%>" ); |
27790 | |
27791 | return; |
27792 | } |
27793 | |
27794 | /* Parse an (optional) member-specification. |
27795 | |
27796 | member-specification: |
27797 | member-declaration member-specification [opt] |
27798 | access-specifier : member-specification [opt] */ |
27799 | |
27800 | static void |
27801 | cp_parser_member_specification_opt (cp_parser* parser) |
27802 | { |
27803 | while (true) |
27804 | { |
27805 | cp_token *token; |
27806 | enum rid keyword; |
27807 | |
27808 | /* Peek at the next token. */ |
27809 | token = cp_lexer_peek_token (lexer: parser->lexer); |
27810 | /* If it's a `}', or EOF then we've seen all the members. */ |
27811 | if (token->type == CPP_CLOSE_BRACE |
27812 | || token->type == CPP_EOF |
27813 | || token->type == CPP_PRAGMA_EOL) |
27814 | break; |
27815 | |
27816 | /* See if this token is a keyword. */ |
27817 | keyword = token->keyword; |
27818 | switch (keyword) |
27819 | { |
27820 | case RID_PUBLIC: |
27821 | case RID_PROTECTED: |
27822 | case RID_PRIVATE: |
27823 | /* Consume the access-specifier. */ |
27824 | cp_lexer_consume_token (lexer: parser->lexer); |
27825 | /* Remember which access-specifier is active. */ |
27826 | current_access_specifier = token->u.value; |
27827 | /* Look for the `:'. */ |
27828 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
27829 | break; |
27830 | |
27831 | default: |
27832 | /* Accept #pragmas at class scope. */ |
27833 | if (token->type == CPP_PRAGMA) |
27834 | { |
27835 | cp_parser_pragma (parser, pragma_member, NULL); |
27836 | break; |
27837 | } |
27838 | |
27839 | /* Otherwise, the next construction must be a |
27840 | member-declaration. */ |
27841 | cp_parser_member_declaration (parser); |
27842 | } |
27843 | } |
27844 | } |
27845 | |
27846 | /* Parse a member-declaration. |
27847 | |
27848 | member-declaration: |
27849 | decl-specifier-seq [opt] member-declarator-list [opt] ; |
27850 | function-definition ; [opt] |
27851 | :: [opt] nested-name-specifier template [opt] unqualified-id ; |
27852 | using-declaration |
27853 | template-declaration |
27854 | alias-declaration |
27855 | |
27856 | member-declarator-list: |
27857 | member-declarator |
27858 | member-declarator-list , member-declarator |
27859 | |
27860 | member-declarator: |
27861 | declarator pure-specifier [opt] |
27862 | declarator constant-initializer [opt] |
27863 | identifier [opt] : constant-expression |
27864 | |
27865 | GNU Extensions: |
27866 | |
27867 | member-declaration: |
27868 | __extension__ member-declaration |
27869 | |
27870 | member-declarator: |
27871 | declarator attributes [opt] pure-specifier [opt] |
27872 | declarator attributes [opt] constant-initializer [opt] |
27873 | identifier [opt] attributes [opt] : constant-expression |
27874 | |
27875 | C++0x Extensions: |
27876 | |
27877 | member-declaration: |
27878 | static_assert-declaration */ |
27879 | |
27880 | static void |
27881 | cp_parser_member_declaration (cp_parser* parser) |
27882 | { |
27883 | cp_decl_specifier_seq decl_specifiers; |
27884 | tree prefix_attributes; |
27885 | tree decl; |
27886 | int declares_class_or_enum; |
27887 | bool friend_p; |
27888 | cp_token *token = NULL; |
27889 | cp_token *decl_spec_token_start = NULL; |
27890 | cp_token *initializer_token_start = NULL; |
27891 | int saved_pedantic; |
27892 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
27893 | |
27894 | /* Check for the `__extension__' keyword. */ |
27895 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
27896 | { |
27897 | /* Recurse. */ |
27898 | cp_parser_member_declaration (parser); |
27899 | /* Restore the old value of the PEDANTIC flag. */ |
27900 | pedantic = saved_pedantic; |
27901 | |
27902 | return; |
27903 | } |
27904 | |
27905 | /* Check for a template-declaration. */ |
27906 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
27907 | { |
27908 | /* An explicit specialization here is an error condition, and we |
27909 | expect the specialization handler to detect and report this. */ |
27910 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_LESS |
27911 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_GREATER) |
27912 | cp_parser_explicit_specialization (parser); |
27913 | else |
27914 | cp_parser_template_declaration (parser, /*member_p=*/true); |
27915 | |
27916 | return; |
27917 | } |
27918 | /* Check for a template introduction. */ |
27919 | else if (cp_parser_template_declaration_after_export (parser, true)) |
27920 | return; |
27921 | |
27922 | /* Check for a using-declaration. */ |
27923 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
27924 | { |
27925 | if (cxx_dialect < cxx11) |
27926 | /* Parse the using-declaration. */ |
27927 | cp_parser_using_declaration (parser, /*access_declaration_p=*/false); |
27928 | else if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_ENUM)) |
27929 | cp_parser_using_enum (parser); |
27930 | else |
27931 | { |
27932 | tree decl; |
27933 | bool alias_decl_expected; |
27934 | cp_parser_parse_tentatively (parser); |
27935 | decl = cp_parser_alias_declaration (parser); |
27936 | /* Note that if we actually see the '=' token after the |
27937 | identifier, cp_parser_alias_declaration commits the |
27938 | tentative parse. In that case, we really expect an |
27939 | alias-declaration. Otherwise, we expect a using |
27940 | declaration. */ |
27941 | alias_decl_expected = |
27942 | !cp_parser_uncommitted_to_tentative_parse_p (parser); |
27943 | cp_parser_parse_definitely (parser); |
27944 | |
27945 | if (alias_decl_expected) |
27946 | finish_member_declaration (decl); |
27947 | else |
27948 | cp_parser_using_declaration (parser, |
27949 | /*access_declaration_p=*/false); |
27950 | } |
27951 | return; |
27952 | } |
27953 | |
27954 | /* Check for @defs. */ |
27955 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_DEFS)) |
27956 | { |
27957 | tree ivar, member; |
27958 | tree ivar_chains = cp_parser_objc_defs_expression (parser); |
27959 | ivar = ivar_chains; |
27960 | while (ivar) |
27961 | { |
27962 | member = ivar; |
27963 | ivar = TREE_CHAIN (member); |
27964 | TREE_CHAIN (member) = NULL_TREE; |
27965 | finish_member_declaration (member); |
27966 | } |
27967 | return; |
27968 | } |
27969 | |
27970 | /* If the next token is `static_assert' we have a static assertion. */ |
27971 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC_ASSERT)) |
27972 | { |
27973 | cp_parser_static_assert (parser, /*member_p=*/true); |
27974 | return; |
27975 | } |
27976 | |
27977 | parser->colon_corrects_to_scope_p = false; |
27978 | |
27979 | cp_omp_declare_simd_data odsd; |
27980 | if (cp_parser_using_declaration (parser, /*access_declaration=*/access_declaration_p: true)) |
27981 | goto out; |
27982 | |
27983 | /* Parse the decl-specifier-seq. */ |
27984 | decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
27985 | cp_parser_decl_specifier_seq (parser, |
27986 | flags: (CP_PARSER_FLAGS_OPTIONAL |
27987 | | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), |
27988 | decl_specs: &decl_specifiers, |
27989 | declares_class_or_enum: &declares_class_or_enum); |
27990 | |
27991 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
27992 | cp_parser_handle_directive_omp_attributes (parser, |
27993 | pattrs: &decl_specifiers.attributes, |
27994 | data: &odsd, start: true); |
27995 | |
27996 | /* Check for an invalid type-name. */ |
27997 | if (!decl_specifiers.any_type_specifiers_p |
27998 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
27999 | goto out; |
28000 | /* If there is no declarator, then the decl-specifier-seq should |
28001 | specify a type. */ |
28002 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
28003 | { |
28004 | /* If there was no decl-specifier-seq, and the next token is a |
28005 | `;', then we have something like: |
28006 | |
28007 | struct S { ; }; |
28008 | |
28009 | [class.mem] |
28010 | |
28011 | Each member-declaration shall declare at least one member |
28012 | name of the class. */ |
28013 | if (!decl_specifiers.any_specifiers_p) |
28014 | { |
28015 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
28016 | if (cxx_dialect < cxx11 && !in_system_header_at (loc: token->location)) |
28017 | { |
28018 | gcc_rich_location richloc (token->location); |
28019 | richloc.add_fixit_remove (); |
28020 | pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>" ); |
28021 | } |
28022 | } |
28023 | else |
28024 | { |
28025 | /* See if this declaration is a friend. */ |
28026 | friend_p = cp_parser_friend_p (&decl_specifiers); |
28027 | /* If there were decl-specifiers, check to see if there was |
28028 | a class-declaration. */ |
28029 | tree type = check_tag_decl (&decl_specifiers, |
28030 | /*explicit_type_instantiation_p=*/false); |
28031 | /* Nested classes have already been added to the class, but |
28032 | a `friend' needs to be explicitly registered. */ |
28033 | if (friend_p) |
28034 | { |
28035 | /* If the `friend' keyword was present, the friend must |
28036 | be introduced with a class-key. */ |
28037 | if (!declares_class_or_enum && cxx_dialect < cxx11) |
28038 | pedwarn (decl_spec_token_start->location, OPT_Wpedantic, |
28039 | "in C++03 a class-key must be used " |
28040 | "when declaring a friend" ); |
28041 | /* In this case: |
28042 | |
28043 | template <typename T> struct A { |
28044 | friend struct A<T>::B; |
28045 | }; |
28046 | |
28047 | A<T>::B will be represented by a TYPENAME_TYPE, and |
28048 | therefore not recognized by check_tag_decl. */ |
28049 | if (!type) |
28050 | { |
28051 | type = decl_specifiers.type; |
28052 | if (type && TREE_CODE (type) == TYPE_DECL) |
28053 | type = TREE_TYPE (type); |
28054 | } |
28055 | /* Warn if an attribute cannot appear here, as per |
28056 | [dcl.attr.grammar]/5. But not when declares_class_or_enum: |
28057 | we ignore attributes in elaborated-type-specifiers. */ |
28058 | if (!declares_class_or_enum |
28059 | && cxx11_attribute_p (decl_specifiers.attributes)) |
28060 | { |
28061 | decl_specifiers.attributes = NULL_TREE; |
28062 | if (warning_at (decl_spec_token_start->location, |
28063 | OPT_Wattributes, "attribute ignored" )) |
28064 | inform (decl_spec_token_start->location, "an attribute " |
28065 | "that appertains to a friend declaration that " |
28066 | "is not a definition is ignored" ); |
28067 | } |
28068 | if (!type || !TYPE_P (type)) |
28069 | error_at (decl_spec_token_start->location, |
28070 | "friend declaration does not name a class or " |
28071 | "function" ); |
28072 | else |
28073 | make_friend_class (current_class_type, type, |
28074 | /*complain=*/true); |
28075 | } |
28076 | /* If there is no TYPE, an error message will already have |
28077 | been issued. */ |
28078 | else if (!type || type == error_mark_node) |
28079 | ; |
28080 | /* An anonymous aggregate has to be handled specially; such |
28081 | a declaration really declares a data member (with a |
28082 | particular type), as opposed to a nested class. */ |
28083 | else if (ANON_AGGR_TYPE_P (type)) |
28084 | { |
28085 | /* C++11 9.5/6. */ |
28086 | if (decl_specifiers.storage_class != sc_none) |
28087 | error_at (decl_spec_token_start->location, |
28088 | "a storage class on an anonymous aggregate " |
28089 | "in class scope is not allowed" ); |
28090 | |
28091 | /* Remove constructors and such from TYPE, now that we |
28092 | know it is an anonymous aggregate. */ |
28093 | fixup_anonymous_aggr (type); |
28094 | /* And make the corresponding data member. */ |
28095 | decl = build_decl (decl_spec_token_start->location, |
28096 | FIELD_DECL, NULL_TREE, type); |
28097 | /* Add it to the class. */ |
28098 | finish_member_declaration (decl); |
28099 | } |
28100 | else |
28101 | cp_parser_check_access_in_redeclaration |
28102 | (TYPE_NAME (type), |
28103 | location: decl_spec_token_start->location); |
28104 | } |
28105 | } |
28106 | else |
28107 | { |
28108 | bool assume_semicolon = false; |
28109 | |
28110 | /* Clear attributes from the decl_specifiers but keep them |
28111 | around as prefix attributes that apply them to the entity |
28112 | being declared. */ |
28113 | prefix_attributes = decl_specifiers.attributes; |
28114 | decl_specifiers.attributes = NULL_TREE; |
28115 | if (parser->omp_declare_simd |
28116 | && (parser->omp_declare_simd->attribs[0] |
28117 | == &decl_specifiers.attributes)) |
28118 | parser->omp_declare_simd->attribs[0] = &prefix_attributes; |
28119 | |
28120 | /* See if these declarations will be friends. */ |
28121 | friend_p = cp_parser_friend_p (&decl_specifiers); |
28122 | |
28123 | /* Keep going until we hit the `;' at the end of the |
28124 | declaration. */ |
28125 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
28126 | { |
28127 | tree attributes = NULL_TREE; |
28128 | tree first_attribute; |
28129 | tree initializer; |
28130 | bool named_bitfld = false; |
28131 | |
28132 | /* Peek at the next token. */ |
28133 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28134 | |
28135 | /* The following code wants to know early if it is a bit-field |
28136 | or some other declaration. Attributes can appear before |
28137 | the `:' token. Skip over them without consuming any tokens |
28138 | to peek if they are followed by `:'. */ |
28139 | if (cp_next_tokens_can_be_attribute_p (parser) |
28140 | || (token->type == CPP_NAME |
28141 | && cp_nth_tokens_can_be_attribute_p (parser, 2) |
28142 | && (named_bitfld = true))) |
28143 | { |
28144 | size_t n |
28145 | = cp_parser_skip_attributes_opt (parser, 1 + named_bitfld); |
28146 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
28147 | } |
28148 | |
28149 | /* Check for a bitfield declaration. */ |
28150 | if (token->type == CPP_COLON |
28151 | || (token->type == CPP_NAME |
28152 | && token == cp_lexer_peek_token (lexer: parser->lexer) |
28153 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON) |
28154 | && (named_bitfld = true))) |
28155 | { |
28156 | tree identifier; |
28157 | tree width; |
28158 | tree late_attributes = NULL_TREE; |
28159 | location_t id_location |
28160 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
28161 | |
28162 | if (named_bitfld) |
28163 | identifier = cp_parser_identifier (parser); |
28164 | else |
28165 | identifier = NULL_TREE; |
28166 | |
28167 | /* Look for attributes that apply to the bitfield. */ |
28168 | attributes = cp_parser_attributes_opt (parser); |
28169 | |
28170 | /* Consume the `:' token. */ |
28171 | cp_lexer_consume_token (lexer: parser->lexer); |
28172 | |
28173 | /* Get the width of the bitfield. */ |
28174 | width = cp_parser_constant_expression (parser, allow_non_constant_p: false, NULL, |
28175 | strict_p: cxx_dialect >= cxx11); |
28176 | |
28177 | /* In C++20 and as extension for C++11 and above we allow |
28178 | default member initializers for bit-fields. */ |
28179 | initializer = NULL_TREE; |
28180 | if (cxx_dialect >= cxx11 |
28181 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
28182 | || cp_lexer_next_token_is (lexer: parser->lexer, |
28183 | type: CPP_OPEN_BRACE))) |
28184 | { |
28185 | location_t loc |
28186 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
28187 | if (cxx_dialect < cxx20 |
28188 | && identifier != NULL_TREE) |
28189 | pedwarn (loc, OPT_Wc__20_extensions, |
28190 | "default member initializers for bit-fields " |
28191 | "only available with %<-std=c++20%> or " |
28192 | "%<-std=gnu++20%>" ); |
28193 | |
28194 | initializer = cp_parser_save_nsdmi (parser); |
28195 | if (identifier == NULL_TREE) |
28196 | { |
28197 | error_at (loc, "default member initializer for " |
28198 | "unnamed bit-field" ); |
28199 | initializer = NULL_TREE; |
28200 | } |
28201 | } |
28202 | else |
28203 | { |
28204 | /* Look for attributes that apply to the bitfield after |
28205 | the `:' token and width. This is where GCC used to |
28206 | parse attributes in the past, pedwarn if there is |
28207 | a std attribute. */ |
28208 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
28209 | pedwarn (input_location, OPT_Wpedantic, |
28210 | "ISO C++ allows bit-field attributes only " |
28211 | "before the %<:%> token" ); |
28212 | |
28213 | late_attributes = cp_parser_attributes_opt (parser); |
28214 | } |
28215 | |
28216 | attributes = attr_chainon (attrs: attributes, attr: late_attributes); |
28217 | |
28218 | /* Remember which attributes are prefix attributes and |
28219 | which are not. */ |
28220 | first_attribute = attributes; |
28221 | /* Combine the attributes. */ |
28222 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
28223 | |
28224 | /* Create the bitfield declaration. */ |
28225 | decl = grokbitfield (identifier |
28226 | ? make_id_declarator (NULL_TREE, |
28227 | unqualified_name: identifier, |
28228 | sfk: sfk_none, |
28229 | id_location) |
28230 | : NULL, |
28231 | &decl_specifiers, |
28232 | width, initializer, |
28233 | attributes); |
28234 | } |
28235 | else |
28236 | { |
28237 | cp_declarator *declarator; |
28238 | tree asm_specification; |
28239 | int ctor_dtor_or_conv_p; |
28240 | bool static_p = (decl_specifiers.storage_class == sc_static); |
28241 | cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
28242 | /* We can't delay parsing for friends, |
28243 | alias-declarations, and typedefs, even though the |
28244 | standard seems to require it. */ |
28245 | if (!friend_p |
28246 | && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) |
28247 | flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
28248 | |
28249 | /* Parse the declarator. */ |
28250 | declarator |
28251 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
28252 | flags, |
28253 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
28254 | /*parenthesized_p=*/NULL, |
28255 | /*member_p=*/true, |
28256 | friend_p, static_p); |
28257 | |
28258 | /* If something went wrong parsing the declarator, make sure |
28259 | that we at least consume some tokens. */ |
28260 | if (declarator == cp_error_declarator) |
28261 | { |
28262 | /* Skip to the end of the statement. */ |
28263 | cp_parser_skip_to_end_of_statement (parser); |
28264 | /* If the next token is not a semicolon, that is |
28265 | probably because we just skipped over the body of |
28266 | a function. So, we consume a semicolon if |
28267 | present, but do not issue an error message if it |
28268 | is not present. */ |
28269 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
28270 | type: CPP_SEMICOLON)) |
28271 | cp_lexer_consume_token (lexer: parser->lexer); |
28272 | goto out; |
28273 | } |
28274 | |
28275 | /* Handle class-scope non-template C++17 deduction guides. */ |
28276 | cp_parser_maybe_adjust_declarator_for_dguide (parser, |
28277 | decl_specs: &decl_specifiers, |
28278 | declarator, |
28279 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p); |
28280 | |
28281 | if (declares_class_or_enum & 2) |
28282 | cp_parser_check_for_definition_in_return_type |
28283 | (declarator, type: decl_specifiers.type, |
28284 | type_location: decl_specifiers.locations[ds_type_spec]); |
28285 | |
28286 | /* Look for an asm-specification. */ |
28287 | asm_specification = cp_parser_asm_specification_opt (parser); |
28288 | /* Look for attributes that apply to the declaration. */ |
28289 | attributes = cp_parser_attributes_opt (parser); |
28290 | /* Remember which attributes are prefix attributes and |
28291 | which are not. */ |
28292 | first_attribute = attributes; |
28293 | /* Combine the attributes. */ |
28294 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
28295 | |
28296 | /* If it's an `=', then we have a constant-initializer or a |
28297 | pure-specifier. It is not correct to parse the |
28298 | initializer before registering the member declaration |
28299 | since the member declaration should be in scope while |
28300 | its initializer is processed. However, the rest of the |
28301 | front end does not yet provide an interface that allows |
28302 | us to handle this correctly. */ |
28303 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
28304 | { |
28305 | /* In [class.mem]: |
28306 | |
28307 | A pure-specifier shall be used only in the declaration of |
28308 | a virtual function. |
28309 | |
28310 | A member-declarator can contain a constant-initializer |
28311 | only if it declares a static member of integral or |
28312 | enumeration type. |
28313 | |
28314 | Therefore, if the DECLARATOR is for a function, we look |
28315 | for a pure-specifier; otherwise, we look for a |
28316 | constant-initializer. When we call `grokfield', it will |
28317 | perform more stringent semantics checks. */ |
28318 | initializer_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
28319 | declarator->init_loc = initializer_token_start->location; |
28320 | if (function_declarator_p (declarator) |
28321 | || (decl_specifiers.type |
28322 | && TREE_CODE (decl_specifiers.type) == TYPE_DECL |
28323 | && declarator->kind == cdk_id |
28324 | && (TREE_CODE (TREE_TYPE (decl_specifiers.type)) |
28325 | == FUNCTION_TYPE))) |
28326 | initializer = cp_parser_pure_specifier (parser); |
28327 | else if (decl_specifiers.storage_class != sc_static) |
28328 | initializer = cp_parser_save_nsdmi (parser); |
28329 | else if (cxx_dialect >= cxx11) |
28330 | { |
28331 | /* Don't require a constant rvalue in C++11, since we |
28332 | might want a reference constant. We'll enforce |
28333 | constancy later. */ |
28334 | cp_lexer_consume_token (lexer: parser->lexer); |
28335 | /* Parse the initializer. */ |
28336 | initializer = cp_parser_initializer_clause (parser); |
28337 | } |
28338 | else |
28339 | /* Parse the initializer. */ |
28340 | initializer = cp_parser_constant_initializer (parser); |
28341 | } |
28342 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE) |
28343 | && !function_declarator_p (declarator)) |
28344 | { |
28345 | declarator->init_loc |
28346 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
28347 | if (decl_specifiers.storage_class != sc_static) |
28348 | initializer = cp_parser_save_nsdmi (parser); |
28349 | else |
28350 | initializer = cp_parser_initializer (parser); |
28351 | } |
28352 | /* Detect invalid bit-field cases such as |
28353 | |
28354 | int *p : 4; |
28355 | int &&r : 3; |
28356 | |
28357 | and similar. */ |
28358 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
28359 | /* If there were no type specifiers, it was a |
28360 | constructor. */ |
28361 | && decl_specifiers.any_type_specifiers_p) |
28362 | { |
28363 | /* This is called for a decent diagnostic only. */ |
28364 | tree d = grokdeclarator (declarator, &decl_specifiers, |
28365 | BITFIELD, /*initialized=*/false, |
28366 | &attributes); |
28367 | if (!error_operand_p (t: d)) |
28368 | error_at (DECL_SOURCE_LOCATION (d), |
28369 | "bit-field %qD has non-integral type %qT" , |
28370 | d, TREE_TYPE (d)); |
28371 | cp_parser_skip_to_end_of_statement (parser); |
28372 | /* Avoid "extra ;" pedwarns. */ |
28373 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
28374 | type: CPP_SEMICOLON)) |
28375 | cp_lexer_consume_token (lexer: parser->lexer); |
28376 | goto out; |
28377 | } |
28378 | /* Otherwise, there is no initializer. */ |
28379 | else |
28380 | initializer = NULL_TREE; |
28381 | |
28382 | /* See if we are probably looking at a function |
28383 | definition. We are certainly not looking at a |
28384 | member-declarator. Calling `grokfield' has |
28385 | side-effects, so we must not do it unless we are sure |
28386 | that we are looking at a member-declarator. */ |
28387 | if (cp_parser_token_starts_function_definition_p |
28388 | (cp_lexer_peek_token (lexer: parser->lexer))) |
28389 | { |
28390 | /* The grammar does not allow a pure-specifier to be |
28391 | used when a member function is defined. (It is |
28392 | possible that this fact is an oversight in the |
28393 | standard, since a pure function may be defined |
28394 | outside of the class-specifier. */ |
28395 | if (initializer && initializer_token_start) |
28396 | error_at (initializer_token_start->location, |
28397 | "pure-specifier on function-definition" ); |
28398 | decl = cp_parser_save_member_function_body (parser, |
28399 | &decl_specifiers, |
28400 | declarator, |
28401 | attributes); |
28402 | |
28403 | if (parser->fully_implicit_function_template_p) |
28404 | decl = finish_fully_implicit_template (parser, decl); |
28405 | /* If the member was not a friend, declare it here. */ |
28406 | if (!friend_p) |
28407 | finish_member_declaration (decl); |
28408 | /* Peek at the next token. */ |
28409 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28410 | /* If the next token is a semicolon, consume it. */ |
28411 | if (token->type == CPP_SEMICOLON) |
28412 | { |
28413 | location_t semicolon_loc |
28414 | = cp_lexer_consume_token (lexer: parser->lexer)->location; |
28415 | gcc_rich_location richloc (semicolon_loc); |
28416 | richloc.add_fixit_remove (); |
28417 | warning_at (&richloc, OPT_Wextra_semi, |
28418 | "extra %<;%> after in-class " |
28419 | "function definition" ); |
28420 | } |
28421 | goto out; |
28422 | } |
28423 | else |
28424 | if (declarator->kind == cdk_function) |
28425 | declarator->id_loc = token->location; |
28426 | |
28427 | /* Create the declaration. */ |
28428 | decl = grokfield (declarator, &decl_specifiers, |
28429 | initializer, /*init_const_expr_p=*/true, |
28430 | asm_specification, attributes); |
28431 | |
28432 | if (parser->fully_implicit_function_template_p) |
28433 | { |
28434 | if (friend_p) |
28435 | finish_fully_implicit_template (parser, 0); |
28436 | else |
28437 | decl = finish_fully_implicit_template (parser, decl); |
28438 | } |
28439 | } |
28440 | |
28441 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
28442 | cp_finalize_oacc_routine (parser, decl, false); |
28443 | |
28444 | /* Reset PREFIX_ATTRIBUTES. */ |
28445 | if (attributes != error_mark_node) |
28446 | { |
28447 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
28448 | attributes = TREE_CHAIN (attributes); |
28449 | if (attributes) |
28450 | TREE_CHAIN (attributes) = NULL_TREE; |
28451 | } |
28452 | |
28453 | /* If there is any qualification still in effect, clear it |
28454 | now; we will be starting fresh with the next declarator. */ |
28455 | parser->scope = NULL_TREE; |
28456 | parser->qualifying_scope = NULL_TREE; |
28457 | parser->object_scope = NULL_TREE; |
28458 | /* If it's a `,', then there are more declarators. */ |
28459 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
28460 | { |
28461 | cp_lexer_consume_token (lexer: parser->lexer); |
28462 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
28463 | { |
28464 | cp_token *token = cp_lexer_previous_token (lexer: parser->lexer); |
28465 | gcc_rich_location richloc (token->location); |
28466 | richloc.add_fixit_remove (); |
28467 | error_at (&richloc, "stray %<,%> at end of " |
28468 | "member declaration" ); |
28469 | } |
28470 | } |
28471 | /* If the next token isn't a `;', then we have a parse error. */ |
28472 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
28473 | type: CPP_SEMICOLON)) |
28474 | { |
28475 | /* The next token might be a ways away from where the |
28476 | actual semicolon is missing. Find the previous token |
28477 | and use that for our error position. */ |
28478 | cp_token *token = cp_lexer_previous_token (lexer: parser->lexer); |
28479 | gcc_rich_location richloc (token->location); |
28480 | richloc.add_fixit_insert_after (new_content: ";" ); |
28481 | error_at (&richloc, "expected %<;%> at end of " |
28482 | "member declaration" ); |
28483 | |
28484 | /* Assume that the user meant to provide a semicolon. If |
28485 | we were to cp_parser_skip_to_end_of_statement, we might |
28486 | skip to a semicolon inside a member function definition |
28487 | and issue nonsensical error messages. */ |
28488 | assume_semicolon = true; |
28489 | } |
28490 | |
28491 | if (decl) |
28492 | { |
28493 | /* Add DECL to the list of members. */ |
28494 | if (!friend_p |
28495 | /* Explicitly include, eg, NSDMIs, for better error |
28496 | recovery (c++/58650). */ |
28497 | || !DECL_DECLARES_FUNCTION_P (decl)) |
28498 | finish_member_declaration (decl); |
28499 | |
28500 | if (DECL_DECLARES_FUNCTION_P (decl)) |
28501 | cp_parser_save_default_args (parser, STRIP_TEMPLATE (decl)); |
28502 | else if (TREE_CODE (decl) == FIELD_DECL |
28503 | && DECL_INITIAL (decl)) |
28504 | /* Add DECL to the queue of NSDMI to be parsed later. */ |
28505 | vec_safe_push (unparsed_nsdmis, obj: decl); |
28506 | } |
28507 | |
28508 | if (assume_semicolon) |
28509 | goto out; |
28510 | } |
28511 | } |
28512 | |
28513 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
28514 | out: |
28515 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
28516 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
28517 | } |
28518 | |
28519 | /* Parse a pure-specifier. |
28520 | |
28521 | pure-specifier: |
28522 | = 0 |
28523 | |
28524 | Returns INTEGER_ZERO_NODE if a pure specifier is found. |
28525 | Otherwise, ERROR_MARK_NODE is returned. */ |
28526 | |
28527 | static tree |
28528 | cp_parser_pure_specifier (cp_parser* parser) |
28529 | { |
28530 | cp_token *token; |
28531 | |
28532 | /* Look for the `=' token. */ |
28533 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
28534 | return error_mark_node; |
28535 | /* Look for the `0' token. */ |
28536 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28537 | |
28538 | if (token->type == CPP_EOF |
28539 | || token->type == CPP_PRAGMA_EOL) |
28540 | return error_mark_node; |
28541 | |
28542 | cp_lexer_consume_token (lexer: parser->lexer); |
28543 | |
28544 | /* Accept = default or = delete in c++0x mode. */ |
28545 | if (token->keyword == RID_DEFAULT |
28546 | || token->keyword == RID_DELETE) |
28547 | { |
28548 | maybe_warn_cpp0x (str: CPP0X_DEFAULTED_DELETED); |
28549 | return token->u.value; |
28550 | } |
28551 | |
28552 | /* c_lex_with_flags marks a single digit '0' with PURE_ZERO. */ |
28553 | if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO)) |
28554 | { |
28555 | cp_parser_error (parser, |
28556 | gmsgid: "invalid pure specifier (only %<= 0%> is allowed)" ); |
28557 | cp_parser_skip_to_end_of_statement (parser); |
28558 | return error_mark_node; |
28559 | } |
28560 | if (PROCESSING_REAL_TEMPLATE_DECL_P ()) |
28561 | { |
28562 | error_at (token->location, "templates may not be %<virtual%>" ); |
28563 | return error_mark_node; |
28564 | } |
28565 | |
28566 | return integer_zero_node; |
28567 | } |
28568 | |
28569 | /* Parse a constant-initializer. |
28570 | |
28571 | constant-initializer: |
28572 | = constant-expression |
28573 | |
28574 | Returns a representation of the constant-expression. */ |
28575 | |
28576 | static tree |
28577 | cp_parser_constant_initializer (cp_parser* parser) |
28578 | { |
28579 | /* Look for the `=' token. */ |
28580 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
28581 | return error_mark_node; |
28582 | |
28583 | /* It is invalid to write: |
28584 | |
28585 | struct S { static const int i = { 7 }; }; |
28586 | |
28587 | */ |
28588 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
28589 | { |
28590 | cp_parser_error (parser, |
28591 | gmsgid: "a brace-enclosed initializer is not allowed here" ); |
28592 | /* Consume the opening brace. */ |
28593 | matching_braces braces; |
28594 | braces.consume_open (parser); |
28595 | /* Skip the initializer. */ |
28596 | cp_parser_skip_to_closing_brace (parser); |
28597 | /* Look for the trailing `}'. */ |
28598 | braces.require_close (parser); |
28599 | |
28600 | return error_mark_node; |
28601 | } |
28602 | |
28603 | return cp_parser_constant_expression (parser); |
28604 | } |
28605 | |
28606 | /* Derived classes [gram.class.derived] */ |
28607 | |
28608 | /* Parse a base-clause. |
28609 | |
28610 | base-clause: |
28611 | : base-specifier-list |
28612 | |
28613 | base-specifier-list: |
28614 | base-specifier ... [opt] |
28615 | base-specifier-list , base-specifier ... [opt] |
28616 | |
28617 | Returns a TREE_LIST representing the base-classes, in the order in |
28618 | which they were declared. The representation of each node is as |
28619 | described by cp_parser_base_specifier. |
28620 | |
28621 | In the case that no bases are specified, this function will return |
28622 | NULL_TREE, not ERROR_MARK_NODE. */ |
28623 | |
28624 | static tree |
28625 | cp_parser_base_clause (cp_parser* parser) |
28626 | { |
28627 | tree bases = NULL_TREE; |
28628 | |
28629 | /* Look for the `:' that begins the list. */ |
28630 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
28631 | |
28632 | /* Scan the base-specifier-list. */ |
28633 | while (true) |
28634 | { |
28635 | cp_token *token; |
28636 | tree base; |
28637 | bool pack_expansion_p = false; |
28638 | |
28639 | /* Look for the base-specifier. */ |
28640 | base = cp_parser_base_specifier (parser); |
28641 | /* Look for the (optional) ellipsis. */ |
28642 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
28643 | { |
28644 | /* Consume the `...'. */ |
28645 | cp_lexer_consume_token (lexer: parser->lexer); |
28646 | |
28647 | pack_expansion_p = true; |
28648 | } |
28649 | |
28650 | /* Add BASE to the front of the list. */ |
28651 | if (base && base != error_mark_node) |
28652 | { |
28653 | if (pack_expansion_p) |
28654 | /* Make this a pack expansion type. */ |
28655 | TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base)); |
28656 | |
28657 | if (!check_for_bare_parameter_packs (TREE_VALUE (base))) |
28658 | { |
28659 | TREE_CHAIN (base) = bases; |
28660 | bases = base; |
28661 | } |
28662 | } |
28663 | /* Peek at the next token. */ |
28664 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28665 | /* If it's not a comma, then the list is complete. */ |
28666 | if (token->type != CPP_COMMA) |
28667 | break; |
28668 | /* Consume the `,'. */ |
28669 | cp_lexer_consume_token (lexer: parser->lexer); |
28670 | } |
28671 | |
28672 | /* PARSER->SCOPE may still be non-NULL at this point, if the last |
28673 | base class had a qualified name. However, the next name that |
28674 | appears is certainly not qualified. */ |
28675 | parser->scope = NULL_TREE; |
28676 | parser->qualifying_scope = NULL_TREE; |
28677 | parser->object_scope = NULL_TREE; |
28678 | |
28679 | return nreverse (bases); |
28680 | } |
28681 | |
28682 | /* Parse a base-specifier. |
28683 | |
28684 | base-specifier: |
28685 | :: [opt] nested-name-specifier [opt] class-name |
28686 | virtual access-specifier [opt] :: [opt] nested-name-specifier |
28687 | [opt] class-name |
28688 | access-specifier virtual [opt] :: [opt] nested-name-specifier |
28689 | [opt] class-name |
28690 | |
28691 | Returns a TREE_LIST. The TREE_PURPOSE will be one of |
28692 | ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_[VIRTUAL]_NODE to |
28693 | indicate the specifiers provided. The TREE_VALUE will be a TYPE |
28694 | (or the ERROR_MARK_NODE) indicating the type that was specified. */ |
28695 | |
28696 | static tree |
28697 | cp_parser_base_specifier (cp_parser* parser) |
28698 | { |
28699 | cp_token *token; |
28700 | bool done = false; |
28701 | bool virtual_p = false; |
28702 | bool duplicate_virtual_error_issued_p = false; |
28703 | bool duplicate_access_error_issued_p = false; |
28704 | bool class_scope_p, template_p; |
28705 | tree access = access_default_node; |
28706 | tree type; |
28707 | |
28708 | /* Process the optional `virtual' and `access-specifier'. */ |
28709 | while (!done) |
28710 | { |
28711 | /* Peek at the next token. */ |
28712 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28713 | /* Process `virtual'. */ |
28714 | switch (token->keyword) |
28715 | { |
28716 | case RID_VIRTUAL: |
28717 | /* If `virtual' appears more than once, issue an error. */ |
28718 | if (virtual_p && !duplicate_virtual_error_issued_p) |
28719 | { |
28720 | cp_parser_error (parser, |
28721 | gmsgid: "%<virtual%> specified more than once in base-specifier" ); |
28722 | duplicate_virtual_error_issued_p = true; |
28723 | } |
28724 | |
28725 | virtual_p = true; |
28726 | |
28727 | /* Consume the `virtual' token. */ |
28728 | cp_lexer_consume_token (lexer: parser->lexer); |
28729 | |
28730 | break; |
28731 | |
28732 | case RID_PUBLIC: |
28733 | case RID_PROTECTED: |
28734 | case RID_PRIVATE: |
28735 | /* If more than one access specifier appears, issue an |
28736 | error. */ |
28737 | if (access != access_default_node |
28738 | && !duplicate_access_error_issued_p) |
28739 | { |
28740 | cp_parser_error (parser, |
28741 | gmsgid: "more than one access specifier in base-specifier" ); |
28742 | duplicate_access_error_issued_p = true; |
28743 | } |
28744 | |
28745 | access = ridpointers[(int) token->keyword]; |
28746 | |
28747 | /* Consume the access-specifier. */ |
28748 | cp_lexer_consume_token (lexer: parser->lexer); |
28749 | |
28750 | break; |
28751 | |
28752 | default: |
28753 | done = true; |
28754 | break; |
28755 | } |
28756 | } |
28757 | /* It is not uncommon to see programs mechanically, erroneously, use |
28758 | the 'typename' keyword to denote (dependent) qualified types |
28759 | as base classes. */ |
28760 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
28761 | { |
28762 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28763 | if (!processing_template_decl) |
28764 | error_at (token->location, |
28765 | "keyword %<typename%> not allowed outside of templates" ); |
28766 | else |
28767 | error_at (token->location, |
28768 | "keyword %<typename%> not allowed in this context " |
28769 | "(the base class is implicitly a type)" ); |
28770 | cp_lexer_consume_token (lexer: parser->lexer); |
28771 | } |
28772 | |
28773 | /* Look for the optional `::' operator. */ |
28774 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
28775 | /* Look for the nested-name-specifier. The simplest way to |
28776 | implement: |
28777 | |
28778 | [temp.res] |
28779 | |
28780 | The keyword `typename' is not permitted in a base-specifier or |
28781 | mem-initializer; in these contexts a qualified name that |
28782 | depends on a template-parameter is implicitly assumed to be a |
28783 | type name. |
28784 | |
28785 | is to pretend that we have seen the `typename' keyword at this |
28786 | point. */ |
28787 | cp_parser_nested_name_specifier_opt (parser, |
28788 | /*typename_keyword_p=*/true, |
28789 | /*check_dependency_p=*/true, |
28790 | /*type_p=*/true, |
28791 | /*is_declaration=*/true); |
28792 | /* If the base class is given by a qualified name, assume that names |
28793 | we see are type names or templates, as appropriate. */ |
28794 | class_scope_p = (parser->scope && TYPE_P (parser->scope)); |
28795 | template_p = class_scope_p && cp_parser_optional_template_keyword (parser); |
28796 | |
28797 | if (!parser->scope |
28798 | && cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
28799 | /* DR 950 allows decltype as a base-specifier. */ |
28800 | type = cp_parser_decltype (parser); |
28801 | else |
28802 | { |
28803 | /* Otherwise, look for the class-name. */ |
28804 | type = cp_parser_class_name (parser, |
28805 | typename_keyword_p: class_scope_p, |
28806 | template_keyword_p: template_p, |
28807 | tag_type: typename_type, |
28808 | /*check_dependency_p=*/true, |
28809 | /*class_head_p=*/false, |
28810 | /*is_declaration=*/true); |
28811 | type = TREE_TYPE (type); |
28812 | } |
28813 | |
28814 | if (type == error_mark_node) |
28815 | return error_mark_node; |
28816 | |
28817 | return finish_base_specifier (type, access, virtual_p); |
28818 | } |
28819 | |
28820 | /* Exception handling [gram.exception] */ |
28821 | |
28822 | /* Save the tokens that make up the noexcept-specifier for a member-function. |
28823 | Returns a DEFERRED_PARSE. */ |
28824 | |
28825 | static tree |
28826 | cp_parser_save_noexcept (cp_parser *parser) |
28827 | { |
28828 | cp_token *first = parser->lexer->next_token; |
28829 | /* We want everything up to, including, the final ')'. */ |
28830 | cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0); |
28831 | cp_token *last = parser->lexer->next_token; |
28832 | |
28833 | /* As with default arguments and NSDMIs, make use of DEFERRED_PARSE |
28834 | to carry the information we will need. */ |
28835 | tree expr = make_node (DEFERRED_PARSE); |
28836 | /* Save away the noexcept-specifier; we will process it when the |
28837 | class is complete. */ |
28838 | DEFPARSE_TOKENS (expr) = cp_token_cache_new (first, last); |
28839 | DEFPARSE_INSTANTIATIONS (expr) = nullptr; |
28840 | expr = build_tree_list (expr, NULL_TREE); |
28841 | return expr; |
28842 | } |
28843 | |
28844 | /* Used for late processing of noexcept-specifiers of member-functions. |
28845 | DEFAULT_ARG is the unparsed operand of a noexcept-specifier which |
28846 | we saved for later; parse it now. DECL is the declaration of the |
28847 | member function. */ |
28848 | |
28849 | static tree |
28850 | cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg) |
28851 | { |
28852 | /* Make sure we've gotten something that hasn't been parsed yet. */ |
28853 | gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE); |
28854 | |
28855 | push_unparsed_function_queues (parser); |
28856 | |
28857 | /* Push the saved tokens for the noexcept-specifier onto the parser's |
28858 | lexer stack. */ |
28859 | cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg); |
28860 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
28861 | |
28862 | /* Parse the cached noexcept-specifier. */ |
28863 | tree parsed_arg |
28864 | = cp_parser_noexcept_specification_opt (parser, |
28865 | CP_PARSER_FLAGS_NONE, |
28866 | /*require_constexpr=*/true, |
28867 | /*consumed_expr=*/NULL, |
28868 | /*return_cond=*/false); |
28869 | |
28870 | /* Revert to the main lexer. */ |
28871 | cp_parser_pop_lexer (parser); |
28872 | |
28873 | /* Restore the queue. */ |
28874 | pop_unparsed_function_queues (parser); |
28875 | |
28876 | /* And we're done. */ |
28877 | return parsed_arg; |
28878 | } |
28879 | |
28880 | /* Perform late checking of overriding function with respect to their |
28881 | noexcept-specifiers. FNDECL is the member function that potentially |
28882 | overrides some virtual function with the same signature. */ |
28883 | |
28884 | static void |
28885 | noexcept_override_late_checks (tree fndecl) |
28886 | { |
28887 | tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl)); |
28888 | tree base_binfo; |
28889 | |
28890 | if (DECL_STATIC_FUNCTION_P (fndecl)) |
28891 | return; |
28892 | |
28893 | for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) |
28894 | { |
28895 | tree basetype = BINFO_TYPE (base_binfo); |
28896 | |
28897 | if (!TYPE_POLYMORPHIC_P (basetype)) |
28898 | continue; |
28899 | |
28900 | tree fn = look_for_overrides_here (basetype, fndecl); |
28901 | if (fn) |
28902 | maybe_check_overriding_exception_spec (fndecl, fn); |
28903 | } |
28904 | } |
28905 | |
28906 | /* Parse an (optional) noexcept-specification. |
28907 | |
28908 | noexcept-specification: |
28909 | noexcept ( constant-expression ) [opt] |
28910 | |
28911 | If no noexcept-specification is present, returns NULL_TREE. |
28912 | Otherwise, if REQUIRE_CONSTEXPR is false, then either parse and return any |
28913 | expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if |
28914 | there are no parentheses. CONSUMED_EXPR will be set accordingly. |
28915 | Otherwise, returns a noexcept specification unless RETURN_COND is true, |
28916 | in which case a boolean condition is returned instead. The parser flags |
28917 | FLAGS is used to control parsing. QUALS are qualifiers indicating whether |
28918 | the (member) function is `const'. */ |
28919 | |
28920 | static tree |
28921 | cp_parser_noexcept_specification_opt (cp_parser* parser, |
28922 | cp_parser_flags flags, |
28923 | bool require_constexpr, |
28924 | bool* consumed_expr, |
28925 | bool return_cond) |
28926 | { |
28927 | cp_token *token; |
28928 | const char *saved_message; |
28929 | |
28930 | /* Peek at the next token. */ |
28931 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28932 | |
28933 | /* Is it a noexcept-specification? */ |
28934 | if (cp_parser_is_keyword (token, keyword: RID_NOEXCEPT)) |
28935 | { |
28936 | tree expr; |
28937 | |
28938 | /* [class.mem]/6 says that a noexcept-specifer (within the |
28939 | member-specification of the class) is a complete-class context of |
28940 | a class. So, if the noexcept-specifier has the optional expression, |
28941 | just save the tokens, and reparse this after we're done with the |
28942 | class. */ |
28943 | |
28944 | if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) |
28945 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN) |
28946 | /* No need to delay parsing for a number literal or true/false. */ |
28947 | && !((cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NUMBER) |
28948 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_KEYWORD)) |
28949 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_PAREN)) |
28950 | && at_class_scope_p () |
28951 | && TYPE_BEING_DEFINED (current_class_type) |
28952 | && !LAMBDA_TYPE_P (current_class_type)) |
28953 | return cp_parser_save_noexcept (parser); |
28954 | |
28955 | cp_lexer_consume_token (lexer: parser->lexer); |
28956 | |
28957 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
28958 | { |
28959 | matching_parens parens; |
28960 | parens.consume_open (parser); |
28961 | |
28962 | if (require_constexpr) |
28963 | { |
28964 | /* Types may not be defined in an exception-specification. */ |
28965 | saved_message = parser->type_definition_forbidden_message; |
28966 | parser->type_definition_forbidden_message |
28967 | = G_("types may not be defined in an exception-specification" ); |
28968 | |
28969 | bool non_constant_p; |
28970 | expr |
28971 | = cp_parser_constant_expression (parser, |
28972 | /*allow_non_constant=*/allow_non_constant_p: true, |
28973 | non_constant_p: &non_constant_p); |
28974 | if (non_constant_p |
28975 | && !require_potential_rvalue_constant_expression (expr)) |
28976 | { |
28977 | expr = NULL_TREE; |
28978 | return_cond = true; |
28979 | } |
28980 | |
28981 | /* Restore the saved message. */ |
28982 | parser->type_definition_forbidden_message = saved_message; |
28983 | } |
28984 | else |
28985 | { |
28986 | expr = cp_parser_expression (parser); |
28987 | *consumed_expr = true; |
28988 | } |
28989 | |
28990 | parens.require_close (parser); |
28991 | } |
28992 | else |
28993 | { |
28994 | expr = boolean_true_node; |
28995 | if (!require_constexpr) |
28996 | *consumed_expr = false; |
28997 | } |
28998 | |
28999 | /* We cannot build a noexcept-spec right away because this will check |
29000 | that expr is a constexpr. */ |
29001 | if (!return_cond) |
29002 | return build_noexcept_spec (expr, tf_warning_or_error); |
29003 | else |
29004 | return expr; |
29005 | } |
29006 | else |
29007 | return NULL_TREE; |
29008 | } |
29009 | |
29010 | /* Parse an (optional) exception-specification. |
29011 | |
29012 | exception-specification: |
29013 | throw ( type-id-list [opt] ) |
29014 | |
29015 | Returns a TREE_LIST representing the exception-specification. The |
29016 | TREE_VALUE of each node is a type. The parser flags FLAGS is used to |
29017 | control parsing. QUALS are qualifiers indicating whether the (member) |
29018 | function is `const'. */ |
29019 | |
29020 | static tree |
29021 | cp_parser_exception_specification_opt (cp_parser* parser, |
29022 | cp_parser_flags flags) |
29023 | { |
29024 | cp_token *token; |
29025 | tree type_id_list; |
29026 | const char *saved_message; |
29027 | |
29028 | /* Peek at the next token. */ |
29029 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29030 | |
29031 | /* Is it a noexcept-specification? */ |
29032 | type_id_list |
29033 | = cp_parser_noexcept_specification_opt (parser, flags, |
29034 | /*require_constexpr=*/true, |
29035 | /*consumed_expr=*/NULL, |
29036 | /*return_cond=*/false); |
29037 | if (type_id_list != NULL_TREE) |
29038 | return type_id_list; |
29039 | |
29040 | /* If it's not `throw', then there's no exception-specification. */ |
29041 | if (!cp_parser_is_keyword (token, keyword: RID_THROW)) |
29042 | return NULL_TREE; |
29043 | |
29044 | location_t loc = token->location; |
29045 | |
29046 | /* Consume the `throw'. */ |
29047 | cp_lexer_consume_token (lexer: parser->lexer); |
29048 | |
29049 | /* Look for the `('. */ |
29050 | matching_parens parens; |
29051 | parens.require_open (parser); |
29052 | |
29053 | /* Peek at the next token. */ |
29054 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29055 | /* If it's not a `)', then there is a type-id-list. */ |
29056 | if (token->type != CPP_CLOSE_PAREN) |
29057 | { |
29058 | /* Types may not be defined in an exception-specification. */ |
29059 | saved_message = parser->type_definition_forbidden_message; |
29060 | parser->type_definition_forbidden_message |
29061 | = G_("types may not be defined in an exception-specification" ); |
29062 | /* Parse the type-id-list. */ |
29063 | type_id_list = cp_parser_type_id_list (parser); |
29064 | /* Restore the saved message. */ |
29065 | parser->type_definition_forbidden_message = saved_message; |
29066 | |
29067 | if (cxx_dialect >= cxx17) |
29068 | { |
29069 | error_at (loc, "ISO C++17 does not allow dynamic exception " |
29070 | "specifications" ); |
29071 | type_id_list = NULL_TREE; |
29072 | } |
29073 | else if (cxx_dialect >= cxx11) |
29074 | warning_at (loc, OPT_Wdeprecated, |
29075 | "dynamic exception specifications are deprecated in " |
29076 | "C++11" ); |
29077 | } |
29078 | /* In C++17, throw() is equivalent to noexcept (true). throw() |
29079 | is deprecated in C++11 and above as well, but is still widely used, |
29080 | so don't warn about it yet. */ |
29081 | else if (cxx_dialect >= cxx17) |
29082 | type_id_list = noexcept_true_spec; |
29083 | else |
29084 | type_id_list = empty_except_spec; |
29085 | |
29086 | /* Look for the `)'. */ |
29087 | parens.require_close (parser); |
29088 | |
29089 | return type_id_list; |
29090 | } |
29091 | |
29092 | /* Parse an (optional) type-id-list. |
29093 | |
29094 | type-id-list: |
29095 | type-id ... [opt] |
29096 | type-id-list , type-id ... [opt] |
29097 | |
29098 | Returns a TREE_LIST. The TREE_VALUE of each node is a TYPE, |
29099 | in the order that the types were presented. */ |
29100 | |
29101 | static tree |
29102 | cp_parser_type_id_list (cp_parser* parser) |
29103 | { |
29104 | tree types = NULL_TREE; |
29105 | |
29106 | while (true) |
29107 | { |
29108 | cp_token *token; |
29109 | tree type; |
29110 | |
29111 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29112 | |
29113 | /* Get the next type-id. */ |
29114 | type = cp_parser_type_id (parser); |
29115 | /* Check for invalid 'auto'. */ |
29116 | if (flag_concepts && type_uses_auto (type)) |
29117 | { |
29118 | error_at (token->location, |
29119 | "invalid use of %<auto%> in exception-specification" ); |
29120 | type = error_mark_node; |
29121 | } |
29122 | /* Parse the optional ellipsis. */ |
29123 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
29124 | { |
29125 | /* Consume the `...'. */ |
29126 | cp_lexer_consume_token (lexer: parser->lexer); |
29127 | |
29128 | /* Turn the type into a pack expansion expression. */ |
29129 | type = make_pack_expansion (type); |
29130 | } |
29131 | /* Add it to the list. */ |
29132 | types = add_exception_specifier (types, type, /*complain=*/1); |
29133 | /* Peek at the next token. */ |
29134 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29135 | /* If it is not a `,', we are done. */ |
29136 | if (token->type != CPP_COMMA) |
29137 | break; |
29138 | /* Consume the `,'. */ |
29139 | cp_lexer_consume_token (lexer: parser->lexer); |
29140 | } |
29141 | |
29142 | return nreverse (types); |
29143 | } |
29144 | |
29145 | /* Parse a try-block. |
29146 | |
29147 | try-block: |
29148 | try compound-statement handler-seq */ |
29149 | |
29150 | static tree |
29151 | cp_parser_try_block (cp_parser* parser) |
29152 | { |
29153 | tree try_block; |
29154 | |
29155 | cp_parser_require_keyword (parser, RID_TRY, RT_TRY); |
29156 | if (parser->in_function_body |
29157 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
29158 | && cxx_dialect < cxx20) |
29159 | pedwarn (input_location, OPT_Wc__20_extensions, |
29160 | "%<try%> in %<constexpr%> function only " |
29161 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
29162 | |
29163 | try_block = begin_try_block (); |
29164 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_TRY_BLOCK, function_body: false); |
29165 | finish_try_block (try_block); |
29166 | cp_parser_handler_seq (parser); |
29167 | finish_handler_sequence (try_block); |
29168 | |
29169 | return try_block; |
29170 | } |
29171 | |
29172 | /* Parse a function-try-block. |
29173 | |
29174 | function-try-block: |
29175 | try ctor-initializer [opt] function-body handler-seq */ |
29176 | |
29177 | static void |
29178 | cp_parser_function_try_block (cp_parser* parser) |
29179 | { |
29180 | tree compound_stmt; |
29181 | tree try_block; |
29182 | |
29183 | /* Look for the `try' keyword. */ |
29184 | if (!cp_parser_require_keyword (parser, RID_TRY, RT_TRY)) |
29185 | return; |
29186 | /* Let the rest of the front end know where we are. */ |
29187 | try_block = begin_function_try_block (&compound_stmt); |
29188 | /* Parse the function-body. */ |
29189 | cp_parser_ctor_initializer_opt_and_function_body |
29190 | (parser, /*in_function_try_block=*/true); |
29191 | /* We're done with the `try' part. */ |
29192 | finish_function_try_block (try_block); |
29193 | /* Parse the handlers. */ |
29194 | cp_parser_handler_seq (parser); |
29195 | /* We're done with the handlers. */ |
29196 | finish_function_handler_sequence (try_block, compound_stmt); |
29197 | } |
29198 | |
29199 | /* Parse a handler-seq. |
29200 | |
29201 | handler-seq: |
29202 | handler handler-seq [opt] */ |
29203 | |
29204 | static void |
29205 | cp_parser_handler_seq (cp_parser* parser) |
29206 | { |
29207 | while (true) |
29208 | { |
29209 | cp_token *token; |
29210 | |
29211 | /* Parse the handler. */ |
29212 | cp_parser_handler (parser); |
29213 | /* Peek at the next token. */ |
29214 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29215 | /* If it's not `catch' then there are no more handlers. */ |
29216 | if (!cp_parser_is_keyword (token, keyword: RID_CATCH)) |
29217 | break; |
29218 | } |
29219 | } |
29220 | |
29221 | /* Parse a handler. |
29222 | |
29223 | handler: |
29224 | catch ( exception-declaration ) compound-statement */ |
29225 | |
29226 | static void |
29227 | cp_parser_handler (cp_parser* parser) |
29228 | { |
29229 | tree handler; |
29230 | tree declaration; |
29231 | |
29232 | cp_parser_require_keyword (parser, RID_CATCH, RT_CATCH); |
29233 | handler = begin_handler (); |
29234 | matching_parens parens; |
29235 | parens.require_open (parser); |
29236 | declaration = cp_parser_exception_declaration (parser); |
29237 | finish_handler_parms (declaration, handler); |
29238 | parens.require_close (parser); |
29239 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
29240 | finish_handler (handler); |
29241 | } |
29242 | |
29243 | /* Parse an exception-declaration. |
29244 | |
29245 | exception-declaration: |
29246 | type-specifier-seq declarator |
29247 | type-specifier-seq abstract-declarator |
29248 | type-specifier-seq |
29249 | ... |
29250 | |
29251 | Returns a VAR_DECL for the declaration, or NULL_TREE if the |
29252 | ellipsis variant is used. */ |
29253 | |
29254 | static tree |
29255 | cp_parser_exception_declaration (cp_parser* parser) |
29256 | { |
29257 | cp_decl_specifier_seq type_specifiers; |
29258 | cp_declarator *declarator; |
29259 | const char *saved_message; |
29260 | |
29261 | /* If it's an ellipsis, it's easy to handle. */ |
29262 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
29263 | { |
29264 | /* Consume the `...' token. */ |
29265 | cp_lexer_consume_token (lexer: parser->lexer); |
29266 | return NULL_TREE; |
29267 | } |
29268 | |
29269 | /* Types may not be defined in exception-declarations. */ |
29270 | saved_message = parser->type_definition_forbidden_message; |
29271 | parser->type_definition_forbidden_message |
29272 | = G_("types may not be defined in exception-declarations" ); |
29273 | |
29274 | /* Parse the type-specifier-seq. */ |
29275 | cp_parser_type_specifier_seq (parser, flags: CP_PARSER_FLAGS_NONE, |
29276 | /*is_declaration=*/true, |
29277 | /*is_trailing_return=*/false, |
29278 | type_specifier_seq: &type_specifiers); |
29279 | /* If it's a `)', then there is no declarator. */ |
29280 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
29281 | declarator = NULL; |
29282 | else |
29283 | declarator = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_EITHER, |
29284 | flags: CP_PARSER_FLAGS_NONE, |
29285 | /*ctor_dtor_or_conv_p=*/NULL, |
29286 | /*parenthesized_p=*/NULL, |
29287 | /*member_p=*/false, |
29288 | /*friend_p=*/false, |
29289 | /*static_p=*/false); |
29290 | |
29291 | /* Restore the saved message. */ |
29292 | parser->type_definition_forbidden_message = saved_message; |
29293 | |
29294 | if (!type_specifiers.any_specifiers_p) |
29295 | return error_mark_node; |
29296 | |
29297 | return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL); |
29298 | } |
29299 | |
29300 | /* Parse a throw-expression. |
29301 | |
29302 | throw-expression: |
29303 | throw assignment-expression [opt] |
29304 | |
29305 | Returns a THROW_EXPR representing the throw-expression. */ |
29306 | |
29307 | static tree |
29308 | cp_parser_throw_expression (cp_parser* parser) |
29309 | { |
29310 | tree expression; |
29311 | cp_token* token; |
29312 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
29313 | |
29314 | cp_parser_require_keyword (parser, RID_THROW, RT_THROW); |
29315 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29316 | /* Figure out whether or not there is an assignment-expression |
29317 | following the "throw" keyword. */ |
29318 | if (token->type == CPP_COMMA |
29319 | || token->type == CPP_SEMICOLON |
29320 | || token->type == CPP_CLOSE_PAREN |
29321 | || token->type == CPP_CLOSE_SQUARE |
29322 | || token->type == CPP_CLOSE_BRACE |
29323 | || token->type == CPP_COLON) |
29324 | expression = NULL_TREE; |
29325 | else |
29326 | expression = cp_parser_assignment_expression (parser); |
29327 | |
29328 | /* Construct a location e.g.: |
29329 | throw x |
29330 | ^~~~~~~ |
29331 | with caret == start at the start of the "throw" token, and |
29332 | the end at the end of the final token we consumed. */ |
29333 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
29334 | lexer: parser->lexer); |
29335 | expression = build_throw (combined_loc, expression, tf_warning_or_error); |
29336 | |
29337 | return expression; |
29338 | } |
29339 | |
29340 | /* Parse a yield-expression. |
29341 | |
29342 | yield-expression: |
29343 | co_yield assignment-expression |
29344 | co_yield braced-init-list |
29345 | |
29346 | Returns a CO_YIELD_EXPR representing the yield-expression. */ |
29347 | |
29348 | static tree |
29349 | cp_parser_yield_expression (cp_parser* parser) |
29350 | { |
29351 | tree expr; |
29352 | |
29353 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29354 | location_t kw_loc = token->location; /* Save for later. */ |
29355 | |
29356 | cp_parser_require_keyword (parser, RID_CO_YIELD, RT_CO_YIELD); |
29357 | |
29358 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
29359 | { |
29360 | cp_lexer_set_source_position (lexer: parser->lexer); |
29361 | /* ??? : probably a moot point? */ |
29362 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
29363 | expr = cp_parser_braced_list (parser); |
29364 | } |
29365 | else |
29366 | expr = cp_parser_assignment_expression (parser); |
29367 | |
29368 | if (expr == error_mark_node) |
29369 | return expr; |
29370 | |
29371 | return finish_co_yield_expr (kw_loc, expr); |
29372 | } |
29373 | |
29374 | /* GNU Extensions */ |
29375 | |
29376 | /* Parse an (optional) asm-specification. |
29377 | |
29378 | asm-specification: |
29379 | asm ( string-literal ) |
29380 | |
29381 | If the asm-specification is present, returns a STRING_CST |
29382 | corresponding to the string-literal. Otherwise, returns |
29383 | NULL_TREE. */ |
29384 | |
29385 | static tree |
29386 | cp_parser_asm_specification_opt (cp_parser* parser) |
29387 | { |
29388 | /* Peek at the next token. */ |
29389 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29390 | /* If the next token isn't the `asm' keyword, then there's no |
29391 | asm-specification. */ |
29392 | if (!cp_parser_is_keyword (token, keyword: RID_ASM)) |
29393 | return NULL_TREE; |
29394 | |
29395 | /* Consume the `asm' token. */ |
29396 | cp_lexer_consume_token (lexer: parser->lexer); |
29397 | /* Look for the `('. */ |
29398 | matching_parens parens; |
29399 | parens.require_open (parser); |
29400 | |
29401 | /* Look for the string-literal. */ |
29402 | tree asm_specification = cp_parser_string_literal (parser, |
29403 | /*translate=*/false, |
29404 | /*wide_ok=*/false); |
29405 | |
29406 | /* Look for the `)'. */ |
29407 | parens.require_close (parser); |
29408 | |
29409 | return asm_specification; |
29410 | } |
29411 | |
29412 | /* Parse an asm-operand-list. |
29413 | |
29414 | asm-operand-list: |
29415 | asm-operand |
29416 | asm-operand-list , asm-operand |
29417 | |
29418 | asm-operand: |
29419 | string-literal ( expression ) |
29420 | [ string-literal ] string-literal ( expression ) |
29421 | |
29422 | Returns a TREE_LIST representing the operands. The TREE_VALUE of |
29423 | each node is the expression. The TREE_PURPOSE is itself a |
29424 | TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed |
29425 | string-literal (or NULL_TREE if not present) and whose TREE_VALUE |
29426 | is a STRING_CST for the string literal before the parenthesis. Returns |
29427 | ERROR_MARK_NODE if any of the operands are invalid. */ |
29428 | |
29429 | static tree |
29430 | cp_parser_asm_operand_list (cp_parser* parser) |
29431 | { |
29432 | tree asm_operands = NULL_TREE; |
29433 | bool invalid_operands = false; |
29434 | |
29435 | while (true) |
29436 | { |
29437 | tree name; |
29438 | |
29439 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
29440 | { |
29441 | /* Consume the `[' token. */ |
29442 | cp_lexer_consume_token (lexer: parser->lexer); |
29443 | /* Read the operand name. */ |
29444 | name = cp_parser_identifier (parser); |
29445 | if (name != error_mark_node) |
29446 | name = build_string (IDENTIFIER_LENGTH (name), |
29447 | IDENTIFIER_POINTER (name)); |
29448 | /* Look for the closing `]'. */ |
29449 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
29450 | } |
29451 | else |
29452 | name = NULL_TREE; |
29453 | /* Look for the string-literal. */ |
29454 | tree string_literal = cp_parser_string_literal (parser, |
29455 | /*translate=*/false, |
29456 | /*wide_ok=*/false); |
29457 | |
29458 | /* Look for the `('. */ |
29459 | matching_parens parens; |
29460 | parens.require_open (parser); |
29461 | /* Parse the expression. */ |
29462 | tree expression = cp_parser_expression (parser); |
29463 | /* Look for the `)'. */ |
29464 | parens.require_close (parser); |
29465 | |
29466 | if (name == error_mark_node |
29467 | || string_literal == error_mark_node |
29468 | || expression == error_mark_node) |
29469 | invalid_operands = true; |
29470 | |
29471 | /* Add this operand to the list. */ |
29472 | asm_operands = tree_cons (build_tree_list (name, string_literal), |
29473 | expression, |
29474 | asm_operands); |
29475 | /* If the next token is not a `,', there are no more |
29476 | operands. */ |
29477 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29478 | break; |
29479 | /* Consume the `,'. */ |
29480 | cp_lexer_consume_token (lexer: parser->lexer); |
29481 | } |
29482 | |
29483 | return invalid_operands ? error_mark_node : nreverse (asm_operands); |
29484 | } |
29485 | |
29486 | /* Parse an asm-clobber-list. |
29487 | |
29488 | asm-clobber-list: |
29489 | string-literal |
29490 | asm-clobber-list , string-literal |
29491 | |
29492 | Returns a TREE_LIST, indicating the clobbers in the order that they |
29493 | appeared. The TREE_VALUE of each node is a STRING_CST. */ |
29494 | |
29495 | static tree |
29496 | cp_parser_asm_clobber_list (cp_parser* parser) |
29497 | { |
29498 | tree clobbers = NULL_TREE; |
29499 | |
29500 | while (true) |
29501 | { |
29502 | /* Look for the string literal. */ |
29503 | tree string_literal = cp_parser_string_literal (parser, |
29504 | /*translate=*/false, |
29505 | /*wide_ok=*/false); |
29506 | /* Add it to the list. */ |
29507 | clobbers = tree_cons (NULL_TREE, string_literal, clobbers); |
29508 | /* If the next token is not a `,', then the list is |
29509 | complete. */ |
29510 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29511 | break; |
29512 | /* Consume the `,' token. */ |
29513 | cp_lexer_consume_token (lexer: parser->lexer); |
29514 | } |
29515 | |
29516 | return clobbers; |
29517 | } |
29518 | |
29519 | /* Parse an asm-label-list. |
29520 | |
29521 | asm-label-list: |
29522 | identifier |
29523 | asm-label-list , identifier |
29524 | |
29525 | Returns a TREE_LIST, indicating the labels in the order that they |
29526 | appeared. The TREE_VALUE of each node is a label. */ |
29527 | |
29528 | static tree |
29529 | cp_parser_asm_label_list (cp_parser* parser) |
29530 | { |
29531 | tree labels = NULL_TREE; |
29532 | |
29533 | while (true) |
29534 | { |
29535 | tree identifier, label, name; |
29536 | |
29537 | /* Look for the identifier. */ |
29538 | identifier = cp_parser_identifier (parser); |
29539 | if (!error_operand_p (t: identifier)) |
29540 | { |
29541 | label = lookup_label (identifier); |
29542 | if (TREE_CODE (label) == LABEL_DECL) |
29543 | { |
29544 | TREE_USED (label) = 1; |
29545 | check_goto (label); |
29546 | name = build_string (IDENTIFIER_LENGTH (identifier), |
29547 | IDENTIFIER_POINTER (identifier)); |
29548 | labels = tree_cons (name, label, labels); |
29549 | } |
29550 | } |
29551 | /* If the next token is not a `,', then the list is |
29552 | complete. */ |
29553 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29554 | break; |
29555 | /* Consume the `,' token. */ |
29556 | cp_lexer_consume_token (lexer: parser->lexer); |
29557 | } |
29558 | |
29559 | return nreverse (labels); |
29560 | } |
29561 | |
29562 | /* Return TRUE iff the next tokens in the stream are possibly the |
29563 | beginning of a GNU extension attribute. */ |
29564 | |
29565 | static bool |
29566 | cp_next_tokens_can_be_gnu_attribute_p (cp_parser *parser) |
29567 | { |
29568 | return cp_nth_tokens_can_be_gnu_attribute_p (parser, 1); |
29569 | } |
29570 | |
29571 | /* Return TRUE iff the next tokens in the stream are possibly the |
29572 | beginning of a standard C++-11 attribute specifier. */ |
29573 | |
29574 | static bool |
29575 | cp_next_tokens_can_be_std_attribute_p (cp_parser *parser) |
29576 | { |
29577 | return cp_nth_tokens_can_be_std_attribute_p (parser, 1); |
29578 | } |
29579 | |
29580 | /* Return TRUE iff the next Nth tokens in the stream are possibly the |
29581 | beginning of a standard C++-11 attribute specifier. */ |
29582 | |
29583 | static bool |
29584 | cp_nth_tokens_can_be_std_attribute_p (cp_parser *parser, size_t n) |
29585 | { |
29586 | cp_token *token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
29587 | |
29588 | return (cxx_dialect >= cxx11 |
29589 | && ((token->type == CPP_KEYWORD && token->keyword == RID_ALIGNAS) |
29590 | || (token->type == CPP_OPEN_SQUARE |
29591 | && (token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n + 1)) |
29592 | && token->type == CPP_OPEN_SQUARE))); |
29593 | } |
29594 | |
29595 | /* Return TRUE iff the next Nth tokens in the stream are possibly the |
29596 | beginning of a GNU extension attribute. */ |
29597 | |
29598 | static bool |
29599 | cp_nth_tokens_can_be_gnu_attribute_p (cp_parser *parser, size_t n) |
29600 | { |
29601 | cp_token *token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
29602 | |
29603 | return token->type == CPP_KEYWORD && token->keyword == RID_ATTRIBUTE; |
29604 | } |
29605 | |
29606 | /* Return true iff the next tokens can be the beginning of either a |
29607 | GNU attribute list, or a standard C++11 attribute sequence. */ |
29608 | |
29609 | static bool |
29610 | cp_next_tokens_can_be_attribute_p (cp_parser *parser) |
29611 | { |
29612 | return (cp_next_tokens_can_be_gnu_attribute_p (parser) |
29613 | || cp_next_tokens_can_be_std_attribute_p (parser)); |
29614 | } |
29615 | |
29616 | /* Return true iff the next Nth tokens can be the beginning of either |
29617 | a GNU attribute list, or a standard C++11 attribute sequence. */ |
29618 | |
29619 | static bool |
29620 | cp_nth_tokens_can_be_attribute_p (cp_parser *parser, size_t n) |
29621 | { |
29622 | return (cp_nth_tokens_can_be_gnu_attribute_p (parser, n) |
29623 | || cp_nth_tokens_can_be_std_attribute_p (parser, n)); |
29624 | } |
29625 | |
29626 | /* Parse either a standard C++-11 attribute-specifier-seq, or a series |
29627 | of GNU attributes, or return NULL. */ |
29628 | |
29629 | static tree |
29630 | cp_parser_attributes_opt (cp_parser *parser) |
29631 | { |
29632 | tree attrs = NULL_TREE; |
29633 | while (true) |
29634 | { |
29635 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
29636 | attrs = attr_chainon (attrs, attr: cp_parser_gnu_attributes_opt (parser)); |
29637 | else if (cp_next_tokens_can_be_std_attribute_p (parser)) |
29638 | attrs = attr_chainon (attrs, attr: cp_parser_std_attribute_spec_seq (parser)); |
29639 | else |
29640 | break; |
29641 | } |
29642 | return attrs; |
29643 | } |
29644 | |
29645 | /* Parse an (optional) series of attributes. |
29646 | |
29647 | attributes: |
29648 | attributes attribute |
29649 | |
29650 | attribute: |
29651 | __attribute__ (( attribute-list [opt] )) |
29652 | |
29653 | The return value is as for cp_parser_gnu_attribute_list. */ |
29654 | |
29655 | static tree |
29656 | cp_parser_gnu_attributes_opt (cp_parser* parser) |
29657 | { |
29658 | tree attributes = NULL_TREE; |
29659 | |
29660 | auto cleanup = make_temp_override |
29661 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
29662 | |
29663 | while (true) |
29664 | { |
29665 | cp_token *token; |
29666 | tree attribute_list; |
29667 | bool ok = true; |
29668 | |
29669 | /* Peek at the next token. */ |
29670 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29671 | /* If it's not `__attribute__', then we're done. */ |
29672 | if (token->keyword != RID_ATTRIBUTE) |
29673 | break; |
29674 | |
29675 | /* Consume the `__attribute__' keyword. */ |
29676 | cp_lexer_consume_token (lexer: parser->lexer); |
29677 | /* Look for the two `(' tokens. */ |
29678 | matching_parens outer_parens; |
29679 | if (!outer_parens.require_open (parser)) |
29680 | ok = false; |
29681 | matching_parens inner_parens; |
29682 | if (!inner_parens.require_open (parser)) |
29683 | ok = false; |
29684 | |
29685 | /* Peek at the next token. */ |
29686 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29687 | if (token->type != CPP_CLOSE_PAREN) |
29688 | /* Parse the attribute-list. */ |
29689 | attribute_list = cp_parser_gnu_attribute_list (parser); |
29690 | else |
29691 | /* If the next token is a `)', then there is no attribute |
29692 | list. */ |
29693 | attribute_list = NULL; |
29694 | |
29695 | /* Look for the two `)' tokens. */ |
29696 | if (!inner_parens.require_close (parser)) |
29697 | ok = false; |
29698 | if (!outer_parens.require_close (parser)) |
29699 | ok = false; |
29700 | if (!ok) |
29701 | cp_parser_skip_to_end_of_statement (parser); |
29702 | |
29703 | /* Add these new attributes to the list. */ |
29704 | attributes = attr_chainon (attrs: attributes, attr: attribute_list); |
29705 | } |
29706 | |
29707 | return attributes; |
29708 | } |
29709 | |
29710 | /* Parse a GNU attribute-list. |
29711 | |
29712 | attribute-list: |
29713 | attribute |
29714 | attribute-list , attribute |
29715 | |
29716 | attribute: |
29717 | identifier |
29718 | identifier ( identifier ) |
29719 | identifier ( identifier , expression-list ) |
29720 | identifier ( expression-list ) |
29721 | |
29722 | Returns a TREE_LIST, or NULL_TREE on error. Each node corresponds |
29723 | to an attribute. The TREE_PURPOSE of each node is the identifier |
29724 | indicating which attribute is in use. The TREE_VALUE represents |
29725 | the arguments, if any. */ |
29726 | |
29727 | static tree |
29728 | cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) |
29729 | { |
29730 | tree attribute_list = NULL_TREE; |
29731 | bool save_translate_strings_p = parser->translate_strings_p; |
29732 | |
29733 | /* Don't create wrapper nodes within attributes: the |
29734 | handlers don't know how to handle them. */ |
29735 | auto_suppress_location_wrappers sentinel; |
29736 | |
29737 | parser->translate_strings_p = false; |
29738 | while (true) |
29739 | { |
29740 | cp_token *token; |
29741 | tree identifier; |
29742 | tree attribute; |
29743 | |
29744 | /* Look for the identifier. We also allow keywords here; for |
29745 | example `__attribute__ ((const))' is legal. */ |
29746 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29747 | if (token->type == CPP_NAME |
29748 | || token->type == CPP_KEYWORD) |
29749 | { |
29750 | tree arguments = NULL_TREE; |
29751 | |
29752 | /* Consume the token, but save it since we need it for the |
29753 | SIMD enabled function parsing. */ |
29754 | cp_token *id_token = cp_lexer_consume_token (lexer: parser->lexer); |
29755 | |
29756 | /* Save away the identifier that indicates which attribute |
29757 | this is. */ |
29758 | identifier = (token->type == CPP_KEYWORD) |
29759 | /* For keywords, use the canonical spelling, not the |
29760 | parsed identifier. */ |
29761 | ? ridpointers[(int) token->keyword] |
29762 | : id_token->u.value; |
29763 | |
29764 | identifier = canonicalize_attr_name (attr_name: identifier); |
29765 | attribute = build_tree_list (identifier, NULL_TREE); |
29766 | |
29767 | /* Peek at the next token. */ |
29768 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29769 | /* If it's an `(', then parse the attribute arguments. */ |
29770 | if (token->type == CPP_OPEN_PAREN) |
29771 | { |
29772 | vec<tree, va_gc> *vec; |
29773 | int attr_flag = (attribute_takes_identifier_p (identifier) |
29774 | ? id_attr : normal_attr); |
29775 | if (is_attribute_p (attr_name: "assume" , ident: identifier)) |
29776 | attr_flag = assume_attr; |
29777 | vec = cp_parser_parenthesized_expression_list |
29778 | (parser, is_attribute_list: attr_flag, /*cast_p=*/false, |
29779 | /*allow_expansion_p=*/false, |
29780 | /*non_constant_p=*/NULL); |
29781 | if (vec == NULL) |
29782 | arguments = error_mark_node; |
29783 | else |
29784 | { |
29785 | arguments = build_tree_list_vec (vec); |
29786 | release_tree_vector (vec); |
29787 | } |
29788 | /* Save the arguments away. */ |
29789 | TREE_VALUE (attribute) = arguments; |
29790 | } |
29791 | |
29792 | if (arguments != error_mark_node) |
29793 | { |
29794 | /* Add this attribute to the list. */ |
29795 | TREE_CHAIN (attribute) = attribute_list; |
29796 | attribute_list = attribute; |
29797 | } |
29798 | |
29799 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29800 | } |
29801 | /* Unless EXACTLY_ONE is set look for more attributes. |
29802 | If the next token isn't a `,', we're done. */ |
29803 | if (exactly_one || token->type != CPP_COMMA) |
29804 | break; |
29805 | |
29806 | /* Consume the comma and keep going. */ |
29807 | cp_lexer_consume_token (lexer: parser->lexer); |
29808 | } |
29809 | parser->translate_strings_p = save_translate_strings_p; |
29810 | |
29811 | /* We built up the list in reverse order. */ |
29812 | return nreverse (attribute_list); |
29813 | } |
29814 | |
29815 | /* Parse arguments of omp::directive attribute. |
29816 | |
29817 | ( directive-name ,[opt] clause-list[opt] ) |
29818 | |
29819 | For directive just remember the first/last tokens for subsequent |
29820 | parsing. */ |
29821 | |
29822 | static void |
29823 | cp_parser_omp_directive_args (cp_parser *parser, tree attribute, bool decl_p) |
29824 | { |
29825 | cp_token *first = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
29826 | if (first->type == CPP_CLOSE_PAREN) |
29827 | { |
29828 | cp_lexer_consume_token (lexer: parser->lexer); |
29829 | error_at (first->location, "expected OpenMP directive name" ); |
29830 | cp_lexer_consume_token (lexer: parser->lexer); |
29831 | TREE_VALUE (attribute) = NULL_TREE; |
29832 | return; |
29833 | } |
29834 | size_t n = cp_parser_skip_balanced_tokens (parser, 1); |
29835 | if (n == 1) |
29836 | { |
29837 | cp_lexer_consume_token (lexer: parser->lexer); |
29838 | error_at (first->location, "expected attribute argument as balanced " |
29839 | "token sequence" ); |
29840 | TREE_VALUE (attribute) = NULL_TREE; |
29841 | return; |
29842 | } |
29843 | for (n = n - 2; n; --n) |
29844 | cp_lexer_consume_token (lexer: parser->lexer); |
29845 | cp_token *last = cp_lexer_peek_token (lexer: parser->lexer); |
29846 | cp_lexer_consume_token (lexer: parser->lexer); |
29847 | tree arg = make_node (DEFERRED_PARSE); |
29848 | DEFPARSE_TOKENS (arg) = cp_token_cache_new (first, last); |
29849 | DEFPARSE_INSTANTIATIONS (arg) = nullptr; |
29850 | if (decl_p) |
29851 | TREE_PUBLIC (arg) = 1; |
29852 | TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute)); |
29853 | } |
29854 | |
29855 | /* Parse arguments of omp::sequence attribute. |
29856 | |
29857 | ( omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... ) */ |
29858 | |
29859 | static void |
29860 | cp_parser_omp_sequence_args (cp_parser *parser, tree attribute) |
29861 | { |
29862 | matching_parens parens; |
29863 | parens.consume_open (parser); |
29864 | do |
29865 | { |
29866 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29867 | if (token->type == CPP_NAME |
29868 | && token->u.value == omp_identifier |
29869 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SCOPE)) |
29870 | { |
29871 | cp_lexer_consume_token (lexer: parser->lexer); |
29872 | cp_lexer_consume_token (lexer: parser->lexer); |
29873 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29874 | } |
29875 | bool directive = false; |
29876 | const char *p; |
29877 | if (token->type != CPP_NAME) |
29878 | p = "" ; |
29879 | else |
29880 | p = IDENTIFIER_POINTER (token->u.value); |
29881 | if (strcmp (s1: p, s2: "directive" ) == 0) |
29882 | directive = true; |
29883 | else if (strcmp (s1: p, s2: "sequence" ) != 0) |
29884 | { |
29885 | error_at (token->location, "expected %<directive%> or %<sequence%>" ); |
29886 | cp_parser_skip_to_closing_parenthesis (parser, |
29887 | /*recovering=*/true, |
29888 | /*or_comma=*/true, |
29889 | /*consume_paren=*/false); |
29890 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29891 | break; |
29892 | cp_lexer_consume_token (lexer: parser->lexer); |
29893 | } |
29894 | cp_lexer_consume_token (lexer: parser->lexer); |
29895 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
29896 | cp_parser_required_error (parser, RT_OPEN_PAREN, false, |
29897 | UNKNOWN_LOCATION); |
29898 | else if (directive) |
29899 | cp_parser_omp_directive_args (parser, attribute, decl_p: false); |
29900 | else |
29901 | cp_parser_omp_sequence_args (parser, attribute); |
29902 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29903 | break; |
29904 | cp_lexer_consume_token (lexer: parser->lexer); |
29905 | } |
29906 | while (1); |
29907 | if (!parens.require_close (parser)) |
29908 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
29909 | /*consume_paren=*/true); |
29910 | } |
29911 | |
29912 | /* Parse a standard C++11 attribute. |
29913 | |
29914 | The returned representation is a TREE_LIST which TREE_PURPOSE is |
29915 | the scoped name of the attribute, and the TREE_VALUE is its |
29916 | arguments list. |
29917 | |
29918 | Note that the scoped name of the attribute is itself a TREE_LIST |
29919 | which TREE_PURPOSE is the namespace of the attribute, and |
29920 | TREE_VALUE its name. This is unlike a GNU attribute -- as parsed |
29921 | by cp_parser_gnu_attribute_list -- that doesn't have any namespace |
29922 | and which TREE_PURPOSE is directly the attribute name. |
29923 | |
29924 | Clients of the attribute code should use get_attribute_namespace |
29925 | and get_attribute_name to get the actual namespace and name of |
29926 | attributes, regardless of their being GNU or C++11 attributes. |
29927 | |
29928 | attribute: |
29929 | attribute-token attribute-argument-clause [opt] |
29930 | |
29931 | attribute-token: |
29932 | identifier |
29933 | attribute-scoped-token |
29934 | |
29935 | attribute-scoped-token: |
29936 | attribute-namespace :: identifier |
29937 | |
29938 | attribute-namespace: |
29939 | identifier |
29940 | |
29941 | attribute-argument-clause: |
29942 | ( balanced-token-seq ) |
29943 | |
29944 | balanced-token-seq: |
29945 | balanced-token [opt] |
29946 | balanced-token-seq balanced-token |
29947 | |
29948 | balanced-token: |
29949 | ( balanced-token-seq ) |
29950 | [ balanced-token-seq ] |
29951 | { balanced-token-seq }. */ |
29952 | |
29953 | static tree |
29954 | cp_parser_std_attribute (cp_parser *parser, tree attr_ns) |
29955 | { |
29956 | tree attribute, attr_id = NULL_TREE, arguments; |
29957 | cp_token *token; |
29958 | |
29959 | auto cleanup = make_temp_override |
29960 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
29961 | |
29962 | /* First, parse name of the attribute, a.k.a attribute-token. */ |
29963 | |
29964 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29965 | if (token->type == CPP_NAME) |
29966 | attr_id = token->u.value; |
29967 | else if (token->type == CPP_KEYWORD) |
29968 | attr_id = ridpointers[(int) token->keyword]; |
29969 | else if (token->flags & NAMED_OP) |
29970 | attr_id = get_identifier (cpp_type2name (token->type, token->flags)); |
29971 | |
29972 | if (attr_id == NULL_TREE) |
29973 | return NULL_TREE; |
29974 | |
29975 | cp_lexer_consume_token (lexer: parser->lexer); |
29976 | |
29977 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29978 | if (token->type == CPP_SCOPE) |
29979 | { |
29980 | /* We are seeing a scoped attribute token. */ |
29981 | |
29982 | cp_lexer_consume_token (lexer: parser->lexer); |
29983 | if (attr_ns) |
29984 | error_at (token->location, "attribute using prefix used together " |
29985 | "with scoped attribute token" ); |
29986 | attr_ns = attr_id; |
29987 | |
29988 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29989 | if (token->type == CPP_NAME) |
29990 | attr_id = token->u.value; |
29991 | else if (token->type == CPP_KEYWORD) |
29992 | attr_id = ridpointers[(int) token->keyword]; |
29993 | else if (token->flags & NAMED_OP) |
29994 | attr_id = get_identifier (cpp_type2name (token->type, token->flags)); |
29995 | else |
29996 | { |
29997 | error_at (token->location, |
29998 | "expected an identifier for the attribute name" ); |
29999 | return error_mark_node; |
30000 | } |
30001 | cp_lexer_consume_token (lexer: parser->lexer); |
30002 | |
30003 | attr_ns = canonicalize_attr_name (attr_name: attr_ns); |
30004 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
30005 | attribute = build_tree_list (build_tree_list (attr_ns, attr_id), |
30006 | NULL_TREE); |
30007 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30008 | } |
30009 | else if (attr_ns) |
30010 | { |
30011 | attr_ns = canonicalize_attr_name (attr_name: attr_ns); |
30012 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
30013 | attribute = build_tree_list (build_tree_list (attr_ns, attr_id), |
30014 | NULL_TREE); |
30015 | } |
30016 | else |
30017 | { |
30018 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
30019 | attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), |
30020 | NULL_TREE); |
30021 | |
30022 | /* We used to treat C++11 noreturn attribute as equivalent to GNU's, |
30023 | but no longer: we have to be able to tell [[noreturn]] and |
30024 | __attribute__((noreturn)) apart. */ |
30025 | /* C++14 deprecated attribute is equivalent to GNU's. */ |
30026 | if (is_attribute_p (attr_name: "deprecated" , ident: attr_id)) |
30027 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
30028 | /* C++17 fallthrough attribute is equivalent to GNU's. */ |
30029 | else if (is_attribute_p (attr_name: "fallthrough" , ident: attr_id)) |
30030 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
30031 | /* C++23 assume attribute is equivalent to GNU's. */ |
30032 | else if (is_attribute_p (attr_name: "assume" , ident: attr_id)) |
30033 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
30034 | /* Transactional Memory TS optimize_for_synchronized attribute is |
30035 | equivalent to GNU transaction_callable. */ |
30036 | else if (is_attribute_p (attr_name: "optimize_for_synchronized" , ident: attr_id)) |
30037 | TREE_PURPOSE (attribute) |
30038 | = get_identifier ("transaction_callable" ); |
30039 | /* Transactional Memory attributes are GNU attributes. */ |
30040 | else if (tm_attr_to_mask (attr_id)) |
30041 | TREE_PURPOSE (attribute) = attr_id; |
30042 | } |
30043 | |
30044 | /* Now parse the optional argument clause of the attribute. */ |
30045 | |
30046 | if (token->type != CPP_OPEN_PAREN) |
30047 | { |
30048 | if ((flag_openmp || flag_openmp_simd) |
30049 | && attr_ns == omp_identifier |
30050 | && (is_attribute_p (attr_name: "directive" , ident: attr_id) |
30051 | || is_attribute_p (attr_name: "sequence" , ident: attr_id) |
30052 | || is_attribute_p (attr_name: "decl" , ident: attr_id))) |
30053 | { |
30054 | error_at (token->location, "%<omp::%E%> attribute requires argument" , |
30055 | attr_id); |
30056 | return NULL_TREE; |
30057 | } |
30058 | return attribute; |
30059 | } |
30060 | |
30061 | { |
30062 | vec<tree, va_gc> *vec; |
30063 | int attr_flag = normal_attr; |
30064 | |
30065 | /* Maybe we don't expect to see any arguments for this attribute. */ |
30066 | const attribute_spec *as |
30067 | = lookup_attribute_spec (TREE_PURPOSE (attribute)); |
30068 | if (as && as->max_length == 0) |
30069 | { |
30070 | error_at (token->location, "%qE attribute does not take any arguments" , |
30071 | attr_id); |
30072 | cp_parser_skip_to_closing_parenthesis (parser, |
30073 | /*recovering=*/true, |
30074 | /*or_comma=*/false, |
30075 | /*consume_paren=*/true); |
30076 | return error_mark_node; |
30077 | } |
30078 | |
30079 | if (is_attribute_p (attr_name: "assume" , ident: attr_id) |
30080 | && (attr_ns == NULL_TREE || attr_ns == gnu_identifier)) |
30081 | /* The assume attribute needs special handling of the argument. */ |
30082 | attr_flag = assume_attr; |
30083 | else if (attr_ns == gnu_identifier |
30084 | && attribute_takes_identifier_p (attr_id)) |
30085 | /* A GNU attribute that takes an identifier in parameter. */ |
30086 | attr_flag = id_attr; |
30087 | else if (attr_ns == NULL_TREE |
30088 | && cxx_dialect >= cxx26 |
30089 | && (is_attribute_p (attr_name: "deprecated" , ident: attr_id) |
30090 | || is_attribute_p (attr_name: "nodiscard" , ident: attr_id))) |
30091 | attr_flag = uneval_string_attr; |
30092 | |
30093 | /* If this is a fake attribute created to handle -Wno-attributes, |
30094 | we must skip parsing the arguments. */ |
30095 | if (as == NULL || attribute_ignored_p (as)) |
30096 | { |
30097 | if ((flag_openmp || flag_openmp_simd) && attr_ns == omp_identifier) |
30098 | { |
30099 | if (is_attribute_p (attr_name: "directive" , ident: attr_id)) |
30100 | { |
30101 | cp_parser_omp_directive_args (parser, attribute, decl_p: false); |
30102 | return attribute; |
30103 | } |
30104 | else if (is_attribute_p (attr_name: "decl" , ident: attr_id)) |
30105 | { |
30106 | TREE_VALUE (TREE_PURPOSE (attribute)) |
30107 | = get_identifier ("directive" ); |
30108 | cp_parser_omp_directive_args (parser, attribute, decl_p: true); |
30109 | return attribute; |
30110 | } |
30111 | else if (is_attribute_p (attr_name: "sequence" , ident: attr_id)) |
30112 | { |
30113 | TREE_VALUE (TREE_PURPOSE (attribute)) |
30114 | = get_identifier ("directive" ); |
30115 | cp_parser_omp_sequence_args (parser, attribute); |
30116 | TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute)); |
30117 | return attribute; |
30118 | } |
30119 | } |
30120 | |
30121 | /* For unknown attributes, just skip balanced tokens instead of |
30122 | trying to parse the arguments. Set TREE_VALUE (attribute) to |
30123 | error_mark_node to distinguish skipped arguments from attributes |
30124 | with no arguments. */ |
30125 | for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n) |
30126 | cp_lexer_consume_token (lexer: parser->lexer); |
30127 | TREE_VALUE (attribute) = error_mark_node; |
30128 | return attribute; |
30129 | } |
30130 | |
30131 | vec = cp_parser_parenthesized_expression_list |
30132 | (parser, is_attribute_list: attr_flag, /*cast_p=*/false, |
30133 | /*allow_expansion_p=*/true, |
30134 | /*non_constant_p=*/NULL); |
30135 | if (vec == NULL) |
30136 | arguments = error_mark_node; |
30137 | else |
30138 | { |
30139 | if (vec->is_empty ()) |
30140 | /* e.g. [[attr()]]. */ |
30141 | error_at (token->location, "parentheses must be omitted if " |
30142 | "%qE attribute argument list is empty" , |
30143 | attr_id); |
30144 | arguments = build_tree_list_vec (vec); |
30145 | release_tree_vector (vec); |
30146 | } |
30147 | |
30148 | if (arguments == error_mark_node) |
30149 | attribute = error_mark_node; |
30150 | else |
30151 | TREE_VALUE (attribute) = arguments; |
30152 | } |
30153 | |
30154 | return attribute; |
30155 | } |
30156 | |
30157 | /* Warn if the attribute ATTRIBUTE appears more than once in the |
30158 | attribute-list ATTRIBUTES. This used to be enforced for certain |
30159 | attributes, but the restriction was removed in P2156. |
30160 | LOC is the location of ATTRIBUTE. Returns true if ATTRIBUTE was not |
30161 | found in ATTRIBUTES. */ |
30162 | |
30163 | static bool |
30164 | cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute) |
30165 | { |
30166 | static auto alist = { "noreturn" , "deprecated" , "nodiscard" , "maybe_unused" , |
30167 | "likely" , "unlikely" , "fallthrough" , |
30168 | "no_unique_address" , "carries_dependency" }; |
30169 | if (attributes) |
30170 | for (const auto &a : alist) |
30171 | if (is_attribute_p (attr_name: a, ident: get_attribute_name (attribute)) |
30172 | && is_attribute_namespace_p (attr_ns: "" , attr: attribute) |
30173 | && lookup_attribute (attr_ns: "" , attr_name: a, list: attributes)) |
30174 | { |
30175 | if (!from_macro_expansion_at (loc)) |
30176 | warning_at (loc, OPT_Wattributes, "attribute %qs specified " |
30177 | "multiple times" , a); |
30178 | return false; |
30179 | } |
30180 | return true; |
30181 | } |
30182 | |
30183 | /* Parse a list of standard C++-11 attributes. |
30184 | |
30185 | attribute-list: |
30186 | attribute [opt] |
30187 | attribute-list , attribute[opt] |
30188 | attribute ... |
30189 | attribute-list , attribute ... |
30190 | */ |
30191 | |
30192 | static tree |
30193 | cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns) |
30194 | { |
30195 | tree attributes = NULL_TREE, attribute = NULL_TREE; |
30196 | cp_token *token = NULL; |
30197 | |
30198 | while (true) |
30199 | { |
30200 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
30201 | attribute = cp_parser_std_attribute (parser, attr_ns); |
30202 | if (attribute == error_mark_node) |
30203 | break; |
30204 | if (attribute != NULL_TREE) |
30205 | { |
30206 | if (cp_parser_check_std_attribute (loc, attributes, attribute)) |
30207 | { |
30208 | TREE_CHAIN (attribute) = attributes; |
30209 | attributes = attribute; |
30210 | } |
30211 | } |
30212 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30213 | if (token->type == CPP_ELLIPSIS) |
30214 | { |
30215 | cp_lexer_consume_token (lexer: parser->lexer); |
30216 | if (attribute == NULL_TREE) |
30217 | error_at (token->location, |
30218 | "expected attribute before %<...%>" ); |
30219 | else if (TREE_VALUE (attribute) == NULL_TREE) |
30220 | { |
30221 | error_at (token->location, "attribute with no arguments " |
30222 | "contains no parameter packs" ); |
30223 | return error_mark_node; |
30224 | } |
30225 | else if (TREE_VALUE (attribute) != error_mark_node) |
30226 | { |
30227 | tree pack = make_pack_expansion (TREE_VALUE (attribute)); |
30228 | if (pack == error_mark_node) |
30229 | return error_mark_node; |
30230 | TREE_VALUE (attribute) = pack; |
30231 | } |
30232 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30233 | } |
30234 | if (token->type != CPP_COMMA) |
30235 | break; |
30236 | cp_lexer_consume_token (lexer: parser->lexer); |
30237 | } |
30238 | attributes = nreverse (attributes); |
30239 | return attributes; |
30240 | } |
30241 | |
30242 | /* Optionally parse a C++20 contract role. A NULL return means that no |
30243 | contract role was specified. |
30244 | |
30245 | contract-role: |
30246 | % default |
30247 | % identifier |
30248 | |
30249 | If the identifier does not name a known contract role, it will |
30250 | be assumed to be default. Returns the identifier for the role |
30251 | token. */ |
30252 | |
30253 | static tree |
30254 | cp_parser_contract_role (cp_parser *parser) |
30255 | { |
30256 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_MOD)); |
30257 | cp_lexer_consume_token (lexer: parser->lexer); |
30258 | |
30259 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30260 | tree role_id = NULL_TREE; |
30261 | if (token->type == CPP_NAME) |
30262 | role_id = token->u.value; |
30263 | else if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT) |
30264 | role_id = get_identifier ("default" ); |
30265 | else |
30266 | { |
30267 | error_at (token->location, "expected contract-role" ); |
30268 | return error_mark_node; |
30269 | } |
30270 | cp_lexer_consume_token (lexer: parser->lexer); |
30271 | |
30272 | /* FIXME: Warn about invalid/unknown roles? */ |
30273 | return role_id; |
30274 | } |
30275 | |
30276 | /* Parse an optional contract mode. |
30277 | |
30278 | contract-mode: |
30279 | contract-semantic |
30280 | [contract-level] [contract-role] |
30281 | |
30282 | contract-semantic: |
30283 | check_never_continue |
30284 | check_maybe_continue |
30285 | check_always_continue |
30286 | |
30287 | contract-level: |
30288 | default |
30289 | audit |
30290 | axiom |
30291 | |
30292 | contract-role: |
30293 | default |
30294 | identifier |
30295 | |
30296 | This grammar is taken from P1332R0. During parsing, this sets options |
30297 | on the MODE object to determine the configuration of the contract. |
30298 | |
30299 | Returns a tree containing the identifiers used in the configuration. |
30300 | This is either an IDENTIFIER with the literal semantic or a TREE_LIST |
30301 | whose TREE_VALUE is the contract-level and whose TREE_PURPOSE is the |
30302 | contract-role, if any. NULL_TREE is returned if no information is |
30303 | given (i.e., all defaults selected). */ |
30304 | |
30305 | static tree |
30306 | cp_parser_contract_mode_opt (cp_parser *parser, |
30307 | bool postcondition_p) |
30308 | { |
30309 | /* The mode is empty; the level and role are default. */ |
30310 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
30311 | return NULL_TREE; |
30312 | |
30313 | /* There is only a role; the level is default. */ |
30314 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
30315 | { |
30316 | tree role_id = cp_parser_contract_role (parser); |
30317 | return build_tree_list (role_id, get_identifier ("default" )); |
30318 | } |
30319 | |
30320 | /* Otherwise, match semantic or level. */ |
30321 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30322 | contract_level level = CONTRACT_INVALID; |
30323 | contract_semantic semantic = CCS_INVALID; |
30324 | tree config_id; |
30325 | if (token->type == CPP_NAME) |
30326 | { |
30327 | config_id = token->u.value; |
30328 | |
30329 | /* Either a named level, a concrete semantic, or an identifier |
30330 | for a postcondition. */ |
30331 | const char *ident = IDENTIFIER_POINTER (token->u.value); |
30332 | level = map_contract_level (ident); |
30333 | semantic = map_contract_semantic (ident); |
30334 | |
30335 | /* The identifier is the return value for a postcondition. */ |
30336 | if (level == CONTRACT_INVALID && semantic == CCS_INVALID |
30337 | && postcondition_p) |
30338 | return NULL_TREE; |
30339 | } |
30340 | else if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT) |
30341 | { |
30342 | config_id = get_identifier ("default" ); |
30343 | level = CONTRACT_DEFAULT; |
30344 | } |
30345 | else |
30346 | { |
30347 | /* We got some other token other than a ':'. */ |
30348 | error_at (token->location, "expected contract semantic or level" ); |
30349 | return NULL_TREE; |
30350 | } |
30351 | |
30352 | /* Consume the literal semantic or level token. */ |
30353 | cp_lexer_consume_token (lexer: parser->lexer); |
30354 | |
30355 | if (semantic == CCS_INVALID && level == CONTRACT_INVALID) |
30356 | { |
30357 | error_at (token->location, |
30358 | "expected contract level: " |
30359 | "%<default%>, %<audit%>, or %<axiom%>" ); |
30360 | return NULL_TREE; |
30361 | } |
30362 | |
30363 | /* We matched an explicit semantic. */ |
30364 | if (semantic != CCS_INVALID) |
30365 | { |
30366 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
30367 | { |
30368 | error ("invalid use of contract role for explicit semantic" ); |
30369 | cp_lexer_consume_token (lexer: parser->lexer); |
30370 | cp_lexer_consume_token (lexer: parser->lexer); |
30371 | } |
30372 | return config_id; |
30373 | } |
30374 | |
30375 | /* We matched a level, there may be a role; otherwise this is default. */ |
30376 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
30377 | { |
30378 | tree role_id = cp_parser_contract_role (parser); |
30379 | return build_tree_list (role_id, config_id); |
30380 | } |
30381 | |
30382 | return build_tree_list (NULL_TREE, config_id); |
30383 | } |
30384 | |
30385 | static tree |
30386 | find_error (tree *tp, int *, void *) |
30387 | { |
30388 | if (*tp == error_mark_node) |
30389 | return *tp; |
30390 | return NULL_TREE; |
30391 | } |
30392 | |
30393 | static bool |
30394 | contains_error_p (tree t) |
30395 | { |
30396 | return walk_tree (&t, find_error, NULL, NULL); |
30397 | } |
30398 | |
30399 | /* Parse a standard C++20 contract attribute specifier. |
30400 | |
30401 | contract-attribute-specifier: |
30402 | [ [ assert contract-level [opt] : conditional-expression ] ] |
30403 | [ [ pre contract-level [opt] : conditional-expression ] ] |
30404 | [ [ post contract-level [opt] identifier [opt] : conditional-expression ] ] |
30405 | |
30406 | For free functions, we cannot determine the type of the postcondition |
30407 | identifier because the we haven't called grokdeclarator yet. In those |
30408 | cases we parse the postcondition as if the identifier was declared as |
30409 | 'auto <identifier>'. We then instantiate the postcondition once the |
30410 | return type is known. |
30411 | |
30412 | For member functions, contracts are in the complete-class context, so the |
30413 | parse is deferred. We also have the return type avaialable (unless it's |
30414 | deduced), so we don't need to parse the postcondition in terms of a |
30415 | placeholder. */ |
30416 | |
30417 | static tree |
30418 | cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute) |
30419 | { |
30420 | gcc_assert (contract_attribute_p (attribute)); |
30421 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
30422 | location_t loc = token->location; |
30423 | |
30424 | bool assertion_p = is_attribute_p (attr_name: "assert" , ident: attribute); |
30425 | bool postcondition_p = is_attribute_p (attr_name: "post" , ident: attribute); |
30426 | |
30427 | /* Parse the optional mode. */ |
30428 | tree mode = cp_parser_contract_mode_opt (parser, postcondition_p); |
30429 | |
30430 | /* Check for postcondition identifiers. */ |
30431 | cp_expr identifier; |
30432 | if (postcondition_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
30433 | identifier = cp_parser_identifier (parser); |
30434 | if (identifier == error_mark_node) |
30435 | return error_mark_node; |
30436 | |
30437 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
30438 | |
30439 | /* Defer the parsing of pre/post contracts inside class definitions. */ |
30440 | tree contract; |
30441 | if (!assertion_p && |
30442 | current_class_type && |
30443 | TYPE_BEING_DEFINED (current_class_type)) |
30444 | { |
30445 | /* Skip until we reach an unenclose ']'. If we ran into an unnested ']' |
30446 | that doesn't close the attribute, return an error and let the attribute |
30447 | handling code emit an error for missing ']]'. */ |
30448 | cp_token *first = cp_lexer_peek_token (lexer: parser->lexer); |
30449 | cp_parser_skip_to_closing_parenthesis_1 (parser, |
30450 | /*recovering=*/false, |
30451 | or_ttype: CPP_CLOSE_SQUARE, |
30452 | /*consume_paren=*/false); |
30453 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_CLOSE_SQUARE |
30454 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_CLOSE_SQUARE) |
30455 | return error_mark_node; |
30456 | cp_token *last = cp_lexer_peek_token (lexer: parser->lexer); |
30457 | |
30458 | /* Build a deferred-parse node. */ |
30459 | tree condition = make_node (DEFERRED_PARSE); |
30460 | DEFPARSE_TOKENS (condition) = cp_token_cache_new (first, last); |
30461 | DEFPARSE_INSTANTIATIONS (condition) = NULL; |
30462 | |
30463 | /* And its corresponding contract. */ |
30464 | contract = grok_contract (attribute, mode, identifier, condition, loc); |
30465 | } |
30466 | else |
30467 | { |
30468 | /* Enable location wrappers when parsing contracts. */ |
30469 | auto suppression = make_temp_override (var&: suppress_location_wrappers, overrider: 0); |
30470 | |
30471 | /* Build a fake variable for the result identifier. */ |
30472 | tree result = NULL_TREE; |
30473 | if (identifier) |
30474 | { |
30475 | begin_scope (sk_block, NULL_TREE); |
30476 | result = make_postcondition_variable (identifier); |
30477 | ++processing_template_decl; |
30478 | } |
30479 | |
30480 | /* Parse the condition, ensuring that parameters or the return variable |
30481 | aren't flagged for use outside the body of a function. */ |
30482 | ++processing_contract_condition; |
30483 | cp_expr condition = cp_parser_conditional_expression (parser); |
30484 | --processing_contract_condition; |
30485 | |
30486 | /* Try to recover from errors by scanning up to the end of the |
30487 | attribute. Sometimes we get partially parsed expressions, so |
30488 | we need to search the condition for errors. */ |
30489 | if (contains_error_p (t: condition)) |
30490 | cp_parser_skip_up_to_closing_square_bracket (parser); |
30491 | |
30492 | /* Build the contract. */ |
30493 | contract = grok_contract (attribute, mode, result, condition, loc); |
30494 | |
30495 | /* Leave our temporary scope for the postcondition result. */ |
30496 | if (result) |
30497 | { |
30498 | --processing_template_decl; |
30499 | pop_bindings_and_leave_scope (); |
30500 | } |
30501 | } |
30502 | |
30503 | if (!flag_contracts) |
30504 | { |
30505 | error_at (loc, "contracts are only available with %<-fcontracts%>" ); |
30506 | return error_mark_node; |
30507 | } |
30508 | |
30509 | return finish_contract_attribute (attribute, contract); |
30510 | } |
30511 | |
30512 | /* Parse a contract condition for a deferred contract. */ |
30513 | |
30514 | void cp_parser_late_contract_condition (cp_parser *parser, |
30515 | tree fn, |
30516 | tree attribute) |
30517 | { |
30518 | tree contract = TREE_VALUE (TREE_VALUE (attribute)); |
30519 | |
30520 | /* Make sure we've gotten something that hasn't been parsed yet or that |
30521 | we're not parsing an invalid contract. */ |
30522 | tree condition = CONTRACT_CONDITION (contract); |
30523 | if (TREE_CODE (condition) != DEFERRED_PARSE) |
30524 | return; |
30525 | |
30526 | tree identifier = NULL_TREE; |
30527 | if (TREE_CODE (contract) == POSTCONDITION_STMT) |
30528 | identifier = POSTCONDITION_IDENTIFIER (contract); |
30529 | |
30530 | /* Build a fake variable for the result identifier. */ |
30531 | tree result = NULL_TREE; |
30532 | if (identifier) |
30533 | { |
30534 | /* TODO: Can we guarantee that the identifier has a location? */ |
30535 | location_t loc = cp_expr_location (t_: contract); |
30536 | tree type = TREE_TYPE (TREE_TYPE (fn)); |
30537 | if (!check_postcondition_result (fn, type, loc)) |
30538 | { |
30539 | invalidate_contract (contract); |
30540 | return; |
30541 | } |
30542 | |
30543 | begin_scope (sk_block, NULL_TREE); |
30544 | result = make_postcondition_variable (identifier, type); |
30545 | ++processing_template_decl; |
30546 | } |
30547 | |
30548 | /* 'this' is not allowed in preconditions of constructors or in postconditions |
30549 | of destructors. Note that the previous value of this variable is |
30550 | established by the calling function, so we need to save it here. */ |
30551 | tree saved_ccr = current_class_ref; |
30552 | tree saved_ccp = current_class_ptr; |
30553 | if ((DECL_CONSTRUCTOR_P (fn) && PRECONDITION_P (contract)) || |
30554 | (DECL_DESTRUCTOR_P (fn) && POSTCONDITION_P (contract))) |
30555 | { |
30556 | current_class_ref = current_class_ptr = NULL_TREE; |
30557 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
30558 | } |
30559 | |
30560 | push_unparsed_function_queues (parser); |
30561 | |
30562 | /* Push the saved tokens onto the parser's lexer stack. */ |
30563 | cp_token_cache *tokens = DEFPARSE_TOKENS (condition); |
30564 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
30565 | |
30566 | /* Parse the condition, ensuring that parameters or the return variable |
30567 | aren't flagged for use outside the body of a function. */ |
30568 | ++processing_contract_condition; |
30569 | condition = cp_parser_conditional_expression (parser); |
30570 | --processing_contract_condition; |
30571 | |
30572 | /* Revert to the main lexer. */ |
30573 | cp_parser_pop_lexer (parser); |
30574 | |
30575 | /* Restore the queue. */ |
30576 | pop_unparsed_function_queues (parser); |
30577 | |
30578 | current_class_ref = saved_ccr; |
30579 | current_class_ptr = saved_ccp; |
30580 | |
30581 | /* Commit to changes. */ |
30582 | update_late_contract (contract, result, condition); |
30583 | |
30584 | /* Leave our temporary scope for the postcondition result. */ |
30585 | if (result) |
30586 | { |
30587 | --processing_template_decl; |
30588 | pop_bindings_and_leave_scope (); |
30589 | } |
30590 | } |
30591 | |
30592 | /* Parse a standard C++-11 attribute specifier. |
30593 | |
30594 | attribute-specifier: |
30595 | [ [ attribute-using-prefix [opt] attribute-list ] ] |
30596 | contract-attribute-specifier |
30597 | alignment-specifier |
30598 | |
30599 | attribute-using-prefix: |
30600 | using attribute-namespace : |
30601 | |
30602 | alignment-specifier: |
30603 | alignas ( type-id ... [opt] ) |
30604 | alignas ( alignment-expression ... [opt] ). |
30605 | |
30606 | Extensions for contracts: |
30607 | |
30608 | contract-attribute-specifier: |
30609 | [ [ assert : contract-mode [opt] : conditional-expression ] ] |
30610 | [ [ pre : contract-mode [opt] : conditional-expression ] ] |
30611 | [ [ post : contract-mode [opt] identifier [opt] : |
30612 | conditional-expression ] ] |
30613 | |
30614 | Return void_list_node if the current token doesn't start an |
30615 | attribute-specifier to differentiate from NULL_TREE returned e.g. |
30616 | for [ [ ] ]. */ |
30617 | |
30618 | static tree |
30619 | cp_parser_std_attribute_spec (cp_parser *parser) |
30620 | { |
30621 | tree attributes = NULL_TREE; |
30622 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30623 | |
30624 | if (token->type == CPP_OPEN_SQUARE |
30625 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_OPEN_SQUARE) |
30626 | { |
30627 | tree attr_ns = NULL_TREE; |
30628 | tree attr_name = NULL_TREE; |
30629 | |
30630 | cp_lexer_consume_token (lexer: parser->lexer); |
30631 | cp_lexer_consume_token (lexer: parser->lexer); |
30632 | |
30633 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30634 | if (token->type == CPP_NAME) |
30635 | { |
30636 | attr_name = token->u.value; |
30637 | attr_name = canonicalize_attr_name (attr_name); |
30638 | } |
30639 | |
30640 | /* Handle contract-attribute-specs specially. */ |
30641 | if (attr_name && contract_attribute_p (id: attr_name)) |
30642 | { |
30643 | tree attrs = cp_parser_contract_attribute_spec (parser, attribute: attr_name); |
30644 | if (attrs != error_mark_node) |
30645 | attributes = attrs; |
30646 | goto finish_attrs; |
30647 | } |
30648 | |
30649 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
30650 | { |
30651 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
30652 | if (token->type == CPP_NAME) |
30653 | attr_ns = token->u.value; |
30654 | else if (token->type == CPP_KEYWORD) |
30655 | attr_ns = ridpointers[(int) token->keyword]; |
30656 | else if (token->flags & NAMED_OP) |
30657 | attr_ns = get_identifier (cpp_type2name (token->type, |
30658 | token->flags)); |
30659 | if (attr_ns |
30660 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_COLON)) |
30661 | { |
30662 | if (cxx_dialect < cxx17) |
30663 | pedwarn (input_location, OPT_Wc__17_extensions, |
30664 | "attribute using prefix only available " |
30665 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
30666 | |
30667 | cp_lexer_consume_token (lexer: parser->lexer); |
30668 | cp_lexer_consume_token (lexer: parser->lexer); |
30669 | cp_lexer_consume_token (lexer: parser->lexer); |
30670 | } |
30671 | else |
30672 | attr_ns = NULL_TREE; |
30673 | } |
30674 | |
30675 | attributes = cp_parser_std_attribute_list (parser, attr_ns); |
30676 | |
30677 | finish_attrs: |
30678 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) |
30679 | || !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
30680 | cp_parser_skip_to_end_of_statement (parser); |
30681 | else |
30682 | /* Warn about parsing c++11 attribute in non-c++11 mode, only |
30683 | when we are sure that we have actually parsed them. */ |
30684 | maybe_warn_cpp0x (str: CPP0X_ATTRIBUTES); |
30685 | } |
30686 | else |
30687 | { |
30688 | tree alignas_expr; |
30689 | |
30690 | /* Look for an alignment-specifier. */ |
30691 | |
30692 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30693 | |
30694 | if (token->type != CPP_KEYWORD |
30695 | || token->keyword != RID_ALIGNAS) |
30696 | return void_list_node; |
30697 | |
30698 | cp_lexer_consume_token (lexer: parser->lexer); |
30699 | maybe_warn_cpp0x (str: CPP0X_ATTRIBUTES); |
30700 | |
30701 | matching_parens parens; |
30702 | if (!parens.require_open (parser)) |
30703 | return error_mark_node; |
30704 | |
30705 | cp_parser_parse_tentatively (parser); |
30706 | alignas_expr = cp_parser_type_id (parser); |
30707 | |
30708 | if (!cp_parser_parse_definitely (parser)) |
30709 | { |
30710 | alignas_expr = cp_parser_assignment_expression (parser); |
30711 | if (alignas_expr == error_mark_node) |
30712 | cp_parser_skip_to_end_of_statement (parser); |
30713 | if (alignas_expr == NULL_TREE |
30714 | || alignas_expr == error_mark_node) |
30715 | return alignas_expr; |
30716 | } |
30717 | |
30718 | alignas_expr = cxx_alignas_expr (alignas_expr); |
30719 | alignas_expr = build_tree_list (NULL_TREE, alignas_expr); |
30720 | |
30721 | /* Handle alignas (pack...). */ |
30722 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
30723 | { |
30724 | cp_lexer_consume_token (lexer: parser->lexer); |
30725 | alignas_expr = make_pack_expansion (alignas_expr); |
30726 | } |
30727 | |
30728 | /* Something went wrong, so don't build the attribute. */ |
30729 | if (alignas_expr == error_mark_node) |
30730 | return error_mark_node; |
30731 | |
30732 | /* Missing ')' means the code cannot possibly be valid; go ahead |
30733 | and commit to make sure we issue a hard error. */ |
30734 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
30735 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
30736 | cp_parser_commit_to_tentative_parse (parser); |
30737 | |
30738 | if (!parens.require_close (parser)) |
30739 | return error_mark_node; |
30740 | |
30741 | /* Build the C++-11 representation of an 'aligned' |
30742 | attribute. */ |
30743 | attributes |
30744 | = build_tree_list (build_tree_list (gnu_identifier, |
30745 | aligned_identifier), alignas_expr); |
30746 | } |
30747 | |
30748 | return attributes; |
30749 | } |
30750 | |
30751 | /* Parse a standard C++-11 attribute-specifier-seq. |
30752 | |
30753 | attribute-specifier-seq: |
30754 | attribute-specifier-seq [opt] attribute-specifier */ |
30755 | |
30756 | static tree |
30757 | cp_parser_std_attribute_spec_seq (cp_parser *parser) |
30758 | { |
30759 | tree attr_specs = NULL_TREE; |
30760 | tree attr_last = NULL_TREE; |
30761 | |
30762 | /* Don't create wrapper nodes within attributes: the |
30763 | handlers don't know how to handle them. */ |
30764 | auto_suppress_location_wrappers sentinel; |
30765 | |
30766 | while (true) |
30767 | { |
30768 | tree attr_spec = cp_parser_std_attribute_spec (parser); |
30769 | if (attr_spec == void_list_node) |
30770 | break; |
30771 | /* Accept [[]][[]]; for which cp_parser_std_attribute_spec |
30772 | returns NULL_TREE as there are no attributes. */ |
30773 | if (attr_spec == NULL_TREE) |
30774 | continue; |
30775 | if (attr_spec == error_mark_node) |
30776 | return error_mark_node; |
30777 | |
30778 | if (attr_last) |
30779 | TREE_CHAIN (attr_last) = attr_spec; |
30780 | else |
30781 | attr_specs = attr_last = attr_spec; |
30782 | attr_last = tree_last (attr_last); |
30783 | } |
30784 | |
30785 | return attr_specs; |
30786 | } |
30787 | |
30788 | /* Skip a balanced-token starting at Nth token (with 1 as the next token), |
30789 | return index of the first token after balanced-token, or N on failure. */ |
30790 | |
30791 | static size_t |
30792 | cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n) |
30793 | { |
30794 | size_t orig_n = n; |
30795 | int nparens = 0, nbraces = 0, nsquares = 0; |
30796 | do |
30797 | switch (cp_lexer_peek_nth_token (lexer: parser->lexer, n: n++)->type) |
30798 | { |
30799 | case CPP_PRAGMA_EOL: |
30800 | if (!parser->lexer->in_pragma) |
30801 | break; |
30802 | /* FALLTHRU */ |
30803 | case CPP_EOF: |
30804 | /* Ran out of tokens. */ |
30805 | return orig_n; |
30806 | case CPP_OPEN_PAREN: |
30807 | ++nparens; |
30808 | break; |
30809 | case CPP_OPEN_BRACE: |
30810 | ++nbraces; |
30811 | break; |
30812 | case CPP_OPEN_SQUARE: |
30813 | ++nsquares; |
30814 | break; |
30815 | case CPP_CLOSE_PAREN: |
30816 | --nparens; |
30817 | break; |
30818 | case CPP_CLOSE_BRACE: |
30819 | --nbraces; |
30820 | break; |
30821 | case CPP_CLOSE_SQUARE: |
30822 | --nsquares; |
30823 | break; |
30824 | default: |
30825 | break; |
30826 | } |
30827 | while (nparens || nbraces || nsquares); |
30828 | return n; |
30829 | } |
30830 | |
30831 | /* Skip GNU attribute tokens starting at Nth token (with 1 as the next token), |
30832 | return index of the first token after the GNU attribute tokens, or N on |
30833 | failure. */ |
30834 | |
30835 | static size_t |
30836 | cp_parser_skip_gnu_attributes_opt (cp_parser *parser, size_t n) |
30837 | { |
30838 | while (true) |
30839 | { |
30840 | if (!cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n, keyword: RID_ATTRIBUTE) |
30841 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_PAREN) |
30842 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 2, type: CPP_OPEN_PAREN)) |
30843 | break; |
30844 | |
30845 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 2); |
30846 | if (n2 == n + 2) |
30847 | break; |
30848 | if (!cp_lexer_nth_token_is (lexer: parser->lexer, n: n2, type: CPP_CLOSE_PAREN)) |
30849 | break; |
30850 | n = n2 + 1; |
30851 | } |
30852 | return n; |
30853 | } |
30854 | |
30855 | /* Skip standard C++11 attribute tokens starting at Nth token (with 1 as the |
30856 | next token), return index of the first token after the standard C++11 |
30857 | attribute tokens, or N on failure. */ |
30858 | |
30859 | static size_t |
30860 | cp_parser_skip_std_attribute_spec_seq (cp_parser *parser, size_t n) |
30861 | { |
30862 | while (true) |
30863 | { |
30864 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_OPEN_SQUARE) |
30865 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_SQUARE)) |
30866 | { |
30867 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 1); |
30868 | if (n2 == n + 1) |
30869 | break; |
30870 | if (!cp_lexer_nth_token_is (lexer: parser->lexer, n: n2, type: CPP_CLOSE_SQUARE)) |
30871 | break; |
30872 | n = n2 + 1; |
30873 | } |
30874 | else if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n, keyword: RID_ALIGNAS) |
30875 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_PAREN)) |
30876 | { |
30877 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 1); |
30878 | if (n2 == n + 1) |
30879 | break; |
30880 | n = n2; |
30881 | } |
30882 | else |
30883 | break; |
30884 | } |
30885 | return n; |
30886 | } |
30887 | |
30888 | /* Skip standard C++11 or GNU attribute tokens starting at Nth token (with 1 |
30889 | as the next token), return index of the first token after the attribute |
30890 | tokens, or N on failure. */ |
30891 | |
30892 | static size_t |
30893 | cp_parser_skip_attributes_opt (cp_parser *parser, size_t n) |
30894 | { |
30895 | if (cp_nth_tokens_can_be_gnu_attribute_p (parser, n)) |
30896 | return cp_parser_skip_gnu_attributes_opt (parser, n); |
30897 | return cp_parser_skip_std_attribute_spec_seq (parser, n); |
30898 | } |
30899 | |
30900 | /* Parse an optional `__extension__' keyword. Returns TRUE if it is |
30901 | present, and FALSE otherwise. *SAVED_PEDANTIC is set to the |
30902 | current value of the PEDANTIC flag, regardless of whether or not |
30903 | the `__extension__' keyword is present. The caller is responsible |
30904 | for restoring the value of the PEDANTIC flag. */ |
30905 | |
30906 | static bool |
30907 | cp_parser_extension_opt (cp_parser* parser, int* saved_pedantic) |
30908 | { |
30909 | /* Save the old value of the PEDANTIC flag. */ |
30910 | *saved_pedantic = pedantic; |
30911 | |
30912 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_EXTENSION)) |
30913 | { |
30914 | /* Consume the `__extension__' token. */ |
30915 | cp_lexer_consume_token (lexer: parser->lexer); |
30916 | /* We're not being pedantic while the `__extension__' keyword is |
30917 | in effect. */ |
30918 | pedantic = 0; |
30919 | |
30920 | return true; |
30921 | } |
30922 | |
30923 | return false; |
30924 | } |
30925 | |
30926 | /* Parse a label declaration. |
30927 | |
30928 | label-declaration: |
30929 | __label__ label-declarator-seq ; |
30930 | |
30931 | label-declarator-seq: |
30932 | identifier , label-declarator-seq |
30933 | identifier */ |
30934 | |
30935 | static void |
30936 | cp_parser_label_declaration (cp_parser* parser) |
30937 | { |
30938 | /* Look for the `__label__' keyword. */ |
30939 | cp_parser_require_keyword (parser, RID_LABEL, RT_LABEL); |
30940 | |
30941 | while (true) |
30942 | { |
30943 | tree identifier; |
30944 | |
30945 | /* Look for an identifier. */ |
30946 | identifier = cp_parser_identifier (parser); |
30947 | /* If we failed, stop. */ |
30948 | if (identifier == error_mark_node) |
30949 | break; |
30950 | /* Declare it as a label. */ |
30951 | finish_label_decl (identifier); |
30952 | /* If the next token is a `;', stop. */ |
30953 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
30954 | break; |
30955 | /* Look for the `,' separating the label declarations. */ |
30956 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
30957 | } |
30958 | |
30959 | /* Look for the final `;'. */ |
30960 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
30961 | } |
30962 | |
30963 | // -------------------------------------------------------------------------- // |
30964 | // Concept definitions |
30965 | |
30966 | static tree |
30967 | cp_parser_concept_definition (cp_parser *parser) |
30968 | { |
30969 | /* A concept definition is an unevaluated context. */ |
30970 | cp_unevaluated u; |
30971 | |
30972 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT)); |
30973 | cp_lexer_consume_token (lexer: parser->lexer); |
30974 | |
30975 | cp_expr id = cp_parser_identifier (parser); |
30976 | if (id == error_mark_node) |
30977 | { |
30978 | cp_parser_skip_to_end_of_statement (parser); |
30979 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
30980 | return NULL_TREE; |
30981 | } |
30982 | |
30983 | tree attrs = cp_parser_attributes_opt (parser); |
30984 | |
30985 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
30986 | { |
30987 | cp_parser_skip_to_end_of_statement (parser); |
30988 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
30989 | return error_mark_node; |
30990 | } |
30991 | |
30992 | processing_constraint_expression_sentinel parsing_constraint; |
30993 | tree init = cp_parser_constraint_expression (parser); |
30994 | if (init == error_mark_node) |
30995 | cp_parser_skip_to_end_of_statement (parser); |
30996 | |
30997 | /* Consume the trailing ';'. Diagnose the problem if it isn't there, |
30998 | but continue as if it were. */ |
30999 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31000 | |
31001 | return finish_concept_definition (id, init, attrs); |
31002 | } |
31003 | |
31004 | // -------------------------------------------------------------------------- // |
31005 | // Requires Clause |
31006 | |
31007 | /* Diagnose an expression that should appear in ()'s within a requires-clause |
31008 | and suggest where to place those parentheses. */ |
31009 | |
31010 | static void |
31011 | cp_parser_diagnose_ungrouped_constraint_plain (location_t loc) |
31012 | { |
31013 | error_at (loc, "expression must be enclosed in parentheses" ); |
31014 | } |
31015 | |
31016 | static void |
31017 | cp_parser_diagnose_ungrouped_constraint_rich (location_t loc) |
31018 | { |
31019 | gcc_rich_location richloc (loc); |
31020 | richloc.add_fixit_insert_before (new_content: "(" ); |
31021 | richloc.add_fixit_insert_after (new_content: ")" ); |
31022 | error_at (&richloc, "expression must be enclosed in parentheses" ); |
31023 | } |
31024 | |
31025 | /* Characterizes the likely kind of expression intended by a mis-written |
31026 | primary constraint. */ |
31027 | enum primary_constraint_error |
31028 | { |
31029 | pce_ok, |
31030 | pce_maybe_operator, |
31031 | pce_maybe_postfix |
31032 | }; |
31033 | |
31034 | /* Returns true if the token(s) following a primary-expression in a |
31035 | constraint-logical-* expression would require parentheses. */ |
31036 | |
31037 | static primary_constraint_error |
31038 | cp_parser_constraint_requires_parens (cp_parser *parser, bool lambda_p) |
31039 | { |
31040 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
31041 | switch (token->type) |
31042 | { |
31043 | default: |
31044 | return pce_ok; |
31045 | |
31046 | case CPP_EQ: |
31047 | { |
31048 | /* An equal sign may be part of the definition of a function, |
31049 | and not an assignment operator, when parsing the expression |
31050 | for a trailing requires-clause. For example: |
31051 | |
31052 | template<typename T> |
31053 | struct S { |
31054 | S() requires C<T> = default; |
31055 | }; |
31056 | |
31057 | Don't try to reparse this a binary operator. */ |
31058 | if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_DELETE) |
31059 | || cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_DEFAULT)) |
31060 | return pce_ok; |
31061 | |
31062 | gcc_fallthrough (); |
31063 | } |
31064 | |
31065 | /* Arithmetic operators. */ |
31066 | case CPP_PLUS: |
31067 | case CPP_MINUS: |
31068 | case CPP_MULT: |
31069 | case CPP_DIV: |
31070 | case CPP_MOD: |
31071 | /* Bitwise operators. */ |
31072 | case CPP_AND: |
31073 | case CPP_OR: |
31074 | case CPP_XOR: |
31075 | case CPP_RSHIFT: |
31076 | case CPP_LSHIFT: |
31077 | /* Relational operators. */ |
31078 | case CPP_EQ_EQ: |
31079 | case CPP_NOT_EQ: |
31080 | case CPP_LESS: |
31081 | case CPP_GREATER: |
31082 | case CPP_LESS_EQ: |
31083 | case CPP_GREATER_EQ: |
31084 | case CPP_SPACESHIP: |
31085 | /* Pointer-to-member. */ |
31086 | case CPP_DOT_STAR: |
31087 | case CPP_DEREF_STAR: |
31088 | /* Assignment operators. */ |
31089 | case CPP_PLUS_EQ: |
31090 | case CPP_MINUS_EQ: |
31091 | case CPP_MULT_EQ: |
31092 | case CPP_DIV_EQ: |
31093 | case CPP_MOD_EQ: |
31094 | case CPP_AND_EQ: |
31095 | case CPP_OR_EQ: |
31096 | case CPP_XOR_EQ: |
31097 | case CPP_RSHIFT_EQ: |
31098 | case CPP_LSHIFT_EQ: |
31099 | /* Conditional operator */ |
31100 | case CPP_QUERY: |
31101 | /* Unenclosed binary or conditional operator. */ |
31102 | return pce_maybe_operator; |
31103 | |
31104 | case CPP_OPEN_PAREN: |
31105 | { |
31106 | /* A primary constraint that precedes the parameter-list of a |
31107 | lambda expression is followed by an open paren. |
31108 | |
31109 | []<typename T> requires C (T a, T b) { ... } |
31110 | |
31111 | Don't try to re-parse this as a postfix expression. */ |
31112 | if (lambda_p) |
31113 | return pce_ok; |
31114 | |
31115 | gcc_fallthrough (); |
31116 | } |
31117 | case CPP_OPEN_SQUARE: |
31118 | { |
31119 | /* A primary-constraint-expression followed by a '[[' is not a |
31120 | postfix expression. */ |
31121 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_SQUARE)) |
31122 | return pce_ok; |
31123 | |
31124 | gcc_fallthrough (); |
31125 | } |
31126 | case CPP_PLUS_PLUS: |
31127 | case CPP_MINUS_MINUS: |
31128 | case CPP_DOT: |
31129 | /* Unenclosed postfix operator. */ |
31130 | return pce_maybe_postfix; |
31131 | |
31132 | case CPP_DEREF: |
31133 | /* A primary constraint that precedes the lambda-declarator of a |
31134 | lambda expression is followed by trailing return type. |
31135 | |
31136 | []<typename T> requires C -> void {} |
31137 | |
31138 | Don't try to re-parse this as a postfix expression in |
31139 | C++23 and later. In C++20 ( needs to come in between but we |
31140 | allow it to be omitted with pedwarn. */ |
31141 | if (lambda_p) |
31142 | return pce_ok; |
31143 | /* Unenclosed postfix operator. */ |
31144 | return pce_maybe_postfix; |
31145 | } |
31146 | } |
31147 | |
31148 | /* Returns true if the next token begins a unary expression, preceded by |
31149 | an operator or keyword. */ |
31150 | |
31151 | static bool |
31152 | cp_parser_unary_constraint_requires_parens (cp_parser *parser) |
31153 | { |
31154 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
31155 | switch (token->type) |
31156 | { |
31157 | case CPP_NOT: |
31158 | case CPP_PLUS: |
31159 | case CPP_MINUS: |
31160 | case CPP_MULT: |
31161 | case CPP_COMPL: |
31162 | case CPP_PLUS_PLUS: |
31163 | case CPP_MINUS_MINUS: |
31164 | return true; |
31165 | |
31166 | case CPP_KEYWORD: |
31167 | { |
31168 | switch (token->keyword) |
31169 | { |
31170 | case RID_STATCAST: |
31171 | case RID_DYNCAST: |
31172 | case RID_REINTCAST: |
31173 | case RID_CONSTCAST: |
31174 | case RID_TYPEID: |
31175 | case RID_SIZEOF: |
31176 | case RID_ALIGNOF: |
31177 | case RID_NOEXCEPT: |
31178 | case RID_NEW: |
31179 | case RID_DELETE: |
31180 | case RID_THROW: |
31181 | return true; |
31182 | |
31183 | default: |
31184 | break; |
31185 | } |
31186 | } |
31187 | |
31188 | default: |
31189 | break; |
31190 | } |
31191 | |
31192 | return false; |
31193 | } |
31194 | |
31195 | /* Parse a primary expression within a constraint. */ |
31196 | |
31197 | static cp_expr |
31198 | cp_parser_constraint_primary_expression (cp_parser *parser, bool lambda_p) |
31199 | { |
31200 | /* If this looks like a unary expression, parse it as such, but diagnose |
31201 | it as ill-formed; it requires parens. */ |
31202 | if (cp_parser_unary_constraint_requires_parens (parser)) |
31203 | { |
31204 | cp_expr e = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
31205 | cp_parser_diagnose_ungrouped_constraint_rich (loc: e.get_location()); |
31206 | return e; |
31207 | } |
31208 | |
31209 | cp_lexer_save_tokens (lexer: parser->lexer); |
31210 | cp_id_kind idk; |
31211 | location_t loc = input_location; |
31212 | cp_expr expr = cp_parser_primary_expression (parser, |
31213 | /*address_p=*/false, |
31214 | /*cast_p=*/false, |
31215 | /*template_arg_p=*/false, |
31216 | idk: &idk); |
31217 | expr.maybe_add_location_wrapper (); |
31218 | |
31219 | primary_constraint_error pce = pce_ok; |
31220 | if (expr != error_mark_node) |
31221 | { |
31222 | /* The primary-expression could be part of an unenclosed non-logical |
31223 | compound expression. */ |
31224 | pce = cp_parser_constraint_requires_parens (parser, lambda_p); |
31225 | } |
31226 | if (pce == pce_ok) |
31227 | { |
31228 | cp_lexer_commit_tokens (lexer: parser->lexer); |
31229 | return finish_constraint_primary_expr (expr); |
31230 | } |
31231 | |
31232 | /* Retry the parse at a lower precedence. If that succeeds, diagnose the |
31233 | error, but return the expression as if it were valid. */ |
31234 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
31235 | cp_parser_parse_tentatively (parser); |
31236 | if (pce == pce_maybe_operator) |
31237 | expr = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
31238 | else |
31239 | expr = cp_parser_simple_cast_expression (parser); |
31240 | if (cp_parser_parse_definitely (parser)) |
31241 | { |
31242 | cp_parser_diagnose_ungrouped_constraint_rich (loc: expr.get_location()); |
31243 | return expr; |
31244 | } |
31245 | |
31246 | /* Otherwise, something has gone very wrong, and we can't generate a more |
31247 | meaningful diagnostic or recover. */ |
31248 | cp_parser_diagnose_ungrouped_constraint_plain (loc); |
31249 | return error_mark_node; |
31250 | } |
31251 | |
31252 | /* Parse a constraint-logical-and-expression. |
31253 | |
31254 | constraint-logical-and-expression: |
31255 | primary-expression |
31256 | constraint-logical-and-expression '&&' primary-expression */ |
31257 | |
31258 | static cp_expr |
31259 | cp_parser_constraint_logical_and_expression (cp_parser *parser, bool lambda_p) |
31260 | { |
31261 | cp_expr lhs = cp_parser_constraint_primary_expression (parser, lambda_p); |
31262 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND_AND)) |
31263 | { |
31264 | cp_token *op = cp_lexer_consume_token (lexer: parser->lexer); |
31265 | tree rhs = cp_parser_constraint_primary_expression (parser, lambda_p); |
31266 | lhs = finish_constraint_and_expr (op->location, lhs, rhs); |
31267 | } |
31268 | return lhs; |
31269 | } |
31270 | |
31271 | /* Parse a constraint-logical-or-expression. |
31272 | |
31273 | constraint-logical-or-expression: |
31274 | constraint-logical-and-expression |
31275 | constraint-logical-or-expression '||' constraint-logical-and-expression */ |
31276 | |
31277 | static cp_expr |
31278 | cp_parser_constraint_logical_or_expression (cp_parser *parser, bool lambda_p) |
31279 | { |
31280 | cp_expr lhs = cp_parser_constraint_logical_and_expression (parser, lambda_p); |
31281 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OR_OR)) |
31282 | { |
31283 | cp_token *op = cp_lexer_consume_token (lexer: parser->lexer); |
31284 | cp_expr rhs = cp_parser_constraint_logical_and_expression (parser, lambda_p); |
31285 | lhs = finish_constraint_or_expr (op->location, lhs, rhs); |
31286 | } |
31287 | return lhs; |
31288 | } |
31289 | |
31290 | /* Parse the expression after a requires-clause. This has a different grammar |
31291 | than that in the concepts TS. */ |
31292 | |
31293 | static tree |
31294 | cp_parser_requires_clause_expression (cp_parser *parser, bool lambda_p) |
31295 | { |
31296 | processing_constraint_expression_sentinel parsing_constraint; |
31297 | ++processing_template_decl; |
31298 | cp_expr expr = cp_parser_constraint_logical_or_expression (parser, lambda_p); |
31299 | --processing_template_decl; |
31300 | if (check_for_bare_parameter_packs (expr)) |
31301 | expr = error_mark_node; |
31302 | return expr; |
31303 | } |
31304 | |
31305 | /* Parse a expression after a requires clause. |
31306 | |
31307 | constraint-expression: |
31308 | logical-or-expression |
31309 | |
31310 | The required logical-or-expression must be a constant expression. Note |
31311 | that we don't check that the expression is constepxr here. We defer until |
31312 | we analyze constraints and then, we only check atomic constraints. */ |
31313 | |
31314 | static tree |
31315 | cp_parser_constraint_expression (cp_parser *parser) |
31316 | { |
31317 | processing_constraint_expression_sentinel parsing_constraint; |
31318 | ++processing_template_decl; |
31319 | cp_expr expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
31320 | prec: PREC_NOT_OPERATOR, NULL); |
31321 | --processing_template_decl; |
31322 | if (check_for_bare_parameter_packs (expr)) |
31323 | expr = error_mark_node; |
31324 | expr.maybe_add_location_wrapper (); |
31325 | return expr; |
31326 | } |
31327 | |
31328 | /* Optionally parse a requires clause: |
31329 | |
31330 | requires-clause: |
31331 | `requires` constraint-logical-or-expression. |
31332 | [ConceptsTS] |
31333 | `requires constraint-expression. |
31334 | |
31335 | LAMBDA_P is true when the requires-clause is parsed before the |
31336 | parameter-list of a lambda-declarator. */ |
31337 | |
31338 | static tree |
31339 | cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p) |
31340 | { |
31341 | /* A requires clause is an unevaluated context. */ |
31342 | cp_unevaluated u; |
31343 | |
31344 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
31345 | if (tok->keyword != RID_REQUIRES) |
31346 | { |
31347 | if (!flag_concepts && tok->type == CPP_NAME |
31348 | && tok->u.value == ridpointers[RID_REQUIRES]) |
31349 | { |
31350 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
31351 | "%<requires%> only available with " |
31352 | "%<-std=c++20%> or %<-fconcepts%>" ); |
31353 | /* Parse and discard the requires-clause. */ |
31354 | cp_lexer_consume_token (lexer: parser->lexer); |
31355 | cp_parser_constraint_expression (parser); |
31356 | } |
31357 | return NULL_TREE; |
31358 | } |
31359 | |
31360 | cp_token *tok2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
31361 | if (tok2->type == CPP_OPEN_BRACE) |
31362 | { |
31363 | /* An opening brace following the start of a requires-clause is |
31364 | ill-formed; the user likely forgot the second `requires' that |
31365 | would start a requires-expression. */ |
31366 | gcc_rich_location richloc (tok2->location); |
31367 | richloc.add_fixit_insert_after (where: tok->location, new_content: " requires" ); |
31368 | error_at (&richloc, "missing additional %<requires%> to start " |
31369 | "a requires-expression" ); |
31370 | /* Don't consume the `requires', so that it's reused as the start of a |
31371 | requires-expression. */ |
31372 | } |
31373 | else |
31374 | cp_lexer_consume_token (lexer: parser->lexer); |
31375 | |
31376 | if (!flag_concepts_ts) |
31377 | return cp_parser_requires_clause_expression (parser, lambda_p); |
31378 | else |
31379 | return cp_parser_constraint_expression (parser); |
31380 | } |
31381 | |
31382 | /*--------------------------------------------------------------------------- |
31383 | Requires expressions |
31384 | ---------------------------------------------------------------------------*/ |
31385 | |
31386 | /* Parse a requires expression |
31387 | |
31388 | requirement-expression: |
31389 | 'requires' requirement-parameter-list [opt] requirement-body */ |
31390 | |
31391 | static tree |
31392 | cp_parser_requires_expression (cp_parser *parser) |
31393 | { |
31394 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES)); |
31395 | location_t loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
31396 | |
31397 | /* Avoid committing to outer tentative parse. */ |
31398 | tentative_firewall firewall (parser); |
31399 | |
31400 | /* This is definitely a requires-expression. */ |
31401 | cp_parser_commit_to_tentative_parse (parser); |
31402 | |
31403 | tree parms, reqs; |
31404 | { |
31405 | /* Local parameters are delared as variables within the scope |
31406 | of the expression. They are not visible past the end of |
31407 | the expression. Expressions within the requires-expression |
31408 | are unevaluated. */ |
31409 | struct scope_sentinel |
31410 | { |
31411 | scope_sentinel () |
31412 | { |
31413 | ++cp_unevaluated_operand; |
31414 | begin_scope (sk_function_parms, NULL_TREE); |
31415 | current_binding_level->requires_expression = true; |
31416 | } |
31417 | |
31418 | ~scope_sentinel () |
31419 | { |
31420 | pop_bindings_and_leave_scope (); |
31421 | --cp_unevaluated_operand; |
31422 | } |
31423 | } s; |
31424 | |
31425 | /* Parse the optional parameter list. */ |
31426 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
31427 | { |
31428 | parms = cp_parser_requirement_parameter_list (parser); |
31429 | if (parms == error_mark_node) |
31430 | return error_mark_node; |
31431 | } |
31432 | else |
31433 | parms = NULL_TREE; |
31434 | |
31435 | /* Parse the requirement body. */ |
31436 | ++processing_template_decl; |
31437 | reqs = cp_parser_requirement_body (parser); |
31438 | --processing_template_decl; |
31439 | if (reqs == error_mark_node) |
31440 | return error_mark_node; |
31441 | } |
31442 | |
31443 | /* This needs to happen after pop_bindings_and_leave_scope, as it reverses |
31444 | the parm chain. */ |
31445 | grokparms (parms, &parms); |
31446 | loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
31447 | tree expr = finish_requires_expr (loc, parms, reqs); |
31448 | if (!processing_template_decl) |
31449 | { |
31450 | /* Perform semantic processing now to diagnose any invalid types and |
31451 | expressions. */ |
31452 | int saved_errorcount = errorcount; |
31453 | tsubst_requires_expr (expr, NULL_TREE, tf_warning_or_error, NULL_TREE); |
31454 | if (errorcount > saved_errorcount) |
31455 | return error_mark_node; |
31456 | } |
31457 | return expr; |
31458 | } |
31459 | |
31460 | /* Parse a parameterized requirement. |
31461 | |
31462 | requirement-parameter-list: |
31463 | '(' parameter-declaration-clause ')' */ |
31464 | |
31465 | static tree |
31466 | cp_parser_requirement_parameter_list (cp_parser *parser) |
31467 | { |
31468 | matching_parens parens; |
31469 | if (!parens.require_open (parser)) |
31470 | return error_mark_node; |
31471 | |
31472 | tree parms = (cp_parser_parameter_declaration_clause |
31473 | (parser, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
31474 | |
31475 | if (!parens.require_close (parser)) |
31476 | return error_mark_node; |
31477 | |
31478 | /* Modify the declared parameters by removing their context |
31479 | so they don't refer to the enclosing scope and explicitly |
31480 | indicating that they are constraint variables. */ |
31481 | for (tree parm = parms; parm; parm = TREE_CHAIN (parm)) |
31482 | { |
31483 | if (parm == void_list_node || parm == explicit_void_list_node) |
31484 | break; |
31485 | tree decl = TREE_VALUE (parm); |
31486 | if (decl != error_mark_node) |
31487 | { |
31488 | DECL_CONTEXT (decl) = NULL_TREE; |
31489 | CONSTRAINT_VAR_P (decl) = true; |
31490 | } |
31491 | } |
31492 | |
31493 | return parms; |
31494 | } |
31495 | |
31496 | /* Parse the body of a requirement. |
31497 | |
31498 | requirement-body: |
31499 | '{' requirement-list '}' */ |
31500 | static tree |
31501 | cp_parser_requirement_body (cp_parser *parser) |
31502 | { |
31503 | matching_braces braces; |
31504 | if (!braces.require_open (parser)) |
31505 | return error_mark_node; |
31506 | |
31507 | tree reqs = cp_parser_requirement_seq (parser); |
31508 | |
31509 | if (!braces.require_close (parser)) |
31510 | return error_mark_node; |
31511 | |
31512 | return reqs; |
31513 | } |
31514 | |
31515 | /* Parse a sequence of requirements. |
31516 | |
31517 | requirement-seq: |
31518 | requirement |
31519 | requirement-seq requirement */ |
31520 | |
31521 | static tree |
31522 | cp_parser_requirement_seq (cp_parser *parser) |
31523 | { |
31524 | tree result = NULL_TREE; |
31525 | do |
31526 | { |
31527 | tree req = cp_parser_requirement (parser); |
31528 | if (req != error_mark_node) |
31529 | result = tree_cons (NULL_TREE, req, result); |
31530 | } |
31531 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_BRACE) |
31532 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EOF)); |
31533 | |
31534 | /* If there are no valid requirements, this is not a valid expression. */ |
31535 | if (!result) |
31536 | return error_mark_node; |
31537 | |
31538 | /* Reverse the order of requirements so they are analyzed in order. */ |
31539 | return nreverse (result); |
31540 | } |
31541 | |
31542 | /* Parse a syntactic requirement or type requirement. |
31543 | |
31544 | requirement: |
31545 | simple-requirement |
31546 | compound-requirement |
31547 | type-requirement |
31548 | nested-requirement */ |
31549 | |
31550 | static tree |
31551 | cp_parser_requirement (cp_parser *parser) |
31552 | { |
31553 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
31554 | return cp_parser_compound_requirement (parser); |
31555 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
31556 | { |
31557 | /* It's probably a type-requirement. */ |
31558 | cp_parser_parse_tentatively (parser); |
31559 | tree req = cp_parser_type_requirement (parser); |
31560 | if (cp_parser_parse_definitely (parser)) |
31561 | return req; |
31562 | /* No, maybe it's something like typename T::type(); */ |
31563 | cp_parser_parse_tentatively (parser); |
31564 | req = cp_parser_simple_requirement (parser); |
31565 | if (cp_parser_parse_definitely (parser)) |
31566 | return req; |
31567 | /* Non-tentative for the error. */ |
31568 | return cp_parser_type_requirement (parser); |
31569 | } |
31570 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_REQUIRES)) |
31571 | return cp_parser_nested_requirement (parser); |
31572 | else |
31573 | return cp_parser_simple_requirement (parser); |
31574 | } |
31575 | |
31576 | /* Parse a simple requirement. |
31577 | |
31578 | simple-requirement: |
31579 | expression ';' */ |
31580 | |
31581 | static tree |
31582 | cp_parser_simple_requirement (cp_parser *parser) |
31583 | { |
31584 | location_t start = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31585 | cp_expr expr = cp_parser_expression (parser, NULL, cast_p: false, decltype_p: false); |
31586 | if (expr == error_mark_node) |
31587 | cp_parser_skip_to_end_of_statement (parser); |
31588 | |
31589 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31590 | |
31591 | if (!expr || expr == error_mark_node) |
31592 | return error_mark_node; |
31593 | |
31594 | /* Sometimes we don't get locations, so use the cached token location |
31595 | as a reasonable approximation. */ |
31596 | if (expr.get_location() == UNKNOWN_LOCATION) |
31597 | expr.set_location (start); |
31598 | |
31599 | for (tree t = expr; ; ) |
31600 | { |
31601 | if (TREE_CODE (t) == TRUTH_ANDIF_EXPR |
31602 | || TREE_CODE (t) == TRUTH_ORIF_EXPR) |
31603 | { |
31604 | t = TREE_OPERAND (t, 0); |
31605 | continue; |
31606 | } |
31607 | if (concept_check_p (t)) |
31608 | { |
31609 | gcc_rich_location richloc (get_start (loc: start)); |
31610 | richloc.add_fixit_insert_before (where: start, new_content: "requires " ); |
31611 | warning_at (&richloc, OPT_Wmissing_requires, "testing " |
31612 | "if a concept-id is a valid expression; add " |
31613 | "%<requires%> to check satisfaction" ); |
31614 | } |
31615 | break; |
31616 | } |
31617 | |
31618 | return finish_simple_requirement (expr.get_location (), expr); |
31619 | } |
31620 | |
31621 | /* Parse a type requirement |
31622 | |
31623 | type-requirement |
31624 | nested-name-specifier [opt] required-type-name ';' |
31625 | |
31626 | required-type-name: |
31627 | type-name |
31628 | 'template' [opt] simple-template-id */ |
31629 | |
31630 | static tree |
31631 | cp_parser_type_requirement (cp_parser *parser) |
31632 | { |
31633 | cp_token *start_tok = cp_lexer_consume_token (lexer: parser->lexer); |
31634 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31635 | |
31636 | // Save the scope before parsing name specifiers. |
31637 | tree saved_scope = parser->scope; |
31638 | tree saved_object_scope = parser->object_scope; |
31639 | tree saved_qualifying_scope = parser->qualifying_scope; |
31640 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
31641 | cp_parser_nested_name_specifier_opt (parser, |
31642 | /*typename_keyword_p=*/true, |
31643 | /*check_dependency_p=*/true, |
31644 | /*type_p=*/true, |
31645 | /*is_declaration=*/false); |
31646 | |
31647 | tree type; |
31648 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
31649 | { |
31650 | cp_lexer_consume_token (lexer: parser->lexer); |
31651 | type = cp_parser_template_id (parser, |
31652 | /*template_keyword_p=*/true, |
31653 | /*check_dependency_p=*/true, |
31654 | /*tag_type=*/none_type, |
31655 | /*is_declaration=*/false); |
31656 | type = make_typename_type (parser->scope, type, typename_type, |
31657 | /*complain=*/tf_error); |
31658 | } |
31659 | else |
31660 | type = cp_parser_type_name (parser, /*typename_keyword_p=*/true); |
31661 | |
31662 | if (TREE_CODE (type) == TYPE_DECL) |
31663 | type = TREE_TYPE (type); |
31664 | |
31665 | parser->scope = saved_scope; |
31666 | parser->object_scope = saved_object_scope; |
31667 | parser->qualifying_scope = saved_qualifying_scope; |
31668 | |
31669 | if (type == error_mark_node) |
31670 | cp_parser_skip_to_end_of_statement (parser); |
31671 | |
31672 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31673 | |
31674 | if (type == error_mark_node) |
31675 | return error_mark_node; |
31676 | |
31677 | loc = make_location (caret: loc, start: start_tok->location, lexer: parser->lexer); |
31678 | return finish_type_requirement (loc, type); |
31679 | } |
31680 | |
31681 | /* Parse a compound requirement |
31682 | |
31683 | compound-requirement: |
31684 | '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] ';' */ |
31685 | |
31686 | static tree |
31687 | cp_parser_compound_requirement (cp_parser *parser) |
31688 | { |
31689 | /* Parse an expression enclosed in '{ }'s. */ |
31690 | matching_braces braces; |
31691 | if (!braces.require_open (parser)) |
31692 | return error_mark_node; |
31693 | |
31694 | cp_token *expr_token = cp_lexer_peek_token (lexer: parser->lexer); |
31695 | |
31696 | tree expr = cp_parser_expression (parser, NULL, cast_p: false, decltype_p: false); |
31697 | if (expr == error_mark_node) |
31698 | cp_parser_skip_to_closing_brace (parser); |
31699 | |
31700 | if (!braces.require_close (parser)) |
31701 | { |
31702 | cp_parser_skip_to_end_of_statement (parser); |
31703 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31704 | return error_mark_node; |
31705 | } |
31706 | |
31707 | /* If the expression was invalid, skip the remainder of the requirement. */ |
31708 | if (!expr || expr == error_mark_node) |
31709 | { |
31710 | cp_parser_skip_to_end_of_statement (parser); |
31711 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31712 | return error_mark_node; |
31713 | } |
31714 | |
31715 | /* Parse the optional noexcept. */ |
31716 | bool noexcept_p = false; |
31717 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_NOEXCEPT)) |
31718 | { |
31719 | cp_lexer_consume_token (lexer: parser->lexer); |
31720 | noexcept_p = true; |
31721 | } |
31722 | |
31723 | /* Parse the optional trailing return type. */ |
31724 | tree type = NULL_TREE; |
31725 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
31726 | { |
31727 | cp_lexer_consume_token (lexer: parser->lexer); |
31728 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
31729 | |
31730 | bool saved_result_type_constraint_p = parser->in_result_type_constraint_p; |
31731 | parser->in_result_type_constraint_p = true; |
31732 | /* C++20 allows either a type-id or a type-constraint. Parsing |
31733 | a type-id will subsume the parsing for a type-constraint but |
31734 | allow for more syntactic forms (e.g., const C<T>*). */ |
31735 | type = cp_parser_trailing_type_id (parser); |
31736 | parser->in_result_type_constraint_p = saved_result_type_constraint_p; |
31737 | if (type == error_mark_node) |
31738 | return error_mark_node; |
31739 | |
31740 | location_t type_loc = make_location (caret: tok->location, start: tok->location, |
31741 | lexer: parser->lexer); |
31742 | |
31743 | /* Check that we haven't written something like 'const C<T>*'. */ |
31744 | if (type_uses_auto (type)) |
31745 | { |
31746 | if (!is_auto (type)) |
31747 | { |
31748 | error_at (type_loc, |
31749 | "result type is not a plain type-constraint" ); |
31750 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31751 | return error_mark_node; |
31752 | } |
31753 | } |
31754 | else if (!flag_concepts_ts) |
31755 | /* P1452R2 removed the trailing-return-type option. */ |
31756 | error_at (type_loc, |
31757 | "return-type-requirement is not a type-constraint" ); |
31758 | } |
31759 | |
31760 | location_t loc = make_location (caret: expr_token->location, |
31761 | start: braces.open_location (), |
31762 | lexer: parser->lexer); |
31763 | |
31764 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31765 | |
31766 | if (expr == error_mark_node || type == error_mark_node) |
31767 | return error_mark_node; |
31768 | |
31769 | return finish_compound_requirement (loc, expr, type, noexcept_p); |
31770 | } |
31771 | |
31772 | /* Parse a nested requirement. This is the same as a requires clause. |
31773 | |
31774 | nested-requirement: |
31775 | requires-clause */ |
31776 | |
31777 | static tree |
31778 | cp_parser_nested_requirement (cp_parser *parser) |
31779 | { |
31780 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES)); |
31781 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
31782 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31783 | tree req = cp_parser_constraint_expression (parser); |
31784 | if (req == error_mark_node) |
31785 | cp_parser_skip_to_end_of_statement (parser); |
31786 | loc = make_location (caret: loc, start: tok->location, lexer: parser->lexer); |
31787 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31788 | if (req == error_mark_node) |
31789 | return error_mark_node; |
31790 | return finish_nested_requirement (loc, req); |
31791 | } |
31792 | |
31793 | /* Support Functions */ |
31794 | |
31795 | /* Return the appropriate prefer_type argument for lookup_name based on |
31796 | tag_type. */ |
31797 | |
31798 | static inline LOOK_want |
31799 | prefer_type_arg (tag_types tag_type) |
31800 | { |
31801 | switch (tag_type) |
31802 | { |
31803 | case none_type: return LOOK_want::NORMAL; // No preference. |
31804 | case scope_type: return LOOK_want::TYPE_NAMESPACE; // Type or namespace. |
31805 | default: return LOOK_want::TYPE; // Type only. |
31806 | } |
31807 | } |
31808 | |
31809 | /* Looks up NAME in the current scope, as given by PARSER->SCOPE. |
31810 | NAME should have one of the representations used for an |
31811 | id-expression. If NAME is the ERROR_MARK_NODE, the ERROR_MARK_NODE |
31812 | is returned. If PARSER->SCOPE is a dependent type, then a |
31813 | SCOPE_REF is returned. |
31814 | |
31815 | If NAME is a TEMPLATE_ID_EXPR, then it will be immediately |
31816 | returned; the name was already resolved when the TEMPLATE_ID_EXPR |
31817 | was formed. Abstractly, such entities should not be passed to this |
31818 | function, because they do not need to be looked up, but it is |
31819 | simpler to check for this special case here, rather than at the |
31820 | call-sites. |
31821 | |
31822 | In cases not explicitly covered above, this function returns a |
31823 | DECL, OVERLOAD, or baselink representing the result of the lookup. |
31824 | If there was no entity with the indicated NAME, the ERROR_MARK_NODE |
31825 | is returned. |
31826 | |
31827 | If TAG_TYPE is not NONE_TYPE, it indicates an explicit type keyword |
31828 | (e.g., "struct") that was used. In that case bindings that do not |
31829 | refer to types are ignored. |
31830 | |
31831 | If IS_TEMPLATE is TRUE, bindings that do not refer to templates are |
31832 | ignored. If IS_TEMPLATE IS 2, the 'template' keyword was specified. |
31833 | |
31834 | If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces |
31835 | are ignored. |
31836 | |
31837 | If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent |
31838 | types. |
31839 | |
31840 | If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a |
31841 | TREE_LIST of candidates if name-lookup results in an ambiguity, and |
31842 | NULL_TREE otherwise. */ |
31843 | |
31844 | static cp_expr |
31845 | cp_parser_lookup_name (cp_parser *parser, tree name, |
31846 | enum tag_types tag_type, |
31847 | int is_template, |
31848 | bool is_namespace, |
31849 | bool check_dependency, |
31850 | tree *ambiguous_decls, |
31851 | location_t name_location) |
31852 | { |
31853 | tree decl; |
31854 | tree object_type = parser->context->object_type; |
31855 | |
31856 | /* Assume that the lookup will be unambiguous. */ |
31857 | if (ambiguous_decls) |
31858 | *ambiguous_decls = NULL_TREE; |
31859 | |
31860 | /* Now that we have looked up the name, the OBJECT_TYPE (if any) is |
31861 | no longer valid. Note that if we are parsing tentatively, and |
31862 | the parse fails, OBJECT_TYPE will be automatically restored. */ |
31863 | parser->context->object_type = NULL_TREE; |
31864 | |
31865 | if (name == error_mark_node) |
31866 | return error_mark_node; |
31867 | |
31868 | /* A template-id has already been resolved; there is no lookup to |
31869 | do. */ |
31870 | if (TREE_CODE (name) == TEMPLATE_ID_EXPR) |
31871 | return name; |
31872 | if (BASELINK_P (name)) |
31873 | { |
31874 | gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) |
31875 | == TEMPLATE_ID_EXPR); |
31876 | return name; |
31877 | } |
31878 | |
31879 | /* A BIT_NOT_EXPR is used to represent a destructor. By this point, |
31880 | it should already have been checked to make sure that the name |
31881 | used matches the type being destroyed. */ |
31882 | if (TREE_CODE (name) == BIT_NOT_EXPR) |
31883 | { |
31884 | tree type; |
31885 | |
31886 | /* Figure out to which type this destructor applies. */ |
31887 | if (parser->scope) |
31888 | type = parser->scope; |
31889 | else if (object_type) |
31890 | type = object_type; |
31891 | else |
31892 | type = current_class_type; |
31893 | /* If that's not a class type, there is no destructor. */ |
31894 | if (!type || !CLASS_TYPE_P (type)) |
31895 | return error_mark_node; |
31896 | |
31897 | /* In a non-static member function, check implicit this->. */ |
31898 | if (current_class_ref) |
31899 | return lookup_destructor (current_class_ref, parser->scope, name, |
31900 | tf_warning_or_error); |
31901 | |
31902 | if (CLASSTYPE_LAZY_DESTRUCTOR (type)) |
31903 | lazily_declare_fn (sfk_destructor, type); |
31904 | |
31905 | if (tree dtor = CLASSTYPE_DESTRUCTOR (type)) |
31906 | return dtor; |
31907 | |
31908 | return error_mark_node; |
31909 | } |
31910 | |
31911 | /* By this point, the NAME should be an ordinary identifier. If |
31912 | the id-expression was a qualified name, the qualifying scope is |
31913 | stored in PARSER->SCOPE at this point. */ |
31914 | gcc_assert (identifier_p (name)); |
31915 | |
31916 | /* Perform the lookup. */ |
31917 | if (parser->scope) |
31918 | { |
31919 | bool dependent_p; |
31920 | |
31921 | if (parser->scope == error_mark_node) |
31922 | return error_mark_node; |
31923 | |
31924 | /* If the SCOPE is dependent, the lookup must be deferred until |
31925 | the template is instantiated -- unless we are explicitly |
31926 | looking up names in uninstantiated templates. Even then, we |
31927 | cannot look up the name if the scope is not a class type; it |
31928 | might, for example, be a template type parameter. */ |
31929 | dependent_p = (TYPE_P (parser->scope) |
31930 | && dependent_scope_p (parser->scope)); |
31931 | if ((check_dependency || !CLASS_TYPE_P (parser->scope)) |
31932 | && dependent_p) |
31933 | /* Defer lookup. */ |
31934 | decl = error_mark_node; |
31935 | else |
31936 | { |
31937 | tree pushed_scope = NULL_TREE; |
31938 | |
31939 | /* If PARSER->SCOPE is a dependent type, then it must be a |
31940 | class type, and we must not be checking dependencies; |
31941 | otherwise, we would have processed this lookup above. So |
31942 | that PARSER->SCOPE is not considered a dependent base by |
31943 | lookup_member, we must enter the scope here. */ |
31944 | if (dependent_p) |
31945 | pushed_scope = push_scope (parser->scope); |
31946 | |
31947 | /* If the PARSER->SCOPE is a template specialization, it |
31948 | may be instantiated during name lookup. In that case, |
31949 | errors may be issued. Even if we rollback the current |
31950 | tentative parse, those errors are valid. */ |
31951 | decl = lookup_qualified_name (scope: parser->scope, name, |
31952 | prefer_type_arg (tag_type), |
31953 | /*complain=*/true); |
31954 | |
31955 | /* 3.4.3.1: In a lookup in which the constructor is an acceptable |
31956 | lookup result and the nested-name-specifier nominates a class C: |
31957 | * if the name specified after the nested-name-specifier, when |
31958 | looked up in C, is the injected-class-name of C (Clause 9), or |
31959 | * if the name specified after the nested-name-specifier is the |
31960 | same as the identifier or the simple-template-id's template- |
31961 | name in the last component of the nested-name-specifier, |
31962 | the name is instead considered to name the constructor of |
31963 | class C. [ Note: for example, the constructor is not an |
31964 | acceptable lookup result in an elaborated-type-specifier so |
31965 | the constructor would not be used in place of the |
31966 | injected-class-name. --end note ] Such a constructor name |
31967 | shall be used only in the declarator-id of a declaration that |
31968 | names a constructor or in a using-declaration. */ |
31969 | if (tag_type == none_type |
31970 | && DECL_SELF_REFERENCE_P (decl) |
31971 | && same_type_p (DECL_CONTEXT (decl), parser->scope)) |
31972 | decl = lookup_qualified_name (scope: parser->scope, ctor_identifier, |
31973 | prefer_type_arg (tag_type), |
31974 | /*complain=*/true); |
31975 | |
31976 | if (pushed_scope) |
31977 | pop_scope (pushed_scope); |
31978 | } |
31979 | |
31980 | /* If the scope is a dependent type and either we deferred lookup or |
31981 | we did lookup but didn't find the name, rememeber the name. */ |
31982 | if (decl == error_mark_node && TYPE_P (parser->scope) |
31983 | && dependent_type_p (parser->scope)) |
31984 | { |
31985 | if (tag_type) |
31986 | { |
31987 | tree type; |
31988 | |
31989 | /* The resolution to Core Issue 180 says that `struct |
31990 | A::B' should be considered a type-name, even if `A' |
31991 | is dependent. */ |
31992 | type = make_typename_type (parser->scope, name, tag_type, |
31993 | /*complain=*/tf_error); |
31994 | if (type != error_mark_node) |
31995 | decl = TYPE_NAME (type); |
31996 | } |
31997 | else if (is_template |
31998 | && (cp_parser_next_token_ends_template_argument_p (parser) |
31999 | || cp_lexer_next_token_is (lexer: parser->lexer, |
32000 | type: CPP_CLOSE_PAREN))) |
32001 | decl = make_unbound_class_template (parser->scope, |
32002 | name, NULL_TREE, |
32003 | /*complain=*/tf_error); |
32004 | else |
32005 | decl = build_qualified_name (/*type=*/NULL_TREE, |
32006 | parser->scope, name, |
32007 | is_template); |
32008 | } |
32009 | parser->qualifying_scope = parser->scope; |
32010 | parser->object_scope = NULL_TREE; |
32011 | } |
32012 | else if (object_type) |
32013 | { |
32014 | bool dep = dependent_scope_p (object_type); |
32015 | |
32016 | /* Look up the name in the scope of the OBJECT_TYPE, unless the |
32017 | OBJECT_TYPE is not a class. */ |
32018 | if (!dep && CLASS_TYPE_P (object_type)) |
32019 | /* If the OBJECT_TYPE is a template specialization, it may |
32020 | be instantiated during name lookup. In that case, errors |
32021 | may be issued. Even if we rollback the current tentative |
32022 | parse, those errors are valid. */ |
32023 | decl = lookup_member (object_type, |
32024 | name, |
32025 | /*protect=*/0, |
32026 | /*prefer_type=*/tag_type != none_type, |
32027 | tf_warning_or_error); |
32028 | else |
32029 | decl = NULL_TREE; |
32030 | |
32031 | /* If we didn't find a member and have dependent bases, the member lookup |
32032 | is now dependent. */ |
32033 | if (!dep && !decl && any_dependent_bases_p (object_type)) |
32034 | dep = true; |
32035 | |
32036 | if (dep && is_template == 2) |
32037 | /* The template keyword specifies a dependent template. */; |
32038 | else if (!decl) |
32039 | /* Look it up in the enclosing context. DR 141: When looking for a |
32040 | template-name after -> or ., only consider class templates. */ |
32041 | decl = lookup_name (name, want: is_namespace ? LOOK_want::NAMESPACE |
32042 | /* DR 141: When looking in the |
32043 | current enclosing context for a |
32044 | template-name after -> or ., only |
32045 | consider class templates. */ |
32046 | : is_template ? LOOK_want::TYPE |
32047 | : prefer_type_arg (tag_type)); |
32048 | |
32049 | /* If we did unqualified lookup of a dependent member-qualified name and |
32050 | found something, do we want to use it? P1787 clarified that we need |
32051 | to look in the object scope first even if it's dependent, but for now |
32052 | let's still use it in some cases. |
32053 | FIXME remember unqualified lookup result to use if member lookup fails |
32054 | at instantiation time. */ |
32055 | if (decl && dep && is_template) |
32056 | { |
32057 | saved_token_sentinel toks (parser->lexer, STS_ROLLBACK); |
32058 | /* Only use the unqualified class template lookup if we're actually |
32059 | looking at a template arg list. */ |
32060 | if (!cp_parser_skip_entire_template_parameter_list (parser)) |
32061 | decl = NULL_TREE; |
32062 | } |
32063 | |
32064 | /* If we know we're looking for a type (e.g. A in p->A::x), |
32065 | mock up a typename. */ |
32066 | if (!decl && dep && tag_type != none_type) |
32067 | { |
32068 | tree type = build_typename_type (object_type, name, name, |
32069 | typename_type); |
32070 | decl = TYPE_NAME (type); |
32071 | } |
32072 | |
32073 | parser->object_scope = object_type; |
32074 | parser->qualifying_scope = NULL_TREE; |
32075 | } |
32076 | else |
32077 | { |
32078 | decl = lookup_name (name, want: is_namespace ? LOOK_want::NAMESPACE |
32079 | : prefer_type_arg (tag_type)); |
32080 | parser->qualifying_scope = NULL_TREE; |
32081 | parser->object_scope = NULL_TREE; |
32082 | } |
32083 | |
32084 | /* If the lookup failed, let our caller know. */ |
32085 | if (!decl || decl == error_mark_node) |
32086 | return error_mark_node; |
32087 | |
32088 | /* If we have resolved the name of a member declaration, check to |
32089 | see if the declaration is accessible. When the name resolves to |
32090 | set of overloaded functions, accessibility is checked when |
32091 | overload resolution is done. If we have a TREE_LIST, then the lookup |
32092 | is either ambiguous or it found multiple injected-class-names, the |
32093 | accessibility of which is trivially satisfied. |
32094 | |
32095 | During an explicit instantiation, access is not checked at all, |
32096 | as per [temp.explicit]. */ |
32097 | if (DECL_P (decl)) |
32098 | check_accessibility_of_qualified_id (decl, object_type, parser->scope, |
32099 | tf_warning_or_error); |
32100 | |
32101 | /* Pull out the template from an injected-class-name (or multiple). */ |
32102 | if (is_template) |
32103 | decl = maybe_get_template_decl_from_type_decl (decl); |
32104 | |
32105 | /* If it's a TREE_LIST, the result of the lookup was ambiguous. */ |
32106 | if (TREE_CODE (decl) == TREE_LIST) |
32107 | { |
32108 | if (ambiguous_decls) |
32109 | *ambiguous_decls = decl; |
32110 | /* The error message we have to print is too complicated for |
32111 | cp_parser_error, so we incorporate its actions directly. */ |
32112 | if (!cp_parser_simulate_error (parser)) |
32113 | { |
32114 | error_at (name_location, "reference to %qD is ambiguous" , |
32115 | name); |
32116 | print_candidates (decl); |
32117 | } |
32118 | return error_mark_node; |
32119 | } |
32120 | |
32121 | gcc_assert (DECL_P (decl) |
32122 | || TREE_CODE (decl) == OVERLOAD |
32123 | || TREE_CODE (decl) == SCOPE_REF |
32124 | || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE |
32125 | || BASELINK_P (decl)); |
32126 | |
32127 | maybe_record_typedef_use (decl); |
32128 | |
32129 | return cp_expr (decl, name_location); |
32130 | } |
32131 | |
32132 | /* Like cp_parser_lookup_name, but for use in the typical case where |
32133 | CHECK_ACCESS is TRUE, IS_TYPE is FALSE, IS_TEMPLATE is FALSE, |
32134 | IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE. */ |
32135 | |
32136 | static tree |
32137 | cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location) |
32138 | { |
32139 | return cp_parser_lookup_name (parser, name, |
32140 | tag_type: none_type, |
32141 | /*is_template=*/false, |
32142 | /*is_namespace=*/false, |
32143 | /*check_dependency=*/true, |
32144 | /*ambiguous_decls=*/NULL, |
32145 | name_location: location); |
32146 | } |
32147 | |
32148 | /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in |
32149 | the current context, return the TYPE_DECL. If TAG_NAME_P is |
32150 | true, the DECL indicates the class being defined in a class-head, |
32151 | or declared in an elaborated-type-specifier. |
32152 | |
32153 | Otherwise, return DECL. */ |
32154 | |
32155 | static tree |
32156 | cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) |
32157 | { |
32158 | /* If the TEMPLATE_DECL is being declared as part of a class-head, |
32159 | the translation from TEMPLATE_DECL to TYPE_DECL occurs: |
32160 | |
32161 | struct A { |
32162 | template <typename T> struct B; |
32163 | }; |
32164 | |
32165 | template <typename T> struct A::B {}; |
32166 | |
32167 | Similarly, in an elaborated-type-specifier: |
32168 | |
32169 | namespace N { struct X{}; } |
32170 | |
32171 | struct A { |
32172 | template <typename T> friend struct N::X; |
32173 | }; |
32174 | |
32175 | However, if the DECL refers to a class type, and we are in |
32176 | the scope of the class, then the name lookup automatically |
32177 | finds the TYPE_DECL created by build_self_reference rather |
32178 | than a TEMPLATE_DECL. For example, in: |
32179 | |
32180 | template <class T> struct S { |
32181 | S s; |
32182 | }; |
32183 | |
32184 | there is no need to handle such case. */ |
32185 | |
32186 | if (DECL_CLASS_TEMPLATE_P (decl) && tag_name_p) |
32187 | return DECL_TEMPLATE_RESULT (decl); |
32188 | |
32189 | return decl; |
32190 | } |
32191 | |
32192 | /* If too many, or too few, template-parameter lists apply to the |
32193 | declarator, issue an error message. Returns TRUE if all went well, |
32194 | and FALSE otherwise. */ |
32195 | |
32196 | static bool |
32197 | cp_parser_check_declarator_template_parameters (cp_parser* parser, |
32198 | cp_declarator *declarator, |
32199 | location_t declarator_location) |
32200 | { |
32201 | switch (declarator->kind) |
32202 | { |
32203 | case cdk_id: |
32204 | { |
32205 | unsigned num_templates = 0; |
32206 | tree scope = declarator->u.id.qualifying_scope; |
32207 | bool template_id_p = false; |
32208 | |
32209 | if (scope) |
32210 | num_templates = num_template_headers_for_class (scope); |
32211 | else if (TREE_CODE (declarator->u.id.unqualified_name) |
32212 | == TEMPLATE_ID_EXPR) |
32213 | { |
32214 | /* If the DECLARATOR has the form `X<y>' then it uses one |
32215 | additional level of template parameters. */ |
32216 | ++num_templates; |
32217 | template_id_p = true; |
32218 | } |
32219 | |
32220 | return cp_parser_check_template_parameters |
32221 | (parser, num_templates, template_id_p, declarator_location, |
32222 | declarator); |
32223 | } |
32224 | |
32225 | case cdk_function: |
32226 | case cdk_array: |
32227 | case cdk_pointer: |
32228 | case cdk_reference: |
32229 | case cdk_ptrmem: |
32230 | return (cp_parser_check_declarator_template_parameters |
32231 | (parser, declarator: declarator->declarator, declarator_location)); |
32232 | |
32233 | case cdk_decomp: |
32234 | case cdk_error: |
32235 | return true; |
32236 | |
32237 | default: |
32238 | gcc_unreachable (); |
32239 | } |
32240 | return false; |
32241 | } |
32242 | |
32243 | /* NUM_TEMPLATES were used in the current declaration. If that is |
32244 | invalid, return FALSE and issue an error messages. Otherwise, |
32245 | return TRUE. If DECLARATOR is non-NULL, then we are checking a |
32246 | declarator and we can print more accurate diagnostics. */ |
32247 | |
32248 | static bool |
32249 | cp_parser_check_template_parameters (cp_parser* parser, |
32250 | unsigned num_templates, |
32251 | bool template_id_p, |
32252 | location_t location, |
32253 | cp_declarator *declarator) |
32254 | { |
32255 | /* If there are the same number of template classes and parameter |
32256 | lists, that's OK. */ |
32257 | if (parser->num_template_parameter_lists == num_templates) |
32258 | return true; |
32259 | /* If there are more, but only one more, and the name ends in an identifier, |
32260 | then we are declaring a primary template. That's OK too. */ |
32261 | if (!template_id_p |
32262 | && parser->num_template_parameter_lists == num_templates + 1) |
32263 | return true; |
32264 | |
32265 | if (cp_parser_simulate_error (parser)) |
32266 | return false; |
32267 | |
32268 | /* If there are more template classes than parameter lists, we have |
32269 | something like: |
32270 | |
32271 | template <class T> void S<T>::R<T>::f (); */ |
32272 | if (parser->num_template_parameter_lists < num_templates) |
32273 | { |
32274 | if (declarator && !current_function_decl) |
32275 | error_at (location, "specializing member %<%T::%E%> " |
32276 | "requires %<template<>%> syntax" , |
32277 | declarator->u.id.qualifying_scope, |
32278 | declarator->u.id.unqualified_name); |
32279 | else if (declarator) |
32280 | error_at (location, "invalid declaration of %<%T::%E%>" , |
32281 | declarator->u.id.qualifying_scope, |
32282 | declarator->u.id.unqualified_name); |
32283 | else |
32284 | error_at (location, "too few template-parameter-lists" ); |
32285 | return false; |
32286 | } |
32287 | /* Otherwise, there are too many template parameter lists. We have |
32288 | something like: |
32289 | |
32290 | template <class T> template <class U> void S::f(); */ |
32291 | error_at (location, "too many template-parameter-lists" ); |
32292 | return false; |
32293 | } |
32294 | |
32295 | /* Parse an optional `::' token indicating that the following name is |
32296 | from the global namespace. If so, PARSER->SCOPE is set to the |
32297 | GLOBAL_NAMESPACE. Otherwise, PARSER->SCOPE is set to NULL_TREE, |
32298 | unless CURRENT_SCOPE_VALID_P is TRUE, in which case it is left alone. |
32299 | Returns the new value of PARSER->SCOPE, if the `::' token is |
32300 | present, and NULL_TREE otherwise. */ |
32301 | |
32302 | static tree |
32303 | cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p) |
32304 | { |
32305 | cp_token *token; |
32306 | |
32307 | /* Peek at the next token. */ |
32308 | token = cp_lexer_peek_token (lexer: parser->lexer); |
32309 | /* If we're looking at a `::' token then we're starting from the |
32310 | global namespace, not our current location. */ |
32311 | if (token->type == CPP_SCOPE) |
32312 | { |
32313 | /* Consume the `::' token. */ |
32314 | cp_lexer_consume_token (lexer: parser->lexer); |
32315 | /* Set the SCOPE so that we know where to start the lookup. */ |
32316 | parser->scope = global_namespace; |
32317 | parser->qualifying_scope = global_namespace; |
32318 | parser->object_scope = NULL_TREE; |
32319 | |
32320 | return parser->scope; |
32321 | } |
32322 | else if (!current_scope_valid_p) |
32323 | { |
32324 | parser->scope = NULL_TREE; |
32325 | parser->qualifying_scope = NULL_TREE; |
32326 | parser->object_scope = NULL_TREE; |
32327 | } |
32328 | |
32329 | return NULL_TREE; |
32330 | } |
32331 | |
32332 | /* Returns TRUE if the upcoming token sequence is the start of a |
32333 | constructor declarator or C++17 deduction guide. If FRIEND_P is true, the |
32334 | declarator is preceded by the `friend' specifier. The parser flags FLAGS |
32335 | is used to control type-specifier parsing. */ |
32336 | |
32337 | static bool |
32338 | cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, |
32339 | bool friend_p) |
32340 | { |
32341 | bool constructor_p; |
32342 | bool outside_class_specifier_p; |
32343 | tree nested_name_specifier; |
32344 | cp_token *next_token; |
32345 | |
32346 | /* The common case is that this is not a constructor declarator, so |
32347 | try to avoid doing lots of work if at all possible. It's not |
32348 | valid declare a constructor at function scope. */ |
32349 | if (parser->in_function_body) |
32350 | return false; |
32351 | /* And only certain tokens can begin a constructor declarator. */ |
32352 | next_token = cp_lexer_peek_token (lexer: parser->lexer); |
32353 | if (next_token->type != CPP_NAME |
32354 | && next_token->type != CPP_SCOPE |
32355 | && next_token->type != CPP_NESTED_NAME_SPECIFIER |
32356 | && next_token->type != CPP_TEMPLATE_ID) |
32357 | return false; |
32358 | |
32359 | /* Parse tentatively; we are going to roll back all of the tokens |
32360 | consumed here. */ |
32361 | cp_parser_parse_tentatively (parser); |
32362 | /* Assume that we are looking at a constructor declarator. */ |
32363 | constructor_p = true; |
32364 | |
32365 | /* Look for the optional `::' operator. */ |
32366 | cp_parser_global_scope_opt (parser, |
32367 | /*current_scope_valid_p=*/false); |
32368 | /* Look for the nested-name-specifier. */ |
32369 | nested_name_specifier |
32370 | = (cp_parser_nested_name_specifier_opt (parser, |
32371 | /*typename_keyword_p=*/false, |
32372 | /*check_dependency_p=*/false, |
32373 | /*type_p=*/false, |
32374 | /*is_declaration=*/false)); |
32375 | |
32376 | /* Resolve the TYPENAME_TYPE, because the call above didn't do it. */ |
32377 | if (nested_name_specifier |
32378 | && TREE_CODE (nested_name_specifier) == TYPENAME_TYPE) |
32379 | { |
32380 | tree s = resolve_typename_type (nested_name_specifier, |
32381 | /*only_current_p=*/false); |
32382 | if (TREE_CODE (s) != TYPENAME_TYPE) |
32383 | nested_name_specifier = s; |
32384 | } |
32385 | |
32386 | outside_class_specifier_p = (!at_class_scope_p () |
32387 | || !TYPE_BEING_DEFINED (current_class_type) |
32388 | || friend_p); |
32389 | |
32390 | /* Outside of a class-specifier, there must be a |
32391 | nested-name-specifier. Except in C++17 mode, where we |
32392 | might be declaring a guiding declaration. */ |
32393 | if (!nested_name_specifier && outside_class_specifier_p |
32394 | && cxx_dialect < cxx17) |
32395 | constructor_p = false; |
32396 | else if (nested_name_specifier == error_mark_node) |
32397 | constructor_p = false; |
32398 | |
32399 | /* If we have a class scope, this is easy; DR 147 says that S::S always |
32400 | names the constructor, and no other qualified name could. */ |
32401 | if (constructor_p && nested_name_specifier |
32402 | && CLASS_TYPE_P (nested_name_specifier)) |
32403 | { |
32404 | tree id = cp_parser_unqualified_id (parser, |
32405 | /*template_keyword_p=*/false, |
32406 | /*check_dependency_p=*/false, |
32407 | /*declarator_p=*/true, |
32408 | /*optional_p=*/false); |
32409 | if (is_overloaded_fn (id)) |
32410 | id = DECL_NAME (get_first_fn (id)); |
32411 | if (!constructor_name_p (id, nested_name_specifier)) |
32412 | constructor_p = false; |
32413 | } |
32414 | /* If we still think that this might be a constructor-declarator, |
32415 | look for a class-name. */ |
32416 | else if (constructor_p) |
32417 | { |
32418 | /* If we have: |
32419 | |
32420 | template <typename T> struct S { |
32421 | S(); |
32422 | }; |
32423 | |
32424 | we must recognize that the nested `S' names a class. */ |
32425 | if (cxx_dialect >= cxx17) |
32426 | cp_parser_parse_tentatively (parser); |
32427 | |
32428 | tree type_decl; |
32429 | type_decl = cp_parser_class_name (parser, |
32430 | /*typename_keyword_p=*/false, |
32431 | /*template_keyword_p=*/false, |
32432 | tag_type: none_type, |
32433 | /*check_dependency_p=*/false, |
32434 | /*class_head_p=*/false, |
32435 | /*is_declaration=*/false); |
32436 | |
32437 | if (cxx_dialect >= cxx17 |
32438 | && !cp_parser_parse_definitely (parser)) |
32439 | { |
32440 | type_decl = NULL_TREE; |
32441 | tree tmpl = cp_parser_template_name (parser, |
32442 | /*template_keyword*/template_keyword_p: false, |
32443 | /*check_dependency_p*/false, |
32444 | /*is_declaration*/false, |
32445 | tag_type: none_type, |
32446 | /*is_identifier*/NULL); |
32447 | if (DECL_CLASS_TEMPLATE_P (tmpl) |
32448 | || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)) |
32449 | /* It's a deduction guide, return true. */; |
32450 | else |
32451 | cp_parser_simulate_error (parser); |
32452 | } |
32453 | |
32454 | /* If there was no class-name, then this is not a constructor. |
32455 | Otherwise, if we are in a class-specifier and we aren't |
32456 | handling a friend declaration, check that its type matches |
32457 | current_class_type (c++/38313). Note: error_mark_node |
32458 | is left alone for error recovery purposes. */ |
32459 | constructor_p = (!cp_parser_error_occurred (parser) |
32460 | && (outside_class_specifier_p |
32461 | || type_decl == NULL_TREE |
32462 | || type_decl == error_mark_node |
32463 | || same_type_p (current_class_type, |
32464 | TREE_TYPE (type_decl)))); |
32465 | |
32466 | /* If we're still considering a constructor, we have to see a `(', |
32467 | to begin the parameter-declaration-clause, followed by either a |
32468 | `)', an `...', or a decl-specifier. We need to check for a |
32469 | type-specifier to avoid being fooled into thinking that: |
32470 | |
32471 | S (f) (int); |
32472 | |
32473 | is a constructor. (It is actually a function named `f' that |
32474 | takes one parameter (of type `int') and returns a value of type |
32475 | `S'. */ |
32476 | if (constructor_p |
32477 | && !cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) |
32478 | constructor_p = false; |
32479 | |
32480 | if (constructor_p |
32481 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
32482 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_ELLIPSIS) |
32483 | /* A parameter declaration begins with a decl-specifier, |
32484 | which is either the "attribute" keyword, a storage class |
32485 | specifier, or (usually) a type-specifier. */ |
32486 | && !cp_lexer_next_token_is_decl_specifier_keyword (lexer: parser->lexer) |
32487 | /* GNU attributes can actually appear both at the start of |
32488 | a parameter and parenthesized declarator. |
32489 | S (__attribute__((unused)) int); |
32490 | is a constructor, but |
32491 | S (__attribute__((unused)) foo) (int); |
32492 | is a function declaration. [[attribute]] can appear in the |
32493 | first form too, but not in the second form. */ |
32494 | && !cp_next_tokens_can_be_std_attribute_p (parser)) |
32495 | { |
32496 | tree type; |
32497 | tree pushed_scope = NULL_TREE; |
32498 | unsigned saved_num_template_parameter_lists; |
32499 | |
32500 | if (cp_parser_allow_gnu_extensions_p (parser) |
32501 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
32502 | { |
32503 | unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, n: 1); |
32504 | while (--n) |
32505 | cp_lexer_consume_token (lexer: parser->lexer); |
32506 | } |
32507 | |
32508 | /* Names appearing in the type-specifier should be looked up |
32509 | in the scope of the class. */ |
32510 | if (current_class_type) |
32511 | type = NULL_TREE; |
32512 | else if (type_decl) |
32513 | { |
32514 | type = TREE_TYPE (type_decl); |
32515 | if (TREE_CODE (type) == TYPENAME_TYPE) |
32516 | { |
32517 | type = resolve_typename_type (type, |
32518 | /*only_current_p=*/false); |
32519 | if (TREE_CODE (type) == TYPENAME_TYPE) |
32520 | { |
32521 | cp_parser_abort_tentative_parse (parser); |
32522 | return false; |
32523 | } |
32524 | } |
32525 | pushed_scope = push_scope (type); |
32526 | } |
32527 | |
32528 | /* Inside the constructor parameter list, surrounding |
32529 | template-parameter-lists do not apply. */ |
32530 | saved_num_template_parameter_lists |
32531 | = parser->num_template_parameter_lists; |
32532 | parser->num_template_parameter_lists = 0; |
32533 | |
32534 | /* Look for the type-specifier. It's not optional, but its typename |
32535 | might be. Unless this is a friend declaration; we don't want to |
32536 | treat |
32537 | |
32538 | friend S (T::fn)(int); |
32539 | |
32540 | as a constructor, but with P0634, we might assume a type when |
32541 | looking for the type-specifier. It is actually a function named |
32542 | `T::fn' that takes one parameter (of type `int') and returns a |
32543 | value of type `S'. Constructors can be friends, but they must |
32544 | use a qualified name. |
32545 | |
32546 | Parse with an empty set of declaration specifiers since we're |
32547 | trying to match a decl-specifier-seq of the first parameter. |
32548 | This must be non-null so that cp_parser_simple_type_specifier |
32549 | will recognize a constrained placeholder type such as: |
32550 | 'C<int> auto' where C is a type concept. */ |
32551 | cp_decl_specifier_seq ctor_specs; |
32552 | clear_decl_specs (decl_specs: &ctor_specs); |
32553 | cp_parser_type_specifier (parser, |
32554 | flags: (friend_p ? CP_PARSER_FLAGS_NONE |
32555 | : (flags & ~CP_PARSER_FLAGS_OPTIONAL)), |
32556 | /*decl_specs=*/&ctor_specs, |
32557 | /*is_declarator=*/is_declaration: true, |
32558 | /*declares_class_or_enum=*/NULL, |
32559 | /*is_cv_qualifier=*/NULL); |
32560 | |
32561 | parser->num_template_parameter_lists |
32562 | = saved_num_template_parameter_lists; |
32563 | |
32564 | /* Leave the scope of the class. */ |
32565 | if (pushed_scope) |
32566 | pop_scope (pushed_scope); |
32567 | |
32568 | constructor_p = !cp_parser_error_occurred (parser); |
32569 | } |
32570 | } |
32571 | |
32572 | /* We did not really want to consume any tokens. */ |
32573 | cp_parser_abort_tentative_parse (parser); |
32574 | |
32575 | /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the |
32576 | declarator-id of a constructor or destructor. */ |
32577 | if (constructor_p |
32578 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_TEMPLATE_ID) |
32579 | { |
32580 | auto_diagnostic_group d; |
32581 | if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING, |
32582 | input_location, OPT_Wtemplate_id_cdtor, |
32583 | "template-id not allowed for constructor in C++20" )) |
32584 | inform (input_location, "remove the %qs" , "< >" ); |
32585 | } |
32586 | |
32587 | return constructor_p; |
32588 | } |
32589 | |
32590 | /* Parse the definition of the function given by the DECL_SPECIFIERS, |
32591 | ATTRIBUTES, and DECLARATOR. The access checks have been deferred; |
32592 | they must be performed once we are in the scope of the function. |
32593 | |
32594 | Returns the function defined. */ |
32595 | |
32596 | static tree |
32597 | cp_parser_function_definition_from_specifiers_and_declarator |
32598 | (cp_parser* parser, |
32599 | cp_decl_specifier_seq *decl_specifiers, |
32600 | tree attributes, |
32601 | const cp_declarator *declarator) |
32602 | { |
32603 | tree fn; |
32604 | bool success_p; |
32605 | |
32606 | /* Begin the function-definition. */ |
32607 | success_p = start_function (decl_specifiers, declarator, attributes); |
32608 | |
32609 | /* The things we're about to see are not directly qualified by any |
32610 | template headers we've seen thus far. */ |
32611 | reset_specialization (); |
32612 | |
32613 | /* If there were names looked up in the decl-specifier-seq that we |
32614 | did not check, check them now. We must wait until we are in the |
32615 | scope of the function to perform the checks, since the function |
32616 | might be a friend. */ |
32617 | perform_deferred_access_checks (tf_warning_or_error); |
32618 | |
32619 | if (success_p) |
32620 | { |
32621 | cp_finalize_omp_declare_simd (parser, fndecl: current_function_decl); |
32622 | parser->omp_declare_simd = NULL; |
32623 | cp_finalize_oacc_routine (parser, current_function_decl, true); |
32624 | parser->oacc_routine = NULL; |
32625 | } |
32626 | |
32627 | if (!success_p) |
32628 | { |
32629 | /* Skip the entire function. */ |
32630 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32631 | fn = error_mark_node; |
32632 | } |
32633 | else if (DECL_INITIAL (current_function_decl) != error_mark_node) |
32634 | { |
32635 | /* Seen already, skip it. An error message has already been output. */ |
32636 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32637 | fn = current_function_decl; |
32638 | current_function_decl = NULL_TREE; |
32639 | /* If this is a function from a class, pop the nested class. */ |
32640 | if (current_class_name) |
32641 | pop_nested_class (); |
32642 | } |
32643 | else |
32644 | { |
32645 | auto_timevar tv (DECL_DECLARED_INLINE_P (current_function_decl) |
32646 | ? TV_PARSE_INLINE : TV_PARSE_FUNC); |
32647 | fn = cp_parser_function_definition_after_declarator (parser, |
32648 | /*inline_p=*/false); |
32649 | } |
32650 | |
32651 | return fn; |
32652 | } |
32653 | |
32654 | /* Parse the part of a function-definition that follows the |
32655 | declarator. INLINE_P is TRUE iff this function is an inline |
32656 | function defined within a class-specifier. |
32657 | |
32658 | Returns the function defined. */ |
32659 | |
32660 | static tree |
32661 | cp_parser_function_definition_after_declarator (cp_parser* parser, |
32662 | bool inline_p) |
32663 | { |
32664 | tree fn; |
32665 | bool saved_in_unbraced_linkage_specification_p; |
32666 | bool saved_in_function_body; |
32667 | unsigned saved_num_template_parameter_lists; |
32668 | cp_token *token; |
32669 | bool fully_implicit_function_template_p |
32670 | = parser->fully_implicit_function_template_p; |
32671 | parser->fully_implicit_function_template_p = false; |
32672 | tree implicit_template_parms |
32673 | = parser->implicit_template_parms; |
32674 | parser->implicit_template_parms = 0; |
32675 | cp_binding_level* implicit_template_scope |
32676 | = parser->implicit_template_scope; |
32677 | parser->implicit_template_scope = 0; |
32678 | |
32679 | saved_in_function_body = parser->in_function_body; |
32680 | parser->in_function_body = true; |
32681 | /* If the next token is `return', then the code may be trying to |
32682 | make use of the "named return value" extension that G++ used to |
32683 | support. */ |
32684 | token = cp_lexer_peek_token (lexer: parser->lexer); |
32685 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_RETURN)) |
32686 | { |
32687 | /* Consume the `return' keyword. */ |
32688 | cp_lexer_consume_token (lexer: parser->lexer); |
32689 | /* Look for the identifier that indicates what value is to be |
32690 | returned. */ |
32691 | cp_parser_identifier (parser); |
32692 | /* Issue an error message. */ |
32693 | error_at (token->location, |
32694 | "named return values are no longer supported" ); |
32695 | /* Skip tokens until we reach the start of the function body. */ |
32696 | while (true) |
32697 | { |
32698 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32699 | if (token->type == CPP_OPEN_BRACE |
32700 | || token->type == CPP_EOF |
32701 | || token->type == CPP_PRAGMA_EOL) |
32702 | break; |
32703 | cp_lexer_consume_token (lexer: parser->lexer); |
32704 | } |
32705 | } |
32706 | /* The `extern' in `extern "C" void f () { ... }' does not apply to |
32707 | anything declared inside `f'. */ |
32708 | saved_in_unbraced_linkage_specification_p |
32709 | = parser->in_unbraced_linkage_specification_p; |
32710 | parser->in_unbraced_linkage_specification_p = false; |
32711 | /* Inside the function, surrounding template-parameter-lists do not |
32712 | apply. */ |
32713 | saved_num_template_parameter_lists |
32714 | = parser->num_template_parameter_lists; |
32715 | parser->num_template_parameter_lists = 0; |
32716 | |
32717 | /* If the next token is `try', `__transaction_atomic', or |
32718 | `__transaction_relaxed`, then we are looking at either function-try-block |
32719 | or function-transaction-block. Note that all of these include the |
32720 | function-body. */ |
32721 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRANSACTION_ATOMIC)) |
32722 | cp_parser_function_transaction (parser, RID_TRANSACTION_ATOMIC); |
32723 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
32724 | keyword: RID_TRANSACTION_RELAXED)) |
32725 | cp_parser_function_transaction (parser, RID_TRANSACTION_RELAXED); |
32726 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
32727 | cp_parser_function_try_block (parser); |
32728 | else |
32729 | cp_parser_ctor_initializer_opt_and_function_body |
32730 | (parser, /*in_function_try_block=*/false); |
32731 | |
32732 | /* Finish the function. */ |
32733 | fn = finish_function (inline_p); |
32734 | |
32735 | if (modules_p () |
32736 | && !inline_p |
32737 | && TYPE_P (DECL_CONTEXT (fn)) |
32738 | && (DECL_DECLARED_INLINE_P (fn) |
32739 | || processing_template_decl)) |
32740 | set_defining_module (fn); |
32741 | |
32742 | /* Generate code for it, if necessary. */ |
32743 | expand_or_defer_fn (fn); |
32744 | |
32745 | /* Restore the saved values. */ |
32746 | parser->in_unbraced_linkage_specification_p |
32747 | = saved_in_unbraced_linkage_specification_p; |
32748 | parser->num_template_parameter_lists |
32749 | = saved_num_template_parameter_lists; |
32750 | parser->in_function_body = saved_in_function_body; |
32751 | |
32752 | parser->fully_implicit_function_template_p |
32753 | = fully_implicit_function_template_p; |
32754 | parser->implicit_template_parms |
32755 | = implicit_template_parms; |
32756 | parser->implicit_template_scope |
32757 | = implicit_template_scope; |
32758 | |
32759 | if (parser->fully_implicit_function_template_p) |
32760 | finish_fully_implicit_template (parser, /*member_decl_opt=*/0); |
32761 | |
32762 | return fn; |
32763 | } |
32764 | |
32765 | /* Parse a template-declaration body (following argument list). */ |
32766 | |
32767 | static void |
32768 | cp_parser_template_declaration_after_parameters (cp_parser* parser, |
32769 | tree parameter_list, |
32770 | bool member_p) |
32771 | { |
32772 | tree decl = NULL_TREE; |
32773 | bool friend_p = false; |
32774 | |
32775 | /* We just processed one more parameter list. */ |
32776 | ++parser->num_template_parameter_lists; |
32777 | |
32778 | /* Get the deferred access checks from the parameter list. These |
32779 | will be checked once we know what is being declared, as for a |
32780 | member template the checks must be performed in the scope of the |
32781 | class containing the member. */ |
32782 | vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks (); |
32783 | |
32784 | /* Tentatively parse for a new template parameter list, which can either be |
32785 | the template keyword or a template introduction. */ |
32786 | if (cp_parser_template_declaration_after_export (parser, member_p)) |
32787 | /* OK */; |
32788 | else if (cxx_dialect >= cxx11 |
32789 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
32790 | decl = cp_parser_alias_declaration (parser); |
32791 | else if (flag_concepts |
32792 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CONCEPT) |
32793 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
32794 | /* -fconcept-ts 'concept bool' syntax is handled below, in |
32795 | cp_parser_single_declaration. */ |
32796 | decl = cp_parser_concept_definition (parser); |
32797 | else |
32798 | { |
32799 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32800 | decl = cp_parser_single_declaration (parser, |
32801 | checks, |
32802 | member_p, |
32803 | /*explicit_specialization_p=*/false, |
32804 | &friend_p); |
32805 | |
32806 | /* If this is a member template declaration, let the front |
32807 | end know. */ |
32808 | if (member_p && !friend_p && decl) |
32809 | { |
32810 | if (TREE_CODE (decl) == TYPE_DECL) |
32811 | cp_parser_check_access_in_redeclaration (type: decl, location: token->location); |
32812 | |
32813 | decl = finish_member_template_decl (decl); |
32814 | } |
32815 | else if (friend_p && decl |
32816 | && DECL_DECLARES_TYPE_P (decl)) |
32817 | make_friend_class (current_class_type, TREE_TYPE (decl), |
32818 | /*complain=*/true); |
32819 | } |
32820 | /* We are done with the current parameter list. */ |
32821 | --parser->num_template_parameter_lists; |
32822 | |
32823 | pop_deferring_access_checks (); |
32824 | |
32825 | /* Finish up. */ |
32826 | finish_template_decl (parameter_list); |
32827 | |
32828 | /* Check the template arguments for a literal operator template. */ |
32829 | if (decl |
32830 | && DECL_DECLARES_FUNCTION_P (decl) |
32831 | && UDLIT_OPER_P (DECL_NAME (decl))) |
32832 | { |
32833 | bool ok = true; |
32834 | if (parameter_list == NULL_TREE) |
32835 | ok = false; |
32836 | else |
32837 | { |
32838 | int num_parms = TREE_VEC_LENGTH (parameter_list); |
32839 | if (num_parms == 1) |
32840 | { |
32841 | tree parm_list = TREE_VEC_ELT (parameter_list, 0); |
32842 | tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); |
32843 | if (TREE_CODE (parm) != PARM_DECL) |
32844 | ok = false; |
32845 | else if (MAYBE_CLASS_TYPE_P (TREE_TYPE (parm)) |
32846 | && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32847 | /* OK, C++20 string literal operator template. We don't need |
32848 | to warn in lower dialects here because we will have already |
32849 | warned about the template parameter. */; |
32850 | else if (TREE_TYPE (parm) != char_type_node |
32851 | || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32852 | ok = false; |
32853 | } |
32854 | else if (num_parms == 2 && cxx_dialect >= cxx14) |
32855 | { |
32856 | tree parm_type = TREE_VEC_ELT (parameter_list, 0); |
32857 | tree type = INNERMOST_TEMPLATE_PARMS (parm_type); |
32858 | tree parm_list = TREE_VEC_ELT (parameter_list, 1); |
32859 | tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); |
32860 | if (TREE_CODE (parm) != PARM_DECL |
32861 | || TREE_TYPE (parm) != TREE_TYPE (type) |
32862 | || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32863 | ok = false; |
32864 | else |
32865 | /* http://cplusplus.github.io/EWG/ewg-active.html#66 */ |
32866 | pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, |
32867 | "ISO C++ did not adopt string literal operator templa" |
32868 | "tes taking an argument pack of characters" ); |
32869 | } |
32870 | else |
32871 | ok = false; |
32872 | } |
32873 | if (!ok) |
32874 | { |
32875 | if (cxx_dialect > cxx17) |
32876 | error_at (DECL_SOURCE_LOCATION (decl), "literal operator " |
32877 | "template %qD has invalid parameter list; expected " |
32878 | "non-type template parameter pack %<<char...>%> or " |
32879 | "single non-type parameter of class type" , |
32880 | decl); |
32881 | else |
32882 | error_at (DECL_SOURCE_LOCATION (decl), "literal operator " |
32883 | "template %qD has invalid parameter list; expected " |
32884 | "non-type template parameter pack %<<char...>%>" , |
32885 | decl); |
32886 | } |
32887 | } |
32888 | |
32889 | /* Register member declarations. */ |
32890 | if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)) |
32891 | finish_member_declaration (decl); |
32892 | /* If DECL is a function template, we must return to parse it later. |
32893 | (Even though there is no definition, there might be default |
32894 | arguments that need handling.) */ |
32895 | if (member_p && decl |
32896 | && DECL_DECLARES_FUNCTION_P (decl)) |
32897 | vec_safe_push (unparsed_funs_with_definitions, obj: decl); |
32898 | } |
32899 | |
32900 | /* Parse a template introduction header for a template-declaration. Returns |
32901 | false if tentative parse fails. */ |
32902 | |
32903 | static bool |
32904 | cp_parser_template_introduction (cp_parser* parser, bool member_p) |
32905 | { |
32906 | cp_parser_parse_tentatively (parser); |
32907 | |
32908 | tree saved_scope = parser->scope; |
32909 | tree saved_object_scope = parser->object_scope; |
32910 | tree saved_qualifying_scope = parser->qualifying_scope; |
32911 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
32912 | |
32913 | cp_token *start_token = cp_lexer_peek_token (lexer: parser->lexer); |
32914 | |
32915 | /* In classes don't parse valid unnamed bitfields as invalid |
32916 | template introductions. */ |
32917 | if (member_p) |
32918 | parser->colon_corrects_to_scope_p = false; |
32919 | |
32920 | /* Look for the optional `::' operator. */ |
32921 | cp_parser_global_scope_opt (parser, |
32922 | /*current_scope_valid_p=*/false); |
32923 | /* Look for the nested-name-specifier. */ |
32924 | cp_parser_nested_name_specifier_opt (parser, |
32925 | /*typename_keyword_p=*/false, |
32926 | /*check_dependency_p=*/true, |
32927 | /*type_p=*/false, |
32928 | /*is_declaration=*/false); |
32929 | |
32930 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32931 | tree concept_name = cp_parser_identifier (parser); |
32932 | |
32933 | /* Look up the concept for which we will be matching |
32934 | template parameters. */ |
32935 | tree tmpl_decl = cp_parser_lookup_name_simple (parser, name: concept_name, |
32936 | location: token->location); |
32937 | parser->scope = saved_scope; |
32938 | parser->object_scope = saved_object_scope; |
32939 | parser->qualifying_scope = saved_qualifying_scope; |
32940 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
32941 | |
32942 | if (concept_name == error_mark_node |
32943 | || (seen_error () && !concept_definition_p (t: tmpl_decl))) |
32944 | cp_parser_simulate_error (parser); |
32945 | |
32946 | /* Look for opening brace for introduction. */ |
32947 | matching_braces braces; |
32948 | braces.require_open (parser); |
32949 | location_t open_loc = input_location; |
32950 | |
32951 | if (!cp_parser_parse_definitely (parser)) |
32952 | return false; |
32953 | |
32954 | push_deferring_access_checks (dk_deferred); |
32955 | |
32956 | /* Build vector of placeholder parameters and grab |
32957 | matching identifiers. */ |
32958 | tree introduction_list = cp_parser_introduction_list (parser); |
32959 | |
32960 | /* Look for closing brace for introduction. */ |
32961 | if (!braces.require_close (parser)) |
32962 | return true; |
32963 | |
32964 | /* The introduction-list shall not be empty. */ |
32965 | int nargs = TREE_VEC_LENGTH (introduction_list); |
32966 | if (nargs == 0) |
32967 | { |
32968 | /* In cp_parser_introduction_list we have already issued an error. */ |
32969 | return true; |
32970 | } |
32971 | |
32972 | if (tmpl_decl == error_mark_node) |
32973 | { |
32974 | cp_parser_name_lookup_error (parser, name: concept_name, decl: tmpl_decl, desired: NLE_NULL, |
32975 | location: token->location); |
32976 | return true; |
32977 | } |
32978 | |
32979 | /* Build and associate the constraint. */ |
32980 | location_t introduction_loc = make_location (caret: open_loc, |
32981 | start: start_token->location, |
32982 | lexer: parser->lexer); |
32983 | tree parms = finish_template_introduction (tmpl_decl, |
32984 | introduction_list, |
32985 | loc: introduction_loc); |
32986 | if (parms && parms != error_mark_node) |
32987 | { |
32988 | if (!flag_concepts_ts) |
32989 | pedwarn (introduction_loc, 0, "template-introductions" |
32990 | " are not part of C++20 concepts; use %qs to enable" , |
32991 | "-fconcepts-ts" ); |
32992 | |
32993 | cp_parser_template_declaration_after_parameters (parser, parameter_list: parms, |
32994 | member_p); |
32995 | return true; |
32996 | } |
32997 | |
32998 | if (parms == NULL_TREE) |
32999 | error_at (token->location, "no matching concept for template-introduction" ); |
33000 | |
33001 | return true; |
33002 | } |
33003 | |
33004 | /* Parse a normal template-declaration following the template keyword. */ |
33005 | |
33006 | static void |
33007 | cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p) |
33008 | { |
33009 | tree parameter_list; |
33010 | bool need_lang_pop; |
33011 | location_t location = input_location; |
33012 | |
33013 | /* Look for the `<' token. */ |
33014 | if (!cp_parser_require (parser, CPP_LESS, RT_LESS)) |
33015 | return; |
33016 | if (at_class_scope_p () && current_function_decl) |
33017 | { |
33018 | /* 14.5.2.2 [temp.mem] |
33019 | |
33020 | A local class shall not have member templates. */ |
33021 | error_at (location, |
33022 | "invalid declaration of member template in local class" ); |
33023 | cp_parser_skip_to_end_of_block_or_statement (parser); |
33024 | return; |
33025 | } |
33026 | /* [temp] |
33027 | |
33028 | A template ... shall not have C linkage. */ |
33029 | if (current_lang_name == lang_name_c) |
33030 | { |
33031 | error_at (location, "template with C linkage" ); |
33032 | maybe_show_extern_c_location (); |
33033 | /* Give it C++ linkage to avoid confusing other parts of the |
33034 | front end. */ |
33035 | push_lang_context (lang_name_cplusplus); |
33036 | need_lang_pop = true; |
33037 | } |
33038 | else |
33039 | need_lang_pop = false; |
33040 | |
33041 | /* We cannot perform access checks on the template parameter |
33042 | declarations until we know what is being declared, just as we |
33043 | cannot check the decl-specifier list. */ |
33044 | push_deferring_access_checks (dk_deferred); |
33045 | |
33046 | /* If the next token is `>', then we have an invalid |
33047 | specialization. Rather than complain about an invalid template |
33048 | parameter, issue an error message here. */ |
33049 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER)) |
33050 | { |
33051 | cp_parser_error (parser, gmsgid: "invalid explicit specialization" ); |
33052 | begin_specialization (); |
33053 | parameter_list = NULL_TREE; |
33054 | } |
33055 | else |
33056 | { |
33057 | /* Parse the template parameters. */ |
33058 | parameter_list = cp_parser_template_parameter_list (parser); |
33059 | } |
33060 | |
33061 | /* Look for the `>'. */ |
33062 | cp_parser_require_end_of_template_parameter_list (parser); |
33063 | |
33064 | /* Manage template requirements */ |
33065 | if (flag_concepts) |
33066 | { |
33067 | tree reqs = get_shorthand_constraints (current_template_parms); |
33068 | if (tree treqs = cp_parser_requires_clause_opt (parser, lambda_p: false)) |
33069 | reqs = combine_constraint_expressions (reqs, treqs); |
33070 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
33071 | } |
33072 | |
33073 | cp_parser_template_declaration_after_parameters (parser, parameter_list, |
33074 | member_p); |
33075 | |
33076 | /* For the erroneous case of a template with C linkage, we pushed an |
33077 | implicit C++ linkage scope; exit that scope now. */ |
33078 | if (need_lang_pop) |
33079 | pop_lang_context (); |
33080 | } |
33081 | |
33082 | /* Parse a template-declaration, assuming that the `export' (and |
33083 | `extern') keywords, if present, has already been scanned. MEMBER_P |
33084 | is as for cp_parser_template_declaration. */ |
33085 | |
33086 | static bool |
33087 | cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) |
33088 | { |
33089 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
33090 | { |
33091 | cp_lexer_consume_token (lexer: parser->lexer); |
33092 | cp_parser_explicit_template_declaration (parser, member_p); |
33093 | return true; |
33094 | } |
33095 | else if (flag_concepts) |
33096 | return cp_parser_template_introduction (parser, member_p); |
33097 | |
33098 | return false; |
33099 | } |
33100 | |
33101 | /* Perform the deferred access checks from a template-parameter-list. |
33102 | CHECKS is a TREE_LIST of access checks, as returned by |
33103 | get_deferred_access_checks. */ |
33104 | |
33105 | static void |
33106 | cp_parser_perform_template_parameter_access_checks (vec<deferred_access_check, va_gc> *checks) |
33107 | { |
33108 | ++processing_template_parmlist; |
33109 | perform_access_checks (checks, tf_warning_or_error); |
33110 | --processing_template_parmlist; |
33111 | } |
33112 | |
33113 | /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or |
33114 | `function-definition' sequence that follows a template header. |
33115 | If MEMBER_P is true, this declaration appears in a class scope. |
33116 | |
33117 | Returns the DECL for the declared entity. If FRIEND_P is non-NULL, |
33118 | *FRIEND_P is set to TRUE iff the declaration is a friend. */ |
33119 | |
33120 | static tree |
33121 | cp_parser_single_declaration (cp_parser* parser, |
33122 | vec<deferred_access_check, va_gc> *checks, |
33123 | bool member_p, |
33124 | bool explicit_specialization_p, |
33125 | bool* friend_p) |
33126 | { |
33127 | int declares_class_or_enum; |
33128 | tree decl = NULL_TREE; |
33129 | cp_decl_specifier_seq decl_specifiers; |
33130 | bool function_definition_p = false; |
33131 | cp_token *decl_spec_token_start; |
33132 | |
33133 | /* This function is only used when processing a template |
33134 | declaration. */ |
33135 | gcc_assert (innermost_scope_kind () == sk_template_parms |
33136 | || innermost_scope_kind () == sk_template_spec); |
33137 | |
33138 | /* Defer access checks until we know what is being declared. */ |
33139 | push_deferring_access_checks (dk_deferred); |
33140 | |
33141 | /* Try the `decl-specifier-seq [opt] init-declarator [opt]' |
33142 | alternative. */ |
33143 | decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
33144 | cp_parser_decl_specifier_seq (parser, |
33145 | flags: (CP_PARSER_FLAGS_OPTIONAL |
33146 | | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), |
33147 | decl_specs: &decl_specifiers, |
33148 | declares_class_or_enum: &declares_class_or_enum); |
33149 | |
33150 | cp_omp_declare_simd_data odsd; |
33151 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
33152 | cp_parser_handle_directive_omp_attributes (parser, |
33153 | pattrs: &decl_specifiers.attributes, |
33154 | data: &odsd, start: true); |
33155 | |
33156 | if (friend_p) |
33157 | *friend_p = cp_parser_friend_p (&decl_specifiers); |
33158 | |
33159 | /* There are no template typedefs. */ |
33160 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) |
33161 | { |
33162 | error_at (decl_spec_token_start->location, |
33163 | "template declaration of %<typedef%>" ); |
33164 | decl = error_mark_node; |
33165 | } |
33166 | |
33167 | /* Gather up the access checks that occurred the |
33168 | decl-specifier-seq. */ |
33169 | stop_deferring_access_checks (); |
33170 | |
33171 | /* Check for the declaration of a template class. */ |
33172 | if (declares_class_or_enum) |
33173 | { |
33174 | if (cp_parser_declares_only_class_p (parser) |
33175 | || (declares_class_or_enum & 2)) |
33176 | { |
33177 | decl = shadow_tag (&decl_specifiers); |
33178 | |
33179 | /* In this case: |
33180 | |
33181 | struct C { |
33182 | friend template <typename T> struct A<T>::B; |
33183 | }; |
33184 | |
33185 | A<T>::B will be represented by a TYPENAME_TYPE, and |
33186 | therefore not recognized by shadow_tag. */ |
33187 | if (friend_p && *friend_p |
33188 | && !decl |
33189 | && decl_specifiers.type |
33190 | && TYPE_P (decl_specifiers.type)) |
33191 | decl = decl_specifiers.type; |
33192 | |
33193 | if (decl && decl != error_mark_node) |
33194 | decl = TYPE_NAME (decl); |
33195 | else |
33196 | decl = error_mark_node; |
33197 | |
33198 | /* If this is a declaration, but not a definition, associate |
33199 | any constraints with the type declaration. Constraints |
33200 | are associated with definitions in cp_parser_class_specifier. */ |
33201 | if (declares_class_or_enum == 1) |
33202 | associate_classtype_constraints (TREE_TYPE (decl)); |
33203 | |
33204 | /* Perform access checks for template parameters. */ |
33205 | cp_parser_perform_template_parameter_access_checks (checks); |
33206 | |
33207 | /* Give a helpful diagnostic for |
33208 | template <class T> struct A { } a; |
33209 | if we aren't already recovering from an error. */ |
33210 | if (!cp_parser_declares_only_class_p (parser) |
33211 | && !seen_error ()) |
33212 | { |
33213 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
33214 | "a class template declaration must not declare " |
33215 | "anything else" ); |
33216 | cp_parser_skip_to_end_of_block_or_statement (parser); |
33217 | goto out; |
33218 | } |
33219 | } |
33220 | } |
33221 | |
33222 | /* Complain about missing 'typename' or other invalid type names. */ |
33223 | if (!decl_specifiers.any_type_specifiers_p |
33224 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
33225 | { |
33226 | /* cp_parser_parse_and_diagnose_invalid_type_name calls |
33227 | cp_parser_skip_to_end_of_block_or_statement, so don't try to parse |
33228 | the rest of this declaration. */ |
33229 | decl = error_mark_node; |
33230 | goto out; |
33231 | } |
33232 | |
33233 | /* If it's not a template class, try for a template function. If |
33234 | the next token is a `;', then this declaration does not declare |
33235 | anything. But, if there were errors in the decl-specifiers, then |
33236 | the error might well have come from an attempted class-specifier. |
33237 | In that case, there's no need to warn about a missing declarator. */ |
33238 | if (!decl |
33239 | && (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON) |
33240 | || decl_specifiers.type != error_mark_node)) |
33241 | { |
33242 | int flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
33243 | /* We don't delay parsing for friends, though CWG 2510 may change |
33244 | that. */ |
33245 | if (member_p && !(friend_p && *friend_p)) |
33246 | flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
33247 | decl = cp_parser_init_declarator (parser, |
33248 | flags, |
33249 | decl_specifiers: &decl_specifiers, |
33250 | checks, |
33251 | /*function_definition_allowed_p=*/true, |
33252 | member_p, |
33253 | declares_class_or_enum, |
33254 | function_definition_p: &function_definition_p, |
33255 | NULL, NULL, NULL); |
33256 | |
33257 | /* 7.1.1-1 [dcl.stc] |
33258 | |
33259 | A storage-class-specifier shall not be specified in an explicit |
33260 | specialization... */ |
33261 | if (decl |
33262 | && explicit_specialization_p |
33263 | && decl_specifiers.storage_class != sc_none) |
33264 | { |
33265 | error_at (decl_spec_token_start->location, |
33266 | "explicit template specialization cannot have a storage class" ); |
33267 | decl = error_mark_node; |
33268 | } |
33269 | |
33270 | if (decl && VAR_P (decl)) |
33271 | check_template_variable (decl); |
33272 | } |
33273 | |
33274 | /* Look for a trailing `;' after the declaration. */ |
33275 | if (!function_definition_p |
33276 | && (decl == error_mark_node |
33277 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))) |
33278 | cp_parser_skip_to_end_of_block_or_statement (parser); |
33279 | |
33280 | out: |
33281 | pop_deferring_access_checks (); |
33282 | |
33283 | /* Clear any current qualification; whatever comes next is the start |
33284 | of something new. */ |
33285 | parser->scope = NULL_TREE; |
33286 | parser->qualifying_scope = NULL_TREE; |
33287 | parser->object_scope = NULL_TREE; |
33288 | |
33289 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
33290 | |
33291 | return decl; |
33292 | } |
33293 | |
33294 | /* Parse a cast-expression that is not the operand of a unary "&". */ |
33295 | |
33296 | static cp_expr |
33297 | cp_parser_simple_cast_expression (cp_parser *parser) |
33298 | { |
33299 | return cp_parser_cast_expression (parser, /*address_p=*/false, |
33300 | /*cast_p=*/false, /*decltype*/decltype_p: false, NULL); |
33301 | } |
33302 | |
33303 | /* Parse a functional cast to TYPE. Returns an expression |
33304 | representing the cast. */ |
33305 | |
33306 | static cp_expr |
33307 | cp_parser_functional_cast (cp_parser* parser, tree type) |
33308 | { |
33309 | vec<tree, va_gc> *vec; |
33310 | tree expression_list; |
33311 | cp_expr cast; |
33312 | |
33313 | location_t start_loc = input_location; |
33314 | |
33315 | if (!type) |
33316 | type = error_mark_node; |
33317 | |
33318 | if (TREE_CODE (type) == TYPE_DECL |
33319 | && is_auto (TREE_TYPE (type))) |
33320 | type = TREE_TYPE (type); |
33321 | |
33322 | if (is_auto (type) |
33323 | && !AUTO_IS_DECLTYPE (type) |
33324 | && !PLACEHOLDER_TYPE_CONSTRAINTS (type) |
33325 | && !CLASS_PLACEHOLDER_TEMPLATE (type)) |
33326 | /* auto(x) and auto{x} need to use a level-less auto. */ |
33327 | type = make_cast_auto (); |
33328 | |
33329 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
33330 | { |
33331 | cp_lexer_set_source_position (lexer: parser->lexer); |
33332 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
33333 | expression_list = cp_parser_braced_list (parser); |
33334 | CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; |
33335 | if (TREE_CODE (type) == TYPE_DECL) |
33336 | type = TREE_TYPE (type); |
33337 | |
33338 | cast = finish_compound_literal (type, expression_list, |
33339 | tf_warning_or_error, fcl_functional); |
33340 | /* Create a location of the form: |
33341 | type_name{i, f} |
33342 | ^~~~~~~~~~~~~~~ |
33343 | with caret == start at the start of the type name, |
33344 | finishing at the closing brace. */ |
33345 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
33346 | lexer: parser->lexer); |
33347 | cast.set_location (combined_loc); |
33348 | return cast; |
33349 | } |
33350 | |
33351 | |
33352 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
33353 | /*cast_p=*/true, |
33354 | /*allow_expansion_p=*/true, |
33355 | /*non_constant_p=*/NULL); |
33356 | if (vec == NULL) |
33357 | expression_list = error_mark_node; |
33358 | else |
33359 | { |
33360 | expression_list = build_tree_list_vec (vec); |
33361 | release_tree_vector (vec); |
33362 | } |
33363 | |
33364 | /* Create a location of the form: |
33365 | float(i) |
33366 | ^~~~~~~~ |
33367 | with caret == start at the start of the type name, |
33368 | finishing at the closing paren. */ |
33369 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
33370 | lexer: parser->lexer); |
33371 | cast = build_functional_cast (combined_loc, type, expression_list, |
33372 | tf_warning_or_error); |
33373 | |
33374 | /* [expr.const]/1: In an integral constant expression "only type |
33375 | conversions to integral or enumeration type can be used". */ |
33376 | if (TREE_CODE (type) == TYPE_DECL) |
33377 | type = TREE_TYPE (type); |
33378 | if (cast != error_mark_node |
33379 | && !cast_valid_in_integral_constant_expression_p (type) |
33380 | && cp_parser_non_integral_constant_expression (parser, |
33381 | thing: NIC_CONSTRUCTOR)) |
33382 | return error_mark_node; |
33383 | |
33384 | return cast; |
33385 | } |
33386 | |
33387 | /* Save the tokens that make up the body of a member function defined |
33388 | in a class-specifier. The DECL_SPECIFIERS and DECLARATOR have |
33389 | already been parsed. The ATTRIBUTES are any GNU "__attribute__" |
33390 | specifiers applied to the declaration. Returns the FUNCTION_DECL |
33391 | for the member function. */ |
33392 | |
33393 | static tree |
33394 | cp_parser_save_member_function_body (cp_parser* parser, |
33395 | cp_decl_specifier_seq *decl_specifiers, |
33396 | cp_declarator *declarator, |
33397 | tree attributes) |
33398 | { |
33399 | cp_token *first; |
33400 | cp_token *last; |
33401 | tree fn; |
33402 | bool function_try_block = false; |
33403 | |
33404 | /* Create the FUNCTION_DECL. */ |
33405 | fn = grokmethod (decl_specifiers, declarator, attributes); |
33406 | cp_finalize_omp_declare_simd (parser, fndecl: fn); |
33407 | cp_finalize_oacc_routine (parser, fn, true); |
33408 | /* If something went badly wrong, bail out now. */ |
33409 | if (fn == error_mark_node) |
33410 | { |
33411 | /* If there's a function-body, skip it. */ |
33412 | if (cp_parser_token_starts_function_definition_p |
33413 | (cp_lexer_peek_token (lexer: parser->lexer))) |
33414 | cp_parser_skip_to_end_of_block_or_statement (parser); |
33415 | return error_mark_node; |
33416 | } |
33417 | |
33418 | /* Remember it, if there are default args to post process. */ |
33419 | cp_parser_save_default_args (parser, fn); |
33420 | |
33421 | /* Save away the tokens that make up the body of the |
33422 | function. */ |
33423 | first = parser->lexer->next_token; |
33424 | |
33425 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRANSACTION_RELAXED)) |
33426 | cp_lexer_consume_token (lexer: parser->lexer); |
33427 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
33428 | keyword: RID_TRANSACTION_ATOMIC)) |
33429 | { |
33430 | cp_lexer_consume_token (lexer: parser->lexer); |
33431 | /* Match cp_parser_txn_attribute_opt [[ identifier ]]. */ |
33432 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE) |
33433 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_SQUARE) |
33434 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NAME) |
33435 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_KEYWORD)) |
33436 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_SQUARE) |
33437 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 5, type: CPP_CLOSE_SQUARE)) |
33438 | { |
33439 | cp_lexer_consume_token (lexer: parser->lexer); |
33440 | cp_lexer_consume_token (lexer: parser->lexer); |
33441 | cp_lexer_consume_token (lexer: parser->lexer); |
33442 | cp_lexer_consume_token (lexer: parser->lexer); |
33443 | cp_lexer_consume_token (lexer: parser->lexer); |
33444 | } |
33445 | else |
33446 | while (cp_next_tokens_can_be_gnu_attribute_p (parser) |
33447 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
33448 | { |
33449 | cp_lexer_consume_token (lexer: parser->lexer); |
33450 | if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) |
33451 | break; |
33452 | } |
33453 | } |
33454 | |
33455 | /* Handle function try blocks. */ |
33456 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
33457 | { |
33458 | cp_lexer_consume_token (lexer: parser->lexer); |
33459 | function_try_block = true; |
33460 | } |
33461 | /* We can have braced-init-list mem-initializers before the fn body. */ |
33462 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
33463 | { |
33464 | cp_lexer_consume_token (lexer: parser->lexer); |
33465 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
33466 | { |
33467 | /* cache_group will stop after an un-nested { } pair, too. */ |
33468 | if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) |
33469 | break; |
33470 | |
33471 | /* variadic mem-inits have ... after the ')'. */ |
33472 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
33473 | cp_lexer_consume_token (lexer: parser->lexer); |
33474 | } |
33475 | } |
33476 | cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); |
33477 | /* Handle function try blocks. */ |
33478 | if (function_try_block) |
33479 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CATCH)) |
33480 | cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); |
33481 | last = parser->lexer->next_token; |
33482 | |
33483 | /* Save away the inline definition; we will process it when the |
33484 | class is complete. */ |
33485 | DECL_PENDING_INLINE_INFO (fn) = cp_token_cache_new (first, last); |
33486 | DECL_PENDING_INLINE_P (fn) = 1; |
33487 | |
33488 | /* We need to know that this was defined in the class, so that |
33489 | friend templates are handled correctly. */ |
33490 | DECL_INITIALIZED_IN_CLASS_P (fn) = 1; |
33491 | |
33492 | /* Add FN to the queue of functions to be parsed later. */ |
33493 | vec_safe_push (unparsed_funs_with_definitions, obj: fn); |
33494 | |
33495 | return fn; |
33496 | } |
33497 | |
33498 | /* Save the tokens that make up the in-class initializer for a non-static |
33499 | data member. Returns a DEFERRED_PARSE. */ |
33500 | |
33501 | static tree |
33502 | cp_parser_save_nsdmi (cp_parser* parser) |
33503 | { |
33504 | return cp_parser_cache_defarg (parser, /*nsdmi=*/true); |
33505 | } |
33506 | |
33507 | /* Parse a template-argument-list, as well as the trailing ">" (but |
33508 | not the opening "<"). See cp_parser_template_argument_list for the |
33509 | return value. */ |
33510 | |
33511 | static tree |
33512 | cp_parser_enclosed_template_argument_list (cp_parser* parser) |
33513 | { |
33514 | tree arguments; |
33515 | tree saved_scope; |
33516 | tree saved_qualifying_scope; |
33517 | tree saved_object_scope; |
33518 | bool saved_greater_than_is_operator_p; |
33519 | |
33520 | /* [temp.names] |
33521 | |
33522 | When parsing a template-id, the first non-nested `>' is taken as |
33523 | the end of the template-argument-list rather than a greater-than |
33524 | operator. */ |
33525 | saved_greater_than_is_operator_p |
33526 | = parser->greater_than_is_operator_p; |
33527 | parser->greater_than_is_operator_p = false; |
33528 | /* Parsing the argument list may modify SCOPE, so we save it |
33529 | here. */ |
33530 | saved_scope = parser->scope; |
33531 | saved_qualifying_scope = parser->qualifying_scope; |
33532 | saved_object_scope = parser->object_scope; |
33533 | /* We need to evaluate the template arguments, even though this |
33534 | template-id may be nested within a "sizeof". */ |
33535 | cp_evaluated ev; |
33536 | /* Parse the template-argument-list itself. */ |
33537 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER) |
33538 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT) |
33539 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ) |
33540 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT_EQ)) |
33541 | { |
33542 | arguments = make_tree_vec (0); |
33543 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (arguments, 0); |
33544 | } |
33545 | else |
33546 | arguments = cp_parser_template_argument_list (parser); |
33547 | /* Look for the `>' that ends the template-argument-list. If we find |
33548 | a '>>' instead, it's probably just a typo. */ |
33549 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT)) |
33550 | { |
33551 | if (cxx_dialect != cxx98) |
33552 | { |
33553 | /* In C++0x, a `>>' in a template argument list or cast |
33554 | expression is considered to be two separate `>' |
33555 | tokens. So, change the current token to a `>', but don't |
33556 | consume it: it will be consumed later when the outer |
33557 | template argument list (or cast expression) is parsed. |
33558 | Note that this replacement of `>' for `>>' is necessary |
33559 | even if we are parsing tentatively: in the tentative |
33560 | case, after calling |
33561 | cp_parser_enclosed_template_argument_list we will always |
33562 | throw away all of the template arguments and the first |
33563 | closing `>', either because the template argument list |
33564 | was erroneous or because we are replacing those tokens |
33565 | with a CPP_TEMPLATE_ID token. The second `>' (which will |
33566 | not have been thrown away) is needed either to close an |
33567 | outer template argument list or to complete a new-style |
33568 | cast. */ |
33569 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33570 | token->type = CPP_GREATER; |
33571 | } |
33572 | else if (!saved_greater_than_is_operator_p) |
33573 | { |
33574 | /* If we're in a nested template argument list, the '>>' has |
33575 | to be a typo for '> >'. We emit the error message, but we |
33576 | continue parsing and we push a '>' as next token, so that |
33577 | the argument list will be parsed correctly. Note that the |
33578 | global source location is still on the token before the |
33579 | '>>', so we need to say explicitly where we want it. */ |
33580 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33581 | gcc_rich_location richloc (token->location); |
33582 | richloc.add_fixit_replace (new_content: "> >" ); |
33583 | error_at (&richloc, "%<>>%> should be %<> >%> " |
33584 | "within a nested template argument list" ); |
33585 | |
33586 | token->type = CPP_GREATER; |
33587 | } |
33588 | else |
33589 | { |
33590 | /* If this is not a nested template argument list, the '>>' |
33591 | is a typo for '>'. Emit an error message and continue. |
33592 | Same deal about the token location, but here we can get it |
33593 | right by consuming the '>>' before issuing the diagnostic. */ |
33594 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
33595 | error_at (token->location, |
33596 | "spurious %<>>%>, use %<>%> to terminate " |
33597 | "a template argument list" ); |
33598 | } |
33599 | } |
33600 | /* Similarly for >>= and >=. */ |
33601 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ) |
33602 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT_EQ)) |
33603 | { |
33604 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
33605 | gcc_rich_location richloc (token->location); |
33606 | enum cpp_ttype new_type; |
33607 | const char *replacement; |
33608 | if (token->type == CPP_GREATER_EQ) |
33609 | { |
33610 | replacement = "> =" ; |
33611 | new_type = CPP_EQ; |
33612 | } |
33613 | else if (!saved_greater_than_is_operator_p) |
33614 | { |
33615 | if (cxx_dialect != cxx98) |
33616 | replacement = ">> =" ; |
33617 | else |
33618 | replacement = "> > =" ; |
33619 | new_type = CPP_GREATER; |
33620 | } |
33621 | else |
33622 | { |
33623 | replacement = "> >=" ; |
33624 | new_type = CPP_GREATER_EQ; |
33625 | } |
33626 | richloc.add_fixit_replace (new_content: replacement); |
33627 | error_at (&richloc, "%qs should be %qs to terminate a template " |
33628 | "argument list" , |
33629 | cpp_type2name (token->type, flags: token->flags), replacement); |
33630 | token->type = new_type; |
33631 | } |
33632 | else |
33633 | cp_parser_require_end_of_template_parameter_list (parser); |
33634 | /* The `>' token might be a greater-than operator again now. */ |
33635 | parser->greater_than_is_operator_p |
33636 | = saved_greater_than_is_operator_p; |
33637 | /* Restore the SAVED_SCOPE. */ |
33638 | parser->scope = saved_scope; |
33639 | parser->qualifying_scope = saved_qualifying_scope; |
33640 | parser->object_scope = saved_object_scope; |
33641 | |
33642 | return arguments; |
33643 | } |
33644 | |
33645 | /* MEMBER_FUNCTION is a member function, or a friend. If default |
33646 | arguments, or the body of the function have not yet been parsed, |
33647 | parse them now. */ |
33648 | |
33649 | static void |
33650 | cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) |
33651 | { |
33652 | auto_timevar tv (TV_PARSE_INMETH); |
33653 | |
33654 | /* If this member is a template, get the underlying |
33655 | FUNCTION_DECL. */ |
33656 | if (DECL_FUNCTION_TEMPLATE_P (member_function)) |
33657 | member_function = DECL_TEMPLATE_RESULT (member_function); |
33658 | |
33659 | /* There should not be any class definitions in progress at this |
33660 | point; the bodies of members are only parsed outside of all class |
33661 | definitions. */ |
33662 | gcc_assert (parser->num_classes_being_defined == 0); |
33663 | /* While we're parsing the member functions we might encounter more |
33664 | classes. We want to handle them right away, but we don't want |
33665 | them getting mixed up with functions that are currently in the |
33666 | queue. */ |
33667 | push_unparsed_function_queues (parser); |
33668 | |
33669 | /* Make sure that any template parameters are in scope. */ |
33670 | maybe_begin_member_template_processing (member_function); |
33671 | |
33672 | /* If the body of the function has not yet been parsed, parse it |
33673 | now. Except if the tokens have been purged (PR c++/39751). */ |
33674 | if (DECL_PENDING_INLINE_P (member_function) |
33675 | && !DECL_PENDING_INLINE_INFO (member_function)->first->purged_p) |
33676 | { |
33677 | tree function_scope; |
33678 | cp_token_cache *tokens; |
33679 | |
33680 | /* The function is no longer pending; we are processing it. */ |
33681 | tokens = DECL_PENDING_INLINE_INFO (member_function); |
33682 | DECL_PENDING_INLINE_INFO (member_function) = NULL; |
33683 | DECL_PENDING_INLINE_P (member_function) = 0; |
33684 | |
33685 | /* If this is a local class, enter the scope of the containing |
33686 | function. */ |
33687 | function_scope = current_function_decl; |
33688 | if (function_scope) |
33689 | push_function_context (); |
33690 | |
33691 | /* Push the body of the function onto the lexer stack. */ |
33692 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
33693 | |
33694 | /* Let the front end know that we going to be defining this |
33695 | function. */ |
33696 | start_preparsed_function (member_function, NULL_TREE, |
33697 | SF_PRE_PARSED | SF_INCLASS_INLINE); |
33698 | |
33699 | /* #pragma omp declare reduction needs special parsing. */ |
33700 | if (DECL_OMP_DECLARE_REDUCTION_P (member_function)) |
33701 | { |
33702 | parser->lexer->in_pragma = true; |
33703 | cp_parser_omp_declare_reduction_exprs (member_function, parser); |
33704 | finish_function (/*inline_p=*/true); |
33705 | cp_check_omp_declare_reduction (member_function); |
33706 | } |
33707 | else |
33708 | /* Now, parse the body of the function. */ |
33709 | cp_parser_function_definition_after_declarator (parser, |
33710 | /*inline_p=*/true); |
33711 | |
33712 | /* Leave the scope of the containing function. */ |
33713 | if (function_scope) |
33714 | pop_function_context (); |
33715 | cp_parser_pop_lexer (parser); |
33716 | } |
33717 | |
33718 | /* Remove any template parameters from the symbol table. */ |
33719 | maybe_end_member_template_processing (); |
33720 | |
33721 | /* Restore the queue. */ |
33722 | pop_unparsed_function_queues (parser); |
33723 | } |
33724 | |
33725 | /* If DECL contains any default args, remember it on the unparsed |
33726 | functions queue. */ |
33727 | |
33728 | static void |
33729 | cp_parser_save_default_args (cp_parser* parser, tree decl) |
33730 | { |
33731 | tree probe; |
33732 | |
33733 | for (probe = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
33734 | probe; |
33735 | probe = TREE_CHAIN (probe)) |
33736 | if (TREE_PURPOSE (probe)) |
33737 | { |
33738 | cp_default_arg_entry entry = {current_class_type, .decl: decl}; |
33739 | vec_safe_push (unparsed_funs_with_default_args, obj: entry); |
33740 | break; |
33741 | } |
33742 | |
33743 | /* Remember if there is a noexcept-specifier to post process. */ |
33744 | tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); |
33745 | if (UNPARSED_NOEXCEPT_SPEC_P (spec)) |
33746 | vec_safe_push (unparsed_noexcepts, obj: decl); |
33747 | |
33748 | /* Contracts are deferred. */ |
33749 | for (tree attr = DECL_ATTRIBUTES (decl); attr; attr = TREE_CHAIN (attr)) |
33750 | if (cxx_contract_attribute_p (attr)) |
33751 | { |
33752 | vec_safe_push (unparsed_contracts, obj: decl); |
33753 | break; |
33754 | } |
33755 | } |
33756 | |
33757 | /* DEFAULT_ARG contains the saved tokens for the initializer of DECL, |
33758 | which is either a FIELD_DECL or PARM_DECL. Parse it and return |
33759 | the result. For a PARM_DECL, PARMTYPE is the corresponding type |
33760 | from the parameter-type-list. */ |
33761 | |
33762 | static tree |
33763 | cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, |
33764 | tree default_arg, tree parmtype) |
33765 | { |
33766 | cp_token_cache *tokens; |
33767 | tree parsed_arg; |
33768 | |
33769 | if (default_arg == error_mark_node) |
33770 | return error_mark_node; |
33771 | |
33772 | /* Push the saved tokens for the default argument onto the parser's |
33773 | lexer stack. */ |
33774 | tokens = DEFPARSE_TOKENS (default_arg); |
33775 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
33776 | |
33777 | start_lambda_scope (decl); |
33778 | |
33779 | /* Parse the default argument. */ |
33780 | parsed_arg = cp_parser_initializer (parser); |
33781 | if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)) |
33782 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
33783 | |
33784 | finish_lambda_scope (); |
33785 | |
33786 | if (parsed_arg == error_mark_node) |
33787 | cp_parser_skip_to_end_of_statement (parser); |
33788 | |
33789 | if (!processing_template_decl) |
33790 | { |
33791 | /* In a non-template class, check conversions now. In a template, |
33792 | we'll wait and instantiate these as needed. */ |
33793 | if (TREE_CODE (decl) == PARM_DECL) |
33794 | parsed_arg = check_default_argument (parmtype, parsed_arg, |
33795 | tf_warning_or_error); |
33796 | else if (maybe_reject_flexarray_init (decl, parsed_arg)) |
33797 | parsed_arg = error_mark_node; |
33798 | else |
33799 | parsed_arg = digest_nsdmi_init (decl, parsed_arg, tf_warning_or_error); |
33800 | } |
33801 | |
33802 | /* If the token stream has not been completely used up, then |
33803 | there was extra junk after the end of the default |
33804 | argument. */ |
33805 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
33806 | { |
33807 | if (TREE_CODE (decl) == PARM_DECL) |
33808 | cp_parser_error (parser, gmsgid: "expected %<,%>" ); |
33809 | else |
33810 | cp_parser_error (parser, gmsgid: "expected %<;%>" ); |
33811 | } |
33812 | |
33813 | /* Revert to the main lexer. */ |
33814 | cp_parser_pop_lexer (parser); |
33815 | |
33816 | return parsed_arg; |
33817 | } |
33818 | |
33819 | /* FIELD is a non-static data member with an initializer which we saved for |
33820 | later; parse it now. */ |
33821 | |
33822 | static void |
33823 | cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field) |
33824 | { |
33825 | tree def; |
33826 | |
33827 | maybe_begin_member_template_processing (field); |
33828 | |
33829 | push_unparsed_function_queues (parser); |
33830 | def = cp_parser_late_parse_one_default_arg (parser, decl: field, |
33831 | DECL_INITIAL (field), |
33832 | NULL_TREE); |
33833 | pop_unparsed_function_queues (parser); |
33834 | |
33835 | maybe_end_member_template_processing (); |
33836 | |
33837 | DECL_INITIAL (field) = def; |
33838 | } |
33839 | |
33840 | /* FN is a FUNCTION_DECL which may contains a parameter with an |
33841 | unparsed DEFERRED_PARSE. Parse the default args now. This function |
33842 | assumes that the current scope is the scope in which the default |
33843 | argument should be processed. */ |
33844 | |
33845 | static void |
33846 | cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) |
33847 | { |
33848 | unsigned char saved_local_variables_forbidden_p; |
33849 | |
33850 | /* While we're parsing the default args, we might (due to the |
33851 | statement expression extension) encounter more classes. We want |
33852 | to handle them right away, but we don't want them getting mixed |
33853 | up with default args that are currently in the queue. */ |
33854 | push_unparsed_function_queues (parser); |
33855 | |
33856 | /* Local variable names (and the `this' keyword) may not appear |
33857 | in a default argument. */ |
33858 | saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; |
33859 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
33860 | |
33861 | push_defarg_context (fn); |
33862 | |
33863 | begin_scope (sk_function_parms, fn); |
33864 | |
33865 | /* Gather the PARM_DECLs into a vec so we can keep track of them when |
33866 | pushdecl clears DECL_CHAIN. */ |
33867 | releasing_vec parms; |
33868 | for (tree parmdecl = DECL_ARGUMENTS (fn); parmdecl; |
33869 | parmdecl = DECL_CHAIN (parmdecl)) |
33870 | vec_safe_push (r&: parms, t: parmdecl); |
33871 | |
33872 | tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); |
33873 | for (int i = 0; |
33874 | parm && parm != void_list_node; |
33875 | parm = TREE_CHAIN (parm), |
33876 | ++i) |
33877 | { |
33878 | tree default_arg = TREE_PURPOSE (parm); |
33879 | tree parsed_arg; |
33880 | |
33881 | tree parmdecl = parms[i]; |
33882 | pushdecl (parmdecl); |
33883 | |
33884 | if (!default_arg) |
33885 | continue; |
33886 | |
33887 | if (TREE_CODE (default_arg) != DEFERRED_PARSE) |
33888 | /* This can happen for a friend declaration for a function |
33889 | already declared with default arguments. */ |
33890 | continue; |
33891 | |
33892 | parsed_arg |
33893 | = cp_parser_late_parse_one_default_arg (parser, decl: parmdecl, |
33894 | default_arg, |
33895 | TREE_VALUE (parm)); |
33896 | TREE_PURPOSE (parm) = parsed_arg; |
33897 | |
33898 | /* Update any instantiations we've already created. */ |
33899 | for (tree copy : DEFPARSE_INSTANTIATIONS (default_arg)) |
33900 | TREE_PURPOSE (copy) = parsed_arg; |
33901 | } |
33902 | |
33903 | pop_bindings_and_leave_scope (); |
33904 | |
33905 | /* Restore DECL_CHAINs after clobbering by pushdecl. */ |
33906 | parm = NULL_TREE; |
33907 | for (int i = parms->length () - 1; i >= 0; --i) |
33908 | { |
33909 | DECL_CHAIN (parms[i]) = parm; |
33910 | parm = parms[i]; |
33911 | } |
33912 | |
33913 | pop_defarg_context (); |
33914 | |
33915 | /* Make sure no default arg is missing. */ |
33916 | check_default_args (fn); |
33917 | |
33918 | /* Restore the state of local_variables_forbidden_p. */ |
33919 | parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; |
33920 | |
33921 | /* Restore the queue. */ |
33922 | pop_unparsed_function_queues (parser); |
33923 | } |
33924 | |
33925 | /* Subroutine of cp_parser_sizeof_operand, for handling C++11 |
33926 | |
33927 | sizeof ... ( identifier ) |
33928 | |
33929 | where the 'sizeof' token has already been consumed. */ |
33930 | |
33931 | static tree |
33932 | cp_parser_sizeof_pack (cp_parser *parser) |
33933 | { |
33934 | /* Consume the `...'. */ |
33935 | cp_lexer_consume_token (lexer: parser->lexer); |
33936 | maybe_warn_variadic_templates (); |
33937 | |
33938 | matching_parens parens; |
33939 | bool paren = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN); |
33940 | if (paren) |
33941 | parens.consume_open (parser); |
33942 | else |
33943 | permerror (cp_lexer_peek_token (lexer: parser->lexer)->location, |
33944 | "%<sizeof...%> argument must be surrounded by parentheses" ); |
33945 | |
33946 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33947 | tree name = cp_parser_identifier (parser); |
33948 | if (name == error_mark_node) |
33949 | return error_mark_node; |
33950 | /* The name is not qualified. */ |
33951 | parser->scope = NULL_TREE; |
33952 | parser->qualifying_scope = NULL_TREE; |
33953 | parser->object_scope = NULL_TREE; |
33954 | tree expr = cp_parser_lookup_name_simple (parser, name, location: token->location); |
33955 | if (expr == error_mark_node) |
33956 | cp_parser_name_lookup_error (parser, name, decl: expr, desired: NLE_NULL, |
33957 | location: token->location); |
33958 | if (TREE_CODE (expr) == TYPE_DECL || TREE_CODE (expr) == TEMPLATE_DECL) |
33959 | expr = TREE_TYPE (expr); |
33960 | else if (TREE_CODE (expr) == CONST_DECL) |
33961 | expr = DECL_INITIAL (expr); |
33962 | expr = make_pack_expansion (expr); |
33963 | if (expr != error_mark_node) |
33964 | PACK_EXPANSION_SIZEOF_P (expr) = true; |
33965 | |
33966 | if (paren) |
33967 | parens.require_close (parser); |
33968 | |
33969 | return expr; |
33970 | } |
33971 | |
33972 | /* Parse the operand of `sizeof' (or a similar operator). Returns |
33973 | either a TYPE or an expression, depending on the form of the |
33974 | input. The KEYWORD indicates which kind of expression we have |
33975 | encountered. */ |
33976 | |
33977 | static tree |
33978 | cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) |
33979 | { |
33980 | tree expr = NULL_TREE; |
33981 | const char *saved_message; |
33982 | const char *saved_message_arg; |
33983 | bool saved_integral_constant_expression_p; |
33984 | bool saved_non_integral_constant_expression_p; |
33985 | |
33986 | /* If it's a `...', then we are computing the length of a parameter |
33987 | pack. */ |
33988 | if (keyword == RID_SIZEOF |
33989 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
33990 | return cp_parser_sizeof_pack (parser); |
33991 | |
33992 | /* Types cannot be defined in a `sizeof' expression. Save away the |
33993 | old message. */ |
33994 | saved_message = parser->type_definition_forbidden_message; |
33995 | saved_message_arg = parser->type_definition_forbidden_message_arg; |
33996 | parser->type_definition_forbidden_message |
33997 | = G_("types may not be defined in %qs expressions" ); |
33998 | parser->type_definition_forbidden_message_arg |
33999 | = IDENTIFIER_POINTER (ridpointers[keyword]); |
34000 | |
34001 | /* The restrictions on constant-expressions do not apply inside |
34002 | sizeof expressions. */ |
34003 | saved_integral_constant_expression_p |
34004 | = parser->integral_constant_expression_p; |
34005 | saved_non_integral_constant_expression_p |
34006 | = parser->non_integral_constant_expression_p; |
34007 | parser->integral_constant_expression_p = false; |
34008 | |
34009 | auto cleanup = make_temp_override |
34010 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
34011 | |
34012 | /* Do not actually evaluate the expression. */ |
34013 | ++cp_unevaluated_operand; |
34014 | ++c_inhibit_evaluation_warnings; |
34015 | /* If it's a `(', then we might be looking at the type-id |
34016 | construction. */ |
34017 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
34018 | { |
34019 | tree type = NULL_TREE; |
34020 | |
34021 | tentative_firewall firewall (parser); |
34022 | |
34023 | /* We can't be sure yet whether we're looking at a type-id or an |
34024 | expression. */ |
34025 | cp_parser_parse_tentatively (parser); |
34026 | |
34027 | matching_parens parens; |
34028 | parens.consume_open (parser); |
34029 | |
34030 | /* Note: as a GNU Extension, compound literals are considered |
34031 | postfix-expressions as they are in C99, so they are valid |
34032 | arguments to sizeof. See comment in cp_parser_cast_expression |
34033 | for details. */ |
34034 | if (cp_parser_compound_literal_p (parser)) |
34035 | cp_parser_simulate_error (parser); |
34036 | else |
34037 | { |
34038 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
34039 | parser->in_type_id_in_expr_p = true; |
34040 | /* Look for the type-id. */ |
34041 | type = cp_parser_type_id (parser); |
34042 | /* Look for the closing `)'. */ |
34043 | parens.require_close (parser); |
34044 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
34045 | } |
34046 | |
34047 | /* If all went well, then we're done. */ |
34048 | if (cp_parser_parse_definitely (parser)) |
34049 | expr = type; |
34050 | else |
34051 | { |
34052 | /* Commit to the tentative_firewall so we get syntax errors. */ |
34053 | cp_parser_commit_to_tentative_parse (parser); |
34054 | |
34055 | expr = cp_parser_unary_expression (parser); |
34056 | } |
34057 | } |
34058 | else |
34059 | expr = cp_parser_unary_expression (parser); |
34060 | |
34061 | /* Go back to evaluating expressions. */ |
34062 | --cp_unevaluated_operand; |
34063 | --c_inhibit_evaluation_warnings; |
34064 | |
34065 | /* And restore the old one. */ |
34066 | parser->type_definition_forbidden_message = saved_message; |
34067 | parser->type_definition_forbidden_message_arg = saved_message_arg; |
34068 | parser->integral_constant_expression_p |
34069 | = saved_integral_constant_expression_p; |
34070 | parser->non_integral_constant_expression_p |
34071 | = saved_non_integral_constant_expression_p; |
34072 | |
34073 | return expr; |
34074 | } |
34075 | |
34076 | /* If the current declaration has no declarator, return true. */ |
34077 | |
34078 | static bool |
34079 | cp_parser_declares_only_class_p (cp_parser *parser) |
34080 | { |
34081 | /* If the next token is a `;' or a `,' then there is no |
34082 | declarator. */ |
34083 | return (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
34084 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
34085 | } |
34086 | |
34087 | /* Update the DECL_SPECS to reflect the storage class indicated by |
34088 | KEYWORD. */ |
34089 | |
34090 | static void |
34091 | cp_parser_set_storage_class (cp_parser *parser, |
34092 | cp_decl_specifier_seq *decl_specs, |
34093 | enum rid keyword, |
34094 | cp_token *token) |
34095 | { |
34096 | cp_storage_class storage_class; |
34097 | |
34098 | switch (keyword) |
34099 | { |
34100 | case RID_AUTO: |
34101 | storage_class = sc_auto; |
34102 | break; |
34103 | case RID_REGISTER: |
34104 | storage_class = sc_register; |
34105 | break; |
34106 | case RID_STATIC: |
34107 | storage_class = sc_static; |
34108 | break; |
34109 | case RID_EXTERN: |
34110 | storage_class = sc_extern; |
34111 | break; |
34112 | case RID_MUTABLE: |
34113 | storage_class = sc_mutable; |
34114 | break; |
34115 | default: |
34116 | gcc_unreachable (); |
34117 | } |
34118 | |
34119 | if (parser->in_unbraced_linkage_specification_p) |
34120 | { |
34121 | error_at (token->location, "invalid use of %qD in linkage specification" , |
34122 | ridpointers[keyword]); |
34123 | return; |
34124 | } |
34125 | else if (decl_specs->storage_class != sc_none) |
34126 | { |
34127 | if (decl_specs->conflicting_specifiers_p) |
34128 | return; |
34129 | gcc_rich_location richloc (token->location); |
34130 | richloc.add_location_if_nearby (loc: decl_specs->locations[ds_storage_class]); |
34131 | if (decl_specs->storage_class == storage_class) |
34132 | error_at (&richloc, "duplicate %qD specifier" , ridpointers[keyword]); |
34133 | else |
34134 | error_at (&richloc, |
34135 | "%qD specifier conflicts with %qs" , |
34136 | ridpointers[keyword], |
34137 | cp_storage_class_name[decl_specs->storage_class]); |
34138 | decl_specs->conflicting_specifiers_p = true; |
34139 | return; |
34140 | } |
34141 | |
34142 | if ((keyword == RID_EXTERN || keyword == RID_STATIC) |
34143 | && decl_spec_seq_has_spec_p (decl_specs, ds_thread) |
34144 | && decl_specs->gnu_thread_keyword_p) |
34145 | { |
34146 | pedwarn (decl_specs->locations[ds_thread], 0, |
34147 | "%<__thread%> before %qD" , ridpointers[keyword]); |
34148 | } |
34149 | |
34150 | decl_specs->storage_class = storage_class; |
34151 | set_and_check_decl_spec_loc (decl_specs, ds: ds_storage_class, token); |
34152 | |
34153 | /* A storage class specifier cannot be applied alongside a typedef |
34154 | specifier. If there is a typedef specifier present then set |
34155 | conflicting_specifiers_p which will trigger an error later |
34156 | on in grokdeclarator. */ |
34157 | if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) |
34158 | && !decl_specs->conflicting_specifiers_p) |
34159 | { |
34160 | gcc_rich_location richloc (token->location); |
34161 | richloc.add_location_if_nearby (loc: decl_specs->locations[ds_typedef]); |
34162 | error_at (&richloc, |
34163 | "%qD specifier conflicts with %<typedef%>" , |
34164 | ridpointers[keyword]); |
34165 | decl_specs->conflicting_specifiers_p = true; |
34166 | } |
34167 | } |
34168 | |
34169 | /* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P |
34170 | is true, the type is a class or enum definition. */ |
34171 | |
34172 | static void |
34173 | cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, |
34174 | tree type_spec, |
34175 | cp_token *token, |
34176 | bool type_definition_p) |
34177 | { |
34178 | decl_specs->any_specifiers_p = true; |
34179 | |
34180 | /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or |
34181 | wchar_t (with, for example, in "typedef int wchar_t;") we remember that |
34182 | this is what happened. In system headers, we ignore these |
34183 | declarations so that G++ can work with system headers that are not |
34184 | C++-safe. */ |
34185 | if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) |
34186 | && !type_definition_p |
34187 | && TYPE_P (type_spec) |
34188 | && (type_spec == boolean_type_node |
34189 | || type_spec == char8_type_node |
34190 | || type_spec == char16_type_node |
34191 | || type_spec == char32_type_node |
34192 | || extended_float_type_p (type: type_spec) |
34193 | || type_spec == wchar_type_node) |
34194 | && (decl_specs->type |
34195 | || decl_spec_seq_has_spec_p (decl_specs, ds_long) |
34196 | || decl_spec_seq_has_spec_p (decl_specs, ds_short) |
34197 | || decl_spec_seq_has_spec_p (decl_specs, ds_unsigned) |
34198 | || decl_spec_seq_has_spec_p (decl_specs, ds_signed))) |
34199 | { |
34200 | decl_specs->redefined_builtin_type = type_spec; |
34201 | set_and_check_decl_spec_loc (decl_specs, |
34202 | ds: ds_redefined_builtin_type_spec, |
34203 | token); |
34204 | if (!decl_specs->type) |
34205 | { |
34206 | decl_specs->type = type_spec; |
34207 | decl_specs->type_definition_p = false; |
34208 | set_and_check_decl_spec_loc (decl_specs,ds: ds_type_spec, token); |
34209 | } |
34210 | } |
34211 | else if (decl_specs->type) |
34212 | decl_specs->multiple_types_p = true; |
34213 | else |
34214 | { |
34215 | decl_specs->type = type_spec; |
34216 | decl_specs->type_definition_p = type_definition_p; |
34217 | decl_specs->redefined_builtin_type = NULL_TREE; |
34218 | set_and_check_decl_spec_loc (decl_specs, ds: ds_type_spec, token); |
34219 | } |
34220 | } |
34221 | |
34222 | /* True iff TOKEN is the GNU keyword __thread. */ |
34223 | |
34224 | static bool |
34225 | token_is__thread (cp_token *token) |
34226 | { |
34227 | gcc_assert (token->keyword == RID_THREAD); |
34228 | return id_equal (id: token->u.value, str: "__thread" ); |
34229 | } |
34230 | |
34231 | /* Set the location for a declarator specifier and check if it is |
34232 | duplicated. |
34233 | |
34234 | DECL_SPECS is the sequence of declarator specifiers onto which to |
34235 | set the location. |
34236 | |
34237 | DS is the single declarator specifier to set which location is to |
34238 | be set onto the existing sequence of declarators. |
34239 | |
34240 | LOCATION is the location for the declarator specifier to |
34241 | consider. */ |
34242 | |
34243 | static void |
34244 | set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs, |
34245 | cp_decl_spec ds, cp_token *token) |
34246 | { |
34247 | gcc_assert (ds < ds_last); |
34248 | |
34249 | if (decl_specs == NULL) |
34250 | return; |
34251 | |
34252 | location_t location = token->location; |
34253 | |
34254 | if (decl_specs->locations[ds] == 0) |
34255 | { |
34256 | decl_specs->locations[ds] = location; |
34257 | if (ds == ds_thread) |
34258 | decl_specs->gnu_thread_keyword_p = token_is__thread (token); |
34259 | } |
34260 | else |
34261 | { |
34262 | if (ds == ds_long) |
34263 | { |
34264 | if (decl_specs->locations[ds_long_long] != 0) |
34265 | error_at (location, |
34266 | "%<long long long%> is too long for GCC" ); |
34267 | else |
34268 | { |
34269 | decl_specs->locations[ds_long_long] = location; |
34270 | pedwarn_cxx98 (location, |
34271 | OPT_Wlong_long, |
34272 | "ISO C++ 1998 does not support %<long long%>" ); |
34273 | } |
34274 | } |
34275 | else if (ds == ds_thread) |
34276 | { |
34277 | bool gnu = token_is__thread (token); |
34278 | gcc_rich_location richloc (location); |
34279 | if (gnu != decl_specs->gnu_thread_keyword_p) |
34280 | { |
34281 | richloc.add_range (loc: decl_specs->locations[ds_thread]); |
34282 | error_at (&richloc, |
34283 | "both %<__thread%> and %<thread_local%> specified" ); |
34284 | } |
34285 | else |
34286 | { |
34287 | richloc.add_fixit_remove (); |
34288 | error_at (&richloc, "duplicate %qD" , token->u.value); |
34289 | } |
34290 | } |
34291 | else |
34292 | { |
34293 | /* These correspond to cp-tree.h:cp_decl_spec, |
34294 | changes here should also be reflected there. */ |
34295 | static const char *const decl_spec_names[] = { |
34296 | "signed" , |
34297 | "unsigned" , |
34298 | "short" , |
34299 | "long" , |
34300 | "const" , |
34301 | "volatile" , |
34302 | "restrict" , |
34303 | "inline" , |
34304 | "virtual" , |
34305 | "explicit" , |
34306 | "friend" , |
34307 | "typedef" , |
34308 | "using" , |
34309 | "constexpr" , |
34310 | "__complex" , |
34311 | "constinit" , |
34312 | "consteval" , |
34313 | "this" |
34314 | }; |
34315 | gcc_rich_location richloc (location); |
34316 | richloc.add_fixit_remove (); |
34317 | error_at (&richloc, "duplicate %qs" , decl_spec_names[ds]); |
34318 | } |
34319 | } |
34320 | } |
34321 | |
34322 | /* Return true iff the declarator specifier DS is present in the |
34323 | sequence of declarator specifiers DECL_SPECS. */ |
34324 | |
34325 | bool |
34326 | decl_spec_seq_has_spec_p (const cp_decl_specifier_seq * decl_specs, |
34327 | cp_decl_spec ds) |
34328 | { |
34329 | gcc_assert (ds < ds_last); |
34330 | |
34331 | if (decl_specs == NULL) |
34332 | return false; |
34333 | |
34334 | return decl_specs->locations[ds] != 0; |
34335 | } |
34336 | |
34337 | /* DECL_SPECIFIERS is the representation of a decl-specifier-seq. |
34338 | Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */ |
34339 | |
34340 | static bool |
34341 | cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers) |
34342 | { |
34343 | return decl_spec_seq_has_spec_p (decl_specs: decl_specifiers, ds: ds_friend); |
34344 | } |
34345 | |
34346 | /* Issue an error message indicating that TOKEN_DESC was expected. |
34347 | If KEYWORD is true, it indicated this function is called by |
34348 | cp_parser_require_keword and the required token can only be |
34349 | a indicated keyword. |
34350 | |
34351 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it |
34352 | within any error as the location of an "opening" token matching |
34353 | the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is |
34354 | RT_CLOSE_PAREN). */ |
34355 | |
34356 | static void |
34357 | cp_parser_required_error (cp_parser *parser, |
34358 | required_token token_desc, |
34359 | bool keyword, |
34360 | location_t matching_location) |
34361 | { |
34362 | if (cp_parser_simulate_error (parser)) |
34363 | return; |
34364 | |
34365 | const char *gmsgid = NULL; |
34366 | switch (token_desc) |
34367 | { |
34368 | case RT_NEW: |
34369 | gmsgid = G_("expected %<new%>" ); |
34370 | break; |
34371 | case RT_DELETE: |
34372 | gmsgid = G_("expected %<delete%>" ); |
34373 | break; |
34374 | case RT_RETURN: |
34375 | gmsgid = G_("expected %<return%>" ); |
34376 | break; |
34377 | case RT_WHILE: |
34378 | gmsgid = G_("expected %<while%>" ); |
34379 | break; |
34380 | case RT_EXTERN: |
34381 | gmsgid = G_("expected %<extern%>" ); |
34382 | break; |
34383 | case RT_STATIC_ASSERT: |
34384 | gmsgid = G_("expected %<static_assert%>" ); |
34385 | break; |
34386 | case RT_DECLTYPE: |
34387 | gmsgid = G_("expected %<decltype%>" ); |
34388 | break; |
34389 | case RT_OPERATOR: |
34390 | gmsgid = G_("expected %<operator%>" ); |
34391 | break; |
34392 | case RT_CLASS: |
34393 | gmsgid = G_("expected %<class%>" ); |
34394 | break; |
34395 | case RT_TEMPLATE: |
34396 | gmsgid = G_("expected %<template%>" ); |
34397 | break; |
34398 | case RT_NAMESPACE: |
34399 | gmsgid = G_("expected %<namespace%>" ); |
34400 | break; |
34401 | case RT_USING: |
34402 | gmsgid = G_("expected %<using%>" ); |
34403 | break; |
34404 | case RT_ASM: |
34405 | gmsgid = G_("expected %<asm%>" ); |
34406 | break; |
34407 | case RT_TRY: |
34408 | gmsgid = G_("expected %<try%>" ); |
34409 | break; |
34410 | case RT_CATCH: |
34411 | gmsgid = G_("expected %<catch%>" ); |
34412 | break; |
34413 | case RT_THROW: |
34414 | gmsgid = G_("expected %<throw%>" ); |
34415 | break; |
34416 | case RT_AUTO: |
34417 | gmsgid = G_("expected %<auto%>" ); |
34418 | break; |
34419 | case RT_LABEL: |
34420 | gmsgid = G_("expected %<__label__%>" ); |
34421 | break; |
34422 | case RT_AT_TRY: |
34423 | gmsgid = G_("expected %<@try%>" ); |
34424 | break; |
34425 | case RT_AT_SYNCHRONIZED: |
34426 | gmsgid = G_("expected %<@synchronized%>" ); |
34427 | break; |
34428 | case RT_AT_THROW: |
34429 | gmsgid = G_("expected %<@throw%>" ); |
34430 | break; |
34431 | case RT_TRANSACTION_ATOMIC: |
34432 | gmsgid = G_("expected %<__transaction_atomic%>" ); |
34433 | break; |
34434 | case RT_TRANSACTION_RELAXED: |
34435 | gmsgid = G_("expected %<__transaction_relaxed%>" ); |
34436 | break; |
34437 | case RT_CO_YIELD: |
34438 | gmsgid = G_("expected %<co_yield%>" ); |
34439 | break; |
34440 | default: |
34441 | break; |
34442 | } |
34443 | |
34444 | if (!gmsgid && !keyword) |
34445 | { |
34446 | switch (token_desc) |
34447 | { |
34448 | case RT_SEMICOLON: |
34449 | gmsgid = G_("expected %<;%>" ); |
34450 | break; |
34451 | case RT_OPEN_PAREN: |
34452 | gmsgid = G_("expected %<(%>" ); |
34453 | break; |
34454 | case RT_CLOSE_BRACE: |
34455 | gmsgid = G_("expected %<}%>" ); |
34456 | break; |
34457 | case RT_OPEN_BRACE: |
34458 | gmsgid = G_("expected %<{%>" ); |
34459 | break; |
34460 | case RT_CLOSE_SQUARE: |
34461 | gmsgid = G_("expected %<]%>" ); |
34462 | break; |
34463 | case RT_OPEN_SQUARE: |
34464 | gmsgid = G_("expected %<[%>" ); |
34465 | break; |
34466 | case RT_COMMA: |
34467 | gmsgid = G_("expected %<,%>" ); |
34468 | break; |
34469 | case RT_SCOPE: |
34470 | gmsgid = G_("expected %<::%>" ); |
34471 | break; |
34472 | case RT_LESS: |
34473 | gmsgid = G_("expected %<<%>" ); |
34474 | break; |
34475 | case RT_GREATER: |
34476 | gmsgid = G_("expected %<>%>" ); |
34477 | break; |
34478 | case RT_EQ: |
34479 | gmsgid = G_("expected %<=%>" ); |
34480 | break; |
34481 | case RT_ELLIPSIS: |
34482 | gmsgid = G_("expected %<...%>" ); |
34483 | break; |
34484 | case RT_MULT: |
34485 | gmsgid = G_("expected %<*%>" ); |
34486 | break; |
34487 | case RT_COMPL: |
34488 | gmsgid = G_("expected %<~%>" ); |
34489 | break; |
34490 | case RT_COLON: |
34491 | gmsgid = G_("expected %<:%>" ); |
34492 | break; |
34493 | case RT_COLON_SCOPE: |
34494 | gmsgid = G_("expected %<:%> or %<::%>" ); |
34495 | break; |
34496 | case RT_CLOSE_PAREN: |
34497 | gmsgid = G_("expected %<)%>" ); |
34498 | break; |
34499 | case RT_COMMA_CLOSE_PAREN: |
34500 | gmsgid = G_("expected %<,%> or %<)%>" ); |
34501 | break; |
34502 | case RT_PRAGMA_EOL: |
34503 | gmsgid = G_("expected end of line" ); |
34504 | break; |
34505 | case RT_NAME: |
34506 | gmsgid = G_("expected identifier" ); |
34507 | break; |
34508 | case RT_SELECT: |
34509 | gmsgid = G_("expected selection-statement" ); |
34510 | break; |
34511 | case RT_ITERATION: |
34512 | gmsgid = G_("expected iteration-statement" ); |
34513 | break; |
34514 | case RT_JUMP: |
34515 | gmsgid = G_("expected jump-statement" ); |
34516 | break; |
34517 | case RT_CLASS_KEY: |
34518 | gmsgid = G_("expected class-key" ); |
34519 | break; |
34520 | case RT_CLASS_TYPENAME_TEMPLATE: |
34521 | gmsgid = G_("expected %<class%>, %<typename%>, or %<template%>" ); |
34522 | break; |
34523 | default: |
34524 | gcc_unreachable (); |
34525 | } |
34526 | } |
34527 | |
34528 | if (gmsgid) |
34529 | cp_parser_error_1 (parser, gmsgid, missing_token_desc: token_desc, matching_location); |
34530 | } |
34531 | |
34532 | |
34533 | /* If the next token is of the indicated TYPE, consume it. Otherwise, |
34534 | issue an error message indicating that TOKEN_DESC was expected. |
34535 | |
34536 | Returns the token consumed, if the token had the appropriate type. |
34537 | Otherwise, returns NULL. |
34538 | |
34539 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it |
34540 | within any error as the location of an "opening" token matching |
34541 | the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is |
34542 | RT_CLOSE_PAREN). */ |
34543 | |
34544 | static cp_token * |
34545 | cp_parser_require (cp_parser* parser, |
34546 | enum cpp_ttype type, |
34547 | required_token token_desc, |
34548 | location_t matching_location) |
34549 | { |
34550 | if (cp_lexer_next_token_is (lexer: parser->lexer, type)) |
34551 | return cp_lexer_consume_token (lexer: parser->lexer); |
34552 | else |
34553 | { |
34554 | /* Output the MESSAGE -- unless we're parsing tentatively. */ |
34555 | if (!cp_parser_simulate_error (parser)) |
34556 | cp_parser_required_error (parser, token_desc, /*keyword=*/false, |
34557 | matching_location); |
34558 | return NULL; |
34559 | } |
34560 | } |
34561 | |
34562 | /* Skip an entire parameter list from start to finish. The next token must |
34563 | be the initial "<" of the parameter list. Returns true on success and |
34564 | false otherwise. */ |
34565 | |
34566 | static bool |
34567 | cp_parser_skip_entire_template_parameter_list (cp_parser* parser) |
34568 | { |
34569 | /* Consume the "<" because cp_parser_skip_to_end_of_template_parameter_list |
34570 | requires it. */ |
34571 | cp_lexer_consume_token (lexer: parser->lexer); |
34572 | return cp_parser_skip_to_end_of_template_parameter_list (parser); |
34573 | } |
34574 | |
34575 | /* Ensure we are at the end of a template parameter list. If we are, return. |
34576 | If we are not, something has gone wrong, in which case issue an error and |
34577 | skip to end of the parameter list. */ |
34578 | |
34579 | static void |
34580 | cp_parser_require_end_of_template_parameter_list (cp_parser* parser) |
34581 | { |
34582 | /* Are we ready, yet? If not, issue error message. */ |
34583 | if (cp_parser_require (parser, type: CPP_GREATER, token_desc: RT_GREATER)) |
34584 | return; |
34585 | |
34586 | cp_parser_skip_to_end_of_template_parameter_list (parser); |
34587 | } |
34588 | |
34589 | /* You should only call this function from inside a template parameter list |
34590 | (i.e. the current token should at least be the initial "<" of the |
34591 | parameter list). If you are skipping the entire list, it may be better to |
34592 | use cp_parser_skip_entire_template_parameter_list. |
34593 | |
34594 | Tokens are skipped until the final ">" is found, or if we see |
34595 | '{', '}', ';', or if we find an unbalanced ')' or ']'. |
34596 | |
34597 | Returns true if we successfully reached the end, and false if |
34598 | something unexpected happened (e.g. end of file). */ |
34599 | |
34600 | static bool |
34601 | cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser) |
34602 | { |
34603 | /* Current level of '< ... >'. */ |
34604 | unsigned level = 0; |
34605 | /* Ignore '<' and '>' nested inside '( ... )' or '[ ... ]'. */ |
34606 | unsigned nesting_depth = 0; |
34607 | |
34608 | /* Skip tokens until the desired token is found. */ |
34609 | while (true) |
34610 | { |
34611 | /* Peek at the next token. */ |
34612 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
34613 | { |
34614 | case CPP_LESS: |
34615 | if (!nesting_depth) |
34616 | ++level; |
34617 | break; |
34618 | |
34619 | case CPP_RSHIFT: |
34620 | if (cxx_dialect == cxx98) |
34621 | /* C++0x views the `>>' operator as two `>' tokens, but |
34622 | C++98 does not. */ |
34623 | break; |
34624 | else if (!nesting_depth && level-- == 0) |
34625 | { |
34626 | /* We've hit a `>>' where the first `>' closes the |
34627 | template argument list, and the second `>' is |
34628 | spurious. Just consume the `>>' and stop; we've |
34629 | already produced at least one error. */ |
34630 | cp_lexer_consume_token (lexer: parser->lexer); |
34631 | return false; |
34632 | } |
34633 | /* Fall through for C++0x, so we handle the second `>' in |
34634 | the `>>'. */ |
34635 | gcc_fallthrough (); |
34636 | |
34637 | case CPP_GREATER: |
34638 | if (!nesting_depth && level-- == 0) |
34639 | { |
34640 | /* We've reached the token we want, consume it and stop. */ |
34641 | cp_lexer_consume_token (lexer: parser->lexer); |
34642 | return true; |
34643 | } |
34644 | break; |
34645 | |
34646 | case CPP_OPEN_PAREN: |
34647 | case CPP_OPEN_SQUARE: |
34648 | ++nesting_depth; |
34649 | break; |
34650 | |
34651 | case CPP_CLOSE_PAREN: |
34652 | case CPP_CLOSE_SQUARE: |
34653 | if (nesting_depth-- == 0) |
34654 | return false; |
34655 | break; |
34656 | |
34657 | case CPP_EOF: |
34658 | case CPP_PRAGMA_EOL: |
34659 | case CPP_SEMICOLON: |
34660 | case CPP_OPEN_BRACE: |
34661 | case CPP_CLOSE_BRACE: |
34662 | /* The '>' was probably forgotten, don't look further. */ |
34663 | return false; |
34664 | |
34665 | default: |
34666 | break; |
34667 | } |
34668 | |
34669 | /* Consume this token. */ |
34670 | cp_lexer_consume_token (lexer: parser->lexer); |
34671 | } |
34672 | } |
34673 | |
34674 | /* If the next token is the indicated keyword, consume it. Otherwise, |
34675 | issue an error message indicating that TOKEN_DESC was expected. |
34676 | |
34677 | Returns the token consumed, if the token had the appropriate type. |
34678 | Otherwise, returns NULL. */ |
34679 | |
34680 | static cp_token * |
34681 | cp_parser_require_keyword (cp_parser* parser, |
34682 | enum rid keyword, |
34683 | required_token token_desc) |
34684 | { |
34685 | cp_token *token = cp_parser_require (parser, type: CPP_KEYWORD, token_desc); |
34686 | |
34687 | if (token && token->keyword != keyword) |
34688 | { |
34689 | cp_parser_required_error (parser, token_desc, /*keyword=*/true, |
34690 | UNKNOWN_LOCATION); |
34691 | return NULL; |
34692 | } |
34693 | |
34694 | return token; |
34695 | } |
34696 | |
34697 | /* Returns TRUE iff TOKEN is a token that can begin the body of a |
34698 | function-definition. */ |
34699 | |
34700 | static bool |
34701 | cp_parser_token_starts_function_definition_p (cp_token* token) |
34702 | { |
34703 | return (/* An ordinary function-body begins with an `{'. */ |
34704 | token->type == CPP_OPEN_BRACE |
34705 | /* A ctor-initializer begins with a `:'. */ |
34706 | || token->type == CPP_COLON |
34707 | /* A function-try-block begins with `try'. */ |
34708 | || token->keyword == RID_TRY |
34709 | /* A function-transaction-block begins with `__transaction_atomic' |
34710 | or `__transaction_relaxed'. */ |
34711 | || token->keyword == RID_TRANSACTION_ATOMIC |
34712 | || token->keyword == RID_TRANSACTION_RELAXED |
34713 | /* The named return value extension begins with `return'. */ |
34714 | || token->keyword == RID_RETURN); |
34715 | } |
34716 | |
34717 | /* Returns TRUE iff the next token is the ":" or "{" beginning a class |
34718 | definition. */ |
34719 | |
34720 | static bool |
34721 | cp_parser_next_token_starts_class_definition_p (cp_parser *parser) |
34722 | { |
34723 | cp_token *token; |
34724 | |
34725 | token = cp_lexer_peek_token (lexer: parser->lexer); |
34726 | return (token->type == CPP_OPEN_BRACE |
34727 | || (token->type == CPP_COLON |
34728 | && !parser->colon_doesnt_start_class_def_p)); |
34729 | } |
34730 | |
34731 | /* Returns TRUE iff the next token is the "," or ">" (or `>>', in |
34732 | C++0x) ending a template-argument. */ |
34733 | |
34734 | static bool |
34735 | cp_parser_next_token_ends_template_argument_p (cp_parser *parser) |
34736 | { |
34737 | cp_token *token; |
34738 | |
34739 | token = cp_lexer_peek_token (lexer: parser->lexer); |
34740 | return (token->type == CPP_COMMA |
34741 | || token->type == CPP_GREATER |
34742 | || token->type == CPP_ELLIPSIS |
34743 | || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT) |
34744 | /* For better diagnostics, treat >>= like that too, that |
34745 | shouldn't appear non-nested in template arguments. */ |
34746 | || token->type == CPP_RSHIFT_EQ); |
34747 | } |
34748 | |
34749 | /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the |
34750 | (n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */ |
34751 | |
34752 | static bool |
34753 | cp_parser_nth_token_starts_template_argument_list_p (cp_parser * parser, |
34754 | size_t n) |
34755 | { |
34756 | cp_token *token; |
34757 | |
34758 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
34759 | if (token->type == CPP_LESS) |
34760 | return true; |
34761 | /* Check for the sequence `<::' in the original code. It would be lexed as |
34762 | `[:', where `[' is a digraph, and there is no whitespace before |
34763 | `:'. */ |
34764 | if (token->type == CPP_OPEN_SQUARE && token->flags & DIGRAPH) |
34765 | { |
34766 | cp_token *token2; |
34767 | token2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n+1); |
34768 | if (token2->type == CPP_COLON && !(token2->flags & PREV_WHITE)) |
34769 | return true; |
34770 | } |
34771 | return false; |
34772 | } |
34773 | |
34774 | /* Returns the kind of tag indicated by TOKEN, if it is a class-key, |
34775 | or none_type otherwise. */ |
34776 | |
34777 | static enum tag_types |
34778 | cp_parser_token_is_class_key (cp_token* token) |
34779 | { |
34780 | switch (token->keyword) |
34781 | { |
34782 | case RID_CLASS: |
34783 | return class_type; |
34784 | case RID_STRUCT: |
34785 | return record_type; |
34786 | case RID_UNION: |
34787 | return union_type; |
34788 | |
34789 | default: |
34790 | return none_type; |
34791 | } |
34792 | } |
34793 | |
34794 | /* Returns the kind of tag indicated by TOKEN, if it is a type-parameter-key, |
34795 | or none_type otherwise or if the token is null. */ |
34796 | |
34797 | static enum tag_types |
34798 | cp_parser_token_is_type_parameter_key (cp_token* token) |
34799 | { |
34800 | if (!token) |
34801 | return none_type; |
34802 | |
34803 | switch (token->keyword) |
34804 | { |
34805 | case RID_CLASS: |
34806 | return class_type; |
34807 | case RID_TYPENAME: |
34808 | return typename_type; |
34809 | |
34810 | default: |
34811 | return none_type; |
34812 | } |
34813 | } |
34814 | |
34815 | /* Diagnose redundant enum-keys. */ |
34816 | |
34817 | static void |
34818 | cp_parser_maybe_warn_enum_key (cp_parser *parser, location_t key_loc, |
34819 | tree type, rid scoped_key) |
34820 | { |
34821 | if (!warn_redundant_tags) |
34822 | return; |
34823 | |
34824 | tree type_decl = TYPE_MAIN_DECL (type); |
34825 | tree name = DECL_NAME (type_decl); |
34826 | /* Look up the NAME to see if it unambiguously refers to the TYPE. */ |
34827 | push_deferring_access_checks (dk_no_check); |
34828 | tree decl = cp_parser_lookup_name_simple (parser, name, location: input_location); |
34829 | pop_deferring_access_checks (); |
34830 | |
34831 | /* The enum-key is redundant for uses of the TYPE that are not |
34832 | declarations and for which name lookup returns just the type |
34833 | itself. */ |
34834 | if (decl != type_decl) |
34835 | return; |
34836 | |
34837 | if (scoped_key != RID_CLASS |
34838 | && scoped_key != RID_STRUCT |
34839 | && current_lang_name != lang_name_cplusplus |
34840 | && current_namespace == global_namespace) |
34841 | { |
34842 | /* Avoid issuing the diagnostic for apparently redundant (unscoped) |
34843 | enum tag in shared C/C++ code in files (such as headers) included |
34844 | in the main source file. */ |
34845 | const line_map_ordinary *map = NULL; |
34846 | linemap_resolve_location (line_table, loc: key_loc, |
34847 | lrk: LRK_MACRO_DEFINITION_LOCATION, |
34848 | loc_map: &map); |
34849 | if (!MAIN_FILE_P (ord_map: map)) |
34850 | return; |
34851 | } |
34852 | |
34853 | gcc_rich_location richloc (key_loc); |
34854 | richloc.add_fixit_remove (where: key_loc); |
34855 | warning_at (&richloc, OPT_Wredundant_tags, |
34856 | "redundant enum-key %<enum%s%> in reference to %q#T" , |
34857 | (scoped_key == RID_CLASS ? " class" |
34858 | : scoped_key == RID_STRUCT ? " struct" : "" ), type); |
34859 | } |
34860 | |
34861 | /* Describes the set of declarations of a struct, class, or class template |
34862 | or its specializations. Used for -Wmismatched-tags. */ |
34863 | |
34864 | class class_decl_loc_t |
34865 | { |
34866 | public: |
34867 | |
34868 | class_decl_loc_t () |
34869 | : locvec (), idxdef (), def_class_key () |
34870 | { |
34871 | locvec.create (nelems: 4); |
34872 | } |
34873 | |
34874 | /* Constructs an object for a single declaration of a class with |
34875 | CLASS_KEY at the current location in the current function (or |
34876 | at another scope). KEY_REDUNDANT is true if the class-key may |
34877 | be omitted in the current context without an ambiguity with |
34878 | another symbol with the same name. |
34879 | DEF_P is true for a class declaration that is a definition. |
34880 | CURLOC is the associated location. */ |
34881 | class_decl_loc_t (tag_types class_key, bool key_redundant, bool def_p, |
34882 | location_t curloc = input_location) |
34883 | : locvec (), idxdef (def_p ? 0 : UINT_MAX), def_class_key (class_key) |
34884 | { |
34885 | locvec.create (nelems: 4); |
34886 | class_key_loc_t ckl (current_function_decl, curloc, class_key, |
34887 | key_redundant); |
34888 | locvec.quick_push (obj: ckl); |
34889 | } |
34890 | |
34891 | /* Copy, assign, and destroy the object. Necessary because LOCVEC |
34892 | isn't safely copyable and assignable and doesn't release storage |
34893 | on its own. */ |
34894 | class_decl_loc_t (const class_decl_loc_t &rhs) |
34895 | : locvec (rhs.locvec.copy ()), idxdef (rhs.idxdef), |
34896 | def_class_key (rhs.def_class_key) |
34897 | { } |
34898 | |
34899 | class_decl_loc_t& operator= (const class_decl_loc_t &rhs) |
34900 | { |
34901 | if (this == &rhs) |
34902 | return *this; |
34903 | locvec.release (); |
34904 | locvec = rhs.locvec.copy (); |
34905 | idxdef = rhs.idxdef; |
34906 | def_class_key = rhs.def_class_key; |
34907 | return *this; |
34908 | } |
34909 | |
34910 | ~class_decl_loc_t () |
34911 | { |
34912 | locvec.release (); |
34913 | } |
34914 | |
34915 | /* Issues -Wmismatched-tags for a single class. */ |
34916 | void diag_mismatched_tags (tree); |
34917 | |
34918 | /* Issues -Wmismatched-tags for all classes. */ |
34919 | static void diag_mismatched_tags (); |
34920 | |
34921 | /* Adds TYPE_DECL to the collection of class decls and diagnoses |
34922 | redundant tags (if -Wredundant-tags is enabled). */ |
34923 | static void add (cp_parser *, location_t, tag_types, tree, bool, bool); |
34924 | |
34925 | /* Either adds this decl to the collection of class decls |
34926 | or diagnoses it, whichever is appropriate. */ |
34927 | void add_or_diag_mismatched_tag (tree, tag_types, bool, bool); |
34928 | |
34929 | private: |
34930 | |
34931 | tree function (unsigned i) const |
34932 | { |
34933 | return locvec[i].func; |
34934 | } |
34935 | |
34936 | location_t location (unsigned i) const |
34937 | { |
34938 | return locvec[i].loc; |
34939 | } |
34940 | |
34941 | bool key_redundant (unsigned i) const |
34942 | { |
34943 | return locvec[i].key_redundant; |
34944 | } |
34945 | |
34946 | tag_types class_key (unsigned i) const |
34947 | { |
34948 | return locvec[i].class_key; |
34949 | } |
34950 | |
34951 | /* True if a definition for the class has been seen. */ |
34952 | bool def_p () const |
34953 | { |
34954 | return idxdef < locvec.length (); |
34955 | } |
34956 | |
34957 | /* The location of a single mention of a class type with the given |
34958 | class-key. */ |
34959 | struct class_key_loc_t |
34960 | { |
34961 | class_key_loc_t (tree func, location_t loc, tag_types key, bool redundant) |
34962 | : func (func), loc (loc), class_key (key), key_redundant (redundant) |
34963 | { } |
34964 | |
34965 | /* The function the type is mentioned in. */ |
34966 | tree func; |
34967 | /* The exact location. */ |
34968 | location_t loc; |
34969 | /* The class-key used in the mention of the type. */ |
34970 | tag_types class_key; |
34971 | /* True when the class-key could be omitted at this location |
34972 | without an ambiguity with another symbol of the same name. */ |
34973 | bool key_redundant; |
34974 | }; |
34975 | /* Avoid using auto_vec here since it's not safe to copy due to pr90904. */ |
34976 | vec <class_key_loc_t> locvec; |
34977 | /* LOCVEC index of the definition or UINT_MAX if none exists. */ |
34978 | unsigned idxdef; |
34979 | /* The class-key the class was last declared with or none_type when |
34980 | it has been declared with a mismatched key. */ |
34981 | tag_types def_class_key; |
34982 | |
34983 | /* A mapping between a TYPE_DECL for a class and the class_decl_loc_t |
34984 | description above. */ |
34985 | typedef hash_map<tree_decl_hash, class_decl_loc_t> class_to_loc_map_t; |
34986 | static class_to_loc_map_t class2loc; |
34987 | }; |
34988 | |
34989 | class_decl_loc_t::class_to_loc_map_t class_decl_loc_t::class2loc; |
34990 | |
34991 | /* Issue an error message if the CLASS_KEY does not match the TYPE. |
34992 | DEF_P is expected to be set for a definition of class TYPE. DECL_P |
34993 | is set for a declaration of class TYPE and clear for a reference to |
34994 | it that is not a declaration of it. */ |
34995 | |
34996 | static void |
34997 | cp_parser_check_class_key (cp_parser *parser, location_t key_loc, |
34998 | tag_types class_key, tree type, bool def_p, |
34999 | bool decl_p) |
35000 | { |
35001 | if (type == error_mark_node) |
35002 | return; |
35003 | |
35004 | bool seen_as_union = TREE_CODE (type) == UNION_TYPE; |
35005 | if (seen_as_union != (class_key == union_type)) |
35006 | { |
35007 | if (permerror (input_location, "%qs tag used in naming %q#T" , |
35008 | class_key == union_type ? "union" |
35009 | : class_key == record_type ? "struct" : "class" , |
35010 | type)) |
35011 | inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), |
35012 | "%q#T was previously declared here" , type); |
35013 | return; |
35014 | } |
35015 | |
35016 | if (!warn_mismatched_tags && !warn_redundant_tags) |
35017 | return; |
35018 | |
35019 | /* Only consider the true class-keys below and ignore typename_type, |
35020 | etc. that are not C++ class-keys. */ |
35021 | if (class_key != class_type |
35022 | && class_key != record_type |
35023 | && class_key != union_type) |
35024 | return; |
35025 | |
35026 | class_decl_loc_t::add (parser, key_loc, class_key, type, def_p, decl_p); |
35027 | } |
35028 | |
35029 | /* Returns the template or specialization of one to which the RECORD_TYPE |
35030 | TYPE corresponds. */ |
35031 | |
35032 | static tree |
35033 | specialization_of (tree type) |
35034 | { |
35035 | tree ret = type; |
35036 | |
35037 | /* Determine the template or its partial specialization to which TYPE |
35038 | corresponds. */ |
35039 | if (tree ti = most_specialized_partial_spec (type, tf_none)) |
35040 | if (ti != error_mark_node) |
35041 | ret = TREE_TYPE (TI_TEMPLATE (ti)); |
35042 | |
35043 | if (ret == type) |
35044 | ret = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (type); |
35045 | |
35046 | return TYPE_MAIN_DECL (ret); |
35047 | } |
35048 | |
35049 | |
35050 | /* Adds the class TYPE to the collection of class decls and diagnoses |
35051 | redundant tags (if -Wredundant-tags is enabled). |
35052 | DEF_P is expected to be set for a definition of class TYPE. DECL_P |
35053 | is set for a (likely, based on syntactic context) declaration of class |
35054 | TYPE and clear for a reference to it that is not a declaration of it. */ |
35055 | |
35056 | void |
35057 | class_decl_loc_t::add (cp_parser *parser, location_t key_loc, |
35058 | tag_types class_key, tree type, bool def_p, bool decl_p) |
35059 | { |
35060 | tree type_decl = TYPE_MAIN_DECL (type); |
35061 | tree name = DECL_NAME (type_decl); |
35062 | /* Look up the NAME to see if it unambiguously refers to the TYPE |
35063 | and set KEY_REDUNDANT if so. */ |
35064 | push_deferring_access_checks (dk_no_check); |
35065 | tree decl = cp_parser_lookup_name_simple (parser, name, location: input_location); |
35066 | pop_deferring_access_checks (); |
35067 | |
35068 | /* The class-key is redundant for uses of the CLASS_TYPE that are |
35069 | neither definitions of it nor declarations, and for which name |
35070 | lookup returns just the type itself. */ |
35071 | bool key_redundant = (!def_p && !decl_p |
35072 | && (decl == type_decl |
35073 | || TREE_CODE (decl) == TEMPLATE_DECL |
35074 | || (CLASS_TYPE_P (type) |
35075 | && TYPE_BEING_DEFINED (type)))); |
35076 | |
35077 | if (key_redundant |
35078 | && class_key != class_type |
35079 | && current_lang_name != lang_name_cplusplus |
35080 | && current_namespace == global_namespace) |
35081 | { |
35082 | /* Avoid issuing the diagnostic for apparently redundant struct |
35083 | and union class-keys in shared C/C++ code in files (such as |
35084 | headers) included in the main source file. */ |
35085 | const line_map_ordinary *map = NULL; |
35086 | linemap_resolve_location (line_table, loc: key_loc, |
35087 | lrk: LRK_MACRO_DEFINITION_LOCATION, |
35088 | loc_map: &map); |
35089 | if (!MAIN_FILE_P (ord_map: map)) |
35090 | key_redundant = false; |
35091 | } |
35092 | |
35093 | /* Set if a declaration of TYPE has previously been seen or if it must |
35094 | exist in a precompiled header. */ |
35095 | bool exist; |
35096 | class_decl_loc_t *rdl = &class2loc.get_or_insert (k: type_decl, existed: &exist); |
35097 | if (!exist) |
35098 | { |
35099 | tree type = TREE_TYPE (type_decl); |
35100 | if (def_p || !COMPLETE_TYPE_P (type)) |
35101 | { |
35102 | /* TYPE_DECL is the first declaration or definition of the type |
35103 | (outside precompiled headers -- see below). Just create |
35104 | a new entry for it and return unless it's a declaration |
35105 | involving a template that may need to be diagnosed by |
35106 | -Wredundant-tags. */ |
35107 | *rdl = class_decl_loc_t (class_key, false, def_p); |
35108 | if (TREE_CODE (decl) != TEMPLATE_DECL) |
35109 | return; |
35110 | } |
35111 | else |
35112 | { |
35113 | /* TYPE was previously defined in some unknown precompiled header. |
35114 | Simply add a record of its definition at an unknown location and |
35115 | proceed below to add a reference to it at the current location. |
35116 | (Declarations in precompiled headers that are not definitions |
35117 | are ignored.) */ |
35118 | tag_types def_key |
35119 | = CLASSTYPE_DECLARED_CLASS (type) ? class_type : record_type; |
35120 | location_t def_loc = DECL_SOURCE_LOCATION (type_decl); |
35121 | *rdl = class_decl_loc_t (def_key, false, true, def_loc); |
35122 | exist = true; |
35123 | } |
35124 | } |
35125 | |
35126 | /* A prior declaration of TYPE_DECL has been seen. */ |
35127 | |
35128 | if (key_redundant) |
35129 | { |
35130 | gcc_rich_location richloc (key_loc); |
35131 | richloc.add_fixit_remove (where: key_loc); |
35132 | warning_at (&richloc, OPT_Wredundant_tags, |
35133 | "redundant class-key %qs in reference to %q#T" , |
35134 | class_key == union_type ? "union" |
35135 | : class_key == record_type ? "struct" : "class" , |
35136 | type); |
35137 | } |
35138 | |
35139 | if (!exist) |
35140 | /* Do nothing if this is the first declaration of the type. */ |
35141 | return; |
35142 | |
35143 | if (rdl->idxdef != UINT_MAX && rdl->def_class_key == class_key) |
35144 | /* Do nothing if the class-key in this declaration matches |
35145 | the definition. */ |
35146 | return; |
35147 | |
35148 | rdl->add_or_diag_mismatched_tag (type_decl, class_key, key_redundant, |
35149 | def_p); |
35150 | } |
35151 | |
35152 | /* Either adds this DECL corresponding to the TYPE_DECL to the collection |
35153 | of class decls or diagnoses it, whichever is appropriate. */ |
35154 | |
35155 | void |
35156 | class_decl_loc_t::add_or_diag_mismatched_tag (tree type_decl, |
35157 | tag_types class_key, |
35158 | bool redundant, |
35159 | bool def_p) |
35160 | { |
35161 | /* Reset the CLASS_KEY associated with this type on mismatch. |
35162 | This is an optimization that lets the diagnostic code skip |
35163 | over classes that use the same class-key in all declarations. */ |
35164 | if (def_class_key != class_key) |
35165 | def_class_key = none_type; |
35166 | |
35167 | /* Set IDXDEF to the index of the vector corresponding to |
35168 | the definition. */ |
35169 | if (def_p) |
35170 | idxdef = locvec.length (); |
35171 | |
35172 | /* Append a record of this declaration to the vector. */ |
35173 | class_key_loc_t ckl (current_function_decl, input_location, class_key, |
35174 | redundant); |
35175 | locvec.safe_push (obj: ckl); |
35176 | |
35177 | if (idxdef == UINT_MAX) |
35178 | return; |
35179 | |
35180 | /* As a space optimization diagnose declarations of a class |
35181 | whose definition has been seen and purge the LOCVEC of |
35182 | all entries except the definition. */ |
35183 | diag_mismatched_tags (type_decl); |
35184 | if (idxdef) |
35185 | { |
35186 | class_decl_loc_t::class_key_loc_t ent = locvec[idxdef]; |
35187 | locvec.release (); |
35188 | locvec.reserve (nelems: 2); |
35189 | locvec.safe_push (obj: ent); |
35190 | idxdef = 0; |
35191 | } |
35192 | else |
35193 | /* Pop the entry pushed above for this declaration. */ |
35194 | locvec.pop (); |
35195 | } |
35196 | |
35197 | /* Issues -Wmismatched-tags for a single class. */ |
35198 | |
35199 | void |
35200 | class_decl_loc_t::diag_mismatched_tags (tree type_decl) |
35201 | { |
35202 | if (!warn_mismatched_tags) |
35203 | return; |
35204 | |
35205 | /* Number of uses of the class. */ |
35206 | const unsigned ndecls = locvec.length (); |
35207 | |
35208 | /* The class (or template) declaration guiding the decisions about |
35209 | the diagnostic. For ordinary classes it's the same as THIS. For |
35210 | uses of instantiations of templates other than their declarations |
35211 | it points to the record for the declaration of the corresponding |
35212 | primary template or partial specialization. */ |
35213 | class_decl_loc_t *cdlguide = this; |
35214 | |
35215 | tree type = TREE_TYPE (type_decl); |
35216 | if (CLASS_TYPE_P (type) && CLASSTYPE_IMPLICIT_INSTANTIATION (type)) |
35217 | { |
35218 | /* For implicit instantiations of a primary template look up |
35219 | the primary or partial specialization and use it as |
35220 | the expected class-key rather than using the class-key of |
35221 | the first reference to the instantiation. The primary must |
35222 | be (and inevitably is) at index zero. */ |
35223 | tree spec = specialization_of (type); |
35224 | cdlguide = class2loc.get (k: spec); |
35225 | /* It's possible that we didn't find SPEC. Consider: |
35226 | |
35227 | template<typename T> struct A { |
35228 | template<typename U> struct W { }; |
35229 | }; |
35230 | struct A<int>::W<int> w; // #1 |
35231 | |
35232 | where while parsing A and #1 we've stashed |
35233 | A<T> |
35234 | A<T>::W<U> |
35235 | A<int>::W<int> |
35236 | into CLASS2LOC. If TYPE is A<int>::W<int>, specialization_of |
35237 | will yield A<int>::W<U> which may be in CLASS2LOC if we had |
35238 | an A<int> class specialization, but otherwise won't be in it. |
35239 | So try to look up A<T>::W<U>. */ |
35240 | if (!cdlguide) |
35241 | { |
35242 | spec = DECL_TEMPLATE_RESULT (most_general_template (spec)); |
35243 | cdlguide = class2loc.get (k: spec); |
35244 | } |
35245 | /* Now we really should have found something. */ |
35246 | gcc_assert (cdlguide != NULL); |
35247 | } |
35248 | /* Skip declarations that consistently use the same class-key. */ |
35249 | else if (def_class_key != none_type) |
35250 | return; |
35251 | |
35252 | /* Set if a definition for the class has been seen. */ |
35253 | const bool def_p = cdlguide->def_p (); |
35254 | |
35255 | /* The index of the declaration whose class-key this declaration |
35256 | is expected to match. It's either the class-key of the class |
35257 | definition if one exists or the first declaration otherwise. */ |
35258 | const unsigned idxguide = def_p ? cdlguide->idxdef : 0; |
35259 | |
35260 | /* The class-key the class is expected to be declared with: it's |
35261 | either the key used in its definition or the first declaration |
35262 | if no definition has been provided. |
35263 | For implicit instantiations of a primary template it's |
35264 | the class-key used to declare the primary with. The primary |
35265 | must be at index zero. */ |
35266 | const tag_types xpect_key = cdlguide->class_key (i: idxguide); |
35267 | |
35268 | unsigned idx = 0; |
35269 | /* Advance IDX to the first declaration that either is not |
35270 | a definition or that doesn't match the first declaration |
35271 | if no definition is provided. */ |
35272 | while (class_key (i: idx) == xpect_key) |
35273 | if (++idx == ndecls) |
35274 | return; |
35275 | |
35276 | /* Save the current function before changing it below. */ |
35277 | tree save_func = current_function_decl; |
35278 | /* Set the function declaration to print in diagnostic context. */ |
35279 | current_function_decl = function (i: idx); |
35280 | |
35281 | const char *xmatchkstr = xpect_key == record_type ? "class" : "struct" ; |
35282 | const char *xpectkstr = xpect_key == record_type ? "struct" : "class" ; |
35283 | |
35284 | location_t loc = location (i: idx); |
35285 | bool key_redundant_p = key_redundant (i: idx); |
35286 | auto_diagnostic_group d; |
35287 | /* Issue a warning for the first mismatched declaration. |
35288 | Avoid using "%#qT" since the class-key for the same type will |
35289 | be the same regardless of which one was used in the declaraion. */ |
35290 | if (warning_at (loc, OPT_Wmismatched_tags, |
35291 | "%qT declared with a mismatched class-key %qs" , |
35292 | type_decl, xmatchkstr)) |
35293 | { |
35294 | /* Suggest how to avoid the warning for each instance since |
35295 | the guidance may be different depending on context. */ |
35296 | inform (loc, |
35297 | (key_redundant_p |
35298 | ? G_("remove the class-key or replace it with %qs" ) |
35299 | : G_("replace the class-key with %qs" )), |
35300 | xpectkstr); |
35301 | |
35302 | /* Also point to the first declaration or definition that guided |
35303 | the decision to issue the warning above. */ |
35304 | inform (cdlguide->location (i: idxguide), |
35305 | (def_p |
35306 | ? G_("%qT defined as %qs here" ) |
35307 | : G_("%qT first declared as %qs here" )), |
35308 | type_decl, xpectkstr); |
35309 | } |
35310 | |
35311 | /* Issue warnings for the remaining inconsistent declarations. */ |
35312 | for (unsigned i = idx + 1; i != ndecls; ++i) |
35313 | { |
35314 | tag_types clskey = class_key (i); |
35315 | /* Skip over the declarations that match either the definition |
35316 | if one was provided or the first declaration. */ |
35317 | if (clskey == xpect_key) |
35318 | continue; |
35319 | |
35320 | loc = location (i); |
35321 | key_redundant_p = key_redundant (i); |
35322 | /* Set the function declaration to print in diagnostic context. */ |
35323 | current_function_decl = function (i); |
35324 | if (warning_at (loc, OPT_Wmismatched_tags, |
35325 | "%qT declared with a mismatched class-key %qs" , |
35326 | type_decl, xmatchkstr)) |
35327 | /* Suggest how to avoid the warning for each instance since |
35328 | the guidance may be different depending on context. */ |
35329 | inform (loc, |
35330 | (key_redundant_p |
35331 | ? G_("remove the class-key or replace it with %qs" ) |
35332 | : G_("replace the class-key with %qs" )), |
35333 | xpectkstr); |
35334 | } |
35335 | |
35336 | /* Restore the current function in case it was replaced above. */ |
35337 | current_function_decl = save_func; |
35338 | } |
35339 | |
35340 | /* Issues -Wmismatched-tags for all classes. Called at the end |
35341 | of processing a translation unit, after declarations of all class |
35342 | types and their uses have been recorded. */ |
35343 | |
35344 | void |
35345 | class_decl_loc_t::diag_mismatched_tags () |
35346 | { |
35347 | /* CLASS2LOC should be empty if both -Wmismatched-tags and |
35348 | -Wredundant-tags are disabled. */ |
35349 | gcc_assert (warn_mismatched_tags |
35350 | || warn_redundant_tags |
35351 | || class2loc.is_empty ()); |
35352 | |
35353 | /* Save the current function before changing on return. It should |
35354 | be null at this point. */ |
35355 | temp_override<tree> cleanup (current_function_decl); |
35356 | |
35357 | if (warn_mismatched_tags) |
35358 | { |
35359 | /* Iterate over the collected class/struct/template declarations. */ |
35360 | typedef class_to_loc_map_t::iterator iter_t; |
35361 | for (iter_t it = class2loc.begin (); it != class2loc.end (); ++it) |
35362 | { |
35363 | tree type_decl = (*it).first; |
35364 | class_decl_loc_t &recloc = (*it).second; |
35365 | recloc.diag_mismatched_tags (type_decl); |
35366 | } |
35367 | } |
35368 | |
35369 | class2loc.empty (); |
35370 | } |
35371 | |
35372 | /* Issue an error message if DECL is redeclared with different |
35373 | access than its original declaration [class.access.spec/3]. |
35374 | This applies to nested classes, nested class templates and |
35375 | enumerations [class.mem/1]. */ |
35376 | |
35377 | static void |
35378 | cp_parser_check_access_in_redeclaration (tree decl, location_t location) |
35379 | { |
35380 | if (!decl |
35381 | || (!(CLASS_TYPE_P (TREE_TYPE (decl)) |
35382 | && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) |
35383 | && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)) |
35384 | return; |
35385 | |
35386 | if ((TREE_PRIVATE (decl) |
35387 | != (current_access_specifier == access_private_node)) |
35388 | || (TREE_PROTECTED (decl) |
35389 | != (current_access_specifier == access_protected_node))) |
35390 | error_at (location, "%qD redeclared with different access" , decl); |
35391 | } |
35392 | |
35393 | /* Look for the `template' keyword, as a syntactic disambiguator. |
35394 | Return TRUE iff it is present, in which case it will be |
35395 | consumed. */ |
35396 | |
35397 | static bool |
35398 | cp_parser_optional_template_keyword (cp_parser *parser) |
35399 | { |
35400 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
35401 | { |
35402 | /* In C++98 the `template' keyword can only be used within templates; |
35403 | outside templates the parser can always figure out what is a |
35404 | template and what is not. In C++11, per the resolution of DR 468, |
35405 | `template' is allowed in cases where it is not strictly necessary. */ |
35406 | if (!processing_template_decl |
35407 | && pedantic && cxx_dialect == cxx98) |
35408 | { |
35409 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
35410 | pedwarn (token->location, OPT_Wpedantic, |
35411 | "in C++98 %<template%> (as a disambiguator) is only " |
35412 | "allowed within templates" ); |
35413 | /* If this part of the token stream is rescanned, the same |
35414 | error message would be generated. So, we purge the token |
35415 | from the stream. */ |
35416 | cp_lexer_purge_token (lexer: parser->lexer); |
35417 | return false; |
35418 | } |
35419 | else |
35420 | { |
35421 | /* Consume the `template' keyword. */ |
35422 | cp_lexer_consume_token (lexer: parser->lexer); |
35423 | return true; |
35424 | } |
35425 | } |
35426 | return false; |
35427 | } |
35428 | |
35429 | /* The next token is a CPP_NESTED_NAME_SPECIFIER. Consume the token, |
35430 | set PARSER->SCOPE, and perform other related actions. */ |
35431 | |
35432 | static void |
35433 | cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser) |
35434 | { |
35435 | struct tree_check *check_value; |
35436 | |
35437 | /* Get the stored value. */ |
35438 | check_value = cp_lexer_consume_token (lexer: parser->lexer)->u.tree_check_value; |
35439 | /* Set the scope from the stored value. */ |
35440 | parser->scope = saved_checks_value (check_value); |
35441 | parser->qualifying_scope = check_value->qualifying_scope; |
35442 | parser->object_scope = parser->context->object_type; |
35443 | parser->context->object_type = NULL_TREE; |
35444 | } |
35445 | |
35446 | /* Consume tokens up through a non-nested END token. Returns TRUE if we |
35447 | encounter the end of a block before what we were looking for. */ |
35448 | |
35449 | static bool |
35450 | cp_parser_cache_group (cp_parser *parser, |
35451 | enum cpp_ttype end, |
35452 | unsigned depth) |
35453 | { |
35454 | while (true) |
35455 | { |
35456 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
35457 | |
35458 | /* Abort a parenthesized expression if we encounter a semicolon. */ |
35459 | if ((end == CPP_CLOSE_PAREN || depth == 0) |
35460 | && token->type == CPP_SEMICOLON) |
35461 | return true; |
35462 | /* If we've reached the end of the file, stop. */ |
35463 | if (token->type == CPP_EOF |
35464 | || (end != CPP_PRAGMA_EOL |
35465 | && token->type == CPP_PRAGMA_EOL)) |
35466 | return true; |
35467 | if (token->type == CPP_CLOSE_BRACE && depth == 0) |
35468 | /* We've hit the end of an enclosing block, so there's been some |
35469 | kind of syntax error. */ |
35470 | return true; |
35471 | |
35472 | /* Consume the token. */ |
35473 | cp_lexer_consume_token (lexer: parser->lexer); |
35474 | /* See if it starts a new group. */ |
35475 | if (token->type == CPP_OPEN_BRACE) |
35476 | { |
35477 | cp_parser_cache_group (parser, end: CPP_CLOSE_BRACE, depth: depth + 1); |
35478 | /* In theory this should probably check end == '}', but |
35479 | cp_parser_save_member_function_body needs it to exit |
35480 | after either '}' or ')' when called with ')'. */ |
35481 | if (depth == 0) |
35482 | return false; |
35483 | } |
35484 | else if (token->type == CPP_OPEN_PAREN) |
35485 | { |
35486 | cp_parser_cache_group (parser, end: CPP_CLOSE_PAREN, depth: depth + 1); |
35487 | if (depth == 0 && end == CPP_CLOSE_PAREN) |
35488 | return false; |
35489 | } |
35490 | else if (token->type == CPP_PRAGMA) |
35491 | cp_parser_cache_group (parser, end: CPP_PRAGMA_EOL, depth: depth + 1); |
35492 | else if (token->type == end) |
35493 | return false; |
35494 | } |
35495 | } |
35496 | |
35497 | /* Like above, for caching a default argument or NSDMI. Both of these are |
35498 | terminated by a non-nested comma, but it can be unclear whether or not a |
35499 | comma is nested in a template argument list unless we do more parsing. |
35500 | In order to handle this ambiguity, when we encounter a ',' after a '<' |
35501 | we try to parse what follows as a parameter-declaration-list (in the |
35502 | case of a default argument) or a member-declarator (in the case of an |
35503 | NSDMI). If that succeeds, then we stop caching. */ |
35504 | |
35505 | static tree |
35506 | cp_parser_cache_defarg (cp_parser *parser, bool nsdmi) |
35507 | { |
35508 | unsigned depth = 0; |
35509 | int maybe_template_id = 0; |
35510 | cp_token *first_token; |
35511 | cp_token *token; |
35512 | tree default_argument; |
35513 | |
35514 | /* Add tokens until we have processed the entire default |
35515 | argument. We add the range [first_token, token). */ |
35516 | first_token = cp_lexer_peek_token (lexer: parser->lexer); |
35517 | if (first_token->type == CPP_OPEN_BRACE) |
35518 | { |
35519 | /* For list-initialization, this is straightforward. */ |
35520 | cp_parser_cache_group (parser, end: CPP_CLOSE_BRACE, /*depth=*/0); |
35521 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35522 | } |
35523 | else while (true) |
35524 | { |
35525 | bool done = false; |
35526 | |
35527 | /* Peek at the next token. */ |
35528 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35529 | /* What we do depends on what token we have. */ |
35530 | switch (token->type) |
35531 | { |
35532 | /* In valid code, a default argument must be |
35533 | immediately followed by a `,' `)', or `...'. */ |
35534 | case CPP_COMMA: |
35535 | if (depth == 0 && maybe_template_id) |
35536 | { |
35537 | /* If we've seen a '<', we might be in a |
35538 | template-argument-list. Until Core issue 325 is |
35539 | resolved, we don't know how this situation ought |
35540 | to be handled, so try to DTRT. We check whether |
35541 | what comes after the comma is a valid parameter |
35542 | declaration list. If it is, then the comma ends |
35543 | the default argument; otherwise the default |
35544 | argument continues. */ |
35545 | bool error = false; |
35546 | cp_token *peek; |
35547 | |
35548 | /* Set ITALP so cp_parser_parameter_declaration_list |
35549 | doesn't decide to commit to this parse. */ |
35550 | bool saved_italp = parser->in_template_argument_list_p; |
35551 | parser->in_template_argument_list_p = true; |
35552 | |
35553 | cp_parser_parse_tentatively (parser); |
35554 | |
35555 | if (nsdmi) |
35556 | { |
35557 | /* Parse declarators until we reach a non-comma or |
35558 | somthing that cannot be an initializer. |
35559 | Just checking whether we're looking at a single |
35560 | declarator is insufficient. Consider: |
35561 | int var = tuple<T,U>::x; |
35562 | The template parameter 'U' looks exactly like a |
35563 | declarator. */ |
35564 | do |
35565 | { |
35566 | int ctor_dtor_or_conv_p; |
35567 | cp_lexer_consume_token (lexer: parser->lexer); |
35568 | cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
35569 | flags: CP_PARSER_FLAGS_NONE, |
35570 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
35571 | /*parenthesized_p=*/NULL, |
35572 | /*member_p=*/true, |
35573 | /*friend_p=*/false, |
35574 | /*static_p=*/false); |
35575 | peek = cp_lexer_peek_token (lexer: parser->lexer); |
35576 | if (cp_parser_error_occurred (parser)) |
35577 | break; |
35578 | } |
35579 | while (peek->type == CPP_COMMA); |
35580 | /* If we met an '=' or ';' then the original comma |
35581 | was the end of the NSDMI. Otherwise assume |
35582 | we're still in the NSDMI. */ |
35583 | error = (peek->type != CPP_EQ |
35584 | && peek->type != CPP_SEMICOLON); |
35585 | } |
35586 | else |
35587 | { |
35588 | cp_lexer_consume_token (lexer: parser->lexer); |
35589 | begin_scope (sk_function_parms, NULL_TREE); |
35590 | tree t = cp_parser_parameter_declaration_list |
35591 | (parser, flags: CP_PARSER_FLAGS_NONE, |
35592 | /*pending_decls*/nullptr); |
35593 | if (t == error_mark_node) |
35594 | error = true; |
35595 | pop_bindings_and_leave_scope (); |
35596 | } |
35597 | if (!cp_parser_error_occurred (parser) && !error) |
35598 | done = true; |
35599 | cp_parser_abort_tentative_parse (parser); |
35600 | |
35601 | parser->in_template_argument_list_p = saved_italp; |
35602 | break; |
35603 | } |
35604 | /* FALLTHRU */ |
35605 | case CPP_CLOSE_PAREN: |
35606 | case CPP_ELLIPSIS: |
35607 | /* If we run into a non-nested `;', `}', or `]', |
35608 | then the code is invalid -- but the default |
35609 | argument is certainly over. */ |
35610 | case CPP_SEMICOLON: |
35611 | case CPP_CLOSE_BRACE: |
35612 | case CPP_CLOSE_SQUARE: |
35613 | if (depth == 0 |
35614 | /* Handle correctly int n = sizeof ... ( p ); */ |
35615 | && token->type != CPP_ELLIPSIS) |
35616 | done = true; |
35617 | /* Update DEPTH, if necessary. */ |
35618 | else if (token->type == CPP_CLOSE_PAREN |
35619 | || token->type == CPP_CLOSE_BRACE |
35620 | || token->type == CPP_CLOSE_SQUARE) |
35621 | --depth; |
35622 | break; |
35623 | |
35624 | case CPP_OPEN_PAREN: |
35625 | case CPP_OPEN_SQUARE: |
35626 | case CPP_OPEN_BRACE: |
35627 | ++depth; |
35628 | break; |
35629 | |
35630 | case CPP_LESS: |
35631 | if (depth == 0) |
35632 | /* This might be the comparison operator, or it might |
35633 | start a template argument list. */ |
35634 | ++maybe_template_id; |
35635 | break; |
35636 | |
35637 | case CPP_RSHIFT: |
35638 | if (cxx_dialect == cxx98) |
35639 | break; |
35640 | /* Fall through for C++0x, which treats the `>>' |
35641 | operator like two `>' tokens in certain |
35642 | cases. */ |
35643 | gcc_fallthrough (); |
35644 | |
35645 | case CPP_GREATER: |
35646 | if (depth == 0) |
35647 | { |
35648 | /* This might be an operator, or it might close a |
35649 | template argument list. But if a previous '<' |
35650 | started a template argument list, this will have |
35651 | closed it, so we can't be in one anymore. */ |
35652 | maybe_template_id -= 1 + (token->type == CPP_RSHIFT); |
35653 | if (maybe_template_id < 0) |
35654 | maybe_template_id = 0; |
35655 | } |
35656 | break; |
35657 | |
35658 | /* If we run out of tokens, issue an error message. */ |
35659 | case CPP_EOF: |
35660 | case CPP_PRAGMA_EOL: |
35661 | error_at (token->location, "file ends in default argument" ); |
35662 | return error_mark_node; |
35663 | |
35664 | case CPP_NAME: |
35665 | case CPP_SCOPE: |
35666 | /* In these cases, we should look for template-ids. |
35667 | For example, if the default argument is |
35668 | `X<int, double>()', we need to do name lookup to |
35669 | figure out whether or not `X' is a template; if |
35670 | so, the `,' does not end the default argument. |
35671 | |
35672 | That is not yet done. */ |
35673 | break; |
35674 | |
35675 | default: |
35676 | break; |
35677 | } |
35678 | |
35679 | /* If we've reached the end, stop. */ |
35680 | if (done) |
35681 | break; |
35682 | |
35683 | /* Add the token to the token block. */ |
35684 | token = cp_lexer_consume_token (lexer: parser->lexer); |
35685 | } |
35686 | |
35687 | /* Create a DEFERRED_PARSE to represent the unparsed default |
35688 | argument. */ |
35689 | default_argument = make_node (DEFERRED_PARSE); |
35690 | DEFPARSE_TOKENS (default_argument) |
35691 | = cp_token_cache_new (first: first_token, last: token); |
35692 | DEFPARSE_INSTANTIATIONS (default_argument) = NULL; |
35693 | |
35694 | return default_argument; |
35695 | } |
35696 | |
35697 | /* A location to use for diagnostics about an unparsed DEFERRED_PARSE. */ |
35698 | |
35699 | location_t |
35700 | defparse_location (tree default_argument) |
35701 | { |
35702 | cp_token_cache *tokens = DEFPARSE_TOKENS (default_argument); |
35703 | location_t start = tokens->first->location; |
35704 | location_t end = tokens->last->location; |
35705 | return make_location (caret: start, start, finish: end); |
35706 | } |
35707 | |
35708 | /* Begin parsing tentatively. We always save tokens while parsing |
35709 | tentatively so that if the tentative parsing fails we can restore the |
35710 | tokens. */ |
35711 | |
35712 | static void |
35713 | cp_parser_parse_tentatively (cp_parser* parser) |
35714 | { |
35715 | /* Enter a new parsing context. */ |
35716 | parser->context = cp_parser_context_new (next: parser->context); |
35717 | /* Begin saving tokens. */ |
35718 | cp_lexer_save_tokens (lexer: parser->lexer); |
35719 | /* In order to avoid repetitive access control error messages, |
35720 | access checks are queued up until we are no longer parsing |
35721 | tentatively. */ |
35722 | push_deferring_access_checks (dk_deferred); |
35723 | } |
35724 | |
35725 | /* Commit to the currently active tentative parse. */ |
35726 | |
35727 | static void |
35728 | cp_parser_commit_to_tentative_parse (cp_parser* parser) |
35729 | { |
35730 | cp_parser_context *context; |
35731 | cp_lexer *lexer; |
35732 | |
35733 | /* Mark all of the levels as committed. */ |
35734 | lexer = parser->lexer; |
35735 | for (context = parser->context; context->next; context = context->next) |
35736 | { |
35737 | if (context->status == CP_PARSER_STATUS_KIND_COMMITTED) |
35738 | break; |
35739 | context->status = CP_PARSER_STATUS_KIND_COMMITTED; |
35740 | while (!cp_lexer_saving_tokens (lexer)) |
35741 | lexer = lexer->next; |
35742 | cp_lexer_commit_tokens (lexer); |
35743 | } |
35744 | } |
35745 | |
35746 | /* Commit to the topmost currently active tentative parse. |
35747 | |
35748 | Note that this function shouldn't be called when there are |
35749 | irreversible side-effects while in a tentative state. For |
35750 | example, we shouldn't create a permanent entry in the symbol |
35751 | table, or issue an error message that might not apply if the |
35752 | tentative parse is aborted. */ |
35753 | |
35754 | static void |
35755 | cp_parser_commit_to_topmost_tentative_parse (cp_parser* parser) |
35756 | { |
35757 | cp_parser_context *context = parser->context; |
35758 | cp_lexer *lexer = parser->lexer; |
35759 | |
35760 | if (context) |
35761 | { |
35762 | if (context->status == CP_PARSER_STATUS_KIND_COMMITTED) |
35763 | return; |
35764 | context->status = CP_PARSER_STATUS_KIND_COMMITTED; |
35765 | |
35766 | while (!cp_lexer_saving_tokens (lexer)) |
35767 | lexer = lexer->next; |
35768 | cp_lexer_commit_tokens (lexer); |
35769 | } |
35770 | } |
35771 | |
35772 | /* Abort the currently active tentative parse. All consumed tokens |
35773 | will be rolled back, and no diagnostics will be issued. */ |
35774 | |
35775 | static void |
35776 | cp_parser_abort_tentative_parse (cp_parser* parser) |
35777 | { |
35778 | gcc_assert (parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED |
35779 | || errorcount > 0); |
35780 | cp_parser_simulate_error (parser); |
35781 | /* Now, pretend that we want to see if the construct was |
35782 | successfully parsed. */ |
35783 | cp_parser_parse_definitely (parser); |
35784 | } |
35785 | |
35786 | /* Stop parsing tentatively. If a parse error has occurred, restore the |
35787 | token stream. Otherwise, commit to the tokens we have consumed. |
35788 | Returns true if no error occurred; false otherwise. */ |
35789 | |
35790 | static bool |
35791 | cp_parser_parse_definitely (cp_parser* parser) |
35792 | { |
35793 | bool error_occurred; |
35794 | cp_parser_context *context; |
35795 | |
35796 | /* Remember whether or not an error occurred, since we are about to |
35797 | destroy that information. */ |
35798 | error_occurred = cp_parser_error_occurred (parser); |
35799 | /* Remove the topmost context from the stack. */ |
35800 | context = parser->context; |
35801 | parser->context = context->next; |
35802 | /* If no parse errors occurred, commit to the tentative parse. */ |
35803 | if (!error_occurred) |
35804 | { |
35805 | /* Commit to the tokens read tentatively, unless that was |
35806 | already done. */ |
35807 | if (context->status != CP_PARSER_STATUS_KIND_COMMITTED) |
35808 | cp_lexer_commit_tokens (lexer: parser->lexer); |
35809 | |
35810 | pop_to_parent_deferring_access_checks (); |
35811 | } |
35812 | /* Otherwise, if errors occurred, roll back our state so that things |
35813 | are just as they were before we began the tentative parse. */ |
35814 | else |
35815 | { |
35816 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
35817 | pop_deferring_access_checks (); |
35818 | } |
35819 | /* Add the context to the front of the free list. */ |
35820 | context->next = cp_parser_context_free_list; |
35821 | cp_parser_context_free_list = context; |
35822 | |
35823 | return !error_occurred; |
35824 | } |
35825 | |
35826 | /* Returns true if we are parsing tentatively and are not committed to |
35827 | this tentative parse. */ |
35828 | |
35829 | static bool |
35830 | cp_parser_uncommitted_to_tentative_parse_p (cp_parser* parser) |
35831 | { |
35832 | return (cp_parser_parsing_tentatively (parser) |
35833 | && parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED); |
35834 | } |
35835 | |
35836 | /* Returns nonzero iff an error has occurred during the most recent |
35837 | tentative parse. */ |
35838 | |
35839 | static bool |
35840 | cp_parser_error_occurred (cp_parser* parser) |
35841 | { |
35842 | return (cp_parser_parsing_tentatively (parser) |
35843 | && parser->context->status == CP_PARSER_STATUS_KIND_ERROR); |
35844 | } |
35845 | |
35846 | /* Returns nonzero if GNU extensions are allowed. */ |
35847 | |
35848 | static bool |
35849 | cp_parser_allow_gnu_extensions_p (cp_parser* parser) |
35850 | { |
35851 | return parser->allow_gnu_extensions_p; |
35852 | } |
35853 | |
35854 | /* Objective-C++ Productions */ |
35855 | |
35856 | |
35857 | /* Parse an Objective-C expression, which feeds into a primary-expression |
35858 | above. |
35859 | |
35860 | objc-expression: |
35861 | objc-message-expression |
35862 | objc-string-literal |
35863 | objc-encode-expression |
35864 | objc-protocol-expression |
35865 | objc-selector-expression |
35866 | |
35867 | Returns a tree representation of the expression. */ |
35868 | |
35869 | static cp_expr |
35870 | cp_parser_objc_expression (cp_parser* parser) |
35871 | { |
35872 | /* Try to figure out what kind of declaration is present. */ |
35873 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
35874 | |
35875 | switch (kwd->type) |
35876 | { |
35877 | case CPP_OPEN_SQUARE: |
35878 | return cp_parser_objc_message_expression (parser); |
35879 | |
35880 | case CPP_OBJC_STRING: |
35881 | kwd = cp_lexer_consume_token (lexer: parser->lexer); |
35882 | return objc_build_string_object (kwd->u.value); |
35883 | |
35884 | case CPP_KEYWORD: |
35885 | switch (kwd->keyword) |
35886 | { |
35887 | case RID_AT_ENCODE: |
35888 | return cp_parser_objc_encode_expression (parser); |
35889 | |
35890 | case RID_AT_PROTOCOL: |
35891 | return cp_parser_objc_protocol_expression (parser); |
35892 | |
35893 | case RID_AT_SELECTOR: |
35894 | return cp_parser_objc_selector_expression (parser); |
35895 | |
35896 | default: |
35897 | break; |
35898 | } |
35899 | /* FALLTHRU */ |
35900 | default: |
35901 | error_at (kwd->location, |
35902 | "misplaced %<@%D%> Objective-C++ construct" , |
35903 | kwd->u.value); |
35904 | cp_parser_skip_to_end_of_block_or_statement (parser); |
35905 | } |
35906 | |
35907 | return error_mark_node; |
35908 | } |
35909 | |
35910 | /* Parse an Objective-C message expression. |
35911 | |
35912 | objc-message-expression: |
35913 | [ objc-message-receiver objc-message-args ] |
35914 | |
35915 | Returns a representation of an Objective-C message. */ |
35916 | |
35917 | static tree |
35918 | cp_parser_objc_message_expression (cp_parser* parser) |
35919 | { |
35920 | tree receiver, messageargs; |
35921 | |
35922 | parser->objective_c_message_context_p = true; |
35923 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35924 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '['. */ |
35925 | receiver = cp_parser_objc_message_receiver (parser); |
35926 | messageargs = cp_parser_objc_message_args (parser); |
35927 | location_t end_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35928 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
35929 | |
35930 | tree result = objc_build_message_expr (receiver, messageargs); |
35931 | |
35932 | /* Construct a location e.g. |
35933 | [self func1:5] |
35934 | ^~~~~~~~~~~~~~ |
35935 | ranging from the '[' to the ']', with the caret at the start. */ |
35936 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: end_loc); |
35937 | protected_set_expr_location (result, combined_loc); |
35938 | |
35939 | parser->objective_c_message_context_p = false; |
35940 | return result; |
35941 | } |
35942 | |
35943 | /* Parse an objc-message-receiver. |
35944 | |
35945 | objc-message-receiver: |
35946 | expression |
35947 | simple-type-specifier |
35948 | |
35949 | Returns a representation of the type or expression. */ |
35950 | |
35951 | static tree |
35952 | cp_parser_objc_message_receiver (cp_parser* parser) |
35953 | { |
35954 | tree rcv; |
35955 | |
35956 | /* An Objective-C message receiver may be either (1) a type |
35957 | or (2) an expression. */ |
35958 | cp_parser_parse_tentatively (parser); |
35959 | rcv = cp_parser_expression (parser); |
35960 | |
35961 | /* If that worked out, fine. */ |
35962 | if (cp_parser_parse_definitely (parser)) |
35963 | return rcv; |
35964 | |
35965 | cp_parser_parse_tentatively (parser); |
35966 | rcv = cp_parser_simple_type_specifier (parser, |
35967 | /*decl_specs=*/NULL, |
35968 | flags: CP_PARSER_FLAGS_NONE); |
35969 | |
35970 | if (cp_parser_parse_definitely (parser)) |
35971 | return objc_get_class_reference (rcv); |
35972 | |
35973 | cp_parser_error (parser, gmsgid: "objective-c++ message receiver expected" ); |
35974 | return error_mark_node; |
35975 | } |
35976 | |
35977 | /* Parse the arguments and selectors comprising an Objective-C message. |
35978 | |
35979 | objc-message-args: |
35980 | objc-selector |
35981 | objc-selector-args |
35982 | objc-selector-args , objc-comma-args |
35983 | |
35984 | objc-selector-args: |
35985 | objc-selector [opt] : assignment-expression |
35986 | objc-selector-args objc-selector [opt] : assignment-expression |
35987 | |
35988 | objc-comma-args: |
35989 | assignment-expression |
35990 | objc-comma-args , assignment-expression |
35991 | |
35992 | Returns a TREE_LIST, with TREE_PURPOSE containing a list of |
35993 | selector arguments and TREE_VALUE containing a list of comma |
35994 | arguments. */ |
35995 | |
35996 | static tree |
35997 | cp_parser_objc_message_args (cp_parser* parser) |
35998 | { |
35999 | tree sel_args = NULL_TREE, addl_args = NULL_TREE; |
36000 | bool maybe_unary_selector_p = true; |
36001 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36002 | |
36003 | while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) |
36004 | { |
36005 | tree selector = NULL_TREE, arg; |
36006 | |
36007 | if (token->type != CPP_COLON) |
36008 | selector = cp_parser_objc_selector (parser); |
36009 | |
36010 | /* Detect if we have a unary selector. */ |
36011 | if (maybe_unary_selector_p |
36012 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
36013 | return build_tree_list (selector, NULL_TREE); |
36014 | |
36015 | maybe_unary_selector_p = false; |
36016 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
36017 | arg = cp_parser_assignment_expression (parser); |
36018 | |
36019 | sel_args |
36020 | = chainon (sel_args, |
36021 | build_tree_list (selector, arg)); |
36022 | |
36023 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36024 | } |
36025 | |
36026 | /* Handle non-selector arguments, if any. */ |
36027 | while (token->type == CPP_COMMA) |
36028 | { |
36029 | tree arg; |
36030 | |
36031 | cp_lexer_consume_token (lexer: parser->lexer); |
36032 | arg = cp_parser_assignment_expression (parser); |
36033 | |
36034 | addl_args |
36035 | = chainon (addl_args, |
36036 | build_tree_list (NULL_TREE, arg)); |
36037 | |
36038 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36039 | } |
36040 | |
36041 | if (sel_args == NULL_TREE && addl_args == NULL_TREE) |
36042 | { |
36043 | cp_parser_error (parser, gmsgid: "objective-c++ message argument(s) are expected" ); |
36044 | return build_tree_list (error_mark_node, error_mark_node); |
36045 | } |
36046 | |
36047 | return build_tree_list (sel_args, addl_args); |
36048 | } |
36049 | |
36050 | /* Parse an Objective-C encode expression. |
36051 | |
36052 | objc-encode-expression: |
36053 | @encode objc-typename |
36054 | |
36055 | Returns an encoded representation of the type argument. */ |
36056 | |
36057 | static cp_expr |
36058 | cp_parser_objc_encode_expression (cp_parser* parser) |
36059 | { |
36060 | tree type; |
36061 | cp_token *token; |
36062 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36063 | |
36064 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@encode'. */ |
36065 | matching_parens parens; |
36066 | parens.require_open (parser); |
36067 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36068 | type = complete_type (cp_parser_type_id (parser)); |
36069 | parens.require_close (parser); |
36070 | |
36071 | if (!type) |
36072 | { |
36073 | error_at (token->location, |
36074 | "%<@encode%> must specify a type as an argument" ); |
36075 | return error_mark_node; |
36076 | } |
36077 | |
36078 | /* This happens if we find @encode(T) (where T is a template |
36079 | typename or something dependent on a template typename) when |
36080 | parsing a template. In that case, we can't compile it |
36081 | immediately, but we rather create an AT_ENCODE_EXPR which will |
36082 | need to be instantiated when the template is used. |
36083 | */ |
36084 | if (dependent_type_p (type)) |
36085 | { |
36086 | tree value = build_min (AT_ENCODE_EXPR, size_type_node, type); |
36087 | TREE_READONLY (value) = 1; |
36088 | return value; |
36089 | } |
36090 | |
36091 | |
36092 | /* Build a location of the form: |
36093 | @encode(int) |
36094 | ^~~~~~~~~~~~ |
36095 | with caret==start at the @ token, finishing at the close paren. */ |
36096 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
36097 | |
36098 | return cp_expr (objc_build_encode_expr (type), combined_loc); |
36099 | } |
36100 | |
36101 | /* Parse an Objective-C @defs expression. */ |
36102 | |
36103 | static tree |
36104 | cp_parser_objc_defs_expression (cp_parser *parser) |
36105 | { |
36106 | tree name; |
36107 | |
36108 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@defs'. */ |
36109 | matching_parens parens; |
36110 | parens.require_open (parser); |
36111 | name = cp_parser_identifier (parser); |
36112 | parens.require_close (parser); |
36113 | |
36114 | return objc_get_class_ivars (name); |
36115 | } |
36116 | |
36117 | /* Parse an Objective-C protocol expression. |
36118 | |
36119 | objc-protocol-expression: |
36120 | @protocol ( identifier ) |
36121 | |
36122 | Returns a representation of the protocol expression. */ |
36123 | |
36124 | static tree |
36125 | cp_parser_objc_protocol_expression (cp_parser* parser) |
36126 | { |
36127 | tree proto; |
36128 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36129 | |
36130 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@protocol'. */ |
36131 | matching_parens parens; |
36132 | parens.require_open (parser); |
36133 | proto = cp_parser_identifier (parser); |
36134 | parens.require_close (parser); |
36135 | |
36136 | /* Build a location of the form: |
36137 | @protocol(prot) |
36138 | ^~~~~~~~~~~~~~~ |
36139 | with caret==start at the @ token, finishing at the close paren. */ |
36140 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
36141 | tree result = objc_build_protocol_expr (proto); |
36142 | protected_set_expr_location (result, combined_loc); |
36143 | return result; |
36144 | } |
36145 | |
36146 | /* Parse an Objective-C selector expression. |
36147 | |
36148 | objc-selector-expression: |
36149 | @selector ( objc-method-signature ) |
36150 | |
36151 | objc-method-signature: |
36152 | objc-selector |
36153 | objc-selector-seq |
36154 | |
36155 | objc-selector-seq: |
36156 | objc-selector : |
36157 | objc-selector-seq objc-selector : |
36158 | |
36159 | Returns a representation of the method selector. */ |
36160 | |
36161 | static tree |
36162 | cp_parser_objc_selector_expression (cp_parser* parser) |
36163 | { |
36164 | tree sel_seq = NULL_TREE; |
36165 | bool maybe_unary_selector_p = true; |
36166 | cp_token *token; |
36167 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36168 | |
36169 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@selector'. */ |
36170 | matching_parens parens; |
36171 | parens.require_open (parser); |
36172 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36173 | |
36174 | while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON |
36175 | || token->type == CPP_SCOPE) |
36176 | { |
36177 | tree selector = NULL_TREE; |
36178 | |
36179 | if (token->type != CPP_COLON |
36180 | || token->type == CPP_SCOPE) |
36181 | selector = cp_parser_objc_selector (parser); |
36182 | |
36183 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON) |
36184 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SCOPE)) |
36185 | { |
36186 | /* Detect if we have a unary selector. */ |
36187 | if (maybe_unary_selector_p) |
36188 | { |
36189 | sel_seq = selector; |
36190 | goto finish_selector; |
36191 | } |
36192 | else |
36193 | { |
36194 | cp_parser_error (parser, gmsgid: "expected %<:%>" ); |
36195 | } |
36196 | } |
36197 | maybe_unary_selector_p = false; |
36198 | token = cp_lexer_consume_token (lexer: parser->lexer); |
36199 | |
36200 | if (token->type == CPP_SCOPE) |
36201 | { |
36202 | sel_seq |
36203 | = chainon (sel_seq, |
36204 | build_tree_list (selector, NULL_TREE)); |
36205 | sel_seq |
36206 | = chainon (sel_seq, |
36207 | build_tree_list (NULL_TREE, NULL_TREE)); |
36208 | } |
36209 | else |
36210 | sel_seq |
36211 | = chainon (sel_seq, |
36212 | build_tree_list (selector, NULL_TREE)); |
36213 | |
36214 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36215 | } |
36216 | |
36217 | finish_selector: |
36218 | parens.require_close (parser); |
36219 | |
36220 | |
36221 | /* Build a location of the form: |
36222 | @selector(func) |
36223 | ^~~~~~~~~~~~~~~ |
36224 | with caret==start at the @ token, finishing at the close paren. */ |
36225 | location_t combined_loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
36226 | tree result = objc_build_selector_expr (combined_loc, sel_seq); |
36227 | /* TODO: objc_build_selector_expr doesn't always honor the location. */ |
36228 | protected_set_expr_location (result, combined_loc); |
36229 | return result; |
36230 | } |
36231 | |
36232 | /* Parse a list of identifiers. |
36233 | |
36234 | objc-identifier-list: |
36235 | identifier |
36236 | objc-identifier-list , identifier |
36237 | |
36238 | Returns a TREE_LIST of identifier nodes. */ |
36239 | |
36240 | static tree |
36241 | cp_parser_objc_identifier_list (cp_parser* parser) |
36242 | { |
36243 | tree identifier; |
36244 | tree list; |
36245 | cp_token *sep; |
36246 | |
36247 | identifier = cp_parser_identifier (parser); |
36248 | if (identifier == error_mark_node) |
36249 | return error_mark_node; |
36250 | |
36251 | list = build_tree_list (NULL_TREE, identifier); |
36252 | sep = cp_lexer_peek_token (lexer: parser->lexer); |
36253 | |
36254 | while (sep->type == CPP_COMMA) |
36255 | { |
36256 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
36257 | identifier = cp_parser_identifier (parser); |
36258 | if (identifier == error_mark_node) |
36259 | return list; |
36260 | |
36261 | list = chainon (list, build_tree_list (NULL_TREE, |
36262 | identifier)); |
36263 | sep = cp_lexer_peek_token (lexer: parser->lexer); |
36264 | } |
36265 | |
36266 | return list; |
36267 | } |
36268 | |
36269 | /* Parse an Objective-C alias declaration. |
36270 | |
36271 | objc-alias-declaration: |
36272 | @compatibility_alias identifier identifier ; |
36273 | |
36274 | This function registers the alias mapping with the Objective-C front end. |
36275 | It returns nothing. */ |
36276 | |
36277 | static void |
36278 | cp_parser_objc_alias_declaration (cp_parser* parser) |
36279 | { |
36280 | tree alias, orig; |
36281 | |
36282 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@compatibility_alias'. */ |
36283 | alias = cp_parser_identifier (parser); |
36284 | orig = cp_parser_identifier (parser); |
36285 | objc_declare_alias (alias, orig); |
36286 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36287 | } |
36288 | |
36289 | /* Parse an Objective-C class forward-declaration. |
36290 | |
36291 | objc-class-declaration: |
36292 | @class objc-identifier-list ; |
36293 | |
36294 | The function registers the forward declarations with the Objective-C |
36295 | front end. It returns nothing. */ |
36296 | |
36297 | static void |
36298 | cp_parser_objc_class_declaration (cp_parser* parser) |
36299 | { |
36300 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@class'. */ |
36301 | while (true) |
36302 | { |
36303 | tree id; |
36304 | |
36305 | id = cp_parser_identifier (parser); |
36306 | if (id == error_mark_node) |
36307 | break; |
36308 | |
36309 | objc_declare_class (id); |
36310 | |
36311 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
36312 | cp_lexer_consume_token (lexer: parser->lexer); |
36313 | else |
36314 | break; |
36315 | } |
36316 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36317 | } |
36318 | |
36319 | /* Parse a list of Objective-C protocol references. |
36320 | |
36321 | objc-protocol-refs-opt: |
36322 | objc-protocol-refs [opt] |
36323 | |
36324 | objc-protocol-refs: |
36325 | < objc-identifier-list > |
36326 | |
36327 | Returns a TREE_LIST of identifiers, if any. */ |
36328 | |
36329 | static tree |
36330 | cp_parser_objc_protocol_refs_opt (cp_parser* parser) |
36331 | { |
36332 | tree protorefs = NULL_TREE; |
36333 | |
36334 | if(cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
36335 | { |
36336 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '<'. */ |
36337 | protorefs = cp_parser_objc_identifier_list (parser); |
36338 | cp_parser_require (parser, type: CPP_GREATER, token_desc: RT_GREATER); |
36339 | } |
36340 | |
36341 | return protorefs; |
36342 | } |
36343 | |
36344 | /* Parse a Objective-C visibility specification. */ |
36345 | |
36346 | static void |
36347 | cp_parser_objc_visibility_spec (cp_parser* parser) |
36348 | { |
36349 | cp_token *vis = cp_lexer_peek_token (lexer: parser->lexer); |
36350 | |
36351 | switch (vis->keyword) |
36352 | { |
36353 | case RID_AT_PRIVATE: |
36354 | objc_set_visibility (OBJC_IVAR_VIS_PRIVATE); |
36355 | break; |
36356 | case RID_AT_PROTECTED: |
36357 | objc_set_visibility (OBJC_IVAR_VIS_PROTECTED); |
36358 | break; |
36359 | case RID_AT_PUBLIC: |
36360 | objc_set_visibility (OBJC_IVAR_VIS_PUBLIC); |
36361 | break; |
36362 | case RID_AT_PACKAGE: |
36363 | objc_set_visibility (OBJC_IVAR_VIS_PACKAGE); |
36364 | break; |
36365 | default: |
36366 | return; |
36367 | } |
36368 | |
36369 | /* Eat '@private'/'@protected'/'@public'. */ |
36370 | cp_lexer_consume_token (lexer: parser->lexer); |
36371 | } |
36372 | |
36373 | /* Parse an Objective-C method type. Return 'true' if it is a class |
36374 | (+) method, and 'false' if it is an instance (-) method. */ |
36375 | |
36376 | static inline bool |
36377 | cp_parser_objc_method_type (cp_parser* parser) |
36378 | { |
36379 | if (cp_lexer_consume_token (lexer: parser->lexer)->type == CPP_PLUS) |
36380 | return true; |
36381 | else |
36382 | return false; |
36383 | } |
36384 | |
36385 | /* Parse an Objective-C protocol qualifier. */ |
36386 | |
36387 | static tree |
36388 | cp_parser_objc_protocol_qualifiers (cp_parser* parser) |
36389 | { |
36390 | tree quals = NULL_TREE, node; |
36391 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36392 | |
36393 | node = token->u.value; |
36394 | |
36395 | while (node && identifier_p (t: node) |
36396 | && (node == ridpointers [(int) RID_IN] |
36397 | || node == ridpointers [(int) RID_OUT] |
36398 | || node == ridpointers [(int) RID_INOUT] |
36399 | || node == ridpointers [(int) RID_BYCOPY] |
36400 | || node == ridpointers [(int) RID_BYREF] |
36401 | || node == ridpointers [(int) RID_ONEWAY])) |
36402 | { |
36403 | quals = tree_cons (NULL_TREE, node, quals); |
36404 | cp_lexer_consume_token (lexer: parser->lexer); |
36405 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36406 | node = token->u.value; |
36407 | } |
36408 | |
36409 | return quals; |
36410 | } |
36411 | |
36412 | /* Parse an Objective-C typename. */ |
36413 | |
36414 | static tree |
36415 | cp_parser_objc_typename (cp_parser* parser) |
36416 | { |
36417 | tree type_name = NULL_TREE; |
36418 | |
36419 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
36420 | { |
36421 | tree proto_quals, cp_type = NULL_TREE; |
36422 | |
36423 | matching_parens parens; |
36424 | parens.consume_open (parser); /* Eat '('. */ |
36425 | proto_quals = cp_parser_objc_protocol_qualifiers (parser); |
36426 | |
36427 | /* An ObjC type name may consist of just protocol qualifiers, in which |
36428 | case the type shall default to 'id'. */ |
36429 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
36430 | { |
36431 | cp_type = cp_parser_type_id (parser); |
36432 | |
36433 | /* If the type could not be parsed, an error has already |
36434 | been produced. For error recovery, behave as if it had |
36435 | not been specified, which will use the default type |
36436 | 'id'. */ |
36437 | if (cp_type == error_mark_node) |
36438 | { |
36439 | cp_type = NULL_TREE; |
36440 | /* We need to skip to the closing parenthesis as |
36441 | cp_parser_type_id() does not seem to do it for |
36442 | us. */ |
36443 | cp_parser_skip_to_closing_parenthesis (parser, |
36444 | /*recovering=*/true, |
36445 | /*or_comma=*/false, |
36446 | /*consume_paren=*/false); |
36447 | } |
36448 | } |
36449 | |
36450 | parens.require_close (parser); |
36451 | type_name = build_tree_list (proto_quals, cp_type); |
36452 | } |
36453 | |
36454 | return type_name; |
36455 | } |
36456 | |
36457 | /* Check to see if TYPE refers to an Objective-C selector name. */ |
36458 | |
36459 | static bool |
36460 | cp_parser_objc_selector_p (enum cpp_ttype type) |
36461 | { |
36462 | return (type == CPP_NAME || type == CPP_KEYWORD |
36463 | || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND |
36464 | || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT |
36465 | || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ |
36466 | || type == CPP_XOR || type == CPP_XOR_EQ); |
36467 | } |
36468 | |
36469 | /* Parse an Objective-C selector. */ |
36470 | |
36471 | static tree |
36472 | cp_parser_objc_selector (cp_parser* parser) |
36473 | { |
36474 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
36475 | |
36476 | if (!cp_parser_objc_selector_p (type: token->type)) |
36477 | { |
36478 | error_at (token->location, "invalid Objective-C++ selector name" ); |
36479 | return error_mark_node; |
36480 | } |
36481 | |
36482 | /* C++ operator names are allowed to appear in ObjC selectors. */ |
36483 | switch (token->type) |
36484 | { |
36485 | case CPP_AND_AND: return get_identifier ("and" ); |
36486 | case CPP_AND_EQ: return get_identifier ("and_eq" ); |
36487 | case CPP_AND: return get_identifier ("bitand" ); |
36488 | case CPP_OR: return get_identifier ("bitor" ); |
36489 | case CPP_COMPL: return get_identifier ("compl" ); |
36490 | case CPP_NOT: return get_identifier ("not" ); |
36491 | case CPP_NOT_EQ: return get_identifier ("not_eq" ); |
36492 | case CPP_OR_OR: return get_identifier ("or" ); |
36493 | case CPP_OR_EQ: return get_identifier ("or_eq" ); |
36494 | case CPP_XOR: return get_identifier ("xor" ); |
36495 | case CPP_XOR_EQ: return get_identifier ("xor_eq" ); |
36496 | default: return token->u.value; |
36497 | } |
36498 | } |
36499 | |
36500 | /* Parse an Objective-C params list. */ |
36501 | |
36502 | static tree |
36503 | cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes) |
36504 | { |
36505 | tree params = NULL_TREE; |
36506 | bool maybe_unary_selector_p = true; |
36507 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36508 | |
36509 | while (cp_parser_objc_selector_p (type: token->type) || token->type == CPP_COLON) |
36510 | { |
36511 | tree selector = NULL_TREE, type_name, identifier; |
36512 | tree parm_attr = NULL_TREE; |
36513 | |
36514 | if (token->keyword == RID_ATTRIBUTE) |
36515 | break; |
36516 | |
36517 | if (token->type != CPP_COLON) |
36518 | selector = cp_parser_objc_selector (parser); |
36519 | |
36520 | /* Detect if we have a unary selector. */ |
36521 | if (maybe_unary_selector_p |
36522 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
36523 | { |
36524 | params = selector; /* Might be followed by attributes. */ |
36525 | break; |
36526 | } |
36527 | |
36528 | maybe_unary_selector_p = false; |
36529 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
36530 | { |
36531 | /* Something went quite wrong. There should be a colon |
36532 | here, but there is not. Stop parsing parameters. */ |
36533 | break; |
36534 | } |
36535 | type_name = cp_parser_objc_typename (parser); |
36536 | /* New ObjC allows attributes on parameters too. */ |
36537 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ATTRIBUTE)) |
36538 | parm_attr = cp_parser_attributes_opt (parser); |
36539 | identifier = cp_parser_identifier (parser); |
36540 | |
36541 | params |
36542 | = chainon (params, |
36543 | objc_build_keyword_decl (selector, |
36544 | type_name, |
36545 | identifier, |
36546 | parm_attr)); |
36547 | |
36548 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36549 | } |
36550 | |
36551 | if (params == NULL_TREE) |
36552 | { |
36553 | cp_parser_error (parser, gmsgid: "objective-c++ method declaration is expected" ); |
36554 | return error_mark_node; |
36555 | } |
36556 | |
36557 | /* We allow tail attributes for the method. */ |
36558 | if (token->keyword == RID_ATTRIBUTE) |
36559 | { |
36560 | *attributes = cp_parser_attributes_opt (parser); |
36561 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
36562 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
36563 | return params; |
36564 | cp_parser_error (parser, |
36565 | gmsgid: "method attributes must be specified at the end" ); |
36566 | return error_mark_node; |
36567 | } |
36568 | |
36569 | if (params == NULL_TREE) |
36570 | { |
36571 | cp_parser_error (parser, gmsgid: "objective-c++ method declaration is expected" ); |
36572 | return error_mark_node; |
36573 | } |
36574 | return params; |
36575 | } |
36576 | |
36577 | /* Parse the non-keyword Objective-C params. */ |
36578 | |
36579 | static tree |
36580 | cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, |
36581 | tree* attributes) |
36582 | { |
36583 | tree params = make_node (TREE_LIST); |
36584 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36585 | *ellipsisp = false; /* Initially, assume no ellipsis. */ |
36586 | |
36587 | while (token->type == CPP_COMMA) |
36588 | { |
36589 | cp_parameter_declarator *parmdecl; |
36590 | tree parm; |
36591 | |
36592 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
36593 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36594 | |
36595 | if (token->type == CPP_ELLIPSIS) |
36596 | { |
36597 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '...'. */ |
36598 | *ellipsisp = true; |
36599 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36600 | break; |
36601 | } |
36602 | |
36603 | /* TODO: parse attributes for tail parameters. */ |
36604 | parmdecl = cp_parser_parameter_declaration (parser, flags: CP_PARSER_FLAGS_NONE, |
36605 | template_parm_p: false, NULL); |
36606 | parm = grokdeclarator (parmdecl->declarator, |
36607 | &parmdecl->decl_specifiers, |
36608 | PARM, /*initialized=*/0, |
36609 | /*attrlist=*/NULL); |
36610 | |
36611 | chainon (params, build_tree_list (NULL_TREE, parm)); |
36612 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36613 | } |
36614 | |
36615 | /* We allow tail attributes for the method. */ |
36616 | if (token->keyword == RID_ATTRIBUTE) |
36617 | { |
36618 | if (*attributes == NULL_TREE) |
36619 | { |
36620 | *attributes = cp_parser_attributes_opt (parser); |
36621 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
36622 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
36623 | return params; |
36624 | } |
36625 | else |
36626 | /* We have an error, but parse the attributes, so that we can |
36627 | carry on. */ |
36628 | *attributes = cp_parser_attributes_opt (parser); |
36629 | |
36630 | cp_parser_error (parser, |
36631 | gmsgid: "method attributes must be specified at the end" ); |
36632 | return error_mark_node; |
36633 | } |
36634 | |
36635 | return params; |
36636 | } |
36637 | |
36638 | /* Parse a linkage specification, a pragma, an extra semicolon or a block. */ |
36639 | |
36640 | static void |
36641 | cp_parser_objc_interstitial_code (cp_parser* parser) |
36642 | { |
36643 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36644 | |
36645 | /* If the next token is `extern' and the following token is a string |
36646 | literal, then we have a linkage specification. */ |
36647 | if (token->keyword == RID_EXTERN |
36648 | && cp_parser_is_pure_string_literal |
36649 | (token: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))) |
36650 | cp_parser_linkage_specification (parser, NULL_TREE); |
36651 | /* Handle #pragma, if any. */ |
36652 | else if (token->type == CPP_PRAGMA) |
36653 | cp_parser_pragma (parser, pragma_objc_icode, NULL); |
36654 | /* Allow stray semicolons. */ |
36655 | else if (token->type == CPP_SEMICOLON) |
36656 | cp_lexer_consume_token (lexer: parser->lexer); |
36657 | /* Mark methods as optional or required, when building protocols. */ |
36658 | else if (token->keyword == RID_AT_OPTIONAL) |
36659 | { |
36660 | cp_lexer_consume_token (lexer: parser->lexer); |
36661 | objc_set_method_opt (true); |
36662 | } |
36663 | else if (token->keyword == RID_AT_REQUIRED) |
36664 | { |
36665 | cp_lexer_consume_token (lexer: parser->lexer); |
36666 | objc_set_method_opt (false); |
36667 | } |
36668 | else if (token->keyword == RID_NAMESPACE) |
36669 | cp_parser_namespace_definition (parser); |
36670 | /* Other stray characters must generate errors. */ |
36671 | else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE) |
36672 | { |
36673 | cp_lexer_consume_token (lexer: parser->lexer); |
36674 | error ("stray %qs between Objective-C++ methods" , |
36675 | token->type == CPP_OPEN_BRACE ? "{" : "}" ); |
36676 | } |
36677 | /* Finally, try to parse a block-declaration, or a function-definition. */ |
36678 | else |
36679 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
36680 | } |
36681 | |
36682 | /* Parse a method signature. */ |
36683 | |
36684 | static tree |
36685 | cp_parser_objc_method_signature (cp_parser* parser, tree* attributes) |
36686 | { |
36687 | tree rettype, kwdparms, optparms; |
36688 | bool ellipsis = false; |
36689 | bool is_class_method; |
36690 | |
36691 | is_class_method = cp_parser_objc_method_type (parser); |
36692 | rettype = cp_parser_objc_typename (parser); |
36693 | *attributes = NULL_TREE; |
36694 | kwdparms = cp_parser_objc_method_keyword_params (parser, attributes); |
36695 | if (kwdparms == error_mark_node) |
36696 | return error_mark_node; |
36697 | optparms = cp_parser_objc_method_tail_params_opt (parser, ellipsisp: &ellipsis, attributes); |
36698 | if (optparms == error_mark_node) |
36699 | return error_mark_node; |
36700 | |
36701 | return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis); |
36702 | } |
36703 | |
36704 | static bool |
36705 | cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser) |
36706 | { |
36707 | tree tattr; |
36708 | cp_lexer_save_tokens (lexer: parser->lexer); |
36709 | tattr = cp_parser_attributes_opt (parser); |
36710 | gcc_assert (tattr) ; |
36711 | |
36712 | /* If the attributes are followed by a method introducer, this is not allowed. |
36713 | Dump the attributes and flag the situation. */ |
36714 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PLUS) |
36715 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MINUS)) |
36716 | return true; |
36717 | |
36718 | /* Otherwise, the attributes introduce some interstitial code, possibly so |
36719 | rewind to allow that check. */ |
36720 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
36721 | return false; |
36722 | } |
36723 | |
36724 | /* Parse an Objective-C method prototype list. */ |
36725 | |
36726 | static void |
36727 | cp_parser_objc_method_prototype_list (cp_parser* parser) |
36728 | { |
36729 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36730 | |
36731 | while (token->keyword != RID_AT_END && token->type != CPP_EOF) |
36732 | { |
36733 | if (token->type == CPP_PLUS || token->type == CPP_MINUS) |
36734 | { |
36735 | tree attributes, sig; |
36736 | bool is_class_method; |
36737 | if (token->type == CPP_PLUS) |
36738 | is_class_method = true; |
36739 | else |
36740 | is_class_method = false; |
36741 | sig = cp_parser_objc_method_signature (parser, attributes: &attributes); |
36742 | if (sig == error_mark_node) |
36743 | { |
36744 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36745 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36746 | continue; |
36747 | } |
36748 | objc_add_method_declaration (is_class_method, sig, attributes); |
36749 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36750 | } |
36751 | else if (token->keyword == RID_AT_PROPERTY) |
36752 | cp_parser_objc_at_property_declaration (parser); |
36753 | else if (token->keyword == RID_ATTRIBUTE |
36754 | && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) |
36755 | warning_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
36756 | OPT_Wattributes, |
36757 | "prefix attributes are ignored for methods" ); |
36758 | else |
36759 | /* Allow for interspersed non-ObjC++ code. */ |
36760 | cp_parser_objc_interstitial_code (parser); |
36761 | |
36762 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36763 | } |
36764 | |
36765 | if (token->type != CPP_EOF) |
36766 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
36767 | else |
36768 | cp_parser_error (parser, gmsgid: "expected %<@end%>" ); |
36769 | |
36770 | objc_finish_interface (); |
36771 | } |
36772 | |
36773 | /* Parse an Objective-C method definition list. */ |
36774 | |
36775 | static void |
36776 | cp_parser_objc_method_definition_list (cp_parser* parser) |
36777 | { |
36778 | for (;;) |
36779 | { |
36780 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36781 | |
36782 | if (token->keyword == RID_AT_END) |
36783 | { |
36784 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
36785 | break; |
36786 | } |
36787 | else if (token->type == CPP_EOF) |
36788 | { |
36789 | cp_parser_error (parser, gmsgid: "expected %<@end%>" ); |
36790 | break; |
36791 | } |
36792 | else if (token->type == CPP_PLUS || token->type == CPP_MINUS) |
36793 | { |
36794 | bool is_class_method = token->type == CPP_PLUS; |
36795 | |
36796 | push_deferring_access_checks (dk_deferred); |
36797 | tree attribute; |
36798 | tree sig = cp_parser_objc_method_signature (parser, attributes: &attribute); |
36799 | if (sig == error_mark_node) |
36800 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36801 | else |
36802 | { |
36803 | objc_start_method_definition (is_class_method, sig, |
36804 | attribute, NULL_TREE); |
36805 | |
36806 | /* For historical reasons, we accept an optional semicolon. */ |
36807 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36808 | cp_lexer_consume_token (lexer: parser->lexer); |
36809 | |
36810 | perform_deferred_access_checks (tf_warning_or_error); |
36811 | stop_deferring_access_checks (); |
36812 | tree meth |
36813 | = cp_parser_function_definition_after_declarator (parser, inline_p: false); |
36814 | pop_deferring_access_checks (); |
36815 | objc_finish_method_definition (meth); |
36816 | } |
36817 | } |
36818 | /* The following case will be removed once @synthesize is |
36819 | completely implemented. */ |
36820 | else if (token->keyword == RID_AT_PROPERTY) |
36821 | cp_parser_objc_at_property_declaration (parser); |
36822 | else if (token->keyword == RID_AT_SYNTHESIZE) |
36823 | cp_parser_objc_at_synthesize_declaration (parser); |
36824 | else if (token->keyword == RID_AT_DYNAMIC) |
36825 | cp_parser_objc_at_dynamic_declaration (parser); |
36826 | else if (token->keyword == RID_ATTRIBUTE |
36827 | && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) |
36828 | warning_at (token->location, OPT_Wattributes, |
36829 | "prefix attributes are ignored for methods" ); |
36830 | else |
36831 | /* Allow for interspersed non-ObjC++ code. */ |
36832 | cp_parser_objc_interstitial_code (parser); |
36833 | } |
36834 | |
36835 | objc_finish_implementation (); |
36836 | } |
36837 | |
36838 | /* Parse Objective-C ivars. */ |
36839 | |
36840 | static void |
36841 | cp_parser_objc_class_ivars (cp_parser* parser) |
36842 | { |
36843 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36844 | |
36845 | if (token->type != CPP_OPEN_BRACE) |
36846 | return; /* No ivars specified. */ |
36847 | |
36848 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '{'. */ |
36849 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36850 | |
36851 | while (token->type != CPP_CLOSE_BRACE |
36852 | && token->keyword != RID_AT_END && token->type != CPP_EOF) |
36853 | { |
36854 | cp_decl_specifier_seq declspecs; |
36855 | int decl_class_or_enum_p; |
36856 | tree prefix_attributes; |
36857 | |
36858 | cp_parser_objc_visibility_spec (parser); |
36859 | |
36860 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
36861 | break; |
36862 | |
36863 | cp_parser_decl_specifier_seq (parser, |
36864 | flags: CP_PARSER_FLAGS_OPTIONAL, |
36865 | decl_specs: &declspecs, |
36866 | declares_class_or_enum: &decl_class_or_enum_p); |
36867 | |
36868 | /* auto, register, static, extern, mutable. */ |
36869 | if (declspecs.storage_class != sc_none) |
36870 | { |
36871 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36872 | declspecs.storage_class = sc_none; |
36873 | } |
36874 | |
36875 | /* thread_local. */ |
36876 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_thread)) |
36877 | { |
36878 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36879 | declspecs.locations[ds_thread] = 0; |
36880 | } |
36881 | |
36882 | /* typedef. */ |
36883 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_typedef)) |
36884 | { |
36885 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36886 | declspecs.locations[ds_typedef] = 0; |
36887 | } |
36888 | |
36889 | prefix_attributes = declspecs.attributes; |
36890 | declspecs.attributes = NULL_TREE; |
36891 | |
36892 | /* Keep going until we hit the `;' at the end of the |
36893 | declaration. */ |
36894 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36895 | { |
36896 | tree width = NULL_TREE, attributes, first_attribute, decl; |
36897 | cp_declarator *declarator = NULL; |
36898 | int ctor_dtor_or_conv_p; |
36899 | |
36900 | /* Check for a (possibly unnamed) bitfield declaration. */ |
36901 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36902 | if (token->type == CPP_COLON) |
36903 | goto eat_colon; |
36904 | |
36905 | if (token->type == CPP_NAME |
36906 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
36907 | == CPP_COLON)) |
36908 | { |
36909 | /* Get the name of the bitfield. */ |
36910 | declarator = make_id_declarator (NULL_TREE, |
36911 | unqualified_name: cp_parser_identifier (parser), |
36912 | sfk: sfk_none, id_location: token->location); |
36913 | |
36914 | eat_colon: |
36915 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ':'. */ |
36916 | /* Get the width of the bitfield. */ |
36917 | width |
36918 | = cp_parser_constant_expression (parser); |
36919 | } |
36920 | else |
36921 | { |
36922 | /* Parse the declarator. */ |
36923 | declarator |
36924 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
36925 | flags: CP_PARSER_FLAGS_NONE, |
36926 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
36927 | /*parenthesized_p=*/NULL, |
36928 | /*member_p=*/false, |
36929 | /*friend_p=*/false, |
36930 | /*static_p=*/false); |
36931 | } |
36932 | |
36933 | /* Look for attributes that apply to the ivar. */ |
36934 | attributes = cp_parser_attributes_opt (parser); |
36935 | /* Remember which attributes are prefix attributes and |
36936 | which are not. */ |
36937 | first_attribute = attributes; |
36938 | /* Combine the attributes. */ |
36939 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
36940 | |
36941 | if (width) |
36942 | /* Create the bitfield declaration. */ |
36943 | decl = grokbitfield (declarator, &declspecs, |
36944 | width, NULL_TREE, attributes); |
36945 | else |
36946 | decl = grokfield (declarator, &declspecs, |
36947 | NULL_TREE, /*init_const_expr_p=*/false, |
36948 | NULL_TREE, attributes); |
36949 | |
36950 | /* Add the instance variable. */ |
36951 | if (decl != error_mark_node && decl != NULL_TREE) |
36952 | objc_add_instance_variable (decl); |
36953 | |
36954 | /* Reset PREFIX_ATTRIBUTES. */ |
36955 | if (attributes != error_mark_node) |
36956 | { |
36957 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
36958 | attributes = TREE_CHAIN (attributes); |
36959 | if (attributes) |
36960 | TREE_CHAIN (attributes) = NULL_TREE; |
36961 | } |
36962 | |
36963 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36964 | |
36965 | if (token->type == CPP_COMMA) |
36966 | { |
36967 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
36968 | continue; |
36969 | } |
36970 | break; |
36971 | } |
36972 | |
36973 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36974 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36975 | } |
36976 | |
36977 | if (token->keyword == RID_AT_END) |
36978 | cp_parser_error (parser, gmsgid: "expected %<}%>" ); |
36979 | |
36980 | /* Do not consume the RID_AT_END, so it will be read again as terminating |
36981 | the @interface of @implementation. */ |
36982 | if (token->keyword != RID_AT_END && token->type != CPP_EOF) |
36983 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '}'. */ |
36984 | |
36985 | /* For historical reasons, we accept an optional semicolon. */ |
36986 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36987 | cp_lexer_consume_token (lexer: parser->lexer); |
36988 | } |
36989 | |
36990 | /* Parse an Objective-C protocol declaration. */ |
36991 | |
36992 | static void |
36993 | cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) |
36994 | { |
36995 | tree proto, protorefs; |
36996 | cp_token *tok; |
36997 | |
36998 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@protocol'. */ |
36999 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
37000 | { |
37001 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
37002 | error_at (tok->location, "identifier expected after %<@protocol%>" ); |
37003 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37004 | return; |
37005 | } |
37006 | |
37007 | /* See if we have a forward declaration or a definition. */ |
37008 | tok = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
37009 | |
37010 | /* Try a forward declaration first. */ |
37011 | if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON) |
37012 | { |
37013 | while (true) |
37014 | { |
37015 | tree id; |
37016 | |
37017 | id = cp_parser_identifier (parser); |
37018 | if (id == error_mark_node) |
37019 | break; |
37020 | |
37021 | objc_declare_protocol (id, attributes); |
37022 | |
37023 | if(cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37024 | cp_lexer_consume_token (lexer: parser->lexer); |
37025 | else |
37026 | break; |
37027 | } |
37028 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37029 | } |
37030 | |
37031 | /* Ok, we got a full-fledged definition (or at least should). */ |
37032 | else |
37033 | { |
37034 | proto = cp_parser_identifier (parser); |
37035 | protorefs = cp_parser_objc_protocol_refs_opt (parser); |
37036 | objc_start_protocol (proto, protorefs, attributes); |
37037 | cp_parser_objc_method_prototype_list (parser); |
37038 | } |
37039 | } |
37040 | |
37041 | /* Parse an Objective-C superclass or category. */ |
37042 | |
37043 | static void |
37044 | cp_parser_objc_superclass_or_category (cp_parser *parser, |
37045 | bool iface_p, |
37046 | tree *super, |
37047 | tree *categ, bool *is_class_extension) |
37048 | { |
37049 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
37050 | |
37051 | *super = *categ = NULL_TREE; |
37052 | *is_class_extension = false; |
37053 | if (next->type == CPP_COLON) |
37054 | { |
37055 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ':'. */ |
37056 | *super = cp_parser_identifier (parser); |
37057 | } |
37058 | else if (next->type == CPP_OPEN_PAREN) |
37059 | { |
37060 | matching_parens parens; |
37061 | parens.consume_open (parser); /* Eat '('. */ |
37062 | |
37063 | /* If there is no category name, and this is an @interface, we |
37064 | have a class extension. */ |
37065 | if (iface_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
37066 | { |
37067 | *categ = NULL_TREE; |
37068 | *is_class_extension = true; |
37069 | } |
37070 | else |
37071 | *categ = cp_parser_identifier (parser); |
37072 | |
37073 | parens.require_close (parser); |
37074 | } |
37075 | } |
37076 | |
37077 | /* Parse an Objective-C class interface. */ |
37078 | |
37079 | static void |
37080 | cp_parser_objc_class_interface (cp_parser* parser, tree attributes) |
37081 | { |
37082 | tree name, super, categ, protos; |
37083 | bool is_class_extension; |
37084 | |
37085 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@interface'. */ |
37086 | location_t nam_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37087 | name = cp_parser_identifier (parser); |
37088 | if (name == error_mark_node) |
37089 | { |
37090 | /* It's hard to recover because even if valid @interface stuff |
37091 | is to follow, we can't compile it (or validate it) if we |
37092 | don't even know which class it refers to. Let's assume this |
37093 | was a stray '@interface' token in the stream and skip it. |
37094 | */ |
37095 | return; |
37096 | } |
37097 | cp_parser_objc_superclass_or_category (parser, iface_p: true, super: &super, categ: &categ, |
37098 | is_class_extension: &is_class_extension); |
37099 | protos = cp_parser_objc_protocol_refs_opt (parser); |
37100 | |
37101 | /* We have either a class or a category on our hands. */ |
37102 | if (categ || is_class_extension) |
37103 | objc_start_category_interface (name, categ, protos, attributes); |
37104 | else |
37105 | { |
37106 | objc_start_class_interface (name, nam_loc, super, protos, attributes); |
37107 | /* Handle instance variable declarations, if any. */ |
37108 | cp_parser_objc_class_ivars (parser); |
37109 | objc_continue_interface (); |
37110 | } |
37111 | |
37112 | cp_parser_objc_method_prototype_list (parser); |
37113 | } |
37114 | |
37115 | /* Parse an Objective-C class implementation. */ |
37116 | |
37117 | static void |
37118 | cp_parser_objc_class_implementation (cp_parser* parser) |
37119 | { |
37120 | tree name, super, categ; |
37121 | bool is_class_extension; |
37122 | |
37123 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@implementation'. */ |
37124 | name = cp_parser_identifier (parser); |
37125 | if (name == error_mark_node) |
37126 | { |
37127 | /* It's hard to recover because even if valid @implementation |
37128 | stuff is to follow, we can't compile it (or validate it) if |
37129 | we don't even know which class it refers to. Let's assume |
37130 | this was a stray '@implementation' token in the stream and |
37131 | skip it. |
37132 | */ |
37133 | return; |
37134 | } |
37135 | cp_parser_objc_superclass_or_category (parser, iface_p: false, super: &super, categ: &categ, |
37136 | is_class_extension: &is_class_extension); |
37137 | |
37138 | /* We have either a class or a category on our hands. */ |
37139 | if (categ) |
37140 | objc_start_category_implementation (name, categ); |
37141 | else |
37142 | { |
37143 | objc_start_class_implementation (name, super); |
37144 | /* Handle instance variable declarations, if any. */ |
37145 | cp_parser_objc_class_ivars (parser); |
37146 | objc_continue_implementation (); |
37147 | } |
37148 | |
37149 | cp_parser_objc_method_definition_list (parser); |
37150 | } |
37151 | |
37152 | /* Consume the @end token and finish off the implementation. */ |
37153 | |
37154 | static void |
37155 | cp_parser_objc_end_implementation (cp_parser* parser) |
37156 | { |
37157 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
37158 | objc_finish_implementation (); |
37159 | } |
37160 | |
37161 | /* Parse an Objective-C declaration. */ |
37162 | |
37163 | static void |
37164 | cp_parser_objc_declaration (cp_parser* parser, tree attributes) |
37165 | { |
37166 | /* Try to figure out what kind of declaration is present. */ |
37167 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
37168 | |
37169 | if (attributes) |
37170 | switch (kwd->keyword) |
37171 | { |
37172 | case RID_AT_ALIAS: |
37173 | case RID_AT_CLASS: |
37174 | case RID_AT_END: |
37175 | error_at (kwd->location, "attributes may not be specified before" |
37176 | " the %<@%D%> Objective-C++ keyword" , |
37177 | kwd->u.value); |
37178 | attributes = NULL; |
37179 | break; |
37180 | case RID_AT_IMPLEMENTATION: |
37181 | warning_at (kwd->location, OPT_Wattributes, |
37182 | "prefix attributes are ignored before %<@%D%>" , |
37183 | kwd->u.value); |
37184 | attributes = NULL; |
37185 | default: |
37186 | break; |
37187 | } |
37188 | |
37189 | switch (kwd->keyword) |
37190 | { |
37191 | case RID_AT_ALIAS: |
37192 | cp_parser_objc_alias_declaration (parser); |
37193 | break; |
37194 | case RID_AT_CLASS: |
37195 | cp_parser_objc_class_declaration (parser); |
37196 | break; |
37197 | case RID_AT_PROTOCOL: |
37198 | cp_parser_objc_protocol_declaration (parser, attributes); |
37199 | break; |
37200 | case RID_AT_INTERFACE: |
37201 | cp_parser_objc_class_interface (parser, attributes); |
37202 | break; |
37203 | case RID_AT_IMPLEMENTATION: |
37204 | cp_parser_objc_class_implementation (parser); |
37205 | break; |
37206 | case RID_AT_END: |
37207 | cp_parser_objc_end_implementation (parser); |
37208 | break; |
37209 | default: |
37210 | error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct" , |
37211 | kwd->u.value); |
37212 | cp_parser_skip_to_end_of_block_or_statement (parser); |
37213 | } |
37214 | } |
37215 | |
37216 | /* Parse an Objective-C try-catch-finally statement. |
37217 | |
37218 | objc-try-catch-finally-stmt: |
37219 | @try compound-statement objc-catch-clause-seq [opt] |
37220 | objc-finally-clause [opt] |
37221 | |
37222 | objc-catch-clause-seq: |
37223 | objc-catch-clause objc-catch-clause-seq [opt] |
37224 | |
37225 | objc-catch-clause: |
37226 | @catch ( objc-exception-declaration ) compound-statement |
37227 | |
37228 | objc-finally-clause: |
37229 | @finally compound-statement |
37230 | |
37231 | objc-exception-declaration: |
37232 | parameter-declaration |
37233 | '...' |
37234 | |
37235 | where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS. |
37236 | |
37237 | Returns NULL_TREE. |
37238 | |
37239 | PS: This function is identical to c_parser_objc_try_catch_finally_statement |
37240 | for C. Keep them in sync. */ |
37241 | |
37242 | static tree |
37243 | cp_parser_objc_try_catch_finally_statement (cp_parser *parser) |
37244 | { |
37245 | location_t location; |
37246 | tree stmt; |
37247 | |
37248 | cp_parser_require_keyword (parser, keyword: RID_AT_TRY, token_desc: RT_AT_TRY); |
37249 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37250 | objc_maybe_warn_exceptions (location); |
37251 | /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST |
37252 | node, lest it get absorbed into the surrounding block. */ |
37253 | stmt = push_stmt_list (); |
37254 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
37255 | objc_begin_try_stmt (location, pop_stmt_list (stmt)); |
37256 | |
37257 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_CATCH)) |
37258 | { |
37259 | cp_parameter_declarator *parm; |
37260 | tree parameter_declaration = error_mark_node; |
37261 | bool seen_open_paren = false; |
37262 | matching_parens parens; |
37263 | |
37264 | cp_lexer_consume_token (lexer: parser->lexer); |
37265 | if (parens.require_open (parser)) |
37266 | seen_open_paren = true; |
37267 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
37268 | { |
37269 | /* We have "@catch (...)" (where the '...' are literally |
37270 | what is in the code). Skip the '...'. |
37271 | parameter_declaration is set to NULL_TREE, and |
37272 | objc_being_catch_clauses() knows that that means |
37273 | '...'. */ |
37274 | cp_lexer_consume_token (lexer: parser->lexer); |
37275 | parameter_declaration = NULL_TREE; |
37276 | } |
37277 | else |
37278 | { |
37279 | /* We have "@catch (NSException *exception)" or something |
37280 | like that. Parse the parameter declaration. */ |
37281 | parm = cp_parser_parameter_declaration (parser, flags: CP_PARSER_FLAGS_NONE, |
37282 | template_parm_p: false, NULL); |
37283 | if (parm == NULL) |
37284 | parameter_declaration = error_mark_node; |
37285 | else |
37286 | parameter_declaration = grokdeclarator (parm->declarator, |
37287 | &parm->decl_specifiers, |
37288 | PARM, /*initialized=*/0, |
37289 | /*attrlist=*/NULL); |
37290 | } |
37291 | if (seen_open_paren) |
37292 | parens.require_close (parser); |
37293 | else |
37294 | { |
37295 | /* If there was no open parenthesis, we are recovering from |
37296 | an error, and we are trying to figure out what mistake |
37297 | the user has made. */ |
37298 | |
37299 | /* If there is an immediate closing parenthesis, the user |
37300 | probably forgot the opening one (ie, they typed "@catch |
37301 | NSException *e)". Parse the closing parenthesis and keep |
37302 | going. */ |
37303 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
37304 | cp_lexer_consume_token (lexer: parser->lexer); |
37305 | |
37306 | /* If these is no immediate closing parenthesis, the user |
37307 | probably doesn't know that parenthesis are required at |
37308 | all (ie, they typed "@catch NSException *e"). So, just |
37309 | forget about the closing parenthesis and keep going. */ |
37310 | } |
37311 | objc_begin_catch_clause (parameter_declaration); |
37312 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
37313 | objc_finish_catch_clause (); |
37314 | } |
37315 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_FINALLY)) |
37316 | { |
37317 | cp_lexer_consume_token (lexer: parser->lexer); |
37318 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37319 | /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST |
37320 | node, lest it get absorbed into the surrounding block. */ |
37321 | stmt = push_stmt_list (); |
37322 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
37323 | objc_build_finally_clause (location, pop_stmt_list (stmt)); |
37324 | } |
37325 | |
37326 | return objc_finish_try_stmt (); |
37327 | } |
37328 | |
37329 | /* Parse an Objective-C synchronized statement. |
37330 | |
37331 | objc-synchronized-stmt: |
37332 | @synchronized ( expression ) compound-statement |
37333 | |
37334 | Returns NULL_TREE. */ |
37335 | |
37336 | static tree |
37337 | cp_parser_objc_synchronized_statement (cp_parser *parser) |
37338 | { |
37339 | location_t location; |
37340 | tree lock, stmt; |
37341 | |
37342 | cp_parser_require_keyword (parser, keyword: RID_AT_SYNCHRONIZED, token_desc: RT_AT_SYNCHRONIZED); |
37343 | |
37344 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37345 | objc_maybe_warn_exceptions (location); |
37346 | matching_parens parens; |
37347 | parens.require_open (parser); |
37348 | lock = cp_parser_expression (parser); |
37349 | parens.require_close (parser); |
37350 | |
37351 | /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST |
37352 | node, lest it get absorbed into the surrounding block. */ |
37353 | stmt = push_stmt_list (); |
37354 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
37355 | |
37356 | return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); |
37357 | } |
37358 | |
37359 | /* Parse an Objective-C throw statement. |
37360 | |
37361 | objc-throw-stmt: |
37362 | @throw assignment-expression [opt] ; |
37363 | |
37364 | Returns a constructed '@throw' statement. */ |
37365 | |
37366 | static tree |
37367 | cp_parser_objc_throw_statement (cp_parser *parser) |
37368 | { |
37369 | tree expr = NULL_TREE; |
37370 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37371 | |
37372 | cp_parser_require_keyword (parser, keyword: RID_AT_THROW, token_desc: RT_AT_THROW); |
37373 | |
37374 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
37375 | expr = cp_parser_expression (parser); |
37376 | |
37377 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37378 | |
37379 | return objc_build_throw_stmt (loc, expr); |
37380 | } |
37381 | |
37382 | /* Parse an Objective-C statement. */ |
37383 | |
37384 | static tree |
37385 | cp_parser_objc_statement (cp_parser * parser) |
37386 | { |
37387 | /* Try to figure out what kind of declaration is present. */ |
37388 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
37389 | |
37390 | switch (kwd->keyword) |
37391 | { |
37392 | case RID_AT_TRY: |
37393 | return cp_parser_objc_try_catch_finally_statement (parser); |
37394 | case RID_AT_SYNCHRONIZED: |
37395 | return cp_parser_objc_synchronized_statement (parser); |
37396 | case RID_AT_THROW: |
37397 | return cp_parser_objc_throw_statement (parser); |
37398 | default: |
37399 | error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct" , |
37400 | kwd->u.value); |
37401 | cp_parser_skip_to_end_of_block_or_statement (parser); |
37402 | } |
37403 | |
37404 | return error_mark_node; |
37405 | } |
37406 | |
37407 | /* If we are compiling ObjC++ and we see an __attribute__ we neeed to |
37408 | look ahead to see if an objc keyword follows the attributes. This |
37409 | is to detect the use of prefix attributes on ObjC @interface and |
37410 | @protocol. */ |
37411 | |
37412 | static bool |
37413 | cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) |
37414 | { |
37415 | cp_lexer_save_tokens (lexer: parser->lexer); |
37416 | tree addon = cp_parser_attributes_opt (parser); |
37417 | if (addon |
37418 | && OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) |
37419 | { |
37420 | cp_lexer_commit_tokens (lexer: parser->lexer); |
37421 | if (*attrib) |
37422 | TREE_CHAIN (*attrib) = addon; |
37423 | else |
37424 | *attrib = addon; |
37425 | return true; |
37426 | } |
37427 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
37428 | return false; |
37429 | } |
37430 | |
37431 | /* This routine is a minimal replacement for |
37432 | c_parser_struct_declaration () used when parsing the list of |
37433 | types/names or ObjC++ properties. For example, when parsing the |
37434 | code |
37435 | |
37436 | @property (readonly) int a, b, c; |
37437 | |
37438 | this function is responsible for parsing "int a, int b, int c" and |
37439 | returning the declarations as CHAIN of DECLs. |
37440 | |
37441 | TODO: Share this code with cp_parser_objc_class_ivars. It's very |
37442 | similar parsing. */ |
37443 | static tree |
37444 | cp_parser_objc_struct_declaration (cp_parser *parser) |
37445 | { |
37446 | tree decls = NULL_TREE; |
37447 | cp_decl_specifier_seq declspecs; |
37448 | int decl_class_or_enum_p; |
37449 | tree prefix_attributes; |
37450 | |
37451 | cp_parser_decl_specifier_seq (parser, |
37452 | flags: CP_PARSER_FLAGS_NONE, |
37453 | decl_specs: &declspecs, |
37454 | declares_class_or_enum: &decl_class_or_enum_p); |
37455 | |
37456 | if (declspecs.type == error_mark_node) |
37457 | return error_mark_node; |
37458 | |
37459 | /* auto, register, static, extern, mutable. */ |
37460 | if (declspecs.storage_class != sc_none) |
37461 | { |
37462 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37463 | declspecs.storage_class = sc_none; |
37464 | } |
37465 | |
37466 | /* thread_local. */ |
37467 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_thread)) |
37468 | { |
37469 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37470 | declspecs.locations[ds_thread] = 0; |
37471 | } |
37472 | |
37473 | /* typedef. */ |
37474 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_typedef)) |
37475 | { |
37476 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37477 | declspecs.locations[ds_typedef] = 0; |
37478 | } |
37479 | |
37480 | prefix_attributes = declspecs.attributes; |
37481 | declspecs.attributes = NULL_TREE; |
37482 | |
37483 | /* Keep going until we hit the `;' at the end of the declaration. */ |
37484 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
37485 | { |
37486 | tree attributes, first_attribute, decl; |
37487 | cp_declarator *declarator; |
37488 | cp_token *token; |
37489 | |
37490 | /* Parse the declarator. */ |
37491 | declarator = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
37492 | flags: CP_PARSER_FLAGS_NONE, |
37493 | NULL, NULL, member_p: false, friend_p: false, static_p: false); |
37494 | |
37495 | /* Look for attributes that apply to the ivar. */ |
37496 | attributes = cp_parser_attributes_opt (parser); |
37497 | /* Remember which attributes are prefix attributes and |
37498 | which are not. */ |
37499 | first_attribute = attributes; |
37500 | /* Combine the attributes. */ |
37501 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
37502 | |
37503 | decl = grokfield (declarator, &declspecs, |
37504 | NULL_TREE, /*init_const_expr_p=*/false, |
37505 | NULL_TREE, attributes); |
37506 | |
37507 | if (decl == error_mark_node || decl == NULL_TREE) |
37508 | return error_mark_node; |
37509 | |
37510 | /* Reset PREFIX_ATTRIBUTES. */ |
37511 | if (attributes != error_mark_node) |
37512 | { |
37513 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
37514 | attributes = TREE_CHAIN (attributes); |
37515 | if (attributes) |
37516 | TREE_CHAIN (attributes) = NULL_TREE; |
37517 | } |
37518 | |
37519 | DECL_CHAIN (decl) = decls; |
37520 | decls = decl; |
37521 | |
37522 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37523 | if (token->type == CPP_COMMA) |
37524 | { |
37525 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
37526 | continue; |
37527 | } |
37528 | else |
37529 | break; |
37530 | } |
37531 | return decls; |
37532 | } |
37533 | |
37534 | /* Parse an Objective-C @property declaration. The syntax is: |
37535 | |
37536 | objc-property-declaration: |
37537 | '@property' objc-property-attributes[opt] struct-declaration ; |
37538 | |
37539 | objc-property-attributes: |
37540 | '(' objc-property-attribute-list ')' |
37541 | |
37542 | objc-property-attribute-list: |
37543 | objc-property-attribute |
37544 | objc-property-attribute-list, objc-property-attribute |
37545 | |
37546 | objc-property-attribute |
37547 | 'getter' = identifier |
37548 | 'setter' = identifier |
37549 | 'readonly' |
37550 | 'readwrite' |
37551 | 'assign' |
37552 | 'retain' |
37553 | 'copy' |
37554 | 'nonatomic' |
37555 | |
37556 | For example: |
37557 | @property NSString *name; |
37558 | @property (readonly) id object; |
37559 | @property (retain, nonatomic, getter=getTheName) id name; |
37560 | @property int a, b, c; |
37561 | |
37562 | PS: This function is identical to |
37563 | c_parser_objc_at_property_declaration for C. Keep them in sync. */ |
37564 | static void |
37565 | cp_parser_objc_at_property_declaration (cp_parser *parser) |
37566 | { |
37567 | /* Parse the optional attribute list. |
37568 | |
37569 | A list of parsed, but not verified, attributes. */ |
37570 | auto_delete_vec<property_attribute_info> prop_attr_list; |
37571 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37572 | |
37573 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@property'. */ |
37574 | |
37575 | /* Parse the optional attribute list... */ |
37576 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
37577 | { |
37578 | /* Eat the '('. */ |
37579 | matching_parens parens; |
37580 | location_t attr_start = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37581 | parens.consume_open (parser); |
37582 | bool syntax_error = false; |
37583 | |
37584 | /* Allow empty @property attribute lists, but with a warning. */ |
37585 | location_t attr_end = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37586 | location_t attr_comb; |
37587 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
37588 | { |
37589 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37590 | warning_at (attr_comb, OPT_Wattributes, |
37591 | "empty property attribute list" ); |
37592 | } |
37593 | else |
37594 | while (true) |
37595 | { |
37596 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
37597 | attr_start = token->location; |
37598 | attr_end = get_finish (loc: token->location); |
37599 | attr_comb = make_location (caret: attr_start, start: attr_start, finish: attr_end); |
37600 | |
37601 | if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA) |
37602 | { |
37603 | warning_at (attr_comb, OPT_Wattributes, |
37604 | "missing property attribute" ); |
37605 | if (token->type == CPP_CLOSE_PAREN) |
37606 | break; |
37607 | cp_lexer_consume_token (lexer: parser->lexer); |
37608 | continue; |
37609 | } |
37610 | |
37611 | tree attr_name = NULL_TREE; |
37612 | if (identifier_p (t: token->u.value)) |
37613 | attr_name = token->u.value; |
37614 | |
37615 | enum rid keyword; |
37616 | if (token->type == CPP_NAME) |
37617 | keyword = C_RID_CODE (token->u.value); |
37618 | else if (token->type == CPP_KEYWORD |
37619 | && token->keyword == RID_CLASS) |
37620 | /* Account for accepting the 'class' keyword in this context. */ |
37621 | keyword = RID_CLASS; |
37622 | else |
37623 | keyword = RID_MAX; /* By definition, an unknown property. */ |
37624 | cp_lexer_consume_token (lexer: parser->lexer); |
37625 | |
37626 | enum objc_property_attribute_kind prop_kind |
37627 | = objc_prop_attr_kind_for_rid (keyword); |
37628 | property_attribute_info *prop |
37629 | = new property_attribute_info (attr_name, attr_comb, prop_kind); |
37630 | prop_attr_list.safe_push (obj: prop); |
37631 | |
37632 | tree meth_name; |
37633 | switch (prop->prop_kind) |
37634 | { |
37635 | default: break; |
37636 | case OBJC_PROPERTY_ATTR_UNKNOWN: |
37637 | if (attr_name) |
37638 | error_at (attr_start, "unknown property attribute %qE" , |
37639 | attr_name); |
37640 | else |
37641 | error_at (attr_start, "unknown property attribute" ); |
37642 | prop->parse_error = syntax_error = true; |
37643 | break; |
37644 | |
37645 | case OBJC_PROPERTY_ATTR_GETTER: |
37646 | case OBJC_PROPERTY_ATTR_SETTER: |
37647 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ)) |
37648 | { |
37649 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37650 | error_at (attr_comb, "expected %<=%> after Objective-C %qE" , |
37651 | attr_name); |
37652 | prop->parse_error = syntax_error = true; |
37653 | break; |
37654 | } |
37655 | |
37656 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37657 | attr_end = token->location; |
37658 | cp_lexer_consume_token (lexer: parser->lexer); /* eat the = */ |
37659 | |
37660 | if (!cp_parser_objc_selector_p |
37661 | (type: cp_lexer_peek_token (lexer: parser->lexer)->type)) |
37662 | { |
37663 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37664 | error_at (attr_comb, "expected %qE selector name" , |
37665 | attr_name); |
37666 | prop->parse_error = syntax_error = true; |
37667 | break; |
37668 | } |
37669 | |
37670 | /* Get the end of the method name, and consume the name. */ |
37671 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37672 | attr_end = get_finish (loc: token->location); |
37673 | /* Because method names may contain C++ keywords, we have a |
37674 | routine to fetch them (this also consumes the token). */ |
37675 | meth_name = cp_parser_objc_selector (parser); |
37676 | |
37677 | if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER) |
37678 | { |
37679 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
37680 | { |
37681 | attr_comb = make_location (caret: attr_end, start: attr_start, |
37682 | finish: attr_end); |
37683 | error_at (attr_comb, "setter method names must" |
37684 | " terminate with %<:%>" ); |
37685 | prop->parse_error = syntax_error = true; |
37686 | } |
37687 | else |
37688 | { |
37689 | attr_end = get_finish (loc: cp_lexer_peek_token |
37690 | (lexer: parser->lexer)->location); |
37691 | cp_lexer_consume_token (lexer: parser->lexer); |
37692 | } |
37693 | attr_comb = make_location (caret: attr_start, start: attr_start, |
37694 | finish: attr_end); |
37695 | } |
37696 | else |
37697 | attr_comb = make_location (caret: attr_start, start: attr_start, |
37698 | finish: attr_end); |
37699 | prop->ident = meth_name; |
37700 | /* Updated location including all that was successfully |
37701 | parsed. */ |
37702 | prop->prop_loc = attr_comb; |
37703 | break; |
37704 | } |
37705 | |
37706 | /* If we see a comma here, then keep going - even if we already |
37707 | saw a syntax error. For simple mistakes e.g. (asign, getter=x) |
37708 | this makes a more useful output and avoid spurious warnings |
37709 | about missing attributes that are, in fact, specified after the |
37710 | one with the syntax error. */ |
37711 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37712 | cp_lexer_consume_token (lexer: parser->lexer); |
37713 | else |
37714 | break; |
37715 | } |
37716 | |
37717 | if (syntax_error || !parens.require_close (parser)) |
37718 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
37719 | /*or_comma=*/false, |
37720 | /*consume_paren=*/true); |
37721 | } |
37722 | |
37723 | /* 'properties' is the list of properties that we read. Usually a |
37724 | single one, but maybe more (eg, in "@property int a, b, c;" there |
37725 | are three). |
37726 | TODO: Update this parsing so that it accepts (erroneous) bitfields so |
37727 | that we can issue a meaningful and consistent (between C/C++) error |
37728 | message from objc_add_property_declaration (). */ |
37729 | tree properties = cp_parser_objc_struct_declaration (parser); |
37730 | |
37731 | if (properties == error_mark_node) |
37732 | cp_parser_skip_to_end_of_statement (parser); |
37733 | else if (properties == NULL_TREE) |
37734 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
37735 | else |
37736 | { |
37737 | /* Comma-separated properties are chained together in reverse order; |
37738 | add them one by one. */ |
37739 | properties = nreverse (properties); |
37740 | for (; properties; properties = TREE_CHAIN (properties)) |
37741 | objc_add_property_declaration (loc, copy_node (properties), |
37742 | prop_attr_list); |
37743 | } |
37744 | |
37745 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37746 | } |
37747 | |
37748 | /* Parse an Objective-C++ @synthesize declaration. The syntax is: |
37749 | |
37750 | objc-synthesize-declaration: |
37751 | @synthesize objc-synthesize-identifier-list ; |
37752 | |
37753 | objc-synthesize-identifier-list: |
37754 | objc-synthesize-identifier |
37755 | objc-synthesize-identifier-list, objc-synthesize-identifier |
37756 | |
37757 | objc-synthesize-identifier |
37758 | identifier |
37759 | identifier = identifier |
37760 | |
37761 | For example: |
37762 | @synthesize MyProperty; |
37763 | @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty; |
37764 | |
37765 | PS: This function is identical to c_parser_objc_at_synthesize_declaration |
37766 | for C. Keep them in sync. |
37767 | */ |
37768 | static void |
37769 | cp_parser_objc_at_synthesize_declaration (cp_parser *parser) |
37770 | { |
37771 | tree list = NULL_TREE; |
37772 | location_t loc; |
37773 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37774 | |
37775 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@synthesize'. */ |
37776 | while (true) |
37777 | { |
37778 | tree property, ivar; |
37779 | property = cp_parser_identifier (parser); |
37780 | if (property == error_mark_node) |
37781 | { |
37782 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37783 | return; |
37784 | } |
37785 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
37786 | { |
37787 | cp_lexer_consume_token (lexer: parser->lexer); |
37788 | ivar = cp_parser_identifier (parser); |
37789 | if (ivar == error_mark_node) |
37790 | { |
37791 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37792 | return; |
37793 | } |
37794 | } |
37795 | else |
37796 | ivar = NULL_TREE; |
37797 | list = chainon (list, build_tree_list (ivar, property)); |
37798 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37799 | cp_lexer_consume_token (lexer: parser->lexer); |
37800 | else |
37801 | break; |
37802 | } |
37803 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37804 | objc_add_synthesize_declaration (loc, list); |
37805 | } |
37806 | |
37807 | /* Parse an Objective-C++ @dynamic declaration. The syntax is: |
37808 | |
37809 | objc-dynamic-declaration: |
37810 | @dynamic identifier-list ; |
37811 | |
37812 | For example: |
37813 | @dynamic MyProperty; |
37814 | @dynamic MyProperty, AnotherProperty; |
37815 | |
37816 | PS: This function is identical to c_parser_objc_at_dynamic_declaration |
37817 | for C. Keep them in sync. |
37818 | */ |
37819 | static void |
37820 | cp_parser_objc_at_dynamic_declaration (cp_parser *parser) |
37821 | { |
37822 | tree list = NULL_TREE; |
37823 | location_t loc; |
37824 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37825 | |
37826 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@dynamic'. */ |
37827 | while (true) |
37828 | { |
37829 | tree property; |
37830 | property = cp_parser_identifier (parser); |
37831 | if (property == error_mark_node) |
37832 | { |
37833 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37834 | return; |
37835 | } |
37836 | list = chainon (list, build_tree_list (NULL, property)); |
37837 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37838 | cp_lexer_consume_token (lexer: parser->lexer); |
37839 | else |
37840 | break; |
37841 | } |
37842 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37843 | objc_add_dynamic_declaration (loc, list); |
37844 | } |
37845 | |
37846 | |
37847 | /* OpenMP 2.5 / 3.0 / 3.1 / 4.0 / 4.5 / 5.0 parsing routines. */ |
37848 | |
37849 | /* Returns name of the next clause. |
37850 | If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and |
37851 | the token is not consumed. Otherwise appropriate pragma_omp_clause is |
37852 | returned and the token is consumed. */ |
37853 | |
37854 | static pragma_omp_clause |
37855 | cp_parser_omp_clause_name (cp_parser *parser) |
37856 | { |
37857 | pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE; |
37858 | |
37859 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
37860 | result = PRAGMA_OACC_CLAUSE_AUTO; |
37861 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
37862 | result = PRAGMA_OMP_CLAUSE_IF; |
37863 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT)) |
37864 | result = PRAGMA_OMP_CLAUSE_DEFAULT; |
37865 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DELETE)) |
37866 | result = PRAGMA_OACC_CLAUSE_DELETE; |
37867 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_PRIVATE)) |
37868 | result = PRAGMA_OMP_CLAUSE_PRIVATE; |
37869 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
37870 | result = PRAGMA_OMP_CLAUSE_FOR; |
37871 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
37872 | { |
37873 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
37874 | const char *p = IDENTIFIER_POINTER (id); |
37875 | |
37876 | switch (p[0]) |
37877 | { |
37878 | case 'a': |
37879 | if (!strcmp (s1: "affinity" , s2: p)) |
37880 | result = PRAGMA_OMP_CLAUSE_AFFINITY; |
37881 | else if (!strcmp (s1: "aligned" , s2: p)) |
37882 | result = PRAGMA_OMP_CLAUSE_ALIGNED; |
37883 | else if (!strcmp (s1: "allocate" , s2: p)) |
37884 | result = PRAGMA_OMP_CLAUSE_ALLOCATE; |
37885 | else if (!strcmp (s1: "async" , s2: p)) |
37886 | result = PRAGMA_OACC_CLAUSE_ASYNC; |
37887 | else if (!strcmp (s1: "attach" , s2: p)) |
37888 | result = PRAGMA_OACC_CLAUSE_ATTACH; |
37889 | break; |
37890 | case 'b': |
37891 | if (!strcmp (s1: "bind" , s2: p)) |
37892 | result = PRAGMA_OMP_CLAUSE_BIND; |
37893 | break; |
37894 | case 'c': |
37895 | if (!strcmp (s1: "collapse" , s2: p)) |
37896 | result = PRAGMA_OMP_CLAUSE_COLLAPSE; |
37897 | else if (!strcmp (s1: "copy" , s2: p)) |
37898 | result = PRAGMA_OACC_CLAUSE_COPY; |
37899 | else if (!strcmp (s1: "copyin" , s2: p)) |
37900 | result = PRAGMA_OMP_CLAUSE_COPYIN; |
37901 | else if (!strcmp (s1: "copyout" , s2: p)) |
37902 | result = PRAGMA_OACC_CLAUSE_COPYOUT; |
37903 | else if (!strcmp (s1: "copyprivate" , s2: p)) |
37904 | result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; |
37905 | else if (!strcmp (s1: "create" , s2: p)) |
37906 | result = PRAGMA_OACC_CLAUSE_CREATE; |
37907 | break; |
37908 | case 'd': |
37909 | if (!strcmp (s1: "defaultmap" , s2: p)) |
37910 | result = PRAGMA_OMP_CLAUSE_DEFAULTMAP; |
37911 | else if (!strcmp (s1: "depend" , s2: p)) |
37912 | result = PRAGMA_OMP_CLAUSE_DEPEND; |
37913 | else if (!strcmp (s1: "detach" , s2: p)) |
37914 | result = PRAGMA_OACC_CLAUSE_DETACH; |
37915 | else if (!strcmp (s1: "device" , s2: p)) |
37916 | result = PRAGMA_OMP_CLAUSE_DEVICE; |
37917 | else if (!strcmp (s1: "deviceptr" , s2: p)) |
37918 | result = PRAGMA_OACC_CLAUSE_DEVICEPTR; |
37919 | else if (!strcmp (s1: "device_resident" , s2: p)) |
37920 | result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT; |
37921 | else if (!strcmp (s1: "device_type" , s2: p)) |
37922 | result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; |
37923 | else if (!strcmp (s1: "dist_schedule" , s2: p)) |
37924 | result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; |
37925 | else if (!strcmp (s1: "doacross" , s2: p)) |
37926 | result = PRAGMA_OMP_CLAUSE_DOACROSS; |
37927 | break; |
37928 | case 'e': |
37929 | if (!strcmp (s1: "enter" , s2: p)) |
37930 | result = PRAGMA_OMP_CLAUSE_ENTER; |
37931 | break; |
37932 | case 'f': |
37933 | if (!strcmp (s1: "filter" , s2: p)) |
37934 | result = PRAGMA_OMP_CLAUSE_FILTER; |
37935 | else if (!strcmp (s1: "final" , s2: p)) |
37936 | result = PRAGMA_OMP_CLAUSE_FINAL; |
37937 | else if (!strcmp (s1: "finalize" , s2: p)) |
37938 | result = PRAGMA_OACC_CLAUSE_FINALIZE; |
37939 | else if (!strcmp (s1: "firstprivate" , s2: p)) |
37940 | result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; |
37941 | else if (!strcmp (s1: "from" , s2: p)) |
37942 | result = PRAGMA_OMP_CLAUSE_FROM; |
37943 | break; |
37944 | case 'g': |
37945 | if (!strcmp (s1: "gang" , s2: p)) |
37946 | result = PRAGMA_OACC_CLAUSE_GANG; |
37947 | else if (!strcmp (s1: "grainsize" , s2: p)) |
37948 | result = PRAGMA_OMP_CLAUSE_GRAINSIZE; |
37949 | break; |
37950 | case 'h': |
37951 | if (!strcmp (s1: "has_device_addr" , s2: p)) |
37952 | result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR; |
37953 | else if (!strcmp (s1: "hint" , s2: p)) |
37954 | result = PRAGMA_OMP_CLAUSE_HINT; |
37955 | else if (!strcmp (s1: "host" , s2: p)) |
37956 | result = PRAGMA_OACC_CLAUSE_HOST; |
37957 | break; |
37958 | case 'i': |
37959 | if (!strcmp (s1: "if_present" , s2: p)) |
37960 | result = PRAGMA_OACC_CLAUSE_IF_PRESENT; |
37961 | else if (!strcmp (s1: "in_reduction" , s2: p)) |
37962 | result = PRAGMA_OMP_CLAUSE_IN_REDUCTION; |
37963 | else if (!strcmp (s1: "inbranch" , s2: p)) |
37964 | result = PRAGMA_OMP_CLAUSE_INBRANCH; |
37965 | else if (!strcmp (s1: "independent" , s2: p)) |
37966 | result = PRAGMA_OACC_CLAUSE_INDEPENDENT; |
37967 | else if (!strcmp (s1: "indirect" , s2: p)) |
37968 | result = PRAGMA_OMP_CLAUSE_INDIRECT; |
37969 | else if (!strcmp (s1: "is_device_ptr" , s2: p)) |
37970 | result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR; |
37971 | break; |
37972 | case 'l': |
37973 | if (!strcmp (s1: "lastprivate" , s2: p)) |
37974 | result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; |
37975 | else if (!strcmp (s1: "linear" , s2: p)) |
37976 | result = PRAGMA_OMP_CLAUSE_LINEAR; |
37977 | else if (!strcmp (s1: "link" , s2: p)) |
37978 | result = PRAGMA_OMP_CLAUSE_LINK; |
37979 | break; |
37980 | case 'm': |
37981 | if (!strcmp (s1: "map" , s2: p)) |
37982 | result = PRAGMA_OMP_CLAUSE_MAP; |
37983 | else if (!strcmp (s1: "mergeable" , s2: p)) |
37984 | result = PRAGMA_OMP_CLAUSE_MERGEABLE; |
37985 | break; |
37986 | case 'n': |
37987 | if (!strcmp (s1: "no_create" , s2: p)) |
37988 | result = PRAGMA_OACC_CLAUSE_NO_CREATE; |
37989 | else if (!strcmp (s1: "nogroup" , s2: p)) |
37990 | result = PRAGMA_OMP_CLAUSE_NOGROUP; |
37991 | else if (!strcmp (s1: "nohost" , s2: p)) |
37992 | result = PRAGMA_OACC_CLAUSE_NOHOST; |
37993 | else if (!strcmp (s1: "nontemporal" , s2: p)) |
37994 | result = PRAGMA_OMP_CLAUSE_NONTEMPORAL; |
37995 | else if (!strcmp (s1: "notinbranch" , s2: p)) |
37996 | result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; |
37997 | else if (!strcmp (s1: "nowait" , s2: p)) |
37998 | result = PRAGMA_OMP_CLAUSE_NOWAIT; |
37999 | else if (!strcmp (s1: "num_gangs" , s2: p)) |
38000 | result = PRAGMA_OACC_CLAUSE_NUM_GANGS; |
38001 | else if (!strcmp (s1: "num_tasks" , s2: p)) |
38002 | result = PRAGMA_OMP_CLAUSE_NUM_TASKS; |
38003 | else if (!strcmp (s1: "num_teams" , s2: p)) |
38004 | result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; |
38005 | else if (!strcmp (s1: "num_threads" , s2: p)) |
38006 | result = PRAGMA_OMP_CLAUSE_NUM_THREADS; |
38007 | else if (!strcmp (s1: "num_workers" , s2: p)) |
38008 | result = PRAGMA_OACC_CLAUSE_NUM_WORKERS; |
38009 | break; |
38010 | case 'o': |
38011 | if (!strcmp (s1: "ordered" , s2: p)) |
38012 | result = PRAGMA_OMP_CLAUSE_ORDERED; |
38013 | else if (!strcmp (s1: "order" , s2: p)) |
38014 | result = PRAGMA_OMP_CLAUSE_ORDER; |
38015 | break; |
38016 | case 'p': |
38017 | if (!strcmp (s1: "parallel" , s2: p)) |
38018 | result = PRAGMA_OMP_CLAUSE_PARALLEL; |
38019 | else if (!strcmp (s1: "present" , s2: p)) |
38020 | result = PRAGMA_OACC_CLAUSE_PRESENT; |
38021 | else if (!strcmp (s1: "present_or_copy" , s2: p) |
38022 | || !strcmp (s1: "pcopy" , s2: p)) |
38023 | result = PRAGMA_OACC_CLAUSE_COPY; |
38024 | else if (!strcmp (s1: "present_or_copyin" , s2: p) |
38025 | || !strcmp (s1: "pcopyin" , s2: p)) |
38026 | result = PRAGMA_OACC_CLAUSE_COPYIN; |
38027 | else if (!strcmp (s1: "present_or_copyout" , s2: p) |
38028 | || !strcmp (s1: "pcopyout" , s2: p)) |
38029 | result = PRAGMA_OACC_CLAUSE_COPYOUT; |
38030 | else if (!strcmp (s1: "present_or_create" , s2: p) |
38031 | || !strcmp (s1: "pcreate" , s2: p)) |
38032 | result = PRAGMA_OACC_CLAUSE_CREATE; |
38033 | else if (!strcmp (s1: "priority" , s2: p)) |
38034 | result = PRAGMA_OMP_CLAUSE_PRIORITY; |
38035 | else if (!strcmp (s1: "proc_bind" , s2: p)) |
38036 | result = PRAGMA_OMP_CLAUSE_PROC_BIND; |
38037 | break; |
38038 | case 'r': |
38039 | if (!strcmp (s1: "reduction" , s2: p)) |
38040 | result = PRAGMA_OMP_CLAUSE_REDUCTION; |
38041 | break; |
38042 | case 's': |
38043 | if (!strcmp (s1: "safelen" , s2: p)) |
38044 | result = PRAGMA_OMP_CLAUSE_SAFELEN; |
38045 | else if (!strcmp (s1: "schedule" , s2: p)) |
38046 | result = PRAGMA_OMP_CLAUSE_SCHEDULE; |
38047 | else if (!strcmp (s1: "sections" , s2: p)) |
38048 | result = PRAGMA_OMP_CLAUSE_SECTIONS; |
38049 | else if (!strcmp (s1: "self" , s2: p)) |
38050 | result = PRAGMA_OACC_CLAUSE_SELF; |
38051 | else if (!strcmp (s1: "seq" , s2: p)) |
38052 | result = PRAGMA_OACC_CLAUSE_SEQ; |
38053 | else if (!strcmp (s1: "shared" , s2: p)) |
38054 | result = PRAGMA_OMP_CLAUSE_SHARED; |
38055 | else if (!strcmp (s1: "simd" , s2: p)) |
38056 | result = PRAGMA_OMP_CLAUSE_SIMD; |
38057 | else if (!strcmp (s1: "simdlen" , s2: p)) |
38058 | result = PRAGMA_OMP_CLAUSE_SIMDLEN; |
38059 | break; |
38060 | case 't': |
38061 | if (!strcmp (s1: "task_reduction" , s2: p)) |
38062 | result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION; |
38063 | else if (!strcmp (s1: "taskgroup" , s2: p)) |
38064 | result = PRAGMA_OMP_CLAUSE_TASKGROUP; |
38065 | else if (!strcmp (s1: "thread_limit" , s2: p)) |
38066 | result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT; |
38067 | else if (!strcmp (s1: "threads" , s2: p)) |
38068 | result = PRAGMA_OMP_CLAUSE_THREADS; |
38069 | else if (!strcmp (s1: "tile" , s2: p)) |
38070 | result = PRAGMA_OACC_CLAUSE_TILE; |
38071 | else if (!strcmp (s1: "to" , s2: p)) |
38072 | result = PRAGMA_OMP_CLAUSE_TO; |
38073 | break; |
38074 | case 'u': |
38075 | if (!strcmp (s1: "uniform" , s2: p)) |
38076 | result = PRAGMA_OMP_CLAUSE_UNIFORM; |
38077 | else if (!strcmp (s1: "untied" , s2: p)) |
38078 | result = PRAGMA_OMP_CLAUSE_UNTIED; |
38079 | else if (!strcmp (s1: "use_device" , s2: p)) |
38080 | result = PRAGMA_OACC_CLAUSE_USE_DEVICE; |
38081 | else if (!strcmp (s1: "use_device_addr" , s2: p)) |
38082 | result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR; |
38083 | else if (!strcmp (s1: "use_device_ptr" , s2: p)) |
38084 | result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR; |
38085 | break; |
38086 | case 'v': |
38087 | if (!strcmp (s1: "vector" , s2: p)) |
38088 | result = PRAGMA_OACC_CLAUSE_VECTOR; |
38089 | else if (!strcmp (s1: "vector_length" , s2: p)) |
38090 | result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH; |
38091 | break; |
38092 | case 'w': |
38093 | if (!strcmp (s1: "wait" , s2: p)) |
38094 | result = PRAGMA_OACC_CLAUSE_WAIT; |
38095 | else if (!strcmp (s1: "worker" , s2: p)) |
38096 | result = PRAGMA_OACC_CLAUSE_WORKER; |
38097 | break; |
38098 | } |
38099 | } |
38100 | |
38101 | if (result != PRAGMA_OMP_CLAUSE_NONE) |
38102 | cp_lexer_consume_token (lexer: parser->lexer); |
38103 | |
38104 | return result; |
38105 | } |
38106 | |
38107 | /* Validate that a clause of the given type does not already exist. */ |
38108 | |
38109 | static void |
38110 | check_no_duplicate_clause (tree clauses, enum omp_clause_code code, |
38111 | const char *name, location_t location) |
38112 | { |
38113 | if (omp_find_clause (clauses, kind: code)) |
38114 | error_at (location, "too many %qs clauses" , name); |
38115 | } |
38116 | |
38117 | /* OpenMP 2.5: |
38118 | variable-list: |
38119 | identifier |
38120 | variable-list , identifier |
38121 | |
38122 | In addition, we match a closing parenthesis (or, if COLON is non-NULL, |
38123 | colon). An opening parenthesis will have been consumed by the caller. |
38124 | |
38125 | If KIND is nonzero, create the appropriate node and install the decl |
38126 | in OMP_CLAUSE_DECL and add the node to the head of the list. |
38127 | |
38128 | If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; |
38129 | return the list created. |
38130 | |
38131 | COLON can be NULL if only closing parenthesis should end the list, |
38132 | or pointer to bool which will receive false if the list is terminated |
38133 | by closing parenthesis or true if the list is terminated by colon. |
38134 | |
38135 | The optional ALLOW_DEREF argument is true if list items can use the deref |
38136 | (->) operator. */ |
38137 | |
38138 | struct omp_dim |
38139 | { |
38140 | tree low_bound, length; |
38141 | location_t loc; |
38142 | bool no_colon; |
38143 | omp_dim (tree lb, tree len, location_t lo, bool nc) |
38144 | : low_bound (lb), length (len), loc (lo), no_colon (nc) {} |
38145 | }; |
38146 | |
38147 | static tree |
38148 | cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, |
38149 | tree list, bool *colon, |
38150 | bool map_lvalue = false) |
38151 | { |
38152 | auto_vec<omp_dim> dims; |
38153 | bool array_section_p; |
38154 | cp_token *token; |
38155 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
38156 | if (colon) |
38157 | { |
38158 | parser->colon_corrects_to_scope_p = false; |
38159 | *colon = false; |
38160 | } |
38161 | while (1) |
38162 | { |
38163 | tree name, decl; |
38164 | |
38165 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38166 | cp_parser_parse_tentatively (parser); |
38167 | /* This condition doesn't include OMP_CLAUSE_DEPEND or |
38168 | OMP_CLAUSE_AFFINITY since lvalue ("locator list") parsing for those is |
38169 | handled further down the function. */ |
38170 | else if (map_lvalue |
38171 | && (kind == OMP_CLAUSE_MAP |
38172 | || kind == OMP_CLAUSE_TO |
38173 | || kind == OMP_CLAUSE_FROM)) |
38174 | { |
38175 | auto s = make_temp_override (var&: parser->omp_array_section_p, overrider: true); |
38176 | token = cp_lexer_peek_token (lexer: parser->lexer); |
38177 | location_t loc = token->location; |
38178 | decl = cp_parser_assignment_expression (parser); |
38179 | |
38180 | /* This code rewrites a parsed expression containing various tree |
38181 | codes used to represent array accesses into a more uniform nest of |
38182 | OMP_ARRAY_SECTION nodes before it is processed by |
38183 | semantics.cc:handle_omp_array_sections_1. It might be more |
38184 | efficient to move this logic to that function instead, analysing |
38185 | the parsed expression directly rather than this preprocessed |
38186 | form. */ |
38187 | dims.truncate (size: 0); |
38188 | if (TREE_CODE (decl) == OMP_ARRAY_SECTION) |
38189 | { |
38190 | while (TREE_CODE (decl) == OMP_ARRAY_SECTION) |
38191 | { |
38192 | tree low_bound = TREE_OPERAND (decl, 1); |
38193 | tree length = TREE_OPERAND (decl, 2); |
38194 | dims.safe_push (obj: omp_dim (low_bound, length, loc, false)); |
38195 | decl = TREE_OPERAND (decl, 0); |
38196 | } |
38197 | |
38198 | while (TREE_CODE (decl) == ARRAY_REF |
38199 | || TREE_CODE (decl) == INDIRECT_REF |
38200 | || TREE_CODE (decl) == COMPOUND_EXPR) |
38201 | { |
38202 | if (REFERENCE_REF_P (decl)) |
38203 | break; |
38204 | |
38205 | if (TREE_CODE (decl) == COMPOUND_EXPR) |
38206 | { |
38207 | decl = TREE_OPERAND (decl, 1); |
38208 | STRIP_NOPS (decl); |
38209 | } |
38210 | else if (TREE_CODE (decl) == INDIRECT_REF) |
38211 | { |
38212 | dims.safe_push (obj: omp_dim (integer_zero_node, |
38213 | integer_one_node, loc, true)); |
38214 | decl = TREE_OPERAND (decl, 0); |
38215 | } |
38216 | else /* ARRAY_REF. */ |
38217 | { |
38218 | tree index = TREE_OPERAND (decl, 1); |
38219 | dims.safe_push (obj: omp_dim (index, integer_one_node, loc, |
38220 | true)); |
38221 | decl = TREE_OPERAND (decl, 0); |
38222 | } |
38223 | } |
38224 | |
38225 | /* Bare references have their own special handling, so remove |
38226 | the explicit dereference added by convert_from_reference. */ |
38227 | if (REFERENCE_REF_P (decl)) |
38228 | decl = TREE_OPERAND (decl, 0); |
38229 | |
38230 | for (int i = dims.length () - 1; i >= 0; i--) |
38231 | decl = grok_omp_array_section (loc, decl, dims[i].low_bound, |
38232 | dims[i].length); |
38233 | } |
38234 | else if (TREE_CODE (decl) == INDIRECT_REF) |
38235 | { |
38236 | bool ref_p = REFERENCE_REF_P (decl); |
38237 | |
38238 | /* If we have "*foo" and |
38239 | - it's an indirection of a reference, "unconvert" it, i.e. |
38240 | strip the indirection (to just "foo"). |
38241 | - it's an indirection of a pointer, turn it into |
38242 | "foo[0:1]". */ |
38243 | decl = TREE_OPERAND (decl, 0); |
38244 | STRIP_NOPS (decl); |
38245 | |
38246 | if (!ref_p) |
38247 | decl = grok_omp_array_section (loc, decl, integer_zero_node, |
38248 | integer_one_node); |
38249 | } |
38250 | else if (TREE_CODE (decl) == ARRAY_REF) |
38251 | { |
38252 | tree idx = TREE_OPERAND (decl, 1); |
38253 | |
38254 | decl = TREE_OPERAND (decl, 0); |
38255 | STRIP_NOPS (decl); |
38256 | |
38257 | decl = grok_omp_array_section (loc, decl, idx, integer_one_node); |
38258 | } |
38259 | else if (TREE_CODE (decl) == NON_LVALUE_EXPR |
38260 | || CONVERT_EXPR_P (decl)) |
38261 | decl = TREE_OPERAND (decl, 0); |
38262 | |
38263 | goto build_clause; |
38264 | } |
38265 | token = cp_lexer_peek_token (lexer: parser->lexer); |
38266 | if (kind != 0 |
38267 | && cp_parser_is_keyword (token, keyword: RID_THIS)) |
38268 | { |
38269 | decl = finish_this_expr (); |
38270 | if (TREE_CODE (decl) == NON_LVALUE_EXPR |
38271 | || CONVERT_EXPR_P (decl)) |
38272 | decl = TREE_OPERAND (decl, 0); |
38273 | cp_lexer_consume_token (lexer: parser->lexer); |
38274 | } |
38275 | else if (cp_parser_is_keyword (token, keyword: RID_FUNCTION_NAME) |
38276 | || cp_parser_is_keyword (token, keyword: RID_PRETTY_FUNCTION_NAME) |
38277 | || cp_parser_is_keyword (token, keyword: RID_C99_FUNCTION_NAME)) |
38278 | { |
38279 | cp_id_kind idk; |
38280 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, template_arg_p: false, |
38281 | idk: &idk); |
38282 | } |
38283 | else if (kind == OMP_CLAUSE_DEPEND |
38284 | && cp_parser_is_keyword (token, keyword: RID_OMP_ALL_MEMORY) |
38285 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
38286 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
38287 | type: CPP_CLOSE_PAREN))) |
38288 | { |
38289 | decl = ridpointers[RID_OMP_ALL_MEMORY]; |
38290 | cp_lexer_consume_token (lexer: parser->lexer); |
38291 | } |
38292 | else |
38293 | { |
38294 | name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
38295 | /*check_dependency_p=*/true, |
38296 | /*template_p=*/NULL, |
38297 | /*declarator_p=*/false, |
38298 | /*optional_p=*/false); |
38299 | if (name == error_mark_node) |
38300 | { |
38301 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38302 | && cp_parser_simulate_error (parser)) |
38303 | goto depend_lvalue; |
38304 | goto skip_comma; |
38305 | } |
38306 | |
38307 | if (identifier_p (t: name)) |
38308 | decl = cp_parser_lookup_name_simple (parser, name, location: token->location); |
38309 | else |
38310 | decl = name; |
38311 | if (decl == error_mark_node) |
38312 | { |
38313 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38314 | && cp_parser_simulate_error (parser)) |
38315 | goto depend_lvalue; |
38316 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, |
38317 | location: token->location); |
38318 | } |
38319 | } |
38320 | if (outer_automatic_var_p (decl)) |
38321 | decl = process_outer_var_ref (decl, tf_warning_or_error); |
38322 | if (decl == error_mark_node) |
38323 | ; |
38324 | else if (kind != 0) |
38325 | { |
38326 | switch (kind) |
38327 | { |
38328 | case OMP_CLAUSE__CACHE_: |
38329 | /* The OpenACC cache directive explicitly only allows "array |
38330 | elements or subarrays". */ |
38331 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_OPEN_SQUARE) |
38332 | { |
38333 | error_at (token->location, "expected %<[%>" ); |
38334 | decl = error_mark_node; |
38335 | break; |
38336 | } |
38337 | /* FALLTHROUGH. */ |
38338 | case OMP_CLAUSE_MAP: |
38339 | case OMP_CLAUSE_FROM: |
38340 | case OMP_CLAUSE_TO: |
38341 | start_component_ref: |
38342 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
38343 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
38344 | { |
38345 | cpp_ttype ttype |
38346 | = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
38347 | ? CPP_DOT : CPP_DEREF; |
38348 | location_t loc |
38349 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38350 | cp_id_kind idk = CP_ID_KIND_NONE; |
38351 | cp_lexer_consume_token (lexer: parser->lexer); |
38352 | decl = convert_from_reference (decl); |
38353 | decl = (cp_parser_postfix_dot_deref_expression |
38354 | (parser, token_type: ttype, postfix_expression: cp_expr (decl, token->location), |
38355 | for_offsetof: false, idk: &idk, location: loc)); |
38356 | } |
38357 | /* FALLTHROUGH. */ |
38358 | case OMP_CLAUSE_AFFINITY: |
38359 | case OMP_CLAUSE_DEPEND: |
38360 | case OMP_CLAUSE_REDUCTION: |
38361 | case OMP_CLAUSE_IN_REDUCTION: |
38362 | case OMP_CLAUSE_TASK_REDUCTION: |
38363 | case OMP_CLAUSE_HAS_DEVICE_ADDR: |
38364 | array_section_p = false; |
38365 | dims.truncate (size: 0); |
38366 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
38367 | { |
38368 | location_t loc = UNKNOWN_LOCATION; |
38369 | tree low_bound = NULL_TREE, length = NULL_TREE; |
38370 | bool no_colon = false; |
38371 | |
38372 | parser->colon_corrects_to_scope_p = false; |
38373 | cp_lexer_consume_token (lexer: parser->lexer); |
38374 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
38375 | { |
38376 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38377 | low_bound = cp_parser_expression (parser); |
38378 | /* Later handling is not prepared to see through these. */ |
38379 | gcc_checking_assert (!location_wrapper_p (low_bound)); |
38380 | } |
38381 | if (!colon) |
38382 | parser->colon_corrects_to_scope_p |
38383 | = saved_colon_corrects_to_scope_p; |
38384 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
38385 | { |
38386 | length = integer_one_node; |
38387 | no_colon = true; |
38388 | } |
38389 | else |
38390 | { |
38391 | /* Look for `:'. */ |
38392 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
38393 | { |
38394 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38395 | && cp_parser_simulate_error (parser)) |
38396 | goto depend_lvalue; |
38397 | goto skip_comma; |
38398 | } |
38399 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38400 | cp_parser_commit_to_tentative_parse (parser); |
38401 | else |
38402 | array_section_p = true; |
38403 | if (!cp_lexer_next_token_is (lexer: parser->lexer, |
38404 | type: CPP_CLOSE_SQUARE)) |
38405 | { |
38406 | length = cp_parser_expression (parser); |
38407 | /* Later handling is not prepared to see through these. */ |
38408 | gcc_checking_assert (!location_wrapper_p (length)); |
38409 | } |
38410 | } |
38411 | /* Look for the closing `]'. */ |
38412 | if (!cp_parser_require (parser, type: CPP_CLOSE_SQUARE, |
38413 | token_desc: RT_CLOSE_SQUARE)) |
38414 | { |
38415 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38416 | && cp_parser_simulate_error (parser)) |
38417 | goto depend_lvalue; |
38418 | goto skip_comma; |
38419 | } |
38420 | |
38421 | dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon)); |
38422 | } |
38423 | |
38424 | if ((kind == OMP_CLAUSE_MAP |
38425 | || kind == OMP_CLAUSE_FROM |
38426 | || kind == OMP_CLAUSE_TO) |
38427 | && !array_section_p |
38428 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
38429 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF))) |
38430 | { |
38431 | for (unsigned i = 0; i < dims.length (); i++) |
38432 | { |
38433 | gcc_assert (dims[i].length == integer_one_node); |
38434 | decl = build_array_ref (dims[i].loc, |
38435 | decl, dims[i].low_bound); |
38436 | } |
38437 | goto start_component_ref; |
38438 | } |
38439 | else |
38440 | for (unsigned i = 0; i < dims.length (); i++) |
38441 | decl = build_omp_array_section (input_location, decl, |
38442 | dims[i].low_bound, |
38443 | dims[i].length); |
38444 | break; |
38445 | default: |
38446 | break; |
38447 | } |
38448 | |
38449 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
38450 | { |
38451 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
38452 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
38453 | && cp_parser_simulate_error (parser)) |
38454 | { |
38455 | depend_lvalue: |
38456 | cp_parser_abort_tentative_parse (parser); |
38457 | decl = cp_parser_assignment_expression (parser, NULL, |
38458 | cast_p: false, decltype_p: false); |
38459 | } |
38460 | else |
38461 | cp_parser_parse_definitely (parser); |
38462 | } |
38463 | |
38464 | build_clause: |
38465 | tree u = build_omp_clause (token->location, kind); |
38466 | OMP_CLAUSE_DECL (u) = decl; |
38467 | OMP_CLAUSE_CHAIN (u) = list; |
38468 | list = u; |
38469 | } |
38470 | else |
38471 | list = tree_cons (decl, NULL_TREE, list); |
38472 | |
38473 | get_comma: |
38474 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
38475 | break; |
38476 | cp_lexer_consume_token (lexer: parser->lexer); |
38477 | } |
38478 | |
38479 | if (colon) |
38480 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
38481 | |
38482 | if (colon != NULL && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
38483 | { |
38484 | *colon = true; |
38485 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
38486 | return list; |
38487 | } |
38488 | |
38489 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_CLOSE_PAREN)) |
38490 | { |
38491 | int ending; |
38492 | |
38493 | /* Try to resync to an unnested comma. Copied from |
38494 | cp_parser_parenthesized_expression_list. */ |
38495 | skip_comma: |
38496 | if (colon) |
38497 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
38498 | ending = cp_parser_skip_to_closing_parenthesis (parser, |
38499 | /*recovering=*/true, |
38500 | /*or_comma=*/true, |
38501 | /*consume_paren=*/true); |
38502 | if (ending < 0) |
38503 | goto get_comma; |
38504 | } |
38505 | |
38506 | return list; |
38507 | } |
38508 | |
38509 | /* Similarly, but expect leading and trailing parenthesis. This is a very |
38510 | common case for omp clauses. */ |
38511 | |
38512 | static tree |
38513 | cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list, |
38514 | bool map_lvalue = false) |
38515 | { |
38516 | if (parser->lexer->in_omp_decl_attribute) |
38517 | { |
38518 | if (kind) |
38519 | { |
38520 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38521 | tree u = build_omp_clause (loc, kind); |
38522 | OMP_CLAUSE_DECL (u) = parser->lexer->in_omp_decl_attribute; |
38523 | OMP_CLAUSE_CHAIN (u) = list; |
38524 | return u; |
38525 | } |
38526 | else |
38527 | return tree_cons (parser->lexer->in_omp_decl_attribute, NULL_TREE, |
38528 | list); |
38529 | } |
38530 | |
38531 | if (cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
38532 | return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, |
38533 | map_lvalue); |
38534 | return list; |
38535 | } |
38536 | |
38537 | /* OpenACC 2.0: |
38538 | copy ( variable-list ) |
38539 | copyin ( variable-list ) |
38540 | copyout ( variable-list ) |
38541 | create ( variable-list ) |
38542 | delete ( variable-list ) |
38543 | present ( variable-list ) |
38544 | |
38545 | OpenACC 2.6: |
38546 | no_create ( variable-list ) |
38547 | attach ( variable-list ) |
38548 | detach ( variable-list ) |
38549 | |
38550 | OpenACC 2.7: |
38551 | copyin (readonly : variable-list ) |
38552 | */ |
38553 | |
38554 | static tree |
38555 | cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind, |
38556 | tree list) |
38557 | { |
38558 | enum gomp_map_kind kind; |
38559 | switch (c_kind) |
38560 | { |
38561 | case PRAGMA_OACC_CLAUSE_ATTACH: |
38562 | kind = GOMP_MAP_ATTACH; |
38563 | break; |
38564 | case PRAGMA_OACC_CLAUSE_COPY: |
38565 | kind = GOMP_MAP_TOFROM; |
38566 | break; |
38567 | case PRAGMA_OACC_CLAUSE_COPYIN: |
38568 | kind = GOMP_MAP_TO; |
38569 | break; |
38570 | case PRAGMA_OACC_CLAUSE_COPYOUT: |
38571 | kind = GOMP_MAP_FROM; |
38572 | break; |
38573 | case PRAGMA_OACC_CLAUSE_CREATE: |
38574 | kind = GOMP_MAP_ALLOC; |
38575 | break; |
38576 | case PRAGMA_OACC_CLAUSE_DELETE: |
38577 | kind = GOMP_MAP_RELEASE; |
38578 | break; |
38579 | case PRAGMA_OACC_CLAUSE_DETACH: |
38580 | kind = GOMP_MAP_DETACH; |
38581 | break; |
38582 | case PRAGMA_OACC_CLAUSE_DEVICE: |
38583 | kind = GOMP_MAP_FORCE_TO; |
38584 | break; |
38585 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
38586 | kind = GOMP_MAP_DEVICE_RESIDENT; |
38587 | break; |
38588 | case PRAGMA_OACC_CLAUSE_LINK: |
38589 | kind = GOMP_MAP_LINK; |
38590 | break; |
38591 | case PRAGMA_OACC_CLAUSE_NO_CREATE: |
38592 | kind = GOMP_MAP_IF_PRESENT; |
38593 | break; |
38594 | case PRAGMA_OACC_CLAUSE_PRESENT: |
38595 | kind = GOMP_MAP_FORCE_PRESENT; |
38596 | break; |
38597 | case PRAGMA_OACC_CLAUSE_SELF: |
38598 | /* "The 'host' clause is a synonym for the 'self' clause." */ |
38599 | case PRAGMA_OACC_CLAUSE_HOST: |
38600 | kind = GOMP_MAP_FORCE_FROM; |
38601 | break; |
38602 | default: |
38603 | gcc_unreachable (); |
38604 | } |
38605 | |
38606 | tree nl = list; |
38607 | bool readonly = false; |
38608 | if (cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
38609 | { |
38610 | /* Turn on readonly modifier parsing for copyin clause. */ |
38611 | if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN) |
38612 | { |
38613 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
38614 | if (token->type == CPP_NAME |
38615 | && !strcmp (IDENTIFIER_POINTER (token->u.value), s2: "readonly" ) |
38616 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
38617 | { |
38618 | cp_lexer_consume_token (lexer: parser->lexer); |
38619 | cp_lexer_consume_token (lexer: parser->lexer); |
38620 | readonly = true; |
38621 | } |
38622 | } |
38623 | nl = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_MAP, list, NULL, |
38624 | map_lvalue: false); |
38625 | } |
38626 | |
38627 | for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
38628 | { |
38629 | OMP_CLAUSE_SET_MAP_KIND (c, kind); |
38630 | if (readonly) |
38631 | OMP_CLAUSE_MAP_READONLY (c) = 1; |
38632 | } |
38633 | |
38634 | return nl; |
38635 | } |
38636 | |
38637 | /* OpenACC 2.0: |
38638 | deviceptr ( variable-list ) */ |
38639 | |
38640 | static tree |
38641 | cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list) |
38642 | { |
38643 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38644 | tree vars, t; |
38645 | |
38646 | /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic |
38647 | cp_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR, |
38648 | variable-list must only allow for pointer variables. */ |
38649 | vars = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
38650 | for (t = vars; t; t = TREE_CHAIN (t)) |
38651 | { |
38652 | tree v = TREE_PURPOSE (t); |
38653 | tree u = build_omp_clause (loc, OMP_CLAUSE_MAP); |
38654 | OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR); |
38655 | OMP_CLAUSE_DECL (u) = v; |
38656 | OMP_CLAUSE_CHAIN (u) = list; |
38657 | list = u; |
38658 | } |
38659 | |
38660 | return list; |
38661 | } |
38662 | |
38663 | /* OpenACC 2.5: |
38664 | auto |
38665 | finalize |
38666 | independent |
38667 | nohost |
38668 | seq */ |
38669 | |
38670 | static tree |
38671 | cp_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code, |
38672 | tree list) |
38673 | { |
38674 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location: loc); |
38675 | |
38676 | tree c = build_omp_clause (loc, code); |
38677 | OMP_CLAUSE_CHAIN (c) = list; |
38678 | |
38679 | return c; |
38680 | } |
38681 | |
38682 | /* OpenACC: |
38683 | num_gangs ( expression ) |
38684 | num_workers ( expression ) |
38685 | vector_length ( expression ) */ |
38686 | |
38687 | static tree |
38688 | cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code, |
38689 | const char *str, tree list) |
38690 | { |
38691 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38692 | |
38693 | matching_parens parens; |
38694 | if (!parens.require_open (parser)) |
38695 | return list; |
38696 | |
38697 | tree t = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
38698 | |
38699 | if (t == error_mark_node |
38700 | || !parens.require_close (parser)) |
38701 | { |
38702 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38703 | /*or_comma=*/false, |
38704 | /*consume_paren=*/true); |
38705 | return list; |
38706 | } |
38707 | |
38708 | check_no_duplicate_clause (clauses: list, code, name: str, location: loc); |
38709 | |
38710 | tree c = build_omp_clause (loc, code); |
38711 | OMP_CLAUSE_OPERAND (c, 0) = t; |
38712 | OMP_CLAUSE_CHAIN (c) = list; |
38713 | return c; |
38714 | } |
38715 | |
38716 | /* OpenACC: |
38717 | |
38718 | gang [( gang-arg-list )] |
38719 | worker [( [num:] int-expr )] |
38720 | vector [( [length:] int-expr )] |
38721 | |
38722 | where gang-arg is one of: |
38723 | |
38724 | [num:] int-expr |
38725 | static: size-expr |
38726 | |
38727 | and size-expr may be: |
38728 | |
38729 | * |
38730 | int-expr |
38731 | */ |
38732 | |
38733 | static tree |
38734 | cp_parser_oacc_shape_clause (cp_parser *parser, location_t loc, |
38735 | omp_clause_code kind, |
38736 | const char *str, tree list) |
38737 | { |
38738 | const char *id = "num" ; |
38739 | cp_lexer *lexer = parser->lexer; |
38740 | tree ops[2] = { NULL_TREE, NULL_TREE }, c; |
38741 | |
38742 | if (kind == OMP_CLAUSE_VECTOR) |
38743 | id = "length" ; |
38744 | |
38745 | if (cp_lexer_next_token_is (lexer, type: CPP_OPEN_PAREN)) |
38746 | { |
38747 | matching_parens parens; |
38748 | parens.consume_open (parser); |
38749 | |
38750 | do |
38751 | { |
38752 | cp_token *next = cp_lexer_peek_token (lexer); |
38753 | int idx = 0; |
38754 | |
38755 | /* Gang static argument. */ |
38756 | if (kind == OMP_CLAUSE_GANG |
38757 | && cp_lexer_next_token_is_keyword (lexer, keyword: RID_STATIC)) |
38758 | { |
38759 | cp_lexer_consume_token (lexer); |
38760 | |
38761 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
38762 | goto cleanup_error; |
38763 | |
38764 | idx = 1; |
38765 | if (ops[idx] != NULL) |
38766 | { |
38767 | cp_parser_error (parser, gmsgid: "too many %<static%> arguments" ); |
38768 | goto cleanup_error; |
38769 | } |
38770 | |
38771 | /* Check for the '*' argument. */ |
38772 | if (cp_lexer_next_token_is (lexer, type: CPP_MULT) |
38773 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
38774 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
38775 | type: CPP_CLOSE_PAREN))) |
38776 | { |
38777 | cp_lexer_consume_token (lexer); |
38778 | ops[idx] = integer_minus_one_node; |
38779 | |
38780 | if (cp_lexer_next_token_is (lexer, type: CPP_COMMA)) |
38781 | { |
38782 | cp_lexer_consume_token (lexer); |
38783 | continue; |
38784 | } |
38785 | else break; |
38786 | } |
38787 | } |
38788 | /* Worker num: argument and vector length: arguments. */ |
38789 | else if (cp_lexer_next_token_is (lexer, type: CPP_NAME) |
38790 | && id_equal (id: next->u.value, str: id) |
38791 | && cp_lexer_nth_token_is (lexer, n: 2, type: CPP_COLON)) |
38792 | { |
38793 | cp_lexer_consume_token (lexer); /* id */ |
38794 | cp_lexer_consume_token (lexer); /* ':' */ |
38795 | } |
38796 | |
38797 | /* Now collect the actual argument. */ |
38798 | if (ops[idx] != NULL_TREE) |
38799 | { |
38800 | cp_parser_error (parser, gmsgid: "unexpected argument" ); |
38801 | goto cleanup_error; |
38802 | } |
38803 | |
38804 | tree expr = cp_parser_assignment_expression (parser, NULL, cast_p: false, |
38805 | decltype_p: false); |
38806 | if (expr == error_mark_node) |
38807 | goto cleanup_error; |
38808 | |
38809 | mark_exp_read (expr); |
38810 | ops[idx] = expr; |
38811 | |
38812 | if (kind == OMP_CLAUSE_GANG |
38813 | && cp_lexer_next_token_is (lexer, type: CPP_COMMA)) |
38814 | { |
38815 | cp_lexer_consume_token (lexer); |
38816 | continue; |
38817 | } |
38818 | break; |
38819 | } |
38820 | while (1); |
38821 | |
38822 | if (!parens.require_close (parser)) |
38823 | goto cleanup_error; |
38824 | } |
38825 | |
38826 | check_no_duplicate_clause (clauses: list, code: kind, name: str, location: loc); |
38827 | |
38828 | c = build_omp_clause (loc, kind); |
38829 | |
38830 | if (ops[1]) |
38831 | OMP_CLAUSE_OPERAND (c, 1) = ops[1]; |
38832 | |
38833 | OMP_CLAUSE_OPERAND (c, 0) = ops[0]; |
38834 | OMP_CLAUSE_CHAIN (c) = list; |
38835 | |
38836 | return c; |
38837 | |
38838 | cleanup_error: |
38839 | cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, consume_paren: true); |
38840 | return list; |
38841 | } |
38842 | |
38843 | /* OpenACC 2.0: |
38844 | tile ( size-expr-list ) */ |
38845 | |
38846 | static tree |
38847 | cp_parser_oacc_clause_tile (cp_parser *parser, location_t clause_loc, tree list) |
38848 | { |
38849 | tree c, expr = error_mark_node; |
38850 | tree tile = NULL_TREE; |
38851 | |
38852 | /* Collapse and tile are mutually exclusive. (The spec doesn't say |
38853 | so, but the spec authors never considered such a case and have |
38854 | differing opinions on what it might mean, including 'not |
38855 | allowed'.) */ |
38856 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile" , location: clause_loc); |
38857 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse" , |
38858 | location: clause_loc); |
38859 | |
38860 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
38861 | return list; |
38862 | |
38863 | do |
38864 | { |
38865 | if (tile && !cp_parser_require (parser, type: CPP_COMMA, token_desc: RT_COMMA)) |
38866 | return list; |
38867 | |
38868 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT) |
38869 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
38870 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN))) |
38871 | { |
38872 | cp_lexer_consume_token (lexer: parser->lexer); |
38873 | expr = integer_zero_node; |
38874 | } |
38875 | else |
38876 | expr = cp_parser_constant_expression (parser); |
38877 | |
38878 | tile = tree_cons (NULL_TREE, expr, tile); |
38879 | } |
38880 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)); |
38881 | |
38882 | /* Consume the trailing ')'. */ |
38883 | cp_lexer_consume_token (lexer: parser->lexer); |
38884 | |
38885 | c = build_omp_clause (clause_loc, OMP_CLAUSE_TILE); |
38886 | tile = nreverse (tile); |
38887 | OMP_CLAUSE_TILE_LIST (c) = tile; |
38888 | OMP_CLAUSE_CHAIN (c) = list; |
38889 | return c; |
38890 | } |
38891 | |
38892 | /* OpenACC 2.0 |
38893 | Parse wait clause or directive parameters. */ |
38894 | |
38895 | static tree |
38896 | cp_parser_oacc_wait_list (cp_parser *parser, location_t clause_loc, tree list) |
38897 | { |
38898 | vec<tree, va_gc> *args; |
38899 | tree t, args_tree; |
38900 | |
38901 | args = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
38902 | /*cast_p=*/false, |
38903 | /*allow_expansion_p=*/true, |
38904 | /*non_constant_p=*/NULL); |
38905 | |
38906 | if (args == NULL || args->length () == 0) |
38907 | { |
38908 | if (args != NULL) |
38909 | { |
38910 | cp_parser_error (parser, gmsgid: "expected integer expression list" ); |
38911 | release_tree_vector (args); |
38912 | } |
38913 | return list; |
38914 | } |
38915 | |
38916 | args_tree = build_tree_list_vec (args); |
38917 | |
38918 | release_tree_vector (args); |
38919 | |
38920 | for (t = args_tree; t; t = TREE_CHAIN (t)) |
38921 | { |
38922 | tree targ = TREE_VALUE (t); |
38923 | |
38924 | if (targ != error_mark_node) |
38925 | { |
38926 | if (!INTEGRAL_TYPE_P (TREE_TYPE (targ))) |
38927 | error ("%<wait%> expression must be integral" ); |
38928 | else |
38929 | { |
38930 | tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT); |
38931 | |
38932 | targ = mark_rvalue_use (targ); |
38933 | OMP_CLAUSE_DECL (c) = targ; |
38934 | OMP_CLAUSE_CHAIN (c) = list; |
38935 | list = c; |
38936 | } |
38937 | } |
38938 | } |
38939 | |
38940 | return list; |
38941 | } |
38942 | |
38943 | /* OpenACC: |
38944 | wait [( int-expr-list )] */ |
38945 | |
38946 | static tree |
38947 | cp_parser_oacc_clause_wait (cp_parser *parser, tree list) |
38948 | { |
38949 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38950 | |
38951 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
38952 | list = cp_parser_oacc_wait_list (parser, clause_loc: location, list); |
38953 | else |
38954 | { |
38955 | tree c = build_omp_clause (location, OMP_CLAUSE_WAIT); |
38956 | |
38957 | OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL); |
38958 | OMP_CLAUSE_CHAIN (c) = list; |
38959 | list = c; |
38960 | } |
38961 | |
38962 | return list; |
38963 | } |
38964 | |
38965 | /* OpenMP 3.0: |
38966 | collapse ( constant-expression ) */ |
38967 | |
38968 | static tree |
38969 | cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location) |
38970 | { |
38971 | tree c, num; |
38972 | location_t loc; |
38973 | HOST_WIDE_INT n; |
38974 | |
38975 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38976 | matching_parens parens; |
38977 | if (!parens.require_open (parser)) |
38978 | return list; |
38979 | |
38980 | num = cp_parser_constant_expression (parser); |
38981 | |
38982 | if (!parens.require_close (parser)) |
38983 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38984 | /*or_comma=*/false, |
38985 | /*consume_paren=*/true); |
38986 | |
38987 | if (num == error_mark_node) |
38988 | return list; |
38989 | num = fold_non_dependent_expr (num); |
38990 | if (!tree_fits_shwi_p (num) |
38991 | || !INTEGRAL_TYPE_P (TREE_TYPE (num)) |
38992 | || (n = tree_to_shwi (num)) <= 0 |
38993 | || (int) n != n) |
38994 | { |
38995 | error_at (loc, "collapse argument needs positive constant integer expression" ); |
38996 | return list; |
38997 | } |
38998 | |
38999 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse" , location); |
39000 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile" , location); |
39001 | c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); |
39002 | OMP_CLAUSE_CHAIN (c) = list; |
39003 | OMP_CLAUSE_COLLAPSE_EXPR (c) = num; |
39004 | |
39005 | return c; |
39006 | } |
39007 | |
39008 | /* OpenMP 2.5: |
39009 | default ( none | shared ) |
39010 | |
39011 | OpenMP 5.1: |
39012 | default ( private | firstprivate ) |
39013 | |
39014 | OpenACC: |
39015 | default ( none | present ) */ |
39016 | |
39017 | static tree |
39018 | cp_parser_omp_clause_default (cp_parser *parser, tree list, |
39019 | location_t location, bool is_oacc) |
39020 | { |
39021 | enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; |
39022 | tree c; |
39023 | |
39024 | matching_parens parens; |
39025 | if (!parens.require_open (parser)) |
39026 | return list; |
39027 | if (!is_oacc && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_PRIVATE)) |
39028 | { |
39029 | kind = OMP_CLAUSE_DEFAULT_PRIVATE; |
39030 | cp_lexer_consume_token (lexer: parser->lexer); |
39031 | } |
39032 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39033 | { |
39034 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39035 | const char *p = IDENTIFIER_POINTER (id); |
39036 | |
39037 | switch (p[0]) |
39038 | { |
39039 | case 'n': |
39040 | if (strcmp (s1: "none" , s2: p) != 0) |
39041 | goto invalid_kind; |
39042 | kind = OMP_CLAUSE_DEFAULT_NONE; |
39043 | break; |
39044 | |
39045 | case 'p': |
39046 | if (strcmp (s1: "present" , s2: p) != 0 || !is_oacc) |
39047 | goto invalid_kind; |
39048 | kind = OMP_CLAUSE_DEFAULT_PRESENT; |
39049 | break; |
39050 | |
39051 | case 'f': |
39052 | if (strcmp (s1: "firstprivate" , s2: p) != 0 || is_oacc) |
39053 | goto invalid_kind; |
39054 | kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; |
39055 | break; |
39056 | |
39057 | case 's': |
39058 | if (strcmp (s1: "shared" , s2: p) != 0 || is_oacc) |
39059 | goto invalid_kind; |
39060 | kind = OMP_CLAUSE_DEFAULT_SHARED; |
39061 | break; |
39062 | |
39063 | default: |
39064 | goto invalid_kind; |
39065 | } |
39066 | |
39067 | cp_lexer_consume_token (lexer: parser->lexer); |
39068 | } |
39069 | else |
39070 | { |
39071 | invalid_kind: |
39072 | if (is_oacc) |
39073 | cp_parser_error (parser, gmsgid: "expected %<none%> or %<present%>" ); |
39074 | else |
39075 | cp_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, " |
39076 | "%<private%> or %<firstprivate%>" ); |
39077 | } |
39078 | |
39079 | if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED |
39080 | || !parens.require_close (parser)) |
39081 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39082 | /*or_comma=*/false, |
39083 | /*consume_paren=*/true); |
39084 | |
39085 | if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) |
39086 | return list; |
39087 | |
39088 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default" , location); |
39089 | c = build_omp_clause (location, OMP_CLAUSE_DEFAULT); |
39090 | OMP_CLAUSE_CHAIN (c) = list; |
39091 | OMP_CLAUSE_DEFAULT_KIND (c) = kind; |
39092 | |
39093 | return c; |
39094 | } |
39095 | |
39096 | /* OpenMP 3.1: |
39097 | final ( expression ) */ |
39098 | |
39099 | static tree |
39100 | cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location) |
39101 | { |
39102 | tree t, c; |
39103 | |
39104 | matching_parens parens; |
39105 | if (!parens.require_open (parser)) |
39106 | return list; |
39107 | |
39108 | t = cp_parser_assignment_expression (parser); |
39109 | |
39110 | if (t == error_mark_node |
39111 | || !parens.require_close (parser)) |
39112 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39113 | /*or_comma=*/false, |
39114 | /*consume_paren=*/true); |
39115 | |
39116 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final" , location); |
39117 | |
39118 | c = build_omp_clause (location, OMP_CLAUSE_FINAL); |
39119 | OMP_CLAUSE_FINAL_EXPR (c) = t; |
39120 | OMP_CLAUSE_CHAIN (c) = list; |
39121 | |
39122 | return c; |
39123 | } |
39124 | |
39125 | /* OpenMP 5.1: |
39126 | indirect [( expression )] |
39127 | */ |
39128 | |
39129 | static tree |
39130 | cp_parser_omp_clause_indirect (cp_parser *parser, tree list, |
39131 | location_t location) |
39132 | { |
39133 | tree t; |
39134 | |
39135 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
39136 | { |
39137 | matching_parens parens; |
39138 | if (!parens.require_open (parser)) |
39139 | return list; |
39140 | |
39141 | bool non_constant_p; |
39142 | t = cp_parser_constant_expression (parser, allow_non_constant_p: true, non_constant_p: &non_constant_p); |
39143 | |
39144 | if (t != error_mark_node && non_constant_p) |
39145 | error_at (location, "expected constant logical expression" ); |
39146 | |
39147 | if (t == error_mark_node |
39148 | || !parens.require_close (parser)) |
39149 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39150 | /*or_comma=*/false, |
39151 | /*consume_paren=*/true); |
39152 | } |
39153 | else |
39154 | t = integer_one_node; |
39155 | |
39156 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect" , location); |
39157 | |
39158 | tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT); |
39159 | OMP_CLAUSE_INDIRECT_EXPR (c) = t; |
39160 | OMP_CLAUSE_CHAIN (c) = list; |
39161 | |
39162 | return c; |
39163 | } |
39164 | |
39165 | /* OpenMP 2.5: |
39166 | if ( expression ) |
39167 | |
39168 | OpenMP 4.5: |
39169 | if ( directive-name-modifier : expression ) |
39170 | |
39171 | directive-name-modifier: |
39172 | parallel | task | taskloop | target data | target | target update |
39173 | | target enter data | target exit data |
39174 | |
39175 | OpenMP 5.0: |
39176 | directive-name-modifier: |
39177 | ... | simd | cancel */ |
39178 | |
39179 | static tree |
39180 | cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location, |
39181 | bool is_omp) |
39182 | { |
39183 | tree t, c; |
39184 | enum tree_code if_modifier = ERROR_MARK; |
39185 | |
39186 | matching_parens parens; |
39187 | if (!parens.require_open (parser)) |
39188 | return list; |
39189 | |
39190 | if (is_omp && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39191 | { |
39192 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39193 | const char *p = IDENTIFIER_POINTER (id); |
39194 | int n = 2; |
39195 | |
39196 | if (strcmp (s1: "cancel" , s2: p) == 0) |
39197 | if_modifier = VOID_CST; |
39198 | else if (strcmp (s1: "parallel" , s2: p) == 0) |
39199 | if_modifier = OMP_PARALLEL; |
39200 | else if (strcmp (s1: "simd" , s2: p) == 0) |
39201 | if_modifier = OMP_SIMD; |
39202 | else if (strcmp (s1: "task" , s2: p) == 0) |
39203 | if_modifier = OMP_TASK; |
39204 | else if (strcmp (s1: "taskloop" , s2: p) == 0) |
39205 | if_modifier = OMP_TASKLOOP; |
39206 | else if (strcmp (s1: "target" , s2: p) == 0) |
39207 | { |
39208 | if_modifier = OMP_TARGET; |
39209 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
39210 | { |
39211 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->u.value; |
39212 | p = IDENTIFIER_POINTER (id); |
39213 | if (strcmp (s1: "data" , s2: p) == 0) |
39214 | if_modifier = OMP_TARGET_DATA; |
39215 | else if (strcmp (s1: "update" , s2: p) == 0) |
39216 | if_modifier = OMP_TARGET_UPDATE; |
39217 | else if (strcmp (s1: "enter" , s2: p) == 0) |
39218 | if_modifier = OMP_TARGET_ENTER_DATA; |
39219 | else if (strcmp (s1: "exit" , s2: p) == 0) |
39220 | if_modifier = OMP_TARGET_EXIT_DATA; |
39221 | if (if_modifier != OMP_TARGET) |
39222 | n = 3; |
39223 | else |
39224 | { |
39225 | location_t loc |
39226 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->location; |
39227 | error_at (loc, "expected %<data%>, %<update%>, %<enter%> " |
39228 | "or %<exit%>" ); |
39229 | if_modifier = ERROR_MARK; |
39230 | } |
39231 | if (if_modifier == OMP_TARGET_ENTER_DATA |
39232 | || if_modifier == OMP_TARGET_EXIT_DATA) |
39233 | { |
39234 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NAME)) |
39235 | { |
39236 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->u.value; |
39237 | p = IDENTIFIER_POINTER (id); |
39238 | if (strcmp (s1: "data" , s2: p) == 0) |
39239 | n = 4; |
39240 | } |
39241 | if (n != 4) |
39242 | { |
39243 | location_t loc |
39244 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->location; |
39245 | error_at (loc, "expected %<data%>" ); |
39246 | if_modifier = ERROR_MARK; |
39247 | } |
39248 | } |
39249 | } |
39250 | } |
39251 | if (if_modifier != ERROR_MARK) |
39252 | { |
39253 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_COLON)) |
39254 | { |
39255 | while (n-- > 0) |
39256 | cp_lexer_consume_token (lexer: parser->lexer); |
39257 | } |
39258 | else |
39259 | { |
39260 | if (n > 2) |
39261 | { |
39262 | location_t loc |
39263 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n)->location; |
39264 | error_at (loc, "expected %<:%>" ); |
39265 | } |
39266 | if_modifier = ERROR_MARK; |
39267 | } |
39268 | } |
39269 | } |
39270 | |
39271 | t = cp_parser_assignment_expression (parser); |
39272 | |
39273 | if (t == error_mark_node |
39274 | || !parens.require_close (parser)) |
39275 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39276 | /*or_comma=*/false, |
39277 | /*consume_paren=*/true); |
39278 | |
39279 | for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) |
39280 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) |
39281 | { |
39282 | if (if_modifier != ERROR_MARK |
39283 | && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) |
39284 | { |
39285 | const char *p = NULL; |
39286 | switch (if_modifier) |
39287 | { |
39288 | case VOID_CST: p = "cancel" ; break; |
39289 | case OMP_PARALLEL: p = "parallel" ; break; |
39290 | case OMP_SIMD: p = "simd" ; break; |
39291 | case OMP_TASK: p = "task" ; break; |
39292 | case OMP_TASKLOOP: p = "taskloop" ; break; |
39293 | case OMP_TARGET_DATA: p = "target data" ; break; |
39294 | case OMP_TARGET: p = "target" ; break; |
39295 | case OMP_TARGET_UPDATE: p = "target update" ; break; |
39296 | case OMP_TARGET_ENTER_DATA: p = "target enter data" ; break; |
39297 | case OMP_TARGET_EXIT_DATA: p = "target exit data" ; break; |
39298 | default: gcc_unreachable (); |
39299 | } |
39300 | error_at (location, "too many %<if%> clauses with %qs modifier" , |
39301 | p); |
39302 | return list; |
39303 | } |
39304 | else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) |
39305 | { |
39306 | if (!is_omp) |
39307 | error_at (location, "too many %<if%> clauses" ); |
39308 | else |
39309 | error_at (location, "too many %<if%> clauses without modifier" ); |
39310 | return list; |
39311 | } |
39312 | else if (if_modifier == ERROR_MARK |
39313 | || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK) |
39314 | { |
39315 | error_at (location, "if any %<if%> clause has modifier, then all " |
39316 | "%<if%> clauses have to use modifier" ); |
39317 | return list; |
39318 | } |
39319 | } |
39320 | |
39321 | c = build_omp_clause (location, OMP_CLAUSE_IF); |
39322 | OMP_CLAUSE_IF_MODIFIER (c) = if_modifier; |
39323 | OMP_CLAUSE_IF_EXPR (c) = t; |
39324 | OMP_CLAUSE_CHAIN (c) = list; |
39325 | |
39326 | return c; |
39327 | } |
39328 | |
39329 | /* OpenMP 3.1: |
39330 | mergeable */ |
39331 | |
39332 | static tree |
39333 | cp_parser_omp_clause_mergeable (cp_parser * /*parser*/, |
39334 | tree list, location_t location) |
39335 | { |
39336 | tree c; |
39337 | |
39338 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable" , |
39339 | location); |
39340 | |
39341 | c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE); |
39342 | OMP_CLAUSE_CHAIN (c) = list; |
39343 | return c; |
39344 | } |
39345 | |
39346 | /* OpenMP 2.5: |
39347 | nowait */ |
39348 | |
39349 | static tree |
39350 | cp_parser_omp_clause_nowait (cp_parser * /*parser*/, |
39351 | tree list, location_t location) |
39352 | { |
39353 | tree c; |
39354 | |
39355 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait" , location); |
39356 | |
39357 | c = build_omp_clause (location, OMP_CLAUSE_NOWAIT); |
39358 | OMP_CLAUSE_CHAIN (c) = list; |
39359 | return c; |
39360 | } |
39361 | |
39362 | /* OpenMP 2.5: |
39363 | num_threads ( expression ) */ |
39364 | |
39365 | static tree |
39366 | cp_parser_omp_clause_num_threads (cp_parser *parser, tree list, |
39367 | location_t location) |
39368 | { |
39369 | tree t, c; |
39370 | |
39371 | matching_parens parens; |
39372 | if (!parens.require_open (parser)) |
39373 | return list; |
39374 | |
39375 | t = cp_parser_assignment_expression (parser); |
39376 | |
39377 | if (t == error_mark_node |
39378 | || !parens.require_close (parser)) |
39379 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39380 | /*or_comma=*/false, |
39381 | /*consume_paren=*/true); |
39382 | |
39383 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, |
39384 | name: "num_threads" , location); |
39385 | |
39386 | c = build_omp_clause (location, OMP_CLAUSE_NUM_THREADS); |
39387 | OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; |
39388 | OMP_CLAUSE_CHAIN (c) = list; |
39389 | |
39390 | return c; |
39391 | } |
39392 | |
39393 | /* OpenMP 4.5: |
39394 | num_tasks ( expression ) |
39395 | |
39396 | OpenMP 5.1: |
39397 | num_tasks ( strict : expression ) */ |
39398 | |
39399 | static tree |
39400 | cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, |
39401 | location_t location) |
39402 | { |
39403 | tree t, c; |
39404 | |
39405 | matching_parens parens; |
39406 | if (!parens.require_open (parser)) |
39407 | return list; |
39408 | |
39409 | bool strict = false; |
39410 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39411 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
39412 | { |
39413 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39414 | if (!strcmp (IDENTIFIER_POINTER (id), s2: "strict" )) |
39415 | { |
39416 | strict = true; |
39417 | cp_lexer_consume_token (lexer: parser->lexer); |
39418 | cp_lexer_consume_token (lexer: parser->lexer); |
39419 | } |
39420 | } |
39421 | |
39422 | t = cp_parser_assignment_expression (parser); |
39423 | |
39424 | if (t == error_mark_node |
39425 | || !parens.require_close (parser)) |
39426 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39427 | /*or_comma=*/false, |
39428 | /*consume_paren=*/true); |
39429 | |
39430 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, |
39431 | name: "num_tasks" , location); |
39432 | |
39433 | c = build_omp_clause (location, OMP_CLAUSE_NUM_TASKS); |
39434 | OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; |
39435 | OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict; |
39436 | OMP_CLAUSE_CHAIN (c) = list; |
39437 | |
39438 | return c; |
39439 | } |
39440 | |
39441 | /* OpenMP 4.5: |
39442 | grainsize ( expression ) |
39443 | |
39444 | OpenMP 5.1: |
39445 | grainsize ( strict : expression ) */ |
39446 | |
39447 | static tree |
39448 | cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, |
39449 | location_t location) |
39450 | { |
39451 | tree t, c; |
39452 | |
39453 | matching_parens parens; |
39454 | if (!parens.require_open (parser)) |
39455 | return list; |
39456 | |
39457 | bool strict = false; |
39458 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39459 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
39460 | { |
39461 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39462 | if (!strcmp (IDENTIFIER_POINTER (id), s2: "strict" )) |
39463 | { |
39464 | strict = true; |
39465 | cp_lexer_consume_token (lexer: parser->lexer); |
39466 | cp_lexer_consume_token (lexer: parser->lexer); |
39467 | } |
39468 | } |
39469 | |
39470 | t = cp_parser_assignment_expression (parser); |
39471 | |
39472 | if (t == error_mark_node |
39473 | || !parens.require_close (parser)) |
39474 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39475 | /*or_comma=*/false, |
39476 | /*consume_paren=*/true); |
39477 | |
39478 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, |
39479 | name: "grainsize" , location); |
39480 | |
39481 | c = build_omp_clause (location, OMP_CLAUSE_GRAINSIZE); |
39482 | OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; |
39483 | OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict; |
39484 | OMP_CLAUSE_CHAIN (c) = list; |
39485 | |
39486 | return c; |
39487 | } |
39488 | |
39489 | /* OpenMP 4.5: |
39490 | priority ( expression ) */ |
39491 | |
39492 | static tree |
39493 | cp_parser_omp_clause_priority (cp_parser *parser, tree list, |
39494 | location_t location) |
39495 | { |
39496 | tree t, c; |
39497 | |
39498 | matching_parens parens; |
39499 | if (!parens.require_open (parser)) |
39500 | return list; |
39501 | |
39502 | t = cp_parser_assignment_expression (parser); |
39503 | |
39504 | if (t == error_mark_node |
39505 | || !parens.require_close (parser)) |
39506 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39507 | /*or_comma=*/false, |
39508 | /*consume_paren=*/true); |
39509 | |
39510 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, |
39511 | name: "priority" , location); |
39512 | |
39513 | c = build_omp_clause (location, OMP_CLAUSE_PRIORITY); |
39514 | OMP_CLAUSE_PRIORITY_EXPR (c) = t; |
39515 | OMP_CLAUSE_CHAIN (c) = list; |
39516 | |
39517 | return c; |
39518 | } |
39519 | |
39520 | /* OpenMP 4.5: |
39521 | hint ( expression ) */ |
39522 | |
39523 | static tree |
39524 | cp_parser_omp_clause_hint (cp_parser *parser, tree list, location_t location) |
39525 | { |
39526 | tree t, c; |
39527 | |
39528 | matching_parens parens; |
39529 | if (!parens.require_open (parser)) |
39530 | return list; |
39531 | |
39532 | t = cp_parser_assignment_expression (parser); |
39533 | |
39534 | if (t != error_mark_node) |
39535 | { |
39536 | t = fold_non_dependent_expr (t); |
39537 | if (!value_dependent_expression_p (t) |
39538 | && (!INTEGRAL_TYPE_P (TREE_TYPE (t)) |
39539 | || !tree_fits_shwi_p (t) |
39540 | || tree_int_cst_sgn (t) == -1)) |
39541 | error_at (location, "expected constant integer expression with " |
39542 | "valid sync-hint value" ); |
39543 | } |
39544 | if (t == error_mark_node |
39545 | || !parens.require_close (parser)) |
39546 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39547 | /*or_comma=*/false, |
39548 | /*consume_paren=*/true); |
39549 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint" , location); |
39550 | |
39551 | c = build_omp_clause (location, OMP_CLAUSE_HINT); |
39552 | OMP_CLAUSE_HINT_EXPR (c) = t; |
39553 | OMP_CLAUSE_CHAIN (c) = list; |
39554 | |
39555 | return c; |
39556 | } |
39557 | |
39558 | /* OpenMP 5.1: |
39559 | filter ( integer-expression ) */ |
39560 | |
39561 | static tree |
39562 | cp_parser_omp_clause_filter (cp_parser *parser, tree list, location_t location) |
39563 | { |
39564 | tree t, c; |
39565 | |
39566 | matching_parens parens; |
39567 | if (!parens.require_open (parser)) |
39568 | return list; |
39569 | |
39570 | t = cp_parser_assignment_expression (parser); |
39571 | |
39572 | if (t == error_mark_node |
39573 | || !parens.require_close (parser)) |
39574 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39575 | /*or_comma=*/false, |
39576 | /*consume_paren=*/true); |
39577 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter" , location); |
39578 | |
39579 | c = build_omp_clause (location, OMP_CLAUSE_FILTER); |
39580 | OMP_CLAUSE_FILTER_EXPR (c) = t; |
39581 | OMP_CLAUSE_CHAIN (c) = list; |
39582 | |
39583 | return c; |
39584 | } |
39585 | |
39586 | /* OpenMP 4.5: |
39587 | defaultmap ( tofrom : scalar ) |
39588 | |
39589 | OpenMP 5.0: |
39590 | defaultmap ( implicit-behavior [ : variable-category ] ) */ |
39591 | |
39592 | static tree |
39593 | cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list, |
39594 | location_t location) |
39595 | { |
39596 | tree c, id; |
39597 | const char *p; |
39598 | enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; |
39599 | enum omp_clause_defaultmap_kind category |
39600 | = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED; |
39601 | |
39602 | matching_parens parens; |
39603 | if (!parens.require_open (parser)) |
39604 | return list; |
39605 | |
39606 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT)) |
39607 | p = "default" ; |
39608 | else if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39609 | { |
39610 | invalid_behavior: |
39611 | cp_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, " |
39612 | "%<tofrom%>, %<firstprivate%>, %<none%> " |
39613 | "or %<default%>" ); |
39614 | goto out_err; |
39615 | } |
39616 | else |
39617 | { |
39618 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39619 | p = IDENTIFIER_POINTER (id); |
39620 | } |
39621 | |
39622 | switch (p[0]) |
39623 | { |
39624 | case 'a': |
39625 | if (strcmp (s1: "alloc" , s2: p) == 0) |
39626 | behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC; |
39627 | else |
39628 | goto invalid_behavior; |
39629 | break; |
39630 | |
39631 | case 'd': |
39632 | if (strcmp (s1: "default" , s2: p) == 0) |
39633 | behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; |
39634 | else |
39635 | goto invalid_behavior; |
39636 | break; |
39637 | |
39638 | case 'f': |
39639 | if (strcmp (s1: "firstprivate" , s2: p) == 0) |
39640 | behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE; |
39641 | else if (strcmp (s1: "from" , s2: p) == 0) |
39642 | behavior = OMP_CLAUSE_DEFAULTMAP_FROM; |
39643 | else |
39644 | goto invalid_behavior; |
39645 | break; |
39646 | |
39647 | case 'n': |
39648 | if (strcmp (s1: "none" , s2: p) == 0) |
39649 | behavior = OMP_CLAUSE_DEFAULTMAP_NONE; |
39650 | else |
39651 | goto invalid_behavior; |
39652 | break; |
39653 | |
39654 | case 'p': |
39655 | if (strcmp (s1: "present" , s2: p) == 0) |
39656 | behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT; |
39657 | else |
39658 | goto invalid_behavior; |
39659 | break; |
39660 | |
39661 | case 't': |
39662 | if (strcmp (s1: "tofrom" , s2: p) == 0) |
39663 | behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM; |
39664 | else if (strcmp (s1: "to" , s2: p) == 0) |
39665 | behavior = OMP_CLAUSE_DEFAULTMAP_TO; |
39666 | else |
39667 | goto invalid_behavior; |
39668 | break; |
39669 | |
39670 | default: |
39671 | goto invalid_behavior; |
39672 | } |
39673 | cp_lexer_consume_token (lexer: parser->lexer); |
39674 | |
39675 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
39676 | { |
39677 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
39678 | goto out_err; |
39679 | |
39680 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39681 | { |
39682 | invalid_category: |
39683 | cp_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, " |
39684 | "%<all%>" ); |
39685 | goto out_err; |
39686 | } |
39687 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39688 | p = IDENTIFIER_POINTER (id); |
39689 | |
39690 | switch (p[0]) |
39691 | { |
39692 | case 'a': |
39693 | if (strcmp (s1: "aggregate" , s2: p) == 0) |
39694 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE; |
39695 | else if (strcmp (s1: "all" , s2: p) == 0) |
39696 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL; |
39697 | else |
39698 | goto invalid_category; |
39699 | break; |
39700 | |
39701 | case 'p': |
39702 | if (strcmp (s1: "pointer" , s2: p) == 0) |
39703 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER; |
39704 | else |
39705 | goto invalid_category; |
39706 | break; |
39707 | |
39708 | case 's': |
39709 | if (strcmp (s1: "scalar" , s2: p) == 0) |
39710 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR; |
39711 | else |
39712 | goto invalid_category; |
39713 | break; |
39714 | |
39715 | default: |
39716 | goto invalid_category; |
39717 | } |
39718 | |
39719 | cp_lexer_consume_token (lexer: parser->lexer); |
39720 | } |
39721 | if (!parens.require_close (parser)) |
39722 | goto out_err; |
39723 | |
39724 | for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) |
39725 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP |
39726 | && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED |
39727 | || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL |
39728 | || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category |
39729 | || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39730 | == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED) |
39731 | || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39732 | == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL))) |
39733 | { |
39734 | enum omp_clause_defaultmap_kind cat = category; |
39735 | location_t loc = OMP_CLAUSE_LOCATION (c); |
39736 | if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED |
39737 | || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL |
39738 | && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39739 | != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED))) |
39740 | cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c); |
39741 | p = NULL; |
39742 | switch (cat) |
39743 | { |
39744 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED: |
39745 | p = NULL; |
39746 | break; |
39747 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL: |
39748 | p = "all" ; |
39749 | break; |
39750 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE: |
39751 | p = "aggregate" ; |
39752 | break; |
39753 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER: |
39754 | p = "pointer" ; |
39755 | break; |
39756 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR: |
39757 | p = "scalar" ; |
39758 | break; |
39759 | default: |
39760 | gcc_unreachable (); |
39761 | } |
39762 | if (p) |
39763 | error_at (loc, "too many %<defaultmap%> clauses with %qs category" , |
39764 | p); |
39765 | else |
39766 | error_at (loc, "too many %<defaultmap%> clauses with unspecified " |
39767 | "category" ); |
39768 | break; |
39769 | } |
39770 | |
39771 | c = build_omp_clause (location, OMP_CLAUSE_DEFAULTMAP); |
39772 | OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category); |
39773 | OMP_CLAUSE_CHAIN (c) = list; |
39774 | return c; |
39775 | |
39776 | out_err: |
39777 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39778 | /*or_comma=*/false, |
39779 | /*consume_paren=*/true); |
39780 | return list; |
39781 | } |
39782 | |
39783 | /* OpenMP 5.0: |
39784 | order ( concurrent ) |
39785 | |
39786 | OpenMP 5.1: |
39787 | order ( order-modifier : concurrent ) |
39788 | |
39789 | order-modifier: |
39790 | reproducible |
39791 | unconstrained */ |
39792 | |
39793 | static tree |
39794 | cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location) |
39795 | { |
39796 | tree c, id; |
39797 | const char *p; |
39798 | bool unconstrained = false; |
39799 | bool reproducible = false; |
39800 | |
39801 | matching_parens parens; |
39802 | if (!parens.require_open (parser)) |
39803 | return list; |
39804 | |
39805 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39806 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
39807 | { |
39808 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39809 | p = IDENTIFIER_POINTER (id); |
39810 | if (strcmp (s1: p, s2: "unconstrained" ) == 0) |
39811 | unconstrained = true; |
39812 | else if (strcmp (s1: p, s2: "reproducible" ) == 0) |
39813 | reproducible = true; |
39814 | else |
39815 | { |
39816 | cp_parser_error (parser, gmsgid: "expected %<reproducible%> or " |
39817 | "%<unconstrained%>" ); |
39818 | goto out_err; |
39819 | } |
39820 | cp_lexer_consume_token (lexer: parser->lexer); |
39821 | cp_lexer_consume_token (lexer: parser->lexer); |
39822 | } |
39823 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39824 | { |
39825 | cp_parser_error (parser, gmsgid: "expected %<concurrent%>" ); |
39826 | goto out_err; |
39827 | } |
39828 | else |
39829 | { |
39830 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39831 | p = IDENTIFIER_POINTER (id); |
39832 | } |
39833 | if (strcmp (s1: p, s2: "concurrent" ) != 0) |
39834 | { |
39835 | cp_parser_error (parser, gmsgid: "expected %<concurrent%>" ); |
39836 | goto out_err; |
39837 | } |
39838 | cp_lexer_consume_token (lexer: parser->lexer); |
39839 | if (!parens.require_close (parser)) |
39840 | goto out_err; |
39841 | |
39842 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order" , location); |
39843 | c = build_omp_clause (location, OMP_CLAUSE_ORDER); |
39844 | OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained; |
39845 | OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible; |
39846 | OMP_CLAUSE_CHAIN (c) = list; |
39847 | return c; |
39848 | |
39849 | out_err: |
39850 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39851 | /*or_comma=*/false, |
39852 | /*consume_paren=*/true); |
39853 | return list; |
39854 | } |
39855 | |
39856 | /* OpenMP 5.0: |
39857 | bind ( teams | parallel | thread ) */ |
39858 | |
39859 | static tree |
39860 | cp_parser_omp_clause_bind (cp_parser *parser, tree list, |
39861 | location_t location) |
39862 | { |
39863 | tree c; |
39864 | const char *p; |
39865 | enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; |
39866 | |
39867 | matching_parens parens; |
39868 | if (!parens.require_open (parser)) |
39869 | return list; |
39870 | |
39871 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39872 | { |
39873 | invalid: |
39874 | cp_parser_error (parser, |
39875 | gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>" ); |
39876 | goto out_err; |
39877 | } |
39878 | else |
39879 | { |
39880 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39881 | p = IDENTIFIER_POINTER (id); |
39882 | } |
39883 | if (strcmp (s1: p, s2: "teams" ) == 0) |
39884 | kind = OMP_CLAUSE_BIND_TEAMS; |
39885 | else if (strcmp (s1: p, s2: "parallel" ) == 0) |
39886 | kind = OMP_CLAUSE_BIND_PARALLEL; |
39887 | else if (strcmp (s1: p, s2: "thread" ) != 0) |
39888 | goto invalid; |
39889 | cp_lexer_consume_token (lexer: parser->lexer); |
39890 | if (!parens.require_close (parser)) |
39891 | goto out_err; |
39892 | |
39893 | /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind", location); */ |
39894 | c = build_omp_clause (location, OMP_CLAUSE_BIND); |
39895 | OMP_CLAUSE_BIND_KIND (c) = kind; |
39896 | OMP_CLAUSE_CHAIN (c) = list; |
39897 | return c; |
39898 | |
39899 | out_err: |
39900 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39901 | /*or_comma=*/false, |
39902 | /*consume_paren=*/true); |
39903 | return list; |
39904 | } |
39905 | |
39906 | /* OpenMP 2.5: |
39907 | ordered |
39908 | |
39909 | OpenMP 4.5: |
39910 | ordered ( constant-expression ) */ |
39911 | |
39912 | static tree |
39913 | cp_parser_omp_clause_ordered (cp_parser *parser, |
39914 | tree list, location_t location) |
39915 | { |
39916 | tree c, num = NULL_TREE; |
39917 | HOST_WIDE_INT n; |
39918 | |
39919 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, |
39920 | name: "ordered" , location); |
39921 | |
39922 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
39923 | { |
39924 | matching_parens parens; |
39925 | parens.consume_open (parser); |
39926 | |
39927 | num = cp_parser_constant_expression (parser); |
39928 | |
39929 | if (!parens.require_close (parser)) |
39930 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39931 | /*or_comma=*/false, |
39932 | /*consume_paren=*/true); |
39933 | |
39934 | if (num == error_mark_node) |
39935 | return list; |
39936 | num = fold_non_dependent_expr (num); |
39937 | if (!tree_fits_shwi_p (num) |
39938 | || !INTEGRAL_TYPE_P (TREE_TYPE (num)) |
39939 | || (n = tree_to_shwi (num)) <= 0 |
39940 | || (int) n != n) |
39941 | { |
39942 | error_at (location, |
39943 | "ordered argument needs positive constant integer " |
39944 | "expression" ); |
39945 | return list; |
39946 | } |
39947 | } |
39948 | |
39949 | c = build_omp_clause (location, OMP_CLAUSE_ORDERED); |
39950 | OMP_CLAUSE_ORDERED_EXPR (c) = num; |
39951 | OMP_CLAUSE_CHAIN (c) = list; |
39952 | return c; |
39953 | } |
39954 | |
39955 | /* OpenMP 2.5: |
39956 | reduction ( reduction-operator : variable-list ) |
39957 | |
39958 | reduction-operator: |
39959 | One of: + * - & ^ | && || |
39960 | |
39961 | OpenMP 3.1: |
39962 | |
39963 | reduction-operator: |
39964 | One of: + * - & ^ | && || min max |
39965 | |
39966 | OpenMP 4.0: |
39967 | |
39968 | reduction-operator: |
39969 | One of: + * - & ^ | && || |
39970 | id-expression |
39971 | |
39972 | OpenMP 5.0: |
39973 | reduction ( reduction-modifier, reduction-operator : variable-list ) |
39974 | in_reduction ( reduction-operator : variable-list ) |
39975 | task_reduction ( reduction-operator : variable-list ) */ |
39976 | |
39977 | static tree |
39978 | cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, |
39979 | bool is_omp, tree list) |
39980 | { |
39981 | enum tree_code code = ERROR_MARK; |
39982 | tree nlist, c, id = NULL_TREE; |
39983 | bool task = false; |
39984 | bool inscan = false; |
39985 | |
39986 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
39987 | return list; |
39988 | |
39989 | if (kind == OMP_CLAUSE_REDUCTION && is_omp) |
39990 | { |
39991 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT) |
39992 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA)) |
39993 | { |
39994 | cp_lexer_consume_token (lexer: parser->lexer); |
39995 | cp_lexer_consume_token (lexer: parser->lexer); |
39996 | } |
39997 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39998 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA)) |
39999 | { |
40000 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40001 | const char *p = IDENTIFIER_POINTER (id); |
40002 | if (strcmp (s1: p, s2: "task" ) == 0) |
40003 | task = true; |
40004 | else if (strcmp (s1: p, s2: "inscan" ) == 0) |
40005 | inscan = true; |
40006 | if (task || inscan) |
40007 | { |
40008 | cp_lexer_consume_token (lexer: parser->lexer); |
40009 | cp_lexer_consume_token (lexer: parser->lexer); |
40010 | } |
40011 | } |
40012 | } |
40013 | |
40014 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
40015 | { |
40016 | case CPP_PLUS: code = PLUS_EXPR; break; |
40017 | case CPP_MULT: code = MULT_EXPR; break; |
40018 | case CPP_MINUS: code = MINUS_EXPR; break; |
40019 | case CPP_AND: code = BIT_AND_EXPR; break; |
40020 | case CPP_XOR: code = BIT_XOR_EXPR; break; |
40021 | case CPP_OR: code = BIT_IOR_EXPR; break; |
40022 | case CPP_AND_AND: code = TRUTH_ANDIF_EXPR; break; |
40023 | case CPP_OR_OR: code = TRUTH_ORIF_EXPR; break; |
40024 | default: break; |
40025 | } |
40026 | |
40027 | if (code != ERROR_MARK) |
40028 | cp_lexer_consume_token (lexer: parser->lexer); |
40029 | else |
40030 | { |
40031 | bool saved_colon_corrects_to_scope_p; |
40032 | saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
40033 | parser->colon_corrects_to_scope_p = false; |
40034 | id = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
40035 | /*check_dependency_p=*/true, |
40036 | /*template_p=*/NULL, |
40037 | /*declarator_p=*/false, |
40038 | /*optional_p=*/false); |
40039 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
40040 | if (identifier_p (t: id)) |
40041 | { |
40042 | const char *p = IDENTIFIER_POINTER (id); |
40043 | |
40044 | if (strcmp (s1: p, s2: "min" ) == 0) |
40045 | code = MIN_EXPR; |
40046 | else if (strcmp (s1: p, s2: "max" ) == 0) |
40047 | code = MAX_EXPR; |
40048 | else if (id == ovl_op_identifier (isass: false, code: PLUS_EXPR)) |
40049 | code = PLUS_EXPR; |
40050 | else if (id == ovl_op_identifier (isass: false, code: MULT_EXPR)) |
40051 | code = MULT_EXPR; |
40052 | else if (id == ovl_op_identifier (isass: false, code: MINUS_EXPR)) |
40053 | code = MINUS_EXPR; |
40054 | else if (id == ovl_op_identifier (isass: false, code: BIT_AND_EXPR)) |
40055 | code = BIT_AND_EXPR; |
40056 | else if (id == ovl_op_identifier (isass: false, code: BIT_IOR_EXPR)) |
40057 | code = BIT_IOR_EXPR; |
40058 | else if (id == ovl_op_identifier (isass: false, code: BIT_XOR_EXPR)) |
40059 | code = BIT_XOR_EXPR; |
40060 | else if (id == ovl_op_identifier (isass: false, code: TRUTH_ANDIF_EXPR)) |
40061 | code = TRUTH_ANDIF_EXPR; |
40062 | else if (id == ovl_op_identifier (isass: false, code: TRUTH_ORIF_EXPR)) |
40063 | code = TRUTH_ORIF_EXPR; |
40064 | id = omp_reduction_id (code, id, NULL_TREE); |
40065 | tree scope = parser->scope; |
40066 | if (scope) |
40067 | id = build_qualified_name (NULL_TREE, scope, id, false); |
40068 | parser->scope = NULL_TREE; |
40069 | parser->qualifying_scope = NULL_TREE; |
40070 | parser->object_scope = NULL_TREE; |
40071 | } |
40072 | else |
40073 | { |
40074 | error ("invalid reduction-identifier" ); |
40075 | resync_fail: |
40076 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40077 | /*or_comma=*/false, |
40078 | /*consume_paren=*/true); |
40079 | return list; |
40080 | } |
40081 | } |
40082 | |
40083 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
40084 | goto resync_fail; |
40085 | |
40086 | nlist = cp_parser_omp_var_list_no_open (parser, kind, list, |
40087 | NULL); |
40088 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40089 | { |
40090 | OMP_CLAUSE_REDUCTION_CODE (c) = code; |
40091 | if (task) |
40092 | OMP_CLAUSE_REDUCTION_TASK (c) = 1; |
40093 | else if (inscan) |
40094 | OMP_CLAUSE_REDUCTION_INSCAN (c) = 1; |
40095 | OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id; |
40096 | } |
40097 | |
40098 | return nlist; |
40099 | } |
40100 | |
40101 | /* OpenMP 2.5: |
40102 | schedule ( schedule-kind ) |
40103 | schedule ( schedule-kind , expression ) |
40104 | |
40105 | schedule-kind: |
40106 | static | dynamic | guided | runtime | auto |
40107 | |
40108 | OpenMP 4.5: |
40109 | schedule ( schedule-modifier : schedule-kind ) |
40110 | schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression ) |
40111 | |
40112 | schedule-modifier: |
40113 | simd |
40114 | monotonic |
40115 | nonmonotonic */ |
40116 | |
40117 | static tree |
40118 | cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location) |
40119 | { |
40120 | tree c, t; |
40121 | int modifiers = 0, nmodifiers = 0; |
40122 | |
40123 | matching_parens parens; |
40124 | if (!parens.require_open (parser)) |
40125 | return list; |
40126 | |
40127 | c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE); |
40128 | |
40129 | location_t comma = UNKNOWN_LOCATION; |
40130 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40131 | { |
40132 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40133 | const char *p = IDENTIFIER_POINTER (id); |
40134 | if (strcmp (s1: "simd" , s2: p) == 0) |
40135 | OMP_CLAUSE_SCHEDULE_SIMD (c) = 1; |
40136 | else if (strcmp (s1: "monotonic" , s2: p) == 0) |
40137 | modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC; |
40138 | else if (strcmp (s1: "nonmonotonic" , s2: p) == 0) |
40139 | modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC; |
40140 | else |
40141 | break; |
40142 | comma = UNKNOWN_LOCATION; |
40143 | cp_lexer_consume_token (lexer: parser->lexer); |
40144 | if (nmodifiers++ == 0 |
40145 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
40146 | { |
40147 | comma = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40148 | cp_lexer_consume_token (lexer: parser->lexer); |
40149 | } |
40150 | else |
40151 | { |
40152 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
40153 | break; |
40154 | } |
40155 | } |
40156 | if (comma != UNKNOWN_LOCATION) |
40157 | error_at (comma, "expected %<:%>" ); |
40158 | |
40159 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40160 | { |
40161 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40162 | const char *p = IDENTIFIER_POINTER (id); |
40163 | |
40164 | switch (p[0]) |
40165 | { |
40166 | case 'd': |
40167 | if (strcmp (s1: "dynamic" , s2: p) != 0) |
40168 | goto invalid_kind; |
40169 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; |
40170 | break; |
40171 | |
40172 | case 'g': |
40173 | if (strcmp (s1: "guided" , s2: p) != 0) |
40174 | goto invalid_kind; |
40175 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; |
40176 | break; |
40177 | |
40178 | case 'r': |
40179 | if (strcmp (s1: "runtime" , s2: p) != 0) |
40180 | goto invalid_kind; |
40181 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; |
40182 | break; |
40183 | |
40184 | default: |
40185 | goto invalid_kind; |
40186 | } |
40187 | } |
40188 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC)) |
40189 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; |
40190 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
40191 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO; |
40192 | else |
40193 | goto invalid_kind; |
40194 | cp_lexer_consume_token (lexer: parser->lexer); |
40195 | |
40196 | if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC |
40197 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) |
40198 | == (OMP_CLAUSE_SCHEDULE_MONOTONIC |
40199 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) |
40200 | { |
40201 | error_at (location, "both %<monotonic%> and %<nonmonotonic%> modifiers " |
40202 | "specified" ); |
40203 | modifiers = 0; |
40204 | } |
40205 | |
40206 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
40207 | { |
40208 | cp_token *token; |
40209 | cp_lexer_consume_token (lexer: parser->lexer); |
40210 | |
40211 | token = cp_lexer_peek_token (lexer: parser->lexer); |
40212 | t = cp_parser_assignment_expression (parser); |
40213 | |
40214 | if (t == error_mark_node) |
40215 | goto resync_fail; |
40216 | else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) |
40217 | error_at (token->location, "schedule %<runtime%> does not take " |
40218 | "a %<chunk_size%> parameter" ); |
40219 | else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) |
40220 | error_at (token->location, "schedule %<auto%> does not take " |
40221 | "a %<chunk_size%> parameter" ); |
40222 | else |
40223 | OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; |
40224 | |
40225 | if (!parens.require_close (parser)) |
40226 | goto resync_fail; |
40227 | } |
40228 | else if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
40229 | goto resync_fail; |
40230 | |
40231 | OMP_CLAUSE_SCHEDULE_KIND (c) |
40232 | = (enum omp_clause_schedule_kind) |
40233 | (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers); |
40234 | |
40235 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule" , location); |
40236 | OMP_CLAUSE_CHAIN (c) = list; |
40237 | return c; |
40238 | |
40239 | invalid_kind: |
40240 | cp_parser_error (parser, gmsgid: "invalid schedule kind" ); |
40241 | resync_fail: |
40242 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40243 | /*or_comma=*/false, |
40244 | /*consume_paren=*/true); |
40245 | return list; |
40246 | } |
40247 | |
40248 | /* OpenMP 3.0: |
40249 | untied */ |
40250 | |
40251 | static tree |
40252 | cp_parser_omp_clause_untied (cp_parser * /*parser*/, |
40253 | tree list, location_t location) |
40254 | { |
40255 | tree c; |
40256 | |
40257 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied" , location); |
40258 | |
40259 | c = build_omp_clause (location, OMP_CLAUSE_UNTIED); |
40260 | OMP_CLAUSE_CHAIN (c) = list; |
40261 | return c; |
40262 | } |
40263 | |
40264 | /* OpenMP 4.0: |
40265 | inbranch |
40266 | notinbranch */ |
40267 | |
40268 | static tree |
40269 | cp_parser_omp_clause_branch (cp_parser * /*parser*/, enum omp_clause_code code, |
40270 | tree list, location_t location) |
40271 | { |
40272 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location); |
40273 | tree c = build_omp_clause (location, code); |
40274 | OMP_CLAUSE_CHAIN (c) = list; |
40275 | return c; |
40276 | } |
40277 | |
40278 | /* OpenMP 4.0: |
40279 | parallel |
40280 | for |
40281 | sections |
40282 | taskgroup */ |
40283 | |
40284 | static tree |
40285 | cp_parser_omp_clause_cancelkind (cp_parser * /*parser*/, |
40286 | enum omp_clause_code code, |
40287 | tree list, location_t location) |
40288 | { |
40289 | tree c = build_omp_clause (location, code); |
40290 | OMP_CLAUSE_CHAIN (c) = list; |
40291 | return c; |
40292 | } |
40293 | |
40294 | /* OpenMP 4.5: |
40295 | nogroup */ |
40296 | |
40297 | static tree |
40298 | cp_parser_omp_clause_nogroup (cp_parser * /*parser*/, |
40299 | tree list, location_t location) |
40300 | { |
40301 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup" , location); |
40302 | tree c = build_omp_clause (location, OMP_CLAUSE_NOGROUP); |
40303 | OMP_CLAUSE_CHAIN (c) = list; |
40304 | return c; |
40305 | } |
40306 | |
40307 | /* OpenMP 4.5: |
40308 | simd |
40309 | threads */ |
40310 | |
40311 | static tree |
40312 | cp_parser_omp_clause_orderedkind (cp_parser * /*parser*/, |
40313 | enum omp_clause_code code, |
40314 | tree list, location_t location) |
40315 | { |
40316 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location); |
40317 | tree c = build_omp_clause (location, code); |
40318 | OMP_CLAUSE_CHAIN (c) = list; |
40319 | return c; |
40320 | } |
40321 | |
40322 | /* OpenMP 4.0: |
40323 | num_teams ( expression ) |
40324 | |
40325 | OpenMP 5.1: |
40326 | num_teams ( expression : expression ) */ |
40327 | |
40328 | static tree |
40329 | cp_parser_omp_clause_num_teams (cp_parser *parser, tree list, |
40330 | location_t location) |
40331 | { |
40332 | tree upper, lower = NULL_TREE, c; |
40333 | |
40334 | matching_parens parens; |
40335 | if (!parens.require_open (parser)) |
40336 | return list; |
40337 | |
40338 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
40339 | parser->colon_corrects_to_scope_p = false; |
40340 | upper = cp_parser_assignment_expression (parser); |
40341 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
40342 | |
40343 | if (upper != error_mark_node |
40344 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
40345 | { |
40346 | lower = upper; |
40347 | cp_lexer_consume_token (lexer: parser->lexer); |
40348 | upper = cp_parser_assignment_expression (parser); |
40349 | } |
40350 | |
40351 | if (upper == error_mark_node |
40352 | || !parens.require_close (parser)) |
40353 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40354 | /*or_comma=*/false, |
40355 | /*consume_paren=*/true); |
40356 | |
40357 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, |
40358 | name: "num_teams" , location); |
40359 | |
40360 | c = build_omp_clause (location, OMP_CLAUSE_NUM_TEAMS); |
40361 | OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper; |
40362 | OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower; |
40363 | OMP_CLAUSE_CHAIN (c) = list; |
40364 | |
40365 | return c; |
40366 | } |
40367 | |
40368 | /* OpenMP 4.0: |
40369 | thread_limit ( expression ) */ |
40370 | |
40371 | static tree |
40372 | cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list, |
40373 | location_t location) |
40374 | { |
40375 | tree t, c; |
40376 | |
40377 | matching_parens parens; |
40378 | if (!parens.require_open (parser)) |
40379 | return list; |
40380 | |
40381 | t = cp_parser_assignment_expression (parser); |
40382 | |
40383 | if (t == error_mark_node |
40384 | || !parens.require_close (parser)) |
40385 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40386 | /*or_comma=*/false, |
40387 | /*consume_paren=*/true); |
40388 | |
40389 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT, |
40390 | name: "thread_limit" , location); |
40391 | |
40392 | c = build_omp_clause (location, OMP_CLAUSE_THREAD_LIMIT); |
40393 | OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t; |
40394 | OMP_CLAUSE_CHAIN (c) = list; |
40395 | |
40396 | return c; |
40397 | } |
40398 | |
40399 | /* OpenMP 4.0: |
40400 | aligned ( variable-list ) |
40401 | aligned ( variable-list : constant-expression ) */ |
40402 | |
40403 | static tree |
40404 | cp_parser_omp_clause_aligned (cp_parser *parser, tree list) |
40405 | { |
40406 | tree nlist, c, alignment = NULL_TREE; |
40407 | bool colon; |
40408 | |
40409 | matching_parens parens; |
40410 | if (!parens.require_open (parser)) |
40411 | return list; |
40412 | |
40413 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_ALIGNED, list, |
40414 | colon: &colon); |
40415 | |
40416 | if (colon) |
40417 | { |
40418 | alignment = cp_parser_constant_expression (parser); |
40419 | |
40420 | if (!parens.require_close (parser)) |
40421 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40422 | /*or_comma=*/false, |
40423 | /*consume_paren=*/true); |
40424 | |
40425 | if (alignment == error_mark_node) |
40426 | alignment = NULL_TREE; |
40427 | } |
40428 | |
40429 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40430 | OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; |
40431 | |
40432 | return nlist; |
40433 | } |
40434 | |
40435 | /* OpenMP 5.0: |
40436 | allocate ( variable-list ) |
40437 | allocate ( expression : variable-list ) |
40438 | |
40439 | OpenMP 5.1: |
40440 | allocate ( allocator-modifier : variable-list ) |
40441 | allocate ( allocator-modifier , allocator-modifier : variable-list ) |
40442 | |
40443 | allocator-modifier: |
40444 | allocator ( expression ) |
40445 | align ( expression ) */ |
40446 | |
40447 | static tree |
40448 | cp_parser_omp_clause_allocate (cp_parser *parser, tree list) |
40449 | { |
40450 | tree nlist, c, allocator = NULL_TREE, align = NULL_TREE; |
40451 | bool colon, has_modifiers = false; |
40452 | |
40453 | matching_parens parens; |
40454 | if (!parens.require_open (parser)) |
40455 | return list; |
40456 | |
40457 | cp_parser_parse_tentatively (parser); |
40458 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
40459 | parser->colon_corrects_to_scope_p = false; |
40460 | for (int mod = 0; mod < 2; mod++) |
40461 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40462 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
40463 | { |
40464 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40465 | const char *p = IDENTIFIER_POINTER (id); |
40466 | if (strcmp (s1: p, s2: "allocator" ) != 0 && strcmp (s1: p, s2: "align" ) != 0) |
40467 | break; |
40468 | cp_lexer_consume_token (lexer: parser->lexer); |
40469 | matching_parens parens2; |
40470 | if (!parens2.require_open (parser)) |
40471 | break; |
40472 | if (strcmp (s1: p, s2: "allocator" ) == 0) |
40473 | { |
40474 | if (allocator != NULL_TREE) |
40475 | break; |
40476 | allocator = cp_parser_assignment_expression (parser); |
40477 | } |
40478 | else |
40479 | { |
40480 | if (align != NULL_TREE) |
40481 | break; |
40482 | align = cp_parser_assignment_expression (parser); |
40483 | } |
40484 | if (!parens2.require_close (parser)) |
40485 | break; |
40486 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
40487 | { |
40488 | has_modifiers = true; |
40489 | break; |
40490 | } |
40491 | if (mod != 0 || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
40492 | break; |
40493 | cp_lexer_consume_token (lexer: parser->lexer); |
40494 | } |
40495 | else |
40496 | break; |
40497 | if (!has_modifiers) |
40498 | { |
40499 | cp_parser_abort_tentative_parse (parser); |
40500 | align = NULL_TREE; |
40501 | allocator = NULL_TREE; |
40502 | cp_parser_parse_tentatively (parser); |
40503 | allocator = cp_parser_assignment_expression (parser); |
40504 | } |
40505 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
40506 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
40507 | { |
40508 | cp_parser_parse_definitely (parser); |
40509 | cp_lexer_consume_token (lexer: parser->lexer); |
40510 | if (allocator == error_mark_node) |
40511 | allocator = NULL_TREE; |
40512 | if (align == error_mark_node) |
40513 | align = NULL_TREE; |
40514 | } |
40515 | else |
40516 | { |
40517 | cp_parser_abort_tentative_parse (parser); |
40518 | allocator = NULL_TREE; |
40519 | align = NULL_TREE; |
40520 | } |
40521 | |
40522 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_ALLOCATE, list, |
40523 | colon: &colon); |
40524 | |
40525 | if (allocator || align) |
40526 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40527 | { |
40528 | OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; |
40529 | OMP_CLAUSE_ALLOCATE_ALIGN (c) = align; |
40530 | } |
40531 | |
40532 | return nlist; |
40533 | } |
40534 | |
40535 | /* OpenMP 2.5: |
40536 | lastprivate ( variable-list ) |
40537 | |
40538 | OpenMP 5.0: |
40539 | lastprivate ( [ lastprivate-modifier : ] variable-list ) */ |
40540 | |
40541 | static tree |
40542 | cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list) |
40543 | { |
40544 | bool conditional = false; |
40545 | |
40546 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
40547 | return list; |
40548 | |
40549 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40550 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
40551 | { |
40552 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40553 | const char *p = IDENTIFIER_POINTER (id); |
40554 | |
40555 | if (strcmp (s1: "conditional" , s2: p) == 0) |
40556 | { |
40557 | conditional = true; |
40558 | cp_lexer_consume_token (lexer: parser->lexer); |
40559 | cp_lexer_consume_token (lexer: parser->lexer); |
40560 | } |
40561 | } |
40562 | |
40563 | tree nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_LASTPRIVATE, |
40564 | list, NULL); |
40565 | |
40566 | if (conditional) |
40567 | for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40568 | OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1; |
40569 | return nlist; |
40570 | } |
40571 | |
40572 | /* OpenMP 4.0: |
40573 | linear ( variable-list ) |
40574 | linear ( variable-list : expression ) |
40575 | |
40576 | OpenMP 4.5: |
40577 | linear ( modifier ( variable-list ) ) |
40578 | linear ( modifier ( variable-list ) : expression ) |
40579 | |
40580 | modifier: |
40581 | val |
40582 | ref |
40583 | uval |
40584 | |
40585 | OpenMP 5.2: |
40586 | linear ( variable-list : modifiers-list ) |
40587 | |
40588 | modifiers: |
40589 | val |
40590 | ref |
40591 | uval |
40592 | step ( expression ) */ |
40593 | |
40594 | static tree |
40595 | cp_parser_omp_clause_linear (cp_parser *parser, tree list, |
40596 | bool declare_simd) |
40597 | { |
40598 | tree nlist, c, step = integer_one_node; |
40599 | bool colon; |
40600 | enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; |
40601 | bool old_linear_modifier = false; |
40602 | |
40603 | matching_parens parens; |
40604 | if (!parens.require_open (parser)) |
40605 | return list; |
40606 | |
40607 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40608 | { |
40609 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40610 | const char *p = IDENTIFIER_POINTER (id); |
40611 | |
40612 | if (strcmp (s1: "ref" , s2: p) == 0) |
40613 | kind = OMP_CLAUSE_LINEAR_REF; |
40614 | else if (strcmp (s1: "val" , s2: p) == 0) |
40615 | kind = OMP_CLAUSE_LINEAR_VAL; |
40616 | else if (strcmp (s1: "uval" , s2: p) == 0) |
40617 | kind = OMP_CLAUSE_LINEAR_UVAL; |
40618 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
40619 | { |
40620 | cp_lexer_consume_token (lexer: parser->lexer); |
40621 | old_linear_modifier = true; |
40622 | } |
40623 | else |
40624 | kind = OMP_CLAUSE_LINEAR_DEFAULT; |
40625 | } |
40626 | |
40627 | if (kind == OMP_CLAUSE_LINEAR_DEFAULT) |
40628 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_LINEAR, list, |
40629 | colon: &colon); |
40630 | else |
40631 | { |
40632 | nlist = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_LINEAR, list); |
40633 | colon = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON); |
40634 | if (colon) |
40635 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
40636 | else if (!parens.require_close (parser)) |
40637 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40638 | /*or_comma=*/false, |
40639 | /*consume_paren=*/true); |
40640 | } |
40641 | |
40642 | if (colon) |
40643 | { |
40644 | bool has_modifiers = false; |
40645 | if (kind == OMP_CLAUSE_LINEAR_DEFAULT |
40646 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40647 | { |
40648 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40649 | const char *p = IDENTIFIER_POINTER (id); |
40650 | size_t pos = 0; |
40651 | if (strcmp (s1: "ref" , s2: p) == 0 |
40652 | || strcmp (s1: "val" , s2: p) == 0 |
40653 | || strcmp (s1: "uval" , s2: p) == 0) |
40654 | pos = 2; |
40655 | else if (strcmp (s1: "step" , s2: p) == 0 |
40656 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
40657 | { |
40658 | pos = cp_parser_skip_balanced_tokens (parser, n: 2); |
40659 | if (pos == 2) |
40660 | pos = 0; |
40661 | } |
40662 | if (pos != 0 |
40663 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: pos, type: CPP_COMMA) |
40664 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: pos, |
40665 | type: CPP_CLOSE_PAREN))) |
40666 | has_modifiers = true; |
40667 | } |
40668 | |
40669 | step = NULL_TREE; |
40670 | if (has_modifiers) |
40671 | { |
40672 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40673 | { |
40674 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40675 | const char *p = IDENTIFIER_POINTER (id); |
40676 | enum omp_clause_linear_kind nkind = OMP_CLAUSE_LINEAR_DEFAULT; |
40677 | if (strcmp (s1: "ref" , s2: p) == 0) |
40678 | nkind = OMP_CLAUSE_LINEAR_REF; |
40679 | else if (strcmp (s1: "val" , s2: p) == 0) |
40680 | nkind = OMP_CLAUSE_LINEAR_VAL; |
40681 | else if (strcmp (s1: "uval" , s2: p) == 0) |
40682 | nkind = OMP_CLAUSE_LINEAR_UVAL; |
40683 | if (nkind != OMP_CLAUSE_LINEAR_DEFAULT) |
40684 | { |
40685 | if (kind != OMP_CLAUSE_LINEAR_DEFAULT) |
40686 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
40687 | "multiple linear modifiers" ); |
40688 | kind = nkind; |
40689 | cp_lexer_consume_token (lexer: parser->lexer); |
40690 | } |
40691 | else if (strcmp (s1: "step" , s2: p) == 0) |
40692 | { |
40693 | location_t step_loc |
40694 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40695 | cp_lexer_consume_token (lexer: parser->lexer); |
40696 | matching_parens parens2; |
40697 | if (parens2.require_open (parser)) |
40698 | { |
40699 | if (step) |
40700 | error_at (step_loc, "multiple %<step%> modifiers" ); |
40701 | if (declare_simd |
40702 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40703 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
40704 | type: CPP_CLOSE_PAREN)) |
40705 | { |
40706 | cp_token *token |
40707 | = cp_lexer_peek_token (lexer: parser->lexer); |
40708 | location_t tok_loc = token->location; |
40709 | cp_parser_parse_tentatively (parser); |
40710 | step = cp_parser_id_expression (parser, template_keyword_p: false, check_dependency_p: true, |
40711 | NULL, declarator_p: false, optional_p: false); |
40712 | if (step != error_mark_node) |
40713 | step = cp_parser_lookup_name_simple (parser, name: step, |
40714 | location: tok_loc); |
40715 | if (step == error_mark_node) |
40716 | { |
40717 | step = NULL_TREE; |
40718 | cp_parser_abort_tentative_parse (parser); |
40719 | } |
40720 | else if (!cp_parser_parse_definitely (parser)) |
40721 | step = NULL_TREE; |
40722 | } |
40723 | if (!step) |
40724 | step = cp_parser_assignment_expression (parser); |
40725 | if (!parens2.require_close (parser)) |
40726 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, |
40727 | or_comma: false, consume_paren: true); |
40728 | } |
40729 | else |
40730 | break; |
40731 | } |
40732 | else |
40733 | break; |
40734 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
40735 | { |
40736 | cp_lexer_consume_token (lexer: parser->lexer); |
40737 | continue; |
40738 | } |
40739 | break; |
40740 | } |
40741 | if (!step) |
40742 | step = integer_one_node; |
40743 | } |
40744 | else if (declare_simd |
40745 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40746 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN)) |
40747 | { |
40748 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
40749 | cp_parser_parse_tentatively (parser); |
40750 | step = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
40751 | /*check_dependency_p=*/true, |
40752 | /*template_p=*/NULL, |
40753 | /*declarator_p=*/false, |
40754 | /*optional_p=*/false); |
40755 | if (step != error_mark_node) |
40756 | step = cp_parser_lookup_name_simple (parser, name: step, location: token->location); |
40757 | if (step == error_mark_node) |
40758 | { |
40759 | step = NULL_TREE; |
40760 | cp_parser_abort_tentative_parse (parser); |
40761 | } |
40762 | else if (!cp_parser_parse_definitely (parser)) |
40763 | step = NULL_TREE; |
40764 | } |
40765 | if (!step) |
40766 | step = cp_parser_assignment_expression (parser); |
40767 | |
40768 | if (!parens.require_close (parser)) |
40769 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40770 | /*or_comma=*/false, |
40771 | /*consume_paren=*/true); |
40772 | |
40773 | if (step == error_mark_node) |
40774 | return list; |
40775 | } |
40776 | |
40777 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40778 | { |
40779 | OMP_CLAUSE_LINEAR_STEP (c) = step; |
40780 | OMP_CLAUSE_LINEAR_KIND (c) = kind; |
40781 | OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier; |
40782 | } |
40783 | |
40784 | return nlist; |
40785 | } |
40786 | |
40787 | /* OpenMP 4.0: |
40788 | safelen ( constant-expression ) */ |
40789 | |
40790 | static tree |
40791 | cp_parser_omp_clause_safelen (cp_parser *parser, tree list, |
40792 | location_t location) |
40793 | { |
40794 | tree t, c; |
40795 | |
40796 | matching_parens parens; |
40797 | if (!parens.require_open (parser)) |
40798 | return list; |
40799 | |
40800 | t = cp_parser_constant_expression (parser); |
40801 | |
40802 | if (t == error_mark_node |
40803 | || !parens.require_close (parser)) |
40804 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40805 | /*or_comma=*/false, |
40806 | /*consume_paren=*/true); |
40807 | |
40808 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen" , location); |
40809 | |
40810 | c = build_omp_clause (location, OMP_CLAUSE_SAFELEN); |
40811 | OMP_CLAUSE_SAFELEN_EXPR (c) = t; |
40812 | OMP_CLAUSE_CHAIN (c) = list; |
40813 | |
40814 | return c; |
40815 | } |
40816 | |
40817 | /* OpenMP 4.0: |
40818 | simdlen ( constant-expression ) */ |
40819 | |
40820 | static tree |
40821 | cp_parser_omp_clause_simdlen (cp_parser *parser, tree list, |
40822 | location_t location) |
40823 | { |
40824 | tree t, c; |
40825 | |
40826 | matching_parens parens; |
40827 | if (!parens.require_open (parser)) |
40828 | return list; |
40829 | |
40830 | t = cp_parser_constant_expression (parser); |
40831 | |
40832 | if (t == error_mark_node |
40833 | || !parens.require_close (parser)) |
40834 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40835 | /*or_comma=*/false, |
40836 | /*consume_paren=*/true); |
40837 | |
40838 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen" , location); |
40839 | |
40840 | c = build_omp_clause (location, OMP_CLAUSE_SIMDLEN); |
40841 | OMP_CLAUSE_SIMDLEN_EXPR (c) = t; |
40842 | OMP_CLAUSE_CHAIN (c) = list; |
40843 | |
40844 | return c; |
40845 | } |
40846 | |
40847 | /* OpenMP 4.5: |
40848 | vec: |
40849 | identifier [+/- integer] |
40850 | vec , identifier [+/- integer] |
40851 | */ |
40852 | |
40853 | static tree |
40854 | cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc, |
40855 | tree list, bool depend_p) |
40856 | { |
40857 | tree vec = NULL; |
40858 | |
40859 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
40860 | { |
40861 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
40862 | return list; |
40863 | } |
40864 | |
40865 | if (!depend_p) |
40866 | { |
40867 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40868 | if (strcmp (IDENTIFIER_POINTER (id), s2: "omp_cur_iteration" ) == 0 |
40869 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_MINUS) |
40870 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NUMBER) |
40871 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_PAREN)) |
40872 | { |
40873 | tree val = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->u.value; |
40874 | if (integer_onep (val)) |
40875 | { |
40876 | cp_lexer_consume_token (lexer: parser->lexer); |
40877 | cp_lexer_consume_token (lexer: parser->lexer); |
40878 | cp_lexer_consume_token (lexer: parser->lexer); |
40879 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); |
40880 | OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; |
40881 | OMP_CLAUSE_CHAIN (u) = list; |
40882 | return u; |
40883 | } |
40884 | } |
40885 | } |
40886 | |
40887 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40888 | { |
40889 | location_t id_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40890 | tree t, identifier = cp_parser_identifier (parser); |
40891 | tree addend = NULL; |
40892 | |
40893 | if (identifier == error_mark_node) |
40894 | t = error_mark_node; |
40895 | else |
40896 | { |
40897 | t = cp_parser_lookup_name_simple |
40898 | (parser, name: identifier, |
40899 | location: cp_lexer_peek_token (lexer: parser->lexer)->location); |
40900 | if (t == error_mark_node) |
40901 | cp_parser_name_lookup_error (parser, name: identifier, decl: t, desired: NLE_NULL, |
40902 | location: id_loc); |
40903 | } |
40904 | |
40905 | bool neg = false; |
40906 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MINUS)) |
40907 | neg = true; |
40908 | else if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PLUS)) |
40909 | { |
40910 | addend = integer_zero_node; |
40911 | goto add_to_vector; |
40912 | } |
40913 | cp_lexer_consume_token (lexer: parser->lexer); |
40914 | |
40915 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NUMBER)) |
40916 | { |
40917 | cp_parser_error (parser, gmsgid: "expected integer" ); |
40918 | return list; |
40919 | } |
40920 | |
40921 | addend = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40922 | if (TREE_CODE (addend) != INTEGER_CST) |
40923 | { |
40924 | cp_parser_error (parser, gmsgid: "expected integer" ); |
40925 | return list; |
40926 | } |
40927 | cp_lexer_consume_token (lexer: parser->lexer); |
40928 | |
40929 | add_to_vector: |
40930 | if (t != error_mark_node) |
40931 | { |
40932 | vec = tree_cons (addend, t, vec); |
40933 | if (neg) |
40934 | OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; |
40935 | } |
40936 | |
40937 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
40938 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
40939 | break; |
40940 | |
40941 | cp_lexer_consume_token (lexer: parser->lexer); |
40942 | } |
40943 | |
40944 | if (vec) |
40945 | { |
40946 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); |
40947 | OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; |
40948 | OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; |
40949 | OMP_CLAUSE_DECL (u) = nreverse (vec); |
40950 | OMP_CLAUSE_CHAIN (u) = list; |
40951 | return u; |
40952 | } |
40953 | return list; |
40954 | } |
40955 | |
40956 | /* OpenMP 5.0: |
40957 | detach ( event-handle ) */ |
40958 | |
40959 | static tree |
40960 | cp_parser_omp_clause_detach (cp_parser *parser, tree list) |
40961 | { |
40962 | matching_parens parens; |
40963 | |
40964 | if (!parens.require_open (parser)) |
40965 | return list; |
40966 | |
40967 | cp_token *token; |
40968 | tree name, decl; |
40969 | |
40970 | token = cp_lexer_peek_token (lexer: parser->lexer); |
40971 | name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
40972 | /*check_dependency_p=*/true, |
40973 | /*template_p=*/NULL, |
40974 | /*declarator_p=*/false, |
40975 | /*optional_p=*/false); |
40976 | if (name == error_mark_node) |
40977 | decl = error_mark_node; |
40978 | else |
40979 | { |
40980 | if (identifier_p (t: name)) |
40981 | decl = cp_parser_lookup_name_simple (parser, name, location: token->location); |
40982 | else |
40983 | decl = name; |
40984 | if (decl == error_mark_node) |
40985 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, |
40986 | location: token->location); |
40987 | } |
40988 | |
40989 | if (decl == error_mark_node |
40990 | || !parens.require_close (parser)) |
40991 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40992 | /*or_comma=*/false, |
40993 | /*consume_paren=*/true); |
40994 | |
40995 | tree u = build_omp_clause (token->location, OMP_CLAUSE_DETACH); |
40996 | OMP_CLAUSE_DECL (u) = decl; |
40997 | OMP_CLAUSE_CHAIN (u) = list; |
40998 | |
40999 | return u; |
41000 | } |
41001 | |
41002 | /* OpenMP 5.0: |
41003 | iterators ( iterators-definition ) |
41004 | |
41005 | iterators-definition: |
41006 | iterator-specifier |
41007 | iterator-specifier , iterators-definition |
41008 | |
41009 | iterator-specifier: |
41010 | identifier = range-specification |
41011 | iterator-type identifier = range-specification |
41012 | |
41013 | range-specification: |
41014 | begin : end |
41015 | begin : end : step */ |
41016 | |
41017 | static tree |
41018 | cp_parser_omp_iterators (cp_parser *parser) |
41019 | { |
41020 | tree ret = NULL_TREE, *last = &ret; |
41021 | cp_lexer_consume_token (lexer: parser->lexer); |
41022 | |
41023 | matching_parens parens; |
41024 | if (!parens.require_open (parser)) |
41025 | return error_mark_node; |
41026 | |
41027 | bool saved_colon_corrects_to_scope_p |
41028 | = parser->colon_corrects_to_scope_p; |
41029 | bool saved_colon_doesnt_start_class_def_p |
41030 | = parser->colon_doesnt_start_class_def_p; |
41031 | |
41032 | do |
41033 | { |
41034 | tree iter_type; |
41035 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
41036 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_EQ)) |
41037 | iter_type = integer_type_node; |
41038 | else |
41039 | { |
41040 | const char *saved_message |
41041 | = parser->type_definition_forbidden_message; |
41042 | parser->type_definition_forbidden_message |
41043 | = G_("types may not be defined in iterator type" ); |
41044 | |
41045 | iter_type = cp_parser_type_id (parser); |
41046 | |
41047 | parser->type_definition_forbidden_message = saved_message; |
41048 | } |
41049 | |
41050 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41051 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
41052 | { |
41053 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
41054 | break; |
41055 | } |
41056 | |
41057 | tree id = cp_parser_identifier (parser); |
41058 | if (id == error_mark_node) |
41059 | break; |
41060 | |
41061 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
41062 | break; |
41063 | |
41064 | parser->colon_corrects_to_scope_p = false; |
41065 | parser->colon_doesnt_start_class_def_p = true; |
41066 | tree begin = cp_parser_assignment_expression (parser); |
41067 | |
41068 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
41069 | break; |
41070 | |
41071 | tree end = cp_parser_assignment_expression (parser); |
41072 | |
41073 | tree step = integer_one_node; |
41074 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
41075 | { |
41076 | cp_lexer_consume_token (lexer: parser->lexer); |
41077 | step = cp_parser_assignment_expression (parser); |
41078 | } |
41079 | |
41080 | tree iter_var = build_decl (loc, VAR_DECL, id, iter_type); |
41081 | DECL_ARTIFICIAL (iter_var) = 1; |
41082 | DECL_CONTEXT (iter_var) = current_function_decl; |
41083 | pushdecl (iter_var); |
41084 | |
41085 | *last = make_tree_vec (6); |
41086 | TREE_VEC_ELT (*last, 0) = iter_var; |
41087 | TREE_VEC_ELT (*last, 1) = begin; |
41088 | TREE_VEC_ELT (*last, 2) = end; |
41089 | TREE_VEC_ELT (*last, 3) = step; |
41090 | last = &TREE_CHAIN (*last); |
41091 | |
41092 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41093 | { |
41094 | cp_lexer_consume_token (lexer: parser->lexer); |
41095 | continue; |
41096 | } |
41097 | break; |
41098 | } |
41099 | while (1); |
41100 | |
41101 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
41102 | parser->colon_doesnt_start_class_def_p |
41103 | = saved_colon_doesnt_start_class_def_p; |
41104 | |
41105 | if (!parens.require_close (parser)) |
41106 | cp_parser_skip_to_closing_parenthesis (parser, |
41107 | /*recovering=*/true, |
41108 | /*or_comma=*/false, |
41109 | /*consume_paren=*/true); |
41110 | |
41111 | return ret ? ret : error_mark_node; |
41112 | } |
41113 | |
41114 | /* OpenMP 5.0: |
41115 | affinity ( [aff-modifier :] variable-list ) |
41116 | aff-modifier: |
41117 | iterator ( iterators-definition ) */ |
41118 | |
41119 | static tree |
41120 | cp_parser_omp_clause_affinity (cp_parser *parser, tree list) |
41121 | { |
41122 | tree nlist, c, iterators = NULL_TREE; |
41123 | |
41124 | matching_parens parens; |
41125 | if (!parens.require_open (parser)) |
41126 | return list; |
41127 | |
41128 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41129 | { |
41130 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41131 | const char *p = IDENTIFIER_POINTER (id); |
41132 | bool parse_iter = ((strcmp (s1: "iterator" , s2: p) == 0) |
41133 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
41134 | type: CPP_OPEN_PAREN))); |
41135 | if (parse_iter) |
41136 | { |
41137 | size_t n = cp_parser_skip_balanced_tokens (parser, n: 2); |
41138 | parse_iter = cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_COLON); |
41139 | } |
41140 | if (parse_iter) |
41141 | { |
41142 | begin_scope (sk_omp, NULL); |
41143 | iterators = cp_parser_omp_iterators (parser); |
41144 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
41145 | { |
41146 | if (iterators) |
41147 | poplevel (0, 1, 0); |
41148 | cp_parser_skip_to_closing_parenthesis (parser, |
41149 | /*recovering=*/true, |
41150 | /*or_comma=*/false, |
41151 | /*consume_paren=*/true); |
41152 | return list; |
41153 | } |
41154 | } |
41155 | } |
41156 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_AFFINITY, |
41157 | list, NULL); |
41158 | if (iterators) |
41159 | { |
41160 | tree block = poplevel (1, 1, 0); |
41161 | if (iterators != error_mark_node) |
41162 | { |
41163 | TREE_VEC_ELT (iterators, 5) = block; |
41164 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
41165 | OMP_CLAUSE_DECL (c) = build_tree_list (iterators, |
41166 | OMP_CLAUSE_DECL (c)); |
41167 | } |
41168 | } |
41169 | return nlist; |
41170 | } |
41171 | |
41172 | /* OpenMP 4.0: |
41173 | depend ( depend-kind : variable-list ) |
41174 | |
41175 | depend-kind: |
41176 | in | out | inout |
41177 | |
41178 | OpenMP 4.5: |
41179 | depend ( source ) |
41180 | |
41181 | depend ( sink : vec ) |
41182 | |
41183 | OpenMP 5.0: |
41184 | depend ( depend-modifier , depend-kind: variable-list ) |
41185 | |
41186 | depend-kind: |
41187 | in | out | inout | mutexinoutset | depobj |
41188 | |
41189 | depend-modifier: |
41190 | iterator ( iterators-definition ) */ |
41191 | |
41192 | static tree |
41193 | cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) |
41194 | { |
41195 | tree nlist, c, iterators = NULL_TREE; |
41196 | enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; |
41197 | enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; |
41198 | |
41199 | matching_parens parens; |
41200 | if (!parens.require_open (parser)) |
41201 | return list; |
41202 | |
41203 | do |
41204 | { |
41205 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
41206 | goto invalid_kind; |
41207 | |
41208 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41209 | const char *p = IDENTIFIER_POINTER (id); |
41210 | |
41211 | if (strcmp (s1: "iterator" , s2: p) == 0 && iterators == NULL_TREE) |
41212 | { |
41213 | begin_scope (sk_omp, NULL); |
41214 | iterators = cp_parser_omp_iterators (parser); |
41215 | cp_parser_require (parser, type: CPP_COMMA, token_desc: RT_COMMA); |
41216 | continue; |
41217 | } |
41218 | if (strcmp (s1: "in" , s2: p) == 0) |
41219 | kind = OMP_CLAUSE_DEPEND_IN; |
41220 | else if (strcmp (s1: "inout" , s2: p) == 0) |
41221 | kind = OMP_CLAUSE_DEPEND_INOUT; |
41222 | else if (strcmp (s1: "inoutset" , s2: p) == 0) |
41223 | kind = OMP_CLAUSE_DEPEND_INOUTSET; |
41224 | else if (strcmp (s1: "mutexinoutset" , s2: p) == 0) |
41225 | kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET; |
41226 | else if (strcmp (s1: "out" , s2: p) == 0) |
41227 | kind = OMP_CLAUSE_DEPEND_OUT; |
41228 | else if (strcmp (s1: "depobj" , s2: p) == 0) |
41229 | kind = OMP_CLAUSE_DEPEND_DEPOBJ; |
41230 | else if (strcmp (s1: "sink" , s2: p) == 0) |
41231 | dkind = OMP_CLAUSE_DOACROSS_SINK; |
41232 | else if (strcmp (s1: "source" , s2: p) == 0) |
41233 | dkind = OMP_CLAUSE_DOACROSS_SOURCE; |
41234 | else |
41235 | goto invalid_kind; |
41236 | break; |
41237 | } |
41238 | while (1); |
41239 | |
41240 | cp_lexer_consume_token (lexer: parser->lexer); |
41241 | |
41242 | if (iterators |
41243 | && (dkind == OMP_CLAUSE_DOACROSS_SOURCE |
41244 | || dkind == OMP_CLAUSE_DOACROSS_SINK)) |
41245 | { |
41246 | poplevel (0, 1, 0); |
41247 | error_at (loc, "%<iterator%> modifier incompatible with %qs" , |
41248 | dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink" ); |
41249 | iterators = NULL_TREE; |
41250 | } |
41251 | |
41252 | if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) |
41253 | { |
41254 | c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); |
41255 | OMP_CLAUSE_DOACROSS_KIND (c) = dkind; |
41256 | OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; |
41257 | OMP_CLAUSE_DECL (c) = NULL_TREE; |
41258 | OMP_CLAUSE_CHAIN (c) = list; |
41259 | if (!parens.require_close (parser)) |
41260 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41261 | /*or_comma=*/false, |
41262 | /*consume_paren=*/true); |
41263 | return c; |
41264 | } |
41265 | |
41266 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
41267 | goto resync_fail; |
41268 | |
41269 | if (dkind == OMP_CLAUSE_DOACROSS_SINK) |
41270 | { |
41271 | nlist = cp_parser_omp_clause_doacross_sink (parser, clause_loc: loc, list, depend_p: true); |
41272 | if (!parens.require_close (parser)) |
41273 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41274 | /*or_comma=*/false, |
41275 | /*consume_paren=*/true); |
41276 | } |
41277 | else |
41278 | { |
41279 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_DEPEND, |
41280 | list, NULL); |
41281 | |
41282 | if (iterators) |
41283 | { |
41284 | tree block = poplevel (1, 1, 0); |
41285 | if (iterators == error_mark_node) |
41286 | iterators = NULL_TREE; |
41287 | else |
41288 | TREE_VEC_ELT (iterators, 5) = block; |
41289 | } |
41290 | |
41291 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
41292 | { |
41293 | OMP_CLAUSE_DEPEND_KIND (c) = kind; |
41294 | if (iterators) |
41295 | OMP_CLAUSE_DECL (c) |
41296 | = build_tree_list (iterators, OMP_CLAUSE_DECL (c)); |
41297 | } |
41298 | } |
41299 | return nlist; |
41300 | |
41301 | invalid_kind: |
41302 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
41303 | resync_fail: |
41304 | if (iterators) |
41305 | poplevel (0, 1, 0); |
41306 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41307 | /*or_comma=*/false, |
41308 | /*consume_paren=*/true); |
41309 | return list; |
41310 | } |
41311 | |
41312 | /* OpenMP 5.2: |
41313 | doacross ( source : ) |
41314 | doacross ( source : omp_cur_iteration ) |
41315 | |
41316 | doacross ( sink : vec ) |
41317 | doacross ( sink : omp_cur_iteration - logical_iteration ) */ |
41318 | |
41319 | static tree |
41320 | cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) |
41321 | { |
41322 | tree nlist; |
41323 | enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; |
41324 | |
41325 | matching_parens parens; |
41326 | if (!parens.require_open (parser)) |
41327 | return list; |
41328 | |
41329 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
41330 | { |
41331 | invalid_kind: |
41332 | cp_parser_error (parser, gmsgid: "invalid doacross kind" ); |
41333 | resync_fail: |
41334 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41335 | /*or_comma=*/false, |
41336 | /*consume_paren=*/true); |
41337 | return list; |
41338 | } |
41339 | |
41340 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41341 | const char *p = IDENTIFIER_POINTER (id); |
41342 | |
41343 | if (strcmp (s1: "sink" , s2: p) == 0) |
41344 | kind = OMP_CLAUSE_DOACROSS_SINK; |
41345 | else if (strcmp (s1: "source" , s2: p) == 0) |
41346 | kind = OMP_CLAUSE_DOACROSS_SOURCE; |
41347 | else |
41348 | goto invalid_kind; |
41349 | |
41350 | cp_lexer_consume_token (lexer: parser->lexer); |
41351 | |
41352 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
41353 | goto resync_fail; |
41354 | |
41355 | if (kind == OMP_CLAUSE_DOACROSS_SOURCE) |
41356 | { |
41357 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41358 | { |
41359 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41360 | p = IDENTIFIER_POINTER (id); |
41361 | if (strcmp (s1: p, s2: "omp_cur_iteration" ) == 0) |
41362 | cp_lexer_consume_token (lexer: parser->lexer); |
41363 | } |
41364 | nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); |
41365 | OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE; |
41366 | OMP_CLAUSE_DECL (nlist) = NULL_TREE; |
41367 | OMP_CLAUSE_CHAIN (nlist) = list; |
41368 | } |
41369 | else |
41370 | nlist = cp_parser_omp_clause_doacross_sink (parser, clause_loc: loc, list, depend_p: false); |
41371 | |
41372 | if (!parens.require_close (parser)) |
41373 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41374 | /*or_comma=*/false, |
41375 | /*consume_paren=*/true); |
41376 | return nlist; |
41377 | } |
41378 | |
41379 | /* OpenMP 4.0: |
41380 | from ( variable-list ) |
41381 | to ( variable-list ) |
41382 | |
41383 | OpenMP 5.1: |
41384 | from ( [present :] variable-list ) |
41385 | to ( [present :] variable-list ) */ |
41386 | |
41387 | static tree |
41388 | cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, |
41389 | tree list) |
41390 | { |
41391 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41392 | return list; |
41393 | |
41394 | bool present = false; |
41395 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
41396 | |
41397 | if (token->type == CPP_NAME |
41398 | && strcmp (IDENTIFIER_POINTER (token->u.value), s2: "present" ) == 0 |
41399 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
41400 | { |
41401 | present = true; |
41402 | cp_lexer_consume_token (lexer: parser->lexer); |
41403 | cp_lexer_consume_token (lexer: parser->lexer); |
41404 | } |
41405 | |
41406 | tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, map_lvalue: true); |
41407 | if (present) |
41408 | for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
41409 | OMP_CLAUSE_MOTION_PRESENT (c) = 1; |
41410 | |
41411 | return nl; |
41412 | } |
41413 | |
41414 | /* OpenMP 4.0: |
41415 | map ( map-kind : variable-list ) |
41416 | map ( variable-list ) |
41417 | |
41418 | map-kind: |
41419 | alloc | to | from | tofrom |
41420 | |
41421 | OpenMP 4.5: |
41422 | map-kind: |
41423 | alloc | to | from | tofrom | release | delete |
41424 | |
41425 | map ( always [,] map-kind: variable-list ) |
41426 | |
41427 | OpenMP 5.0: |
41428 | map ( [map-type-modifier[,] ...] map-kind: variable-list ) |
41429 | |
41430 | map-type-modifier: |
41431 | always | close */ |
41432 | |
41433 | static tree |
41434 | cp_parser_omp_clause_map (cp_parser *parser, tree list) |
41435 | { |
41436 | tree nlist, c; |
41437 | enum gomp_map_kind kind = GOMP_MAP_TOFROM; |
41438 | |
41439 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41440 | return list; |
41441 | |
41442 | int pos = 1; |
41443 | int map_kind_pos = 0; |
41444 | while (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos)->type == CPP_NAME |
41445 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos)->keyword == RID_DELETE) |
41446 | { |
41447 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos + 1)->type == CPP_COLON) |
41448 | { |
41449 | map_kind_pos = pos; |
41450 | break; |
41451 | } |
41452 | |
41453 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos + 1)->type == CPP_COMMA) |
41454 | pos++; |
41455 | pos++; |
41456 | } |
41457 | |
41458 | bool always_modifier = false; |
41459 | bool close_modifier = false; |
41460 | bool present_modifier = false; |
41461 | for (int pos = 1; pos < map_kind_pos; ++pos) |
41462 | { |
41463 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
41464 | if (tok->type == CPP_COMMA) |
41465 | { |
41466 | cp_lexer_consume_token (lexer: parser->lexer); |
41467 | continue; |
41468 | } |
41469 | |
41470 | const char *p = IDENTIFIER_POINTER (tok->u.value); |
41471 | if (strcmp (s1: "always" , s2: p) == 0) |
41472 | { |
41473 | if (always_modifier) |
41474 | { |
41475 | cp_parser_error (parser, gmsgid: "too many %<always%> modifiers" ); |
41476 | cp_parser_skip_to_closing_parenthesis (parser, |
41477 | /*recovering=*/true, |
41478 | /*or_comma=*/false, |
41479 | /*consume_paren=*/true); |
41480 | return list; |
41481 | } |
41482 | always_modifier = true; |
41483 | } |
41484 | else if (strcmp (s1: "close" , s2: p) == 0) |
41485 | { |
41486 | if (close_modifier) |
41487 | { |
41488 | cp_parser_error (parser, gmsgid: "too many %<close%> modifiers" ); |
41489 | cp_parser_skip_to_closing_parenthesis (parser, |
41490 | /*recovering=*/true, |
41491 | /*or_comma=*/false, |
41492 | /*consume_paren=*/true); |
41493 | return list; |
41494 | } |
41495 | close_modifier = true; |
41496 | } |
41497 | else if (strcmp (s1: "present" , s2: p) == 0) |
41498 | { |
41499 | if (present_modifier) |
41500 | { |
41501 | cp_parser_error (parser, gmsgid: "too many %<present%> modifiers" ); |
41502 | cp_parser_skip_to_closing_parenthesis (parser, |
41503 | /*recovering=*/true, |
41504 | /*or_comma=*/false, |
41505 | /*consume_paren=*/true); |
41506 | return list; |
41507 | } |
41508 | present_modifier = true; |
41509 | } |
41510 | else |
41511 | { |
41512 | cp_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other" |
41513 | " than %<always%>, %<close%> or %<present%>" ); |
41514 | cp_parser_skip_to_closing_parenthesis (parser, |
41515 | /*recovering=*/true, |
41516 | /*or_comma=*/false, |
41517 | /*consume_paren=*/true); |
41518 | return list; |
41519 | } |
41520 | |
41521 | cp_lexer_consume_token (lexer: parser->lexer); |
41522 | } |
41523 | |
41524 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
41525 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
41526 | { |
41527 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41528 | const char *p = IDENTIFIER_POINTER (id); |
41529 | int always_present_modifier = always_modifier && present_modifier; |
41530 | |
41531 | if (strcmp (s1: "alloc" , s2: p) == 0) |
41532 | kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC; |
41533 | else if (strcmp (s1: "to" , s2: p) == 0) |
41534 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO |
41535 | : present_modifier ? GOMP_MAP_PRESENT_TO |
41536 | : always_modifier ? GOMP_MAP_ALWAYS_TO |
41537 | : GOMP_MAP_TO); |
41538 | else if (strcmp (s1: "from" , s2: p) == 0) |
41539 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM |
41540 | : present_modifier ? GOMP_MAP_PRESENT_FROM |
41541 | : always_modifier ? GOMP_MAP_ALWAYS_FROM |
41542 | : GOMP_MAP_FROM); |
41543 | else if (strcmp (s1: "tofrom" , s2: p) == 0) |
41544 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM |
41545 | : present_modifier ? GOMP_MAP_PRESENT_TOFROM |
41546 | : always_modifier ? GOMP_MAP_ALWAYS_TOFROM |
41547 | : GOMP_MAP_TOFROM); |
41548 | else if (strcmp (s1: "release" , s2: p) == 0) |
41549 | kind = GOMP_MAP_RELEASE; |
41550 | else |
41551 | { |
41552 | cp_parser_error (parser, gmsgid: "invalid map kind" ); |
41553 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41554 | /*or_comma=*/false, |
41555 | /*consume_paren=*/true); |
41556 | return list; |
41557 | } |
41558 | cp_lexer_consume_token (lexer: parser->lexer); |
41559 | cp_lexer_consume_token (lexer: parser->lexer); |
41560 | } |
41561 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DELETE) |
41562 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
41563 | { |
41564 | kind = GOMP_MAP_DELETE; |
41565 | cp_lexer_consume_token (lexer: parser->lexer); |
41566 | cp_lexer_consume_token (lexer: parser->lexer); |
41567 | } |
41568 | |
41569 | /* We introduce a scope here so that errors parsing e.g. "always", "close" |
41570 | tokens do not propagate to later directives that might use them |
41571 | legally. */ |
41572 | begin_scope (sk_omp, NULL); |
41573 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_MAP, list, |
41574 | NULL, map_lvalue: true); |
41575 | finish_scope (); |
41576 | |
41577 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
41578 | OMP_CLAUSE_SET_MAP_KIND (c, kind); |
41579 | |
41580 | return nlist; |
41581 | } |
41582 | |
41583 | /* OpenMP 4.0: |
41584 | device ( expression ) |
41585 | |
41586 | OpenMP 5.0: |
41587 | device ( [device-modifier :] integer-expression ) |
41588 | |
41589 | device-modifier: |
41590 | ancestor | device_num */ |
41591 | |
41592 | static tree |
41593 | cp_parser_omp_clause_device (cp_parser *parser, tree list, |
41594 | location_t location) |
41595 | { |
41596 | tree t, c; |
41597 | bool ancestor = false; |
41598 | |
41599 | matching_parens parens; |
41600 | if (!parens.require_open (parser)) |
41601 | return list; |
41602 | |
41603 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
41604 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
41605 | { |
41606 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
41607 | const char *p = IDENTIFIER_POINTER (tok->u.value); |
41608 | if (strcmp (s1: "ancestor" , s2: p) == 0) |
41609 | { |
41610 | ancestor = true; |
41611 | |
41612 | /* A requires directive with the reverse_offload clause must be |
41613 | specified. */ |
41614 | if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) |
41615 | { |
41616 | error_at (tok->location, "%<ancestor%> device modifier not " |
41617 | "preceded by %<requires%> directive " |
41618 | "with %<reverse_offload%> clause" ); |
41619 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
41620 | return list; |
41621 | } |
41622 | } |
41623 | else if (strcmp (s1: "device_num" , s2: p) == 0) |
41624 | ; |
41625 | else |
41626 | { |
41627 | error_at (tok->location, "expected %<ancestor%> or %<device_num%>" ); |
41628 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
41629 | return list; |
41630 | } |
41631 | cp_lexer_consume_token (lexer: parser->lexer); |
41632 | cp_lexer_consume_token (lexer: parser->lexer); |
41633 | } |
41634 | |
41635 | t = cp_parser_assignment_expression (parser); |
41636 | |
41637 | if (t == error_mark_node |
41638 | || !parens.require_close (parser)) |
41639 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41640 | /*or_comma=*/false, |
41641 | /*consume_paren=*/true); |
41642 | |
41643 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, |
41644 | name: "device" , location); |
41645 | |
41646 | c = build_omp_clause (location, OMP_CLAUSE_DEVICE); |
41647 | OMP_CLAUSE_DEVICE_ID (c) = t; |
41648 | OMP_CLAUSE_CHAIN (c) = list; |
41649 | OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor; |
41650 | |
41651 | return c; |
41652 | } |
41653 | |
41654 | /* OpenMP 4.0: |
41655 | dist_schedule ( static ) |
41656 | dist_schedule ( static , expression ) */ |
41657 | |
41658 | static tree |
41659 | cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, |
41660 | location_t location) |
41661 | { |
41662 | tree c, t; |
41663 | |
41664 | matching_parens parens; |
41665 | if (!parens.require_open (parser)) |
41666 | return list; |
41667 | |
41668 | c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE); |
41669 | |
41670 | if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC)) |
41671 | goto invalid_kind; |
41672 | cp_lexer_consume_token (lexer: parser->lexer); |
41673 | |
41674 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41675 | { |
41676 | cp_lexer_consume_token (lexer: parser->lexer); |
41677 | |
41678 | t = cp_parser_assignment_expression (parser); |
41679 | |
41680 | if (t == error_mark_node) |
41681 | goto resync_fail; |
41682 | OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; |
41683 | |
41684 | if (!parens.require_close (parser)) |
41685 | goto resync_fail; |
41686 | } |
41687 | else if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41688 | goto resync_fail; |
41689 | |
41690 | /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, |
41691 | "dist_schedule", location); */ |
41692 | if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE)) |
41693 | warning_at (location, OPT_Wopenmp, "too many %qs clauses" , "dist_schedule" ); |
41694 | OMP_CLAUSE_CHAIN (c) = list; |
41695 | return c; |
41696 | |
41697 | invalid_kind: |
41698 | cp_parser_error (parser, gmsgid: "invalid dist_schedule kind" ); |
41699 | resync_fail: |
41700 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41701 | /*or_comma=*/false, |
41702 | /*consume_paren=*/true); |
41703 | return list; |
41704 | } |
41705 | |
41706 | /* OpenMP 4.0: |
41707 | proc_bind ( proc-bind-kind ) |
41708 | |
41709 | proc-bind-kind: |
41710 | primary | master | close | spread |
41711 | where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */ |
41712 | |
41713 | static tree |
41714 | cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list, |
41715 | location_t location) |
41716 | { |
41717 | tree c; |
41718 | enum omp_clause_proc_bind_kind kind; |
41719 | |
41720 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41721 | return list; |
41722 | |
41723 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41724 | { |
41725 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41726 | const char *p = IDENTIFIER_POINTER (id); |
41727 | |
41728 | if (strcmp (s1: "primary" , s2: p) == 0) |
41729 | kind = OMP_CLAUSE_PROC_BIND_PRIMARY; |
41730 | else if (strcmp (s1: "master" , s2: p) == 0) |
41731 | kind = OMP_CLAUSE_PROC_BIND_MASTER; |
41732 | else if (strcmp (s1: "close" , s2: p) == 0) |
41733 | kind = OMP_CLAUSE_PROC_BIND_CLOSE; |
41734 | else if (strcmp (s1: "spread" , s2: p) == 0) |
41735 | kind = OMP_CLAUSE_PROC_BIND_SPREAD; |
41736 | else |
41737 | goto invalid_kind; |
41738 | } |
41739 | else |
41740 | goto invalid_kind; |
41741 | |
41742 | cp_lexer_consume_token (lexer: parser->lexer); |
41743 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41744 | goto resync_fail; |
41745 | |
41746 | c = build_omp_clause (location, OMP_CLAUSE_PROC_BIND); |
41747 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind" , |
41748 | location); |
41749 | OMP_CLAUSE_PROC_BIND_KIND (c) = kind; |
41750 | OMP_CLAUSE_CHAIN (c) = list; |
41751 | return c; |
41752 | |
41753 | invalid_kind: |
41754 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
41755 | resync_fail: |
41756 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41757 | /*or_comma=*/false, |
41758 | /*consume_paren=*/true); |
41759 | return list; |
41760 | } |
41761 | |
41762 | /* OpenMP 5.0: |
41763 | device_type ( host | nohost | any ) */ |
41764 | |
41765 | static tree |
41766 | cp_parser_omp_clause_device_type (cp_parser *parser, tree list, |
41767 | location_t location) |
41768 | { |
41769 | tree c; |
41770 | enum omp_clause_device_type_kind kind; |
41771 | |
41772 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41773 | return list; |
41774 | |
41775 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41776 | { |
41777 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41778 | const char *p = IDENTIFIER_POINTER (id); |
41779 | |
41780 | if (strcmp (s1: "host" , s2: p) == 0) |
41781 | kind = OMP_CLAUSE_DEVICE_TYPE_HOST; |
41782 | else if (strcmp (s1: "nohost" , s2: p) == 0) |
41783 | kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST; |
41784 | else if (strcmp (s1: "any" , s2: p) == 0) |
41785 | kind = OMP_CLAUSE_DEVICE_TYPE_ANY; |
41786 | else |
41787 | goto invalid_kind; |
41788 | } |
41789 | else |
41790 | goto invalid_kind; |
41791 | |
41792 | cp_lexer_consume_token (lexer: parser->lexer); |
41793 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41794 | goto resync_fail; |
41795 | |
41796 | c = build_omp_clause (location, OMP_CLAUSE_DEVICE_TYPE); |
41797 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE, name: "device_type" , |
41798 | location); |
41799 | OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind; |
41800 | OMP_CLAUSE_CHAIN (c) = list; |
41801 | return c; |
41802 | |
41803 | invalid_kind: |
41804 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
41805 | resync_fail: |
41806 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41807 | /*or_comma=*/false, |
41808 | /*consume_paren=*/true); |
41809 | return list; |
41810 | } |
41811 | |
41812 | /* OpenACC: |
41813 | async [( int-expr )] */ |
41814 | |
41815 | static tree |
41816 | cp_parser_oacc_clause_async (cp_parser *parser, tree list) |
41817 | { |
41818 | tree c, t; |
41819 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41820 | |
41821 | t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL); |
41822 | |
41823 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
41824 | { |
41825 | matching_parens parens; |
41826 | parens.consume_open (parser); |
41827 | |
41828 | t = cp_parser_assignment_expression (parser); |
41829 | if (t == error_mark_node |
41830 | || !parens.require_close (parser)) |
41831 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41832 | /*or_comma=*/false, |
41833 | /*consume_paren=*/true); |
41834 | } |
41835 | |
41836 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async" , location: loc); |
41837 | |
41838 | c = build_omp_clause (loc, OMP_CLAUSE_ASYNC); |
41839 | OMP_CLAUSE_ASYNC_EXPR (c) = t; |
41840 | OMP_CLAUSE_CHAIN (c) = list; |
41841 | list = c; |
41842 | |
41843 | return list; |
41844 | } |
41845 | |
41846 | /* OpenACC 2.7: |
41847 | self [( expression )] */ |
41848 | |
41849 | static tree |
41850 | cp_parser_oacc_compute_clause_self (cp_parser *parser, tree list) |
41851 | { |
41852 | tree t; |
41853 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41854 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
41855 | { |
41856 | matching_parens parens; |
41857 | parens.consume_open (parser); |
41858 | t = cp_parser_assignment_expression (parser); |
41859 | if (t == error_mark_node |
41860 | || !parens.require_close (parser)) |
41861 | { |
41862 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41863 | /*or_comma=*/false, |
41864 | /*consume_paren=*/true); |
41865 | return list; |
41866 | } |
41867 | } |
41868 | else |
41869 | t = truthvalue_true_node; |
41870 | |
41871 | for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c)) |
41872 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF) |
41873 | { |
41874 | error_at (location, "too many %<self%> clauses" ); |
41875 | return list; |
41876 | } |
41877 | |
41878 | tree c = build_omp_clause (location, OMP_CLAUSE_SELF); |
41879 | OMP_CLAUSE_SELF_EXPR (c) = t; |
41880 | OMP_CLAUSE_CHAIN (c) = list; |
41881 | return c; |
41882 | } |
41883 | |
41884 | /* Parse all OpenACC clauses. The set clauses allowed by the directive |
41885 | is a bitmask in MASK. Return the list of clauses found. */ |
41886 | |
41887 | static tree |
41888 | cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask, |
41889 | const char *where, cp_token *pragma_tok, |
41890 | bool finish_p = true, bool target_p = false) |
41891 | { |
41892 | tree clauses = NULL; |
41893 | bool first = true; |
41894 | |
41895 | /* Don't create location wrapper nodes within OpenACC clauses. */ |
41896 | auto_suppress_location_wrappers sentinel; |
41897 | |
41898 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
41899 | { |
41900 | location_t here; |
41901 | pragma_omp_clause c_kind; |
41902 | omp_clause_code code; |
41903 | const char *c_name; |
41904 | tree prev = clauses; |
41905 | |
41906 | if (!first && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41907 | cp_lexer_consume_token (lexer: parser->lexer); |
41908 | |
41909 | here = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41910 | c_kind = cp_parser_omp_clause_name (parser); |
41911 | |
41912 | switch (c_kind) |
41913 | { |
41914 | case PRAGMA_OACC_CLAUSE_ASYNC: |
41915 | clauses = cp_parser_oacc_clause_async (parser, list: clauses); |
41916 | c_name = "async" ; |
41917 | break; |
41918 | case PRAGMA_OACC_CLAUSE_AUTO: |
41919 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO, |
41920 | list: clauses); |
41921 | c_name = "auto" ; |
41922 | break; |
41923 | case PRAGMA_OACC_CLAUSE_ATTACH: |
41924 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41925 | c_name = "attach" ; |
41926 | break; |
41927 | case PRAGMA_OACC_CLAUSE_COLLAPSE: |
41928 | clauses = cp_parser_omp_clause_collapse (parser, list: clauses, location: here); |
41929 | c_name = "collapse" ; |
41930 | break; |
41931 | case PRAGMA_OACC_CLAUSE_COPY: |
41932 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41933 | c_name = "copy" ; |
41934 | break; |
41935 | case PRAGMA_OACC_CLAUSE_COPYIN: |
41936 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41937 | c_name = "copyin" ; |
41938 | break; |
41939 | case PRAGMA_OACC_CLAUSE_COPYOUT: |
41940 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41941 | c_name = "copyout" ; |
41942 | break; |
41943 | case PRAGMA_OACC_CLAUSE_CREATE: |
41944 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41945 | c_name = "create" ; |
41946 | break; |
41947 | case PRAGMA_OACC_CLAUSE_DELETE: |
41948 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41949 | c_name = "delete" ; |
41950 | break; |
41951 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
41952 | clauses = cp_parser_omp_clause_default (parser, list: clauses, location: here, is_oacc: true); |
41953 | c_name = "default" ; |
41954 | break; |
41955 | case PRAGMA_OACC_CLAUSE_DETACH: |
41956 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41957 | c_name = "detach" ; |
41958 | break; |
41959 | case PRAGMA_OACC_CLAUSE_DEVICE: |
41960 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41961 | c_name = "device" ; |
41962 | break; |
41963 | case PRAGMA_OACC_CLAUSE_DEVICEPTR: |
41964 | clauses = cp_parser_oacc_data_clause_deviceptr (parser, list: clauses); |
41965 | c_name = "deviceptr" ; |
41966 | break; |
41967 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
41968 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41969 | c_name = "device_resident" ; |
41970 | break; |
41971 | case PRAGMA_OACC_CLAUSE_FINALIZE: |
41972 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE, |
41973 | list: clauses); |
41974 | c_name = "finalize" ; |
41975 | break; |
41976 | case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE: |
41977 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, |
41978 | list: clauses); |
41979 | c_name = "firstprivate" ; |
41980 | break; |
41981 | case PRAGMA_OACC_CLAUSE_GANG: |
41982 | c_name = "gang" ; |
41983 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG, |
41984 | str: c_name, list: clauses); |
41985 | break; |
41986 | case PRAGMA_OACC_CLAUSE_HOST: |
41987 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41988 | c_name = "host" ; |
41989 | break; |
41990 | case PRAGMA_OACC_CLAUSE_IF: |
41991 | clauses = cp_parser_omp_clause_if (parser, list: clauses, location: here, is_omp: false); |
41992 | c_name = "if" ; |
41993 | break; |
41994 | case PRAGMA_OACC_CLAUSE_IF_PRESENT: |
41995 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT, |
41996 | list: clauses); |
41997 | c_name = "if_present" ; |
41998 | break; |
41999 | case PRAGMA_OACC_CLAUSE_INDEPENDENT: |
42000 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT, |
42001 | list: clauses); |
42002 | c_name = "independent" ; |
42003 | break; |
42004 | case PRAGMA_OACC_CLAUSE_LINK: |
42005 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
42006 | c_name = "link" ; |
42007 | break; |
42008 | case PRAGMA_OACC_CLAUSE_NO_CREATE: |
42009 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
42010 | c_name = "no_create" ; |
42011 | break; |
42012 | case PRAGMA_OACC_CLAUSE_NOHOST: |
42013 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST, |
42014 | list: clauses); |
42015 | c_name = "nohost" ; |
42016 | break; |
42017 | case PRAGMA_OACC_CLAUSE_NUM_GANGS: |
42018 | code = OMP_CLAUSE_NUM_GANGS; |
42019 | c_name = "num_gangs" ; |
42020 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
42021 | list: clauses); |
42022 | break; |
42023 | case PRAGMA_OACC_CLAUSE_NUM_WORKERS: |
42024 | c_name = "num_workers" ; |
42025 | code = OMP_CLAUSE_NUM_WORKERS; |
42026 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
42027 | list: clauses); |
42028 | break; |
42029 | case PRAGMA_OACC_CLAUSE_PRESENT: |
42030 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
42031 | c_name = "present" ; |
42032 | break; |
42033 | case PRAGMA_OACC_CLAUSE_PRIVATE: |
42034 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_PRIVATE, |
42035 | list: clauses); |
42036 | c_name = "private" ; |
42037 | break; |
42038 | case PRAGMA_OACC_CLAUSE_REDUCTION: |
42039 | clauses |
42040 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION, |
42041 | is_omp: false, list: clauses); |
42042 | c_name = "reduction" ; |
42043 | break; |
42044 | case PRAGMA_OACC_CLAUSE_SELF: |
42045 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0) |
42046 | /* OpenACC compute construct */ |
42047 | clauses = cp_parser_oacc_compute_clause_self (parser, list: clauses); |
42048 | else |
42049 | /* OpenACC 'update' directive */ |
42050 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
42051 | c_name = "self" ; |
42052 | break; |
42053 | case PRAGMA_OACC_CLAUSE_SEQ: |
42054 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ, |
42055 | list: clauses); |
42056 | c_name = "seq" ; |
42057 | break; |
42058 | case PRAGMA_OACC_CLAUSE_TILE: |
42059 | clauses = cp_parser_oacc_clause_tile (parser, clause_loc: here, list: clauses); |
42060 | c_name = "tile" ; |
42061 | break; |
42062 | case PRAGMA_OACC_CLAUSE_USE_DEVICE: |
42063 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR, |
42064 | list: clauses); |
42065 | c_name = "use_device" ; |
42066 | break; |
42067 | case PRAGMA_OACC_CLAUSE_VECTOR: |
42068 | c_name = "vector" ; |
42069 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, |
42070 | kind: OMP_CLAUSE_VECTOR, |
42071 | str: c_name, list: clauses); |
42072 | break; |
42073 | case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH: |
42074 | c_name = "vector_length" ; |
42075 | code = OMP_CLAUSE_VECTOR_LENGTH; |
42076 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
42077 | list: clauses); |
42078 | break; |
42079 | case PRAGMA_OACC_CLAUSE_WAIT: |
42080 | clauses = cp_parser_oacc_clause_wait (parser, list: clauses); |
42081 | c_name = "wait" ; |
42082 | break; |
42083 | case PRAGMA_OACC_CLAUSE_WORKER: |
42084 | c_name = "worker" ; |
42085 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, |
42086 | kind: OMP_CLAUSE_WORKER, |
42087 | str: c_name, list: clauses); |
42088 | break; |
42089 | default: |
42090 | cp_parser_error (parser, gmsgid: "expected an OpenACC clause" ); |
42091 | goto saw_error; |
42092 | } |
42093 | |
42094 | first = false; |
42095 | |
42096 | if (((mask >> c_kind) & 1) == 0) |
42097 | { |
42098 | /* Remove the invalid clause(s) from the list to avoid |
42099 | confusing the rest of the compiler. */ |
42100 | clauses = prev; |
42101 | error_at (here, "%qs is not valid for %qs" , c_name, where); |
42102 | } |
42103 | } |
42104 | |
42105 | saw_error: |
42106 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
42107 | |
42108 | if (finish_p) |
42109 | return finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET |
42110 | : C_ORT_ACC); |
42111 | |
42112 | return clauses; |
42113 | } |
42114 | |
42115 | /* Parse all OpenMP clauses. The set clauses allowed by the directive |
42116 | is a bitmask in MASK. Return the list of clauses found. |
42117 | FINISH_P set if finish_omp_clauses should be called. |
42118 | NESTED non-zero if clauses should be terminated by closing paren instead |
42119 | of end of pragma. If it is 2, additionally commas are required in between |
42120 | the clauses. */ |
42121 | |
42122 | static tree |
42123 | cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, |
42124 | const char *where, cp_token *pragma_tok, |
42125 | bool finish_p = true, int nested = 0) |
42126 | { |
42127 | tree clauses = NULL; |
42128 | bool first = true; |
42129 | cp_token *token = NULL; |
42130 | |
42131 | /* Don't create location wrapper nodes within OpenMP clauses. */ |
42132 | auto_suppress_location_wrappers sentinel; |
42133 | |
42134 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
42135 | { |
42136 | pragma_omp_clause c_kind; |
42137 | const char *c_name; |
42138 | tree prev = clauses; |
42139 | |
42140 | if (nested && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
42141 | break; |
42142 | |
42143 | if (!first || nested != 2) |
42144 | { |
42145 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
42146 | cp_lexer_consume_token (lexer: parser->lexer); |
42147 | else if (nested == 2) |
42148 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
42149 | "clauses in %<simd%> trait should be separated " |
42150 | "by %<,%>" ); |
42151 | } |
42152 | |
42153 | token = cp_lexer_peek_token (lexer: parser->lexer); |
42154 | c_kind = cp_parser_omp_clause_name (parser); |
42155 | |
42156 | switch (c_kind) |
42157 | { |
42158 | case PRAGMA_OMP_CLAUSE_BIND: |
42159 | clauses = cp_parser_omp_clause_bind (parser, list: clauses, |
42160 | location: token->location); |
42161 | c_name = "bind" ; |
42162 | break; |
42163 | case PRAGMA_OMP_CLAUSE_COLLAPSE: |
42164 | clauses = cp_parser_omp_clause_collapse (parser, list: clauses, |
42165 | location: token->location); |
42166 | c_name = "collapse" ; |
42167 | break; |
42168 | case PRAGMA_OMP_CLAUSE_COPYIN: |
42169 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_COPYIN, list: clauses); |
42170 | c_name = "copyin" ; |
42171 | break; |
42172 | case PRAGMA_OMP_CLAUSE_COPYPRIVATE: |
42173 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_COPYPRIVATE, |
42174 | list: clauses); |
42175 | c_name = "copyprivate" ; |
42176 | break; |
42177 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
42178 | clauses = cp_parser_omp_clause_default (parser, list: clauses, |
42179 | location: token->location, is_oacc: false); |
42180 | c_name = "default" ; |
42181 | break; |
42182 | case PRAGMA_OMP_CLAUSE_FILTER: |
42183 | clauses = cp_parser_omp_clause_filter (parser, list: clauses, |
42184 | location: token->location); |
42185 | c_name = "filter" ; |
42186 | break; |
42187 | case PRAGMA_OMP_CLAUSE_FINAL: |
42188 | clauses = cp_parser_omp_clause_final (parser, list: clauses, location: token->location); |
42189 | c_name = "final" ; |
42190 | break; |
42191 | case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: |
42192 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, |
42193 | list: clauses); |
42194 | c_name = "firstprivate" ; |
42195 | break; |
42196 | case PRAGMA_OMP_CLAUSE_GRAINSIZE: |
42197 | clauses = cp_parser_omp_clause_grainsize (parser, list: clauses, |
42198 | location: token->location); |
42199 | c_name = "grainsize" ; |
42200 | break; |
42201 | case PRAGMA_OMP_CLAUSE_HINT: |
42202 | clauses = cp_parser_omp_clause_hint (parser, list: clauses, |
42203 | location: token->location); |
42204 | c_name = "hint" ; |
42205 | break; |
42206 | case PRAGMA_OMP_CLAUSE_DEFAULTMAP: |
42207 | clauses = cp_parser_omp_clause_defaultmap (parser, list: clauses, |
42208 | location: token->location); |
42209 | c_name = "defaultmap" ; |
42210 | break; |
42211 | case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR: |
42212 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR, |
42213 | list: clauses); |
42214 | c_name = "use_device_ptr" ; |
42215 | break; |
42216 | case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR: |
42217 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR, |
42218 | list: clauses); |
42219 | c_name = "use_device_addr" ; |
42220 | break; |
42221 | case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR: |
42222 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, |
42223 | list: clauses); |
42224 | c_name = "is_device_ptr" ; |
42225 | break; |
42226 | case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR: |
42227 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR, |
42228 | list: clauses); |
42229 | c_name = "has_device_addr" ; |
42230 | break; |
42231 | case PRAGMA_OMP_CLAUSE_IF: |
42232 | clauses = cp_parser_omp_clause_if (parser, list: clauses, location: token->location, |
42233 | is_omp: true); |
42234 | c_name = "if" ; |
42235 | break; |
42236 | case PRAGMA_OMP_CLAUSE_IN_REDUCTION: |
42237 | clauses |
42238 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION, |
42239 | is_omp: true, list: clauses); |
42240 | c_name = "in_reduction" ; |
42241 | break; |
42242 | case PRAGMA_OMP_CLAUSE_INDIRECT: |
42243 | clauses = cp_parser_omp_clause_indirect (parser, list: clauses, |
42244 | location: token->location); |
42245 | c_name = "indirect" ; |
42246 | break; |
42247 | case PRAGMA_OMP_CLAUSE_LASTPRIVATE: |
42248 | clauses = cp_parser_omp_clause_lastprivate (parser, list: clauses); |
42249 | c_name = "lastprivate" ; |
42250 | break; |
42251 | case PRAGMA_OMP_CLAUSE_MERGEABLE: |
42252 | clauses = cp_parser_omp_clause_mergeable (parser, list: clauses, |
42253 | location: token->location); |
42254 | c_name = "mergeable" ; |
42255 | break; |
42256 | case PRAGMA_OMP_CLAUSE_NOWAIT: |
42257 | clauses = cp_parser_omp_clause_nowait (parser, list: clauses, |
42258 | location: token->location); |
42259 | c_name = "nowait" ; |
42260 | break; |
42261 | case PRAGMA_OMP_CLAUSE_NUM_TASKS: |
42262 | clauses = cp_parser_omp_clause_num_tasks (parser, list: clauses, |
42263 | location: token->location); |
42264 | c_name = "num_tasks" ; |
42265 | break; |
42266 | case PRAGMA_OMP_CLAUSE_NUM_THREADS: |
42267 | clauses = cp_parser_omp_clause_num_threads (parser, list: clauses, |
42268 | location: token->location); |
42269 | c_name = "num_threads" ; |
42270 | break; |
42271 | case PRAGMA_OMP_CLAUSE_ORDER: |
42272 | clauses = cp_parser_omp_clause_order (parser, list: clauses, |
42273 | location: token->location); |
42274 | c_name = "order" ; |
42275 | break; |
42276 | case PRAGMA_OMP_CLAUSE_ORDERED: |
42277 | clauses = cp_parser_omp_clause_ordered (parser, list: clauses, |
42278 | location: token->location); |
42279 | c_name = "ordered" ; |
42280 | break; |
42281 | case PRAGMA_OMP_CLAUSE_PRIORITY: |
42282 | clauses = cp_parser_omp_clause_priority (parser, list: clauses, |
42283 | location: token->location); |
42284 | c_name = "priority" ; |
42285 | break; |
42286 | case PRAGMA_OMP_CLAUSE_PRIVATE: |
42287 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_PRIVATE, |
42288 | list: clauses); |
42289 | c_name = "private" ; |
42290 | break; |
42291 | case PRAGMA_OMP_CLAUSE_REDUCTION: |
42292 | clauses |
42293 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION, |
42294 | is_omp: true, list: clauses); |
42295 | c_name = "reduction" ; |
42296 | break; |
42297 | case PRAGMA_OMP_CLAUSE_SCHEDULE: |
42298 | clauses = cp_parser_omp_clause_schedule (parser, list: clauses, |
42299 | location: token->location); |
42300 | c_name = "schedule" ; |
42301 | break; |
42302 | case PRAGMA_OMP_CLAUSE_SHARED: |
42303 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_SHARED, |
42304 | list: clauses); |
42305 | c_name = "shared" ; |
42306 | break; |
42307 | case PRAGMA_OMP_CLAUSE_TASK_REDUCTION: |
42308 | clauses |
42309 | = cp_parser_omp_clause_reduction (parser, |
42310 | kind: OMP_CLAUSE_TASK_REDUCTION, |
42311 | is_omp: true, list: clauses); |
42312 | c_name = "task_reduction" ; |
42313 | break; |
42314 | case PRAGMA_OMP_CLAUSE_UNTIED: |
42315 | clauses = cp_parser_omp_clause_untied (parser, list: clauses, |
42316 | location: token->location); |
42317 | c_name = "untied" ; |
42318 | break; |
42319 | case PRAGMA_OMP_CLAUSE_INBRANCH: |
42320 | clauses = cp_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH, |
42321 | list: clauses, location: token->location); |
42322 | c_name = "inbranch" ; |
42323 | break; |
42324 | case PRAGMA_OMP_CLAUSE_NONTEMPORAL: |
42325 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_NONTEMPORAL, |
42326 | list: clauses); |
42327 | c_name = "nontemporal" ; |
42328 | break; |
42329 | case PRAGMA_OMP_CLAUSE_NOTINBRANCH: |
42330 | clauses = cp_parser_omp_clause_branch (parser, |
42331 | code: OMP_CLAUSE_NOTINBRANCH, |
42332 | list: clauses, location: token->location); |
42333 | c_name = "notinbranch" ; |
42334 | break; |
42335 | case PRAGMA_OMP_CLAUSE_PARALLEL: |
42336 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL, |
42337 | list: clauses, location: token->location); |
42338 | c_name = "parallel" ; |
42339 | if (!first) |
42340 | { |
42341 | clause_not_first: |
42342 | error_at (token->location, "%qs must be the first clause of %qs" , |
42343 | c_name, where); |
42344 | clauses = prev; |
42345 | } |
42346 | break; |
42347 | case PRAGMA_OMP_CLAUSE_FOR: |
42348 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR, |
42349 | list: clauses, location: token->location); |
42350 | c_name = "for" ; |
42351 | if (!first) |
42352 | goto clause_not_first; |
42353 | break; |
42354 | case PRAGMA_OMP_CLAUSE_SECTIONS: |
42355 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS, |
42356 | list: clauses, location: token->location); |
42357 | c_name = "sections" ; |
42358 | if (!first) |
42359 | goto clause_not_first; |
42360 | break; |
42361 | case PRAGMA_OMP_CLAUSE_TASKGROUP: |
42362 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP, |
42363 | list: clauses, location: token->location); |
42364 | c_name = "taskgroup" ; |
42365 | if (!first) |
42366 | goto clause_not_first; |
42367 | break; |
42368 | case PRAGMA_OMP_CLAUSE_LINK: |
42369 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_LINK, list: clauses); |
42370 | c_name = "link" ; |
42371 | break; |
42372 | case PRAGMA_OMP_CLAUSE_TO: |
42373 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0) |
42374 | { |
42375 | tree nl = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
42376 | list: clauses); |
42377 | for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c)) |
42378 | OMP_CLAUSE_ENTER_TO (c) = 1; |
42379 | clauses = nl; |
42380 | } |
42381 | else |
42382 | clauses = cp_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO, |
42383 | list: clauses); |
42384 | c_name = "to" ; |
42385 | break; |
42386 | case PRAGMA_OMP_CLAUSE_FROM: |
42387 | clauses = cp_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM, |
42388 | list: clauses); |
42389 | c_name = "from" ; |
42390 | break; |
42391 | case PRAGMA_OMP_CLAUSE_UNIFORM: |
42392 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_UNIFORM, |
42393 | list: clauses); |
42394 | c_name = "uniform" ; |
42395 | break; |
42396 | case PRAGMA_OMP_CLAUSE_NUM_TEAMS: |
42397 | clauses = cp_parser_omp_clause_num_teams (parser, list: clauses, |
42398 | location: token->location); |
42399 | c_name = "num_teams" ; |
42400 | break; |
42401 | case PRAGMA_OMP_CLAUSE_THREAD_LIMIT: |
42402 | clauses = cp_parser_omp_clause_thread_limit (parser, list: clauses, |
42403 | location: token->location); |
42404 | c_name = "thread_limit" ; |
42405 | break; |
42406 | case PRAGMA_OMP_CLAUSE_ALIGNED: |
42407 | clauses = cp_parser_omp_clause_aligned (parser, list: clauses); |
42408 | c_name = "aligned" ; |
42409 | break; |
42410 | case PRAGMA_OMP_CLAUSE_ALLOCATE: |
42411 | clauses = cp_parser_omp_clause_allocate (parser, list: clauses); |
42412 | c_name = "allocate" ; |
42413 | break; |
42414 | case PRAGMA_OMP_CLAUSE_LINEAR: |
42415 | { |
42416 | bool declare_simd = false; |
42417 | if (((mask >> PRAGMA_OMP_CLAUSE_UNIFORM) & 1) != 0) |
42418 | declare_simd = true; |
42419 | clauses = cp_parser_omp_clause_linear (parser, list: clauses, declare_simd); |
42420 | } |
42421 | c_name = "linear" ; |
42422 | break; |
42423 | case PRAGMA_OMP_CLAUSE_AFFINITY: |
42424 | clauses = cp_parser_omp_clause_affinity (parser, list: clauses); |
42425 | c_name = "affinity" ; |
42426 | break; |
42427 | case PRAGMA_OMP_CLAUSE_DEPEND: |
42428 | clauses = cp_parser_omp_clause_depend (parser, list: clauses, |
42429 | loc: token->location); |
42430 | c_name = "depend" ; |
42431 | break; |
42432 | case PRAGMA_OMP_CLAUSE_DOACROSS: |
42433 | clauses = cp_parser_omp_clause_doacross (parser, list: clauses, |
42434 | loc: token->location); |
42435 | c_name = "doacross" ; |
42436 | break; |
42437 | case PRAGMA_OMP_CLAUSE_DETACH: |
42438 | clauses = cp_parser_omp_clause_detach (parser, list: clauses); |
42439 | c_name = "detach" ; |
42440 | break; |
42441 | case PRAGMA_OMP_CLAUSE_MAP: |
42442 | clauses = cp_parser_omp_clause_map (parser, list: clauses); |
42443 | c_name = "map" ; |
42444 | break; |
42445 | case PRAGMA_OMP_CLAUSE_DEVICE: |
42446 | clauses = cp_parser_omp_clause_device (parser, list: clauses, |
42447 | location: token->location); |
42448 | c_name = "device" ; |
42449 | break; |
42450 | case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE: |
42451 | clauses = cp_parser_omp_clause_dist_schedule (parser, list: clauses, |
42452 | location: token->location); |
42453 | c_name = "dist_schedule" ; |
42454 | break; |
42455 | case PRAGMA_OMP_CLAUSE_PROC_BIND: |
42456 | clauses = cp_parser_omp_clause_proc_bind (parser, list: clauses, |
42457 | location: token->location); |
42458 | c_name = "proc_bind" ; |
42459 | break; |
42460 | case PRAGMA_OMP_CLAUSE_DEVICE_TYPE: |
42461 | clauses = cp_parser_omp_clause_device_type (parser, list: clauses, |
42462 | location: token->location); |
42463 | c_name = "device_type" ; |
42464 | break; |
42465 | case PRAGMA_OMP_CLAUSE_SAFELEN: |
42466 | clauses = cp_parser_omp_clause_safelen (parser, list: clauses, |
42467 | location: token->location); |
42468 | c_name = "safelen" ; |
42469 | break; |
42470 | case PRAGMA_OMP_CLAUSE_SIMDLEN: |
42471 | clauses = cp_parser_omp_clause_simdlen (parser, list: clauses, |
42472 | location: token->location); |
42473 | c_name = "simdlen" ; |
42474 | break; |
42475 | case PRAGMA_OMP_CLAUSE_NOGROUP: |
42476 | clauses = cp_parser_omp_clause_nogroup (parser, list: clauses, |
42477 | location: token->location); |
42478 | c_name = "nogroup" ; |
42479 | break; |
42480 | case PRAGMA_OMP_CLAUSE_THREADS: |
42481 | clauses |
42482 | = cp_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS, |
42483 | list: clauses, location: token->location); |
42484 | c_name = "threads" ; |
42485 | break; |
42486 | case PRAGMA_OMP_CLAUSE_SIMD: |
42487 | clauses |
42488 | = cp_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD, |
42489 | list: clauses, location: token->location); |
42490 | c_name = "simd" ; |
42491 | break; |
42492 | case PRAGMA_OMP_CLAUSE_ENTER: |
42493 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
42494 | list: clauses); |
42495 | c_name = "enter" ; |
42496 | break; |
42497 | default: |
42498 | cp_parser_error (parser, gmsgid: "expected an OpenMP clause" ); |
42499 | goto saw_error; |
42500 | } |
42501 | |
42502 | first = false; |
42503 | |
42504 | if (((mask >> c_kind) & 1) == 0) |
42505 | { |
42506 | /* Remove the invalid clause(s) from the list to avoid |
42507 | confusing the rest of the compiler. */ |
42508 | clauses = prev; |
42509 | error_at (token->location, "%qs is not valid for %qs" , c_name, where); |
42510 | } |
42511 | } |
42512 | saw_error: |
42513 | if (!nested) |
42514 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
42515 | if (finish_p) |
42516 | { |
42517 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0) |
42518 | return finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD); |
42519 | else |
42520 | return finish_omp_clauses (clauses, C_ORT_OMP); |
42521 | } |
42522 | return clauses; |
42523 | } |
42524 | |
42525 | /* OpenMP 2.5: |
42526 | structured-block: |
42527 | statement |
42528 | |
42529 | In practice, we're also interested in adding the statement to an |
42530 | outer node. So it is convenient if we work around the fact that |
42531 | cp_parser_statement calls add_stmt. */ |
42532 | |
42533 | static unsigned |
42534 | cp_parser_begin_omp_structured_block (cp_parser *parser) |
42535 | { |
42536 | unsigned save = parser->in_statement; |
42537 | |
42538 | /* Only move the values to IN_OMP_BLOCK if they weren't false. |
42539 | This preserves the "not within loop or switch" style error messages |
42540 | for nonsense cases like |
42541 | void foo() { |
42542 | #pragma omp single |
42543 | break; |
42544 | } |
42545 | */ |
42546 | if (parser->in_statement) |
42547 | parser->in_statement = IN_OMP_BLOCK; |
42548 | |
42549 | return save; |
42550 | } |
42551 | |
42552 | static void |
42553 | cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save) |
42554 | { |
42555 | parser->in_statement = save; |
42556 | } |
42557 | |
42558 | static tree |
42559 | cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) |
42560 | { |
42561 | tree stmt = begin_omp_structured_block (); |
42562 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
42563 | |
42564 | parser->omp_attrs_forbidden_p = true; |
42565 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
42566 | |
42567 | cp_parser_end_omp_structured_block (parser, save); |
42568 | return finish_omp_structured_block (stmt); |
42569 | } |
42570 | |
42571 | /* OpenMP 5.x: |
42572 | # pragma omp allocate (list) clauses |
42573 | |
42574 | OpenMP 5.0 clause: |
42575 | allocator (omp_allocator_handle_t expression) |
42576 | |
42577 | OpenMP 5.1 additional clause: |
42578 | align (constant-expression)] */ |
42579 | |
42580 | static void |
42581 | cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) |
42582 | { |
42583 | tree allocator = NULL_TREE; |
42584 | tree alignment = NULL_TREE; |
42585 | location_t loc = pragma_tok->location; |
42586 | tree nl = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE); |
42587 | |
42588 | do |
42589 | { |
42590 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
42591 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
42592 | cp_lexer_consume_token (lexer: parser->lexer); |
42593 | |
42594 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42595 | break; |
42596 | matching_parens parens; |
42597 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42598 | const char *p = IDENTIFIER_POINTER (id); |
42599 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42600 | cp_lexer_consume_token (lexer: parser->lexer); |
42601 | if (strcmp (s1: p, s2: "allocator" ) != 0 && strcmp (s1: p, s2: "align" ) != 0) |
42602 | { |
42603 | error_at (cloc, "expected %<allocator%> or %<align%>" ); |
42604 | break; |
42605 | } |
42606 | if (!parens.require_open (parser)) |
42607 | break; |
42608 | tree expr = cp_parser_assignment_expression (parser); |
42609 | if (p[2] == 'i' && alignment) |
42610 | { |
42611 | error_at (cloc, "too many %qs clauses" , "align" ); |
42612 | break; |
42613 | } |
42614 | else if (p[2] == 'i') |
42615 | { |
42616 | if (expr != error_mark_node) |
42617 | alignment = expr; |
42618 | /* FIXME: Remove when adding check to semantics.cc; cf FIXME below. */ |
42619 | if (alignment |
42620 | && !type_dependent_expression_p (alignment) |
42621 | && !INTEGRAL_TYPE_P (TREE_TYPE (alignment))) |
42622 | { |
42623 | error_at (cloc, "%<align%> clause argument needs to be " |
42624 | "positive constant power of two integer " |
42625 | "expression" ); |
42626 | alignment = NULL_TREE; |
42627 | } |
42628 | else if (alignment) |
42629 | { |
42630 | alignment = mark_rvalue_use (alignment); |
42631 | if (!processing_template_decl) |
42632 | { |
42633 | alignment = maybe_constant_value (alignment); |
42634 | if (TREE_CODE (alignment) != INTEGER_CST |
42635 | || !tree_fits_uhwi_p (alignment) |
42636 | || !integer_pow2p (alignment)) |
42637 | { |
42638 | error_at (cloc, "%<align%> clause argument needs to be " |
42639 | "positive constant power of two integer " |
42640 | "expression" ); |
42641 | alignment = NULL_TREE; |
42642 | } |
42643 | } |
42644 | } |
42645 | } |
42646 | else if (allocator) |
42647 | { |
42648 | error_at (cloc, "too many %qs clauses" , "allocator" ); |
42649 | break; |
42650 | } |
42651 | else |
42652 | { |
42653 | if (expr != error_mark_node) |
42654 | allocator = expr; |
42655 | } |
42656 | parens.require_close (parser); |
42657 | } while (true); |
42658 | cp_parser_require_pragma_eol (parser, pragma_tok); |
42659 | |
42660 | if (allocator || alignment) |
42661 | for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) |
42662 | { |
42663 | OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; |
42664 | OMP_CLAUSE_ALLOCATE_ALIGN (c) = alignment; |
42665 | } |
42666 | |
42667 | /* FIXME: When implementing properly, delete the align/allocate expr error |
42668 | check above and add one in semantics.cc (to properly handle templates). |
42669 | Base this on the allocator/align modifiers check for the 'allocate' clause |
42670 | in semantics.cc's finish_omp_clauses. */ |
42671 | sorry_at (loc, "%<#pragma omp allocate%> not yet supported" ); |
42672 | } |
42673 | |
42674 | /* OpenMP 2.5: |
42675 | # pragma omp atomic new-line |
42676 | expression-stmt |
42677 | |
42678 | expression-stmt: |
42679 | x binop= expr | x++ | ++x | x-- | --x |
42680 | binop: |
42681 | +, *, -, /, &, ^, |, <<, >> |
42682 | |
42683 | where x is an lvalue expression with scalar type. |
42684 | |
42685 | OpenMP 3.1: |
42686 | # pragma omp atomic new-line |
42687 | update-stmt |
42688 | |
42689 | # pragma omp atomic read new-line |
42690 | read-stmt |
42691 | |
42692 | # pragma omp atomic write new-line |
42693 | write-stmt |
42694 | |
42695 | # pragma omp atomic update new-line |
42696 | update-stmt |
42697 | |
42698 | # pragma omp atomic capture new-line |
42699 | capture-stmt |
42700 | |
42701 | # pragma omp atomic capture new-line |
42702 | capture-block |
42703 | |
42704 | read-stmt: |
42705 | v = x |
42706 | write-stmt: |
42707 | x = expr |
42708 | update-stmt: |
42709 | expression-stmt | x = x binop expr |
42710 | capture-stmt: |
42711 | v = expression-stmt |
42712 | capture-block: |
42713 | { v = x; update-stmt; } | { update-stmt; v = x; } |
42714 | |
42715 | OpenMP 4.0: |
42716 | update-stmt: |
42717 | expression-stmt | x = x binop expr | x = expr binop x |
42718 | capture-stmt: |
42719 | v = update-stmt |
42720 | capture-block: |
42721 | { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; } |
42722 | |
42723 | OpenMP 5.1: |
42724 | # pragma omp atomic compare new-line |
42725 | conditional-update-atomic |
42726 | |
42727 | # pragma omp atomic compare capture new-line |
42728 | conditional-update-capture-atomic |
42729 | |
42730 | conditional-update-atomic: |
42731 | cond-expr-stmt | cond-update-stmt |
42732 | cond-expr-stmt: |
42733 | x = expr ordop x ? expr : x; |
42734 | x = x ordop expr ? expr : x; |
42735 | x = x == e ? d : x; |
42736 | cond-update-stmt: |
42737 | if (expr ordop x) { x = expr; } |
42738 | if (x ordop expr) { x = expr; } |
42739 | if (x == e) { x = d; } |
42740 | ordop: |
42741 | <, > |
42742 | conditional-update-capture-atomic: |
42743 | v = cond-expr-stmt |
42744 | { v = x; cond-expr-stmt } |
42745 | { cond-expr-stmt v = x; } |
42746 | { v = x; cond-update-stmt } |
42747 | { cond-update-stmt v = x; } |
42748 | if (x == e) { x = d; } else { v = x; } |
42749 | { r = x == e; if (r) { x = d; } } |
42750 | { r = x == e; if (r) { x = d; } else { v = x; } } |
42751 | |
42752 | where x, r and v are lvalue expressions with scalar type, |
42753 | expr, e and d are expressions with scalar type and e might be |
42754 | the same as v. */ |
42755 | |
42756 | static void |
42757 | cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) |
42758 | { |
42759 | tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE; |
42760 | tree rhs1 = NULL_TREE, orig_lhs, r = NULL_TREE; |
42761 | location_t loc = pragma_tok->location; |
42762 | enum tree_code code = ERROR_MARK, opcode = NOP_EXPR; |
42763 | enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED; |
42764 | bool structured_block = false; |
42765 | tree clauses = NULL_TREE; |
42766 | bool capture = false; |
42767 | bool compare = false; |
42768 | bool weak = false; |
42769 | enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42770 | bool no_semicolon = false; |
42771 | bool = false; |
42772 | |
42773 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
42774 | { |
42775 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
42776 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
42777 | cp_lexer_consume_token (lexer: parser->lexer); |
42778 | |
42779 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42780 | { |
42781 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42782 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42783 | const char *p = IDENTIFIER_POINTER (id); |
42784 | enum tree_code new_code = ERROR_MARK; |
42785 | enum omp_memory_order new_memory_order |
42786 | = OMP_MEMORY_ORDER_UNSPECIFIED; |
42787 | bool new_capture = false; |
42788 | bool new_compare = false; |
42789 | bool new_weak = false; |
42790 | enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42791 | |
42792 | if (!strcmp (s1: p, s2: "read" )) |
42793 | new_code = OMP_ATOMIC_READ; |
42794 | else if (!strcmp (s1: p, s2: "write" )) |
42795 | new_code = NOP_EXPR; |
42796 | else if (!strcmp (s1: p, s2: "update" )) |
42797 | new_code = OMP_ATOMIC; |
42798 | else if (openacc && !strcmp (s1: p, s2: "capture" )) |
42799 | new_code = OMP_ATOMIC_CAPTURE_NEW; |
42800 | else if (openacc) |
42801 | { |
42802 | p = NULL; |
42803 | error_at (cloc, "expected %<read%>, %<write%>, %<update%>, " |
42804 | "or %<capture%> clause" ); |
42805 | } |
42806 | else if (!strcmp (s1: p, s2: "capture" )) |
42807 | new_capture = true; |
42808 | else if (!strcmp (s1: p, s2: "compare" )) |
42809 | new_compare = true; |
42810 | else if (!strcmp (s1: p, s2: "weak" )) |
42811 | new_weak = true; |
42812 | else if (!strcmp (s1: p, s2: "fail" )) |
42813 | { |
42814 | matching_parens parens; |
42815 | |
42816 | cp_lexer_consume_token (lexer: parser->lexer); |
42817 | if (!parens.require_open (parser)) |
42818 | continue; |
42819 | |
42820 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42821 | { |
42822 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42823 | const char *q = IDENTIFIER_POINTER (id); |
42824 | |
42825 | if (!strcmp (s1: q, s2: "seq_cst" )) |
42826 | new_fail = OMP_MEMORY_ORDER_SEQ_CST; |
42827 | else if (!strcmp (s1: q, s2: "acquire" )) |
42828 | new_fail = OMP_MEMORY_ORDER_ACQUIRE; |
42829 | else if (!strcmp (s1: q, s2: "relaxed" )) |
42830 | new_fail = OMP_MEMORY_ORDER_RELAXED; |
42831 | } |
42832 | |
42833 | if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
42834 | { |
42835 | cp_lexer_consume_token (lexer: parser->lexer); |
42836 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
42837 | error_at (cloc, "too many %qs clauses" , "fail" ); |
42838 | else |
42839 | fail = new_fail; |
42840 | } |
42841 | else |
42842 | cp_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> " |
42843 | "or %<relaxed%>" ); |
42844 | if (new_fail == OMP_MEMORY_ORDER_UNSPECIFIED |
42845 | || !parens.require_close (parser)) |
42846 | cp_parser_skip_to_closing_parenthesis (parser, |
42847 | /*recovering=*/true, |
42848 | /*or_comma=*/false, |
42849 | /*consume_paren=*/true); |
42850 | continue; |
42851 | } |
42852 | else if (!strcmp (s1: p, s2: "seq_cst" )) |
42853 | new_memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42854 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
42855 | new_memory_order = OMP_MEMORY_ORDER_ACQ_REL; |
42856 | else if (!strcmp (s1: p, s2: "release" )) |
42857 | new_memory_order = OMP_MEMORY_ORDER_RELEASE; |
42858 | else if (!strcmp (s1: p, s2: "acquire" )) |
42859 | new_memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42860 | else if (!strcmp (s1: p, s2: "relaxed" )) |
42861 | new_memory_order = OMP_MEMORY_ORDER_RELAXED; |
42862 | else if (!strcmp (s1: p, s2: "hint" )) |
42863 | { |
42864 | cp_lexer_consume_token (lexer: parser->lexer); |
42865 | clauses = cp_parser_omp_clause_hint (parser, list: clauses, location: cloc); |
42866 | continue; |
42867 | } |
42868 | else |
42869 | { |
42870 | p = NULL; |
42871 | error_at (cloc, "expected %<read%>, %<write%>, %<update%>, " |
42872 | "%<capture%>, %<compare%>, %<weak%>, %<fail%>, " |
42873 | "%<seq_cst%>, %<acq_rel%>, %<release%>, " |
42874 | "%<relaxed%> or %<hint%> clause" ); |
42875 | } |
42876 | if (p) |
42877 | { |
42878 | if (new_code != ERROR_MARK) |
42879 | { |
42880 | /* OpenACC permits 'update capture'. */ |
42881 | if (openacc |
42882 | && code == OMP_ATOMIC |
42883 | && new_code == OMP_ATOMIC_CAPTURE_NEW) |
42884 | code = new_code; |
42885 | else if (code != ERROR_MARK) |
42886 | error_at (cloc, "too many atomic clauses" ); |
42887 | else |
42888 | code = new_code; |
42889 | } |
42890 | else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED) |
42891 | { |
42892 | if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED) |
42893 | error_at (cloc, "too many memory order clauses" ); |
42894 | else |
42895 | memory_order = new_memory_order; |
42896 | } |
42897 | else if (new_capture) |
42898 | { |
42899 | if (capture) |
42900 | error_at (cloc, "too many %qs clauses" , "capture" ); |
42901 | else |
42902 | capture = true; |
42903 | } |
42904 | else if (new_compare) |
42905 | { |
42906 | if (compare) |
42907 | error_at (cloc, "too many %qs clauses" , "compare" ); |
42908 | else |
42909 | compare = true; |
42910 | } |
42911 | else if (new_weak) |
42912 | { |
42913 | if (weak) |
42914 | error_at (cloc, "too many %qs clauses" , "weak" ); |
42915 | else |
42916 | weak = true; |
42917 | } |
42918 | cp_lexer_consume_token (lexer: parser->lexer); |
42919 | continue; |
42920 | } |
42921 | } |
42922 | break; |
42923 | } |
42924 | cp_parser_require_pragma_eol (parser, pragma_tok); |
42925 | |
42926 | if (code == ERROR_MARK) |
42927 | code = OMP_ATOMIC; |
42928 | if (capture) |
42929 | { |
42930 | if (code != OMP_ATOMIC) |
42931 | error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> " |
42932 | "clauses" , "capture" ); |
42933 | else |
42934 | code = OMP_ATOMIC_CAPTURE_NEW; |
42935 | } |
42936 | if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW) |
42937 | { |
42938 | error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> " |
42939 | "clauses" , "compare" ); |
42940 | compare = false; |
42941 | } |
42942 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare) |
42943 | { |
42944 | error_at (loc, "%qs clause requires %qs clause" , "fail" , "compare" ); |
42945 | fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42946 | } |
42947 | if (weak && !compare) |
42948 | { |
42949 | error_at (loc, "%qs clause requires %qs clause" , "weak" , "compare" ); |
42950 | weak = false; |
42951 | } |
42952 | if (openacc) |
42953 | memory_order = OMP_MEMORY_ORDER_RELAXED; |
42954 | else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED) |
42955 | { |
42956 | omp_requires_mask |
42957 | = (enum omp_requires) (omp_requires_mask |
42958 | | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED); |
42959 | switch ((enum omp_memory_order) |
42960 | (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER)) |
42961 | { |
42962 | case OMP_MEMORY_ORDER_UNSPECIFIED: |
42963 | case OMP_MEMORY_ORDER_RELAXED: |
42964 | memory_order = OMP_MEMORY_ORDER_RELAXED; |
42965 | break; |
42966 | case OMP_MEMORY_ORDER_SEQ_CST: |
42967 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42968 | break; |
42969 | case OMP_MEMORY_ORDER_ACQUIRE: |
42970 | if (code == NOP_EXPR) /* atomic write */ |
42971 | { |
42972 | error_at (loc, "%<#pragma omp atomic write%> incompatible with " |
42973 | "%<acquire%> clause implicitly provided by a " |
42974 | "%<requires%> directive" ); |
42975 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42976 | } |
42977 | else |
42978 | memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42979 | break; |
42980 | case OMP_MEMORY_ORDER_RELEASE: |
42981 | if (code == OMP_ATOMIC_READ) |
42982 | { |
42983 | error_at (loc, "%<#pragma omp atomic read%> incompatible with " |
42984 | "%<release%> clause implicitly provided by a " |
42985 | "%<requires%> directive" ); |
42986 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42987 | } |
42988 | else |
42989 | memory_order = OMP_MEMORY_ORDER_RELEASE; |
42990 | break; |
42991 | case OMP_MEMORY_ORDER_ACQ_REL: |
42992 | switch (code) |
42993 | { |
42994 | case OMP_ATOMIC_READ: |
42995 | memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42996 | break; |
42997 | case NOP_EXPR: /* atomic write */ |
42998 | memory_order = OMP_MEMORY_ORDER_RELEASE; |
42999 | break; |
43000 | default: |
43001 | memory_order = OMP_MEMORY_ORDER_ACQ_REL; |
43002 | break; |
43003 | } |
43004 | break; |
43005 | default: |
43006 | gcc_unreachable (); |
43007 | } |
43008 | } |
43009 | else |
43010 | switch (code) |
43011 | { |
43012 | case OMP_ATOMIC_READ: |
43013 | if (memory_order == OMP_MEMORY_ORDER_RELEASE) |
43014 | { |
43015 | error_at (loc, "%<#pragma omp atomic read%> incompatible with " |
43016 | "%<release%> clause" ); |
43017 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
43018 | } |
43019 | else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) |
43020 | memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
43021 | break; |
43022 | case NOP_EXPR: /* atomic write */ |
43023 | if (memory_order == OMP_MEMORY_ORDER_ACQUIRE) |
43024 | { |
43025 | error_at (loc, "%<#pragma omp atomic write%> incompatible with " |
43026 | "%<acquire%> clause" ); |
43027 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
43028 | } |
43029 | else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) |
43030 | memory_order = OMP_MEMORY_ORDER_RELEASE; |
43031 | break; |
43032 | default: |
43033 | break; |
43034 | } |
43035 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
43036 | memory_order |
43037 | = (enum omp_memory_order) (memory_order |
43038 | | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT)); |
43039 | |
43040 | switch (code) |
43041 | { |
43042 | case OMP_ATOMIC_READ: |
43043 | case NOP_EXPR: /* atomic write */ |
43044 | v = cp_parser_unary_expression (parser); |
43045 | if (v == error_mark_node) |
43046 | goto saw_error; |
43047 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
43048 | goto saw_error; |
43049 | if (code == NOP_EXPR) |
43050 | lhs = cp_parser_expression (parser); |
43051 | else |
43052 | lhs = cp_parser_unary_expression (parser); |
43053 | if (lhs == error_mark_node) |
43054 | goto saw_error; |
43055 | if (code == NOP_EXPR) |
43056 | { |
43057 | /* atomic write is represented by OMP_ATOMIC with NOP_EXPR |
43058 | opcode. */ |
43059 | code = OMP_ATOMIC; |
43060 | rhs = lhs; |
43061 | lhs = v; |
43062 | v = NULL_TREE; |
43063 | } |
43064 | goto done; |
43065 | case OMP_ATOMIC_CAPTURE_NEW: |
43066 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
43067 | { |
43068 | cp_lexer_consume_token (lexer: parser->lexer); |
43069 | structured_block = true; |
43070 | } |
43071 | else if (compare |
43072 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
43073 | break; |
43074 | else |
43075 | { |
43076 | v = cp_parser_unary_expression (parser); |
43077 | if (v == error_mark_node) |
43078 | goto saw_error; |
43079 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
43080 | goto saw_error; |
43081 | if (compare |
43082 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
43083 | { |
43084 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43085 | error_at (eloc, "expected expression" ); |
43086 | goto saw_error; |
43087 | } |
43088 | } |
43089 | default: |
43090 | break; |
43091 | } |
43092 | |
43093 | restart: |
43094 | if (compare && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
43095 | { |
43096 | cp_lexer_consume_token (lexer: parser->lexer); |
43097 | |
43098 | matching_parens parens; |
43099 | if (!parens.require_open (parser)) |
43100 | goto saw_error; |
43101 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43102 | tree cmp_expr; |
43103 | if (r) |
43104 | cmp_expr = cp_parser_unary_expression (parser); |
43105 | else |
43106 | cmp_expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
43107 | prec: PREC_NOT_OPERATOR, NULL); |
43108 | if (!parens.require_close (parser)) |
43109 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
43110 | if (cmp_expr == error_mark_node) |
43111 | goto saw_error; |
43112 | if (r) |
43113 | { |
43114 | if (!cp_tree_equal (cmp_expr, r)) |
43115 | goto bad_if; |
43116 | cmp_expr = rhs; |
43117 | rhs = NULL_TREE; |
43118 | gcc_assert (TREE_CODE (cmp_expr) == EQ_EXPR); |
43119 | } |
43120 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
43121 | ; |
43122 | else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW) |
43123 | { |
43124 | error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc), |
43125 | "expected %<==%> comparison in %<if%> condition" ); |
43126 | goto saw_error; |
43127 | } |
43128 | else if (TREE_CODE (cmp_expr) != GT_EXPR |
43129 | && TREE_CODE (cmp_expr) != LT_EXPR) |
43130 | { |
43131 | error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc), |
43132 | "expected %<==%>, %<<%> or %<>%> comparison in %<if%> " |
43133 | "condition" ); |
43134 | goto saw_error; |
43135 | } |
43136 | if (!cp_parser_require (parser, type: CPP_OPEN_BRACE, token_desc: RT_OPEN_BRACE)) |
43137 | goto saw_error; |
43138 | |
43139 | extra_scope = true; |
43140 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43141 | lhs = cp_parser_unary_expression (parser); |
43142 | orig_lhs = lhs; |
43143 | if (lhs == error_mark_node) |
43144 | goto saw_error; |
43145 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
43146 | { |
43147 | cp_parser_error (parser, gmsgid: "expected %<=%>" ); |
43148 | goto saw_error; |
43149 | } |
43150 | cp_lexer_consume_token (lexer: parser->lexer); |
43151 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43152 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
43153 | rhs1 = cp_parser_expression (parser); |
43154 | else |
43155 | rhs1 = cp_parser_simple_cast_expression (parser); |
43156 | |
43157 | if (!cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
43158 | goto saw_error; |
43159 | |
43160 | if (!cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE)) |
43161 | goto saw_error; |
43162 | |
43163 | extra_scope = false; |
43164 | no_semicolon = true; |
43165 | |
43166 | if (cp_tree_equal (TREE_OPERAND (cmp_expr, 0), lhs)) |
43167 | { |
43168 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
43169 | { |
43170 | opcode = COND_EXPR; |
43171 | rhs = TREE_OPERAND (cmp_expr, 1); |
43172 | } |
43173 | else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), rhs1)) |
43174 | { |
43175 | opcode = (TREE_CODE (cmp_expr) == GT_EXPR |
43176 | ? MIN_EXPR : MAX_EXPR); |
43177 | rhs = rhs1; |
43178 | rhs1 = TREE_OPERAND (cmp_expr, 0); |
43179 | } |
43180 | else |
43181 | goto bad_if; |
43182 | } |
43183 | else if (TREE_CODE (cmp_expr) == EQ_EXPR) |
43184 | goto bad_if; |
43185 | else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), lhs) |
43186 | && cp_tree_equal (TREE_OPERAND (cmp_expr, 0), rhs1)) |
43187 | { |
43188 | opcode = (TREE_CODE (cmp_expr) == GT_EXPR |
43189 | ? MAX_EXPR : MIN_EXPR); |
43190 | rhs = rhs1; |
43191 | rhs1 = TREE_OPERAND (cmp_expr, 1); |
43192 | } |
43193 | else |
43194 | { |
43195 | bad_if: |
43196 | cp_parser_error (parser, |
43197 | gmsgid: "invalid form of %<#pragma omp atomic compare%>" ); |
43198 | goto saw_error; |
43199 | } |
43200 | |
43201 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ELSE)) |
43202 | { |
43203 | if (code != OMP_ATOMIC_CAPTURE_NEW |
43204 | || (structured_block && r == NULL_TREE) |
43205 | || TREE_CODE (cmp_expr) != EQ_EXPR) |
43206 | { |
43207 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43208 | error_at (eloc, "unexpected %<else%>" ); |
43209 | goto saw_error; |
43210 | } |
43211 | |
43212 | cp_lexer_consume_token (lexer: parser->lexer); |
43213 | |
43214 | if (!cp_parser_require (parser, type: CPP_OPEN_BRACE, token_desc: RT_OPEN_BRACE)) |
43215 | goto saw_error; |
43216 | |
43217 | extra_scope = true; |
43218 | v = cp_parser_unary_expression (parser); |
43219 | if (v == error_mark_node) |
43220 | goto saw_error; |
43221 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
43222 | goto saw_error; |
43223 | |
43224 | tree expr = cp_parser_simple_cast_expression (parser); |
43225 | |
43226 | if (!cp_tree_equal (expr, lhs)) |
43227 | goto bad_if; |
43228 | |
43229 | if (!cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
43230 | goto saw_error; |
43231 | |
43232 | if (!cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE)) |
43233 | goto saw_error; |
43234 | |
43235 | extra_scope = false; |
43236 | code = OMP_ATOMIC_CAPTURE_OLD; |
43237 | if (r == NULL_TREE) |
43238 | /* Signal to c_finish_omp_atomic that in |
43239 | if (x == e) { x = d; } else { v = x; } |
43240 | case the store to v should be conditional. */ |
43241 | r = void_list_node; |
43242 | } |
43243 | else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
43244 | { |
43245 | cp_parser_error (parser, gmsgid: "expected %<else%>" ); |
43246 | goto saw_error; |
43247 | } |
43248 | else if (code == OMP_ATOMIC_CAPTURE_NEW |
43249 | && r != NULL_TREE |
43250 | && v == NULL_TREE) |
43251 | code = OMP_ATOMIC; |
43252 | goto stmt_done; |
43253 | } |
43254 | lhs = cp_parser_unary_expression (parser); |
43255 | orig_lhs = lhs; |
43256 | switch (TREE_CODE (lhs)) |
43257 | { |
43258 | case ERROR_MARK: |
43259 | goto saw_error; |
43260 | |
43261 | case POSTINCREMENT_EXPR: |
43262 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
43263 | code = OMP_ATOMIC_CAPTURE_OLD; |
43264 | /* FALLTHROUGH */ |
43265 | case PREINCREMENT_EXPR: |
43266 | lhs = TREE_OPERAND (lhs, 0); |
43267 | opcode = PLUS_EXPR; |
43268 | rhs = integer_one_node; |
43269 | if (compare) |
43270 | goto invalid_compare; |
43271 | break; |
43272 | |
43273 | case POSTDECREMENT_EXPR: |
43274 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
43275 | code = OMP_ATOMIC_CAPTURE_OLD; |
43276 | /* FALLTHROUGH */ |
43277 | case PREDECREMENT_EXPR: |
43278 | lhs = TREE_OPERAND (lhs, 0); |
43279 | opcode = MINUS_EXPR; |
43280 | rhs = integer_one_node; |
43281 | if (compare) |
43282 | goto invalid_compare; |
43283 | break; |
43284 | |
43285 | case COMPOUND_EXPR: |
43286 | if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR |
43287 | && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR |
43288 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR |
43289 | && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0) |
43290 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND |
43291 | (TREE_OPERAND (lhs, 1), 0), 0))) |
43292 | == BOOLEAN_TYPE) |
43293 | /* Undo effects of boolean_increment for post {in,de}crement. */ |
43294 | lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0); |
43295 | /* FALLTHRU */ |
43296 | case MODIFY_EXPR: |
43297 | if (TREE_CODE (lhs) == MODIFY_EXPR |
43298 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE) |
43299 | { |
43300 | /* Undo effects of boolean_increment. */ |
43301 | if (integer_onep (TREE_OPERAND (lhs, 1))) |
43302 | { |
43303 | /* This is pre or post increment. */ |
43304 | rhs = TREE_OPERAND (lhs, 1); |
43305 | lhs = TREE_OPERAND (lhs, 0); |
43306 | opcode = NOP_EXPR; |
43307 | if (code == OMP_ATOMIC_CAPTURE_NEW |
43308 | && !structured_block |
43309 | && TREE_CODE (orig_lhs) == COMPOUND_EXPR) |
43310 | code = OMP_ATOMIC_CAPTURE_OLD; |
43311 | if (compare) |
43312 | goto invalid_compare; |
43313 | break; |
43314 | } |
43315 | } |
43316 | /* FALLTHRU */ |
43317 | default: |
43318 | if (compare && !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
43319 | { |
43320 | cp_parser_error (parser, gmsgid: "expected %<=%>" ); |
43321 | goto saw_error; |
43322 | } |
43323 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
43324 | { |
43325 | case CPP_MULT_EQ: |
43326 | opcode = MULT_EXPR; |
43327 | break; |
43328 | case CPP_DIV_EQ: |
43329 | opcode = TRUNC_DIV_EXPR; |
43330 | break; |
43331 | case CPP_PLUS_EQ: |
43332 | opcode = PLUS_EXPR; |
43333 | break; |
43334 | case CPP_MINUS_EQ: |
43335 | opcode = MINUS_EXPR; |
43336 | break; |
43337 | case CPP_LSHIFT_EQ: |
43338 | opcode = LSHIFT_EXPR; |
43339 | break; |
43340 | case CPP_RSHIFT_EQ: |
43341 | opcode = RSHIFT_EXPR; |
43342 | break; |
43343 | case CPP_AND_EQ: |
43344 | opcode = BIT_AND_EXPR; |
43345 | break; |
43346 | case CPP_OR_EQ: |
43347 | opcode = BIT_IOR_EXPR; |
43348 | break; |
43349 | case CPP_XOR_EQ: |
43350 | opcode = BIT_XOR_EXPR; |
43351 | break; |
43352 | case CPP_EQ: |
43353 | enum cp_parser_prec oprec; |
43354 | cp_token *token; |
43355 | cp_lexer_consume_token (lexer: parser->lexer); |
43356 | cp_parser_parse_tentatively (parser); |
43357 | rhs1 = cp_parser_simple_cast_expression (parser); |
43358 | if (rhs1 == error_mark_node) |
43359 | { |
43360 | cp_parser_abort_tentative_parse (parser); |
43361 | cp_parser_simple_cast_expression (parser); |
43362 | goto saw_error; |
43363 | } |
43364 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43365 | if (token->type != CPP_SEMICOLON |
43366 | && (!compare || token->type != CPP_QUERY) |
43367 | && !cp_tree_equal (lhs, rhs1)) |
43368 | { |
43369 | cp_parser_abort_tentative_parse (parser); |
43370 | cp_parser_parse_tentatively (parser); |
43371 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
43372 | prec: PREC_NOT_OPERATOR, NULL); |
43373 | if (rhs == error_mark_node) |
43374 | { |
43375 | cp_parser_abort_tentative_parse (parser); |
43376 | cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
43377 | prec: PREC_NOT_OPERATOR, NULL); |
43378 | goto saw_error; |
43379 | } |
43380 | switch (TREE_CODE (rhs)) |
43381 | { |
43382 | case MULT_EXPR: |
43383 | case TRUNC_DIV_EXPR: |
43384 | case RDIV_EXPR: |
43385 | case PLUS_EXPR: |
43386 | case MINUS_EXPR: |
43387 | case LSHIFT_EXPR: |
43388 | case RSHIFT_EXPR: |
43389 | case BIT_AND_EXPR: |
43390 | case BIT_IOR_EXPR: |
43391 | case BIT_XOR_EXPR: |
43392 | if (compare) |
43393 | break; |
43394 | if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1))) |
43395 | { |
43396 | if (cp_parser_parse_definitely (parser)) |
43397 | { |
43398 | opcode = TREE_CODE (rhs); |
43399 | rhs1 = TREE_OPERAND (rhs, 0); |
43400 | rhs = TREE_OPERAND (rhs, 1); |
43401 | goto stmt_done; |
43402 | } |
43403 | else |
43404 | goto saw_error; |
43405 | } |
43406 | break; |
43407 | case EQ_EXPR: |
43408 | if (!compare |
43409 | || code != OMP_ATOMIC_CAPTURE_NEW |
43410 | || !structured_block |
43411 | || v |
43412 | || r) |
43413 | break; |
43414 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
43415 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, |
43416 | n: 2, keyword: RID_IF)) |
43417 | { |
43418 | if (cp_parser_parse_definitely (parser)) |
43419 | { |
43420 | r = lhs; |
43421 | lhs = NULL_TREE; |
43422 | rhs1 = NULL_TREE; |
43423 | cp_lexer_consume_token (lexer: parser->lexer); |
43424 | goto restart; |
43425 | } |
43426 | } |
43427 | break; |
43428 | case GT_EXPR: |
43429 | case LT_EXPR: |
43430 | if (compare |
43431 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY) |
43432 | && cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)) |
43433 | && cp_parser_parse_definitely (parser)) |
43434 | { |
43435 | opcode = TREE_CODE (rhs); |
43436 | rhs1 = TREE_OPERAND (rhs, 0); |
43437 | rhs = TREE_OPERAND (rhs, 1); |
43438 | cond_expr: |
43439 | cp_lexer_consume_token (lexer: parser->lexer); |
43440 | bool saved_colon_corrects_to_scope_p |
43441 | = parser->colon_corrects_to_scope_p; |
43442 | parser->colon_corrects_to_scope_p = false; |
43443 | tree e1 = cp_parser_expression (parser); |
43444 | parser->colon_corrects_to_scope_p |
43445 | = saved_colon_corrects_to_scope_p; |
43446 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
43447 | tree e2 = cp_parser_simple_cast_expression (parser); |
43448 | if (cp_tree_equal (lhs, e2)) |
43449 | { |
43450 | if (cp_tree_equal (lhs, rhs1)) |
43451 | { |
43452 | if (opcode == EQ_EXPR) |
43453 | { |
43454 | opcode = COND_EXPR; |
43455 | rhs1 = e1; |
43456 | goto stmt_done; |
43457 | } |
43458 | if (cp_tree_equal (rhs, e1)) |
43459 | { |
43460 | opcode |
43461 | = opcode == GT_EXPR ? MIN_EXPR : MAX_EXPR; |
43462 | rhs = e1; |
43463 | goto stmt_done; |
43464 | } |
43465 | } |
43466 | else |
43467 | { |
43468 | gcc_assert (opcode != EQ_EXPR); |
43469 | if (cp_tree_equal (rhs1, e1)) |
43470 | { |
43471 | opcode |
43472 | = opcode == GT_EXPR ? MAX_EXPR : MIN_EXPR; |
43473 | rhs1 = rhs; |
43474 | rhs = e1; |
43475 | goto stmt_done; |
43476 | } |
43477 | } |
43478 | } |
43479 | cp_parser_error (parser, |
43480 | gmsgid: "invalid form of " |
43481 | "%<#pragma omp atomic compare%>" ); |
43482 | goto saw_error; |
43483 | } |
43484 | break; |
43485 | default: |
43486 | break; |
43487 | } |
43488 | cp_parser_abort_tentative_parse (parser); |
43489 | if (structured_block |
43490 | && code == OMP_ATOMIC_CAPTURE_OLD |
43491 | && !compare) |
43492 | { |
43493 | rhs = cp_parser_expression (parser); |
43494 | if (rhs == error_mark_node) |
43495 | goto saw_error; |
43496 | opcode = NOP_EXPR; |
43497 | rhs1 = NULL_TREE; |
43498 | goto stmt_done; |
43499 | } |
43500 | cp_parser_error (parser, |
43501 | gmsgid: "invalid form of %<#pragma omp atomic%>" ); |
43502 | goto saw_error; |
43503 | } |
43504 | if (!cp_parser_parse_definitely (parser)) |
43505 | goto saw_error; |
43506 | switch (token->type) |
43507 | { |
43508 | case CPP_SEMICOLON: |
43509 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW) |
43510 | { |
43511 | code = OMP_ATOMIC_CAPTURE_OLD; |
43512 | v = lhs; |
43513 | lhs = NULL_TREE; |
43514 | lhs1 = rhs1; |
43515 | rhs1 = NULL_TREE; |
43516 | cp_lexer_consume_token (lexer: parser->lexer); |
43517 | goto restart; |
43518 | } |
43519 | else if (structured_block && !compare) |
43520 | { |
43521 | opcode = NOP_EXPR; |
43522 | rhs = rhs1; |
43523 | rhs1 = NULL_TREE; |
43524 | goto stmt_done; |
43525 | } |
43526 | cp_parser_error (parser, |
43527 | gmsgid: "invalid form of %<#pragma omp atomic%>" ); |
43528 | goto saw_error; |
43529 | case CPP_MULT: |
43530 | opcode = MULT_EXPR; |
43531 | break; |
43532 | case CPP_DIV: |
43533 | opcode = TRUNC_DIV_EXPR; |
43534 | break; |
43535 | case CPP_PLUS: |
43536 | opcode = PLUS_EXPR; |
43537 | break; |
43538 | case CPP_MINUS: |
43539 | opcode = MINUS_EXPR; |
43540 | break; |
43541 | case CPP_LSHIFT: |
43542 | opcode = LSHIFT_EXPR; |
43543 | break; |
43544 | case CPP_RSHIFT: |
43545 | opcode = RSHIFT_EXPR; |
43546 | break; |
43547 | case CPP_AND: |
43548 | opcode = BIT_AND_EXPR; |
43549 | break; |
43550 | case CPP_OR: |
43551 | opcode = BIT_IOR_EXPR; |
43552 | break; |
43553 | case CPP_XOR: |
43554 | opcode = BIT_XOR_EXPR; |
43555 | break; |
43556 | case CPP_EQ_EQ: |
43557 | opcode = EQ_EXPR; |
43558 | break; |
43559 | case CPP_GREATER: |
43560 | opcode = GT_EXPR; |
43561 | break; |
43562 | case CPP_LESS: |
43563 | opcode = LT_EXPR; |
43564 | break; |
43565 | default: |
43566 | cp_parser_error (parser, |
43567 | gmsgid: "invalid operator for %<#pragma omp atomic%>" ); |
43568 | goto saw_error; |
43569 | } |
43570 | if (compare |
43571 | && TREE_CODE_CLASS (opcode) != tcc_comparison) |
43572 | { |
43573 | cp_parser_error (parser, |
43574 | gmsgid: "invalid form of " |
43575 | "%<#pragma omp atomic compare%>" ); |
43576 | goto saw_error; |
43577 | } |
43578 | oprec = TOKEN_PRECEDENCE (token); |
43579 | gcc_assert (oprec != PREC_NOT_OPERATOR); |
43580 | if (commutative_tree_code (opcode)) |
43581 | oprec = (enum cp_parser_prec) (oprec - 1); |
43582 | cp_lexer_consume_token (lexer: parser->lexer); |
43583 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
43584 | prec: oprec, NULL); |
43585 | if (rhs == error_mark_node) |
43586 | goto saw_error; |
43587 | if (compare) |
43588 | { |
43589 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
43590 | { |
43591 | cp_parser_error (parser, |
43592 | gmsgid: "invalid form of " |
43593 | "%<#pragma omp atomic compare%>" ); |
43594 | goto saw_error; |
43595 | } |
43596 | goto cond_expr; |
43597 | } |
43598 | goto stmt_done; |
43599 | default: |
43600 | cp_parser_error (parser, |
43601 | gmsgid: "invalid operator for %<#pragma omp atomic%>" ); |
43602 | goto saw_error; |
43603 | } |
43604 | cp_lexer_consume_token (lexer: parser->lexer); |
43605 | |
43606 | rhs = cp_parser_expression (parser); |
43607 | if (rhs == error_mark_node) |
43608 | goto saw_error; |
43609 | break; |
43610 | } |
43611 | stmt_done: |
43612 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE) |
43613 | { |
43614 | if (!no_semicolon |
43615 | && !cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
43616 | goto saw_error; |
43617 | no_semicolon = false; |
43618 | v = cp_parser_unary_expression (parser); |
43619 | if (v == error_mark_node) |
43620 | goto saw_error; |
43621 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
43622 | goto saw_error; |
43623 | lhs1 = cp_parser_unary_expression (parser); |
43624 | if (lhs1 == error_mark_node) |
43625 | goto saw_error; |
43626 | } |
43627 | if (structured_block) |
43628 | { |
43629 | if (!no_semicolon) |
43630 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
43631 | cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE); |
43632 | } |
43633 | done: |
43634 | if (weak && opcode != COND_EXPR) |
43635 | { |
43636 | error_at (loc, "%<weak%> clause requires atomic equality comparison" ); |
43637 | weak = false; |
43638 | } |
43639 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
43640 | finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1, |
43641 | rhs1, r, clauses, memory_order, weak); |
43642 | if (!structured_block && !no_semicolon) |
43643 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
43644 | return; |
43645 | |
43646 | invalid_compare: |
43647 | error ("invalid form of %<pragma omp atomic compare%>" ); |
43648 | /* FALLTHRU */ |
43649 | saw_error: |
43650 | cp_parser_skip_to_end_of_block_or_statement (parser); |
43651 | if (extra_scope && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43652 | cp_lexer_consume_token (lexer: parser->lexer); |
43653 | if (structured_block) |
43654 | { |
43655 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43656 | cp_lexer_consume_token (lexer: parser->lexer); |
43657 | else if (code == OMP_ATOMIC_CAPTURE_NEW) |
43658 | { |
43659 | cp_parser_skip_to_end_of_block_or_statement (parser); |
43660 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43661 | cp_lexer_consume_token (lexer: parser->lexer); |
43662 | } |
43663 | } |
43664 | } |
43665 | |
43666 | |
43667 | /* OpenMP 2.5: |
43668 | # pragma omp barrier new-line */ |
43669 | |
43670 | static void |
43671 | cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok) |
43672 | { |
43673 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43674 | finish_omp_barrier (); |
43675 | } |
43676 | |
43677 | /* OpenMP 2.5: |
43678 | # pragma omp critical [(name)] new-line |
43679 | structured-block |
43680 | |
43681 | OpenMP 4.5: |
43682 | # pragma omp critical [(name) [hint(expression)]] new-line |
43683 | structured-block */ |
43684 | |
43685 | #define OMP_CRITICAL_CLAUSE_MASK \ |
43686 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) ) |
43687 | |
43688 | static tree |
43689 | cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
43690 | { |
43691 | tree stmt, name = NULL_TREE, clauses = NULL_TREE; |
43692 | |
43693 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
43694 | { |
43695 | matching_parens parens; |
43696 | parens.consume_open (parser); |
43697 | |
43698 | name = cp_parser_identifier (parser); |
43699 | |
43700 | if (name == error_mark_node |
43701 | || !parens.require_close (parser)) |
43702 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
43703 | /*or_comma=*/false, |
43704 | /*consume_paren=*/true); |
43705 | if (name == error_mark_node) |
43706 | name = NULL; |
43707 | |
43708 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
43709 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
43710 | cp_lexer_consume_token (lexer: parser->lexer); |
43711 | } |
43712 | |
43713 | clauses = cp_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK, |
43714 | where: "#pragma omp critical" , pragma_tok); |
43715 | |
43716 | stmt = cp_parser_omp_structured_block (parser, if_p); |
43717 | return c_finish_omp_critical (input_location, stmt, name, clauses); |
43718 | } |
43719 | |
43720 | /* OpenMP 5.0: |
43721 | # pragma omp depobj ( depobj ) depobj-clause new-line |
43722 | |
43723 | depobj-clause: |
43724 | depend (dependence-type : locator) |
43725 | destroy |
43726 | update (dependence-type) |
43727 | |
43728 | OpenMP 5.2 additionally: |
43729 | destroy ( depobj ) |
43730 | |
43731 | dependence-type: |
43732 | in |
43733 | out |
43734 | inout |
43735 | mutexinout */ |
43736 | |
43737 | static void |
43738 | cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) |
43739 | { |
43740 | location_t loc = pragma_tok->location; |
43741 | matching_parens parens; |
43742 | if (!parens.require_open (parser)) |
43743 | { |
43744 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
43745 | return; |
43746 | } |
43747 | |
43748 | tree depobj = cp_parser_assignment_expression (parser); |
43749 | |
43750 | if (!parens.require_close (parser)) |
43751 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
43752 | /*or_comma=*/false, |
43753 | /*consume_paren=*/true); |
43754 | |
43755 | tree clause = NULL_TREE; |
43756 | enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; |
43757 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
43758 | cp_lexer_consume_token (lexer: parser->lexer); |
43759 | location_t c_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43760 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43761 | { |
43762 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43763 | const char *p = IDENTIFIER_POINTER (id); |
43764 | |
43765 | cp_lexer_consume_token (lexer: parser->lexer); |
43766 | if (!strcmp (s1: "depend" , s2: p)) |
43767 | { |
43768 | /* Don't create location wrapper nodes within the depend clause. */ |
43769 | auto_suppress_location_wrappers sentinel; |
43770 | clause = cp_parser_omp_clause_depend (parser, NULL_TREE, loc: c_loc); |
43771 | if (clause) |
43772 | clause = finish_omp_clauses (clause, C_ORT_OMP); |
43773 | if (!clause) |
43774 | clause = error_mark_node; |
43775 | } |
43776 | else if (!strcmp (s1: "destroy" , s2: p)) |
43777 | { |
43778 | kind = OMP_CLAUSE_DEPEND_LAST; |
43779 | matching_parens c_parens; |
43780 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
43781 | && c_parens.require_open (parser)) |
43782 | { |
43783 | tree destobj = cp_parser_assignment_expression (parser); |
43784 | if (depobj != error_mark_node |
43785 | && destobj != error_mark_node |
43786 | && !operand_equal_p (destobj, depobj, flags: OEP_MATCH_SIDE_EFFECTS |
43787 | | OEP_LEXICOGRAPHIC)) |
43788 | warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp, |
43789 | "the %<destroy%> expression %qE should be the same " |
43790 | "as the %<depobj%> argument %qE" , destobj, depobj); |
43791 | if (!c_parens.require_close (parser)) |
43792 | cp_parser_skip_to_closing_parenthesis (parser, |
43793 | /*recovering=*/true, |
43794 | /*or_comma=*/false, |
43795 | /*consume_paren=*/true); |
43796 | } |
43797 | } |
43798 | else if (!strcmp (s1: "update" , s2: p)) |
43799 | { |
43800 | matching_parens c_parens; |
43801 | if (c_parens.require_open (parser)) |
43802 | { |
43803 | location_t c2_loc |
43804 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43805 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43806 | { |
43807 | tree id2 = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43808 | const char *p2 = IDENTIFIER_POINTER (id2); |
43809 | |
43810 | cp_lexer_consume_token (lexer: parser->lexer); |
43811 | if (!strcmp (s1: "in" , s2: p2)) |
43812 | kind = OMP_CLAUSE_DEPEND_IN; |
43813 | else if (!strcmp (s1: "out" , s2: p2)) |
43814 | kind = OMP_CLAUSE_DEPEND_OUT; |
43815 | else if (!strcmp (s1: "inout" , s2: p2)) |
43816 | kind = OMP_CLAUSE_DEPEND_INOUT; |
43817 | else if (!strcmp (s1: "mutexinoutset" , s2: p2)) |
43818 | kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET; |
43819 | else if (!strcmp (s1: "inoutset" , s2: p2)) |
43820 | kind = OMP_CLAUSE_DEPEND_INOUTSET; |
43821 | } |
43822 | if (kind == OMP_CLAUSE_DEPEND_INVALID) |
43823 | { |
43824 | clause = error_mark_node; |
43825 | error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " |
43826 | "%<mutexinoutset%> or %<inoutset%>" ); |
43827 | } |
43828 | if (!c_parens.require_close (parser)) |
43829 | cp_parser_skip_to_closing_parenthesis (parser, |
43830 | /*recovering=*/true, |
43831 | /*or_comma=*/false, |
43832 | /*consume_paren=*/true); |
43833 | } |
43834 | else |
43835 | clause = error_mark_node; |
43836 | } |
43837 | } |
43838 | if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) |
43839 | { |
43840 | clause = error_mark_node; |
43841 | error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause" ); |
43842 | } |
43843 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43844 | |
43845 | finish_omp_depobj (loc, depobj, kind, clause); |
43846 | } |
43847 | |
43848 | |
43849 | /* OpenMP 2.5: |
43850 | # pragma omp flush flush-vars[opt] new-line |
43851 | |
43852 | flush-vars: |
43853 | ( variable-list ) |
43854 | |
43855 | OpenMP 5.0: |
43856 | # pragma omp flush memory-order-clause new-line */ |
43857 | |
43858 | static void |
43859 | cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) |
43860 | { |
43861 | enum memmodel mo = MEMMODEL_LAST; |
43862 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
43863 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
43864 | cp_lexer_consume_token (lexer: parser->lexer); |
43865 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43866 | { |
43867 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43868 | const char *p = IDENTIFIER_POINTER (id); |
43869 | if (!strcmp (s1: p, s2: "seq_cst" )) |
43870 | mo = MEMMODEL_SEQ_CST; |
43871 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
43872 | mo = MEMMODEL_ACQ_REL; |
43873 | else if (!strcmp (s1: p, s2: "release" )) |
43874 | mo = MEMMODEL_RELEASE; |
43875 | else if (!strcmp (s1: p, s2: "acquire" )) |
43876 | mo = MEMMODEL_ACQUIRE; |
43877 | else |
43878 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
43879 | "expected %<seq_cst%>, %<acq_rel%>, %<release%> or " |
43880 | "%<acquire%>" ); |
43881 | cp_lexer_consume_token (lexer: parser->lexer); |
43882 | } |
43883 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
43884 | { |
43885 | if (mo != MEMMODEL_LAST) |
43886 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
43887 | "%<flush%> list specified together with memory order " |
43888 | "clause" ); |
43889 | (void) cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
43890 | } |
43891 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43892 | |
43893 | finish_omp_flush (mo); |
43894 | } |
43895 | |
43896 | /* Helper function, to parse omp for increment expression. */ |
43897 | |
43898 | static tree |
43899 | cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code) |
43900 | { |
43901 | tree cond = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
43902 | prec: PREC_NOT_OPERATOR, NULL); |
43903 | if (cond == error_mark_node |
43904 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
43905 | { |
43906 | cp_parser_skip_to_end_of_statement (parser); |
43907 | return error_mark_node; |
43908 | } |
43909 | |
43910 | switch (TREE_CODE (cond)) |
43911 | { |
43912 | case GT_EXPR: |
43913 | case GE_EXPR: |
43914 | case LT_EXPR: |
43915 | case LE_EXPR: |
43916 | break; |
43917 | case NE_EXPR: |
43918 | if (code != OACC_LOOP) |
43919 | break; |
43920 | gcc_fallthrough (); |
43921 | default: |
43922 | return error_mark_node; |
43923 | } |
43924 | |
43925 | /* If decl is an iterator, preserve LHS and RHS of the relational |
43926 | expr until finish_omp_for. */ |
43927 | if (decl |
43928 | && (type_dependent_expression_p (decl) |
43929 | || CLASS_TYPE_P (TREE_TYPE (decl)))) |
43930 | return cond; |
43931 | |
43932 | return build_x_binary_op (cp_expr_loc_or_input_loc (t: cond), |
43933 | TREE_CODE (cond), |
43934 | TREE_OPERAND (cond, 0), ERROR_MARK, |
43935 | TREE_OPERAND (cond, 1), ERROR_MARK, |
43936 | NULL_TREE, /*overload=*/NULL, tf_warning_or_error); |
43937 | } |
43938 | |
43939 | /* Helper function, to parse omp for increment expression. */ |
43940 | |
43941 | static tree |
43942 | cp_parser_omp_for_incr (cp_parser *parser, tree decl) |
43943 | { |
43944 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
43945 | enum tree_code op; |
43946 | tree lhs, rhs; |
43947 | cp_id_kind idk; |
43948 | bool decl_first; |
43949 | |
43950 | if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) |
43951 | { |
43952 | op = (token->type == CPP_PLUS_PLUS |
43953 | ? PREINCREMENT_EXPR : PREDECREMENT_EXPR); |
43954 | cp_lexer_consume_token (lexer: parser->lexer); |
43955 | lhs = cp_parser_simple_cast_expression (parser); |
43956 | if (lhs != decl |
43957 | && (!processing_template_decl || !cp_tree_equal (lhs, decl))) |
43958 | return error_mark_node; |
43959 | return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); |
43960 | } |
43961 | |
43962 | lhs = cp_parser_primary_expression (parser, address_p: false, cast_p: false, template_arg_p: false, idk: &idk); |
43963 | if (lhs != decl |
43964 | && (!processing_template_decl || !cp_tree_equal (lhs, decl))) |
43965 | return error_mark_node; |
43966 | |
43967 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43968 | if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) |
43969 | { |
43970 | op = (token->type == CPP_PLUS_PLUS |
43971 | ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR); |
43972 | cp_lexer_consume_token (lexer: parser->lexer); |
43973 | return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); |
43974 | } |
43975 | |
43976 | op = cp_parser_assignment_operator_opt (parser); |
43977 | if (op == ERROR_MARK) |
43978 | return error_mark_node; |
43979 | |
43980 | if (op != NOP_EXPR) |
43981 | { |
43982 | rhs = cp_parser_assignment_expression (parser); |
43983 | rhs = build2 (op, TREE_TYPE (decl), decl, rhs); |
43984 | return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs); |
43985 | } |
43986 | |
43987 | lhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
43988 | prec: PREC_ADDITIVE_EXPRESSION, NULL); |
43989 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43990 | decl_first = (lhs == decl |
43991 | || (processing_template_decl && cp_tree_equal (lhs, decl))); |
43992 | if (decl_first) |
43993 | lhs = NULL_TREE; |
43994 | if (token->type != CPP_PLUS |
43995 | && token->type != CPP_MINUS) |
43996 | return error_mark_node; |
43997 | |
43998 | do |
43999 | { |
44000 | op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR; |
44001 | cp_lexer_consume_token (lexer: parser->lexer); |
44002 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
44003 | prec: PREC_ADDITIVE_EXPRESSION, NULL); |
44004 | token = cp_lexer_peek_token (lexer: parser->lexer); |
44005 | if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first) |
44006 | { |
44007 | if (lhs == NULL_TREE) |
44008 | { |
44009 | if (op == PLUS_EXPR) |
44010 | lhs = rhs; |
44011 | else |
44012 | lhs = build_x_unary_op (input_location, NEGATE_EXPR, rhs, |
44013 | NULL_TREE, tf_warning_or_error); |
44014 | } |
44015 | else |
44016 | lhs = build_x_binary_op (input_location, op, |
44017 | lhs, ERROR_MARK, |
44018 | rhs, ERROR_MARK, |
44019 | NULL_TREE, NULL, tf_warning_or_error); |
44020 | } |
44021 | } |
44022 | while (token->type == CPP_PLUS || token->type == CPP_MINUS); |
44023 | |
44024 | if (!decl_first) |
44025 | { |
44026 | if ((rhs != decl |
44027 | && (!processing_template_decl || !cp_tree_equal (rhs, decl))) |
44028 | || op == MINUS_EXPR) |
44029 | return error_mark_node; |
44030 | rhs = build2 (op, TREE_TYPE (decl), lhs, decl); |
44031 | } |
44032 | else |
44033 | rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs); |
44034 | |
44035 | return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs); |
44036 | } |
44037 | |
44038 | /* Parse the initialization statement of an OpenMP for loop. Range-for |
44039 | is handled separately in cp_convert_omp_range_for. |
44040 | |
44041 | On entry SL is the current statement list. Parsing of some forms |
44042 | of initialization pops this list and stores its contents in either INIT |
44043 | or THIS_PRE_BODY, and sets SL to null. Initialization for class |
44044 | iterators is added directly to SL and it is not popped until later. |
44045 | |
44046 | On return, DECL is set if the initialization is by binding the |
44047 | iteration variable. If the initialization is by assignment, REAL_DECL |
44048 | is set to point to a variable in an outer scope. ORIG_INIT is set |
44049 | if the iteration variable is of class type; this is a copy saved for |
44050 | error checking in finish_omp_for. |
44051 | |
44052 | Return true if the resulting construct should have an |
44053 | OMP_CLAUSE_PRIVATE added to it. */ |
44054 | |
44055 | static tree |
44056 | cp_parser_omp_for_loop_init (cp_parser *parser, |
44057 | tree &this_pre_body, |
44058 | tree &sl, |
44059 | tree &init, |
44060 | tree &orig_init, |
44061 | tree &decl, |
44062 | tree &real_decl) |
44063 | { |
44064 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
44065 | return NULL_TREE; |
44066 | |
44067 | tree add_private_clause = NULL_TREE; |
44068 | |
44069 | /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too): |
44070 | |
44071 | init-expr: |
44072 | var = lb |
44073 | integer-type var = lb |
44074 | random-access-iterator-type var = lb |
44075 | pointer-type var = lb |
44076 | */ |
44077 | cp_decl_specifier_seq type_specifiers; |
44078 | |
44079 | /* First, try to parse as an initialized declaration. See |
44080 | cp_parser_condition, from whence the bulk of this is copied. */ |
44081 | |
44082 | cp_parser_parse_tentatively (parser); |
44083 | cp_parser_type_specifier_seq (parser, flags: CP_PARSER_FLAGS_NONE, |
44084 | /*is_declaration=*/true, |
44085 | /*is_trailing_return=*/false, |
44086 | type_specifier_seq: &type_specifiers); |
44087 | if (cp_parser_parse_definitely (parser)) |
44088 | { |
44089 | /* If parsing a type specifier seq succeeded, then this |
44090 | MUST be a initialized declaration. */ |
44091 | tree asm_specification, attributes; |
44092 | cp_declarator *declarator; |
44093 | |
44094 | declarator = cp_parser_declarator (parser, |
44095 | dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
44096 | flags: CP_PARSER_FLAGS_NONE, |
44097 | /*ctor_dtor_or_conv_p=*/NULL, |
44098 | /*parenthesized_p=*/NULL, |
44099 | /*member_p=*/false, |
44100 | /*friend_p=*/false, |
44101 | /*static_p=*/false); |
44102 | attributes = cp_parser_attributes_opt (parser); |
44103 | asm_specification = cp_parser_asm_specification_opt (parser); |
44104 | |
44105 | if (declarator == cp_error_declarator) |
44106 | cp_parser_skip_to_end_of_statement (parser); |
44107 | |
44108 | else |
44109 | { |
44110 | tree pushed_scope, auto_node; |
44111 | |
44112 | decl = start_decl (declarator, &type_specifiers, |
44113 | SD_INITIALIZED, attributes, |
44114 | /*prefix_attributes=*/NULL_TREE, |
44115 | &pushed_scope); |
44116 | |
44117 | auto_node = type_uses_auto (TREE_TYPE (decl)); |
44118 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ)) |
44119 | { |
44120 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
44121 | type: CPP_OPEN_PAREN)) |
44122 | error ("parenthesized initialization is not allowed in " |
44123 | "OpenMP %<for%> loop" ); |
44124 | else |
44125 | /* Trigger an error. */ |
44126 | cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ); |
44127 | |
44128 | init = error_mark_node; |
44129 | cp_parser_skip_to_end_of_statement (parser); |
44130 | } |
44131 | else if (CLASS_TYPE_P (TREE_TYPE (decl)) |
44132 | || type_dependent_expression_p (decl) |
44133 | || auto_node) |
44134 | { |
44135 | bool is_non_constant_init; |
44136 | |
44137 | init = cp_parser_initializer (parser, |
44138 | /*is_direct_init=*/nullptr, |
44139 | non_constant_p: &is_non_constant_init); |
44140 | |
44141 | if (auto_node) |
44142 | { |
44143 | TREE_TYPE (decl) |
44144 | = do_auto_deduction (TREE_TYPE (decl), init, |
44145 | auto_node); |
44146 | |
44147 | if (!CLASS_TYPE_P (TREE_TYPE (decl)) |
44148 | && !type_dependent_expression_p (decl)) |
44149 | goto non_class; |
44150 | } |
44151 | |
44152 | cp_finish_decl (decl, init, !is_non_constant_init, |
44153 | asm_specification, |
44154 | LOOKUP_ONLYCONVERTING); |
44155 | orig_init = init; |
44156 | |
44157 | /* In the case of a class iterator, do not pop sl here. |
44158 | Both class initialization and finalization must happen in |
44159 | the enclosing init block scope. For now set the init |
44160 | expression to null; it'll be filled in properly in |
44161 | finish_omp_for before stuffing it in the OMP_FOR. */ |
44162 | if (CLASS_TYPE_P (TREE_TYPE (decl))) |
44163 | init = NULL_TREE; |
44164 | else /* It is a parameterized type. */ |
44165 | { |
44166 | init = pop_stmt_list (sl); |
44167 | sl = NULL_TREE; |
44168 | if (init && TREE_CODE (init) == STATEMENT_LIST) |
44169 | { |
44170 | tree_stmt_iterator i = tsi_start (t: init); |
44171 | /* Move lambda DECL_EXPRs to the enclosing block. */ |
44172 | while (!tsi_end_p (i)) |
44173 | { |
44174 | tree t = tsi_stmt (i); |
44175 | if (TREE_CODE (t) == DECL_EXPR |
44176 | && TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) |
44177 | { |
44178 | tsi_delink (&i); |
44179 | add_stmt (t); |
44180 | continue; |
44181 | } |
44182 | break; |
44183 | } |
44184 | if (tsi_one_before_end_p (i)) |
44185 | { |
44186 | tree t = tsi_stmt (i); |
44187 | tsi_delink (&i); |
44188 | free_stmt_list (init); |
44189 | init = t; |
44190 | } |
44191 | } |
44192 | } |
44193 | } |
44194 | else |
44195 | /* This is an initialized declaration of non-class, |
44196 | non-parameterized type iteration variable. */ |
44197 | { |
44198 | /* Consume '='. */ |
44199 | cp_lexer_consume_token (lexer: parser->lexer); |
44200 | init = cp_parser_assignment_expression (parser); |
44201 | |
44202 | non_class: |
44203 | if (TYPE_REF_P (TREE_TYPE (decl))) |
44204 | init = error_mark_node; |
44205 | else |
44206 | cp_finish_decl (decl, NULL_TREE, |
44207 | /*init_const_expr_p=*/false, |
44208 | asm_specification, |
44209 | LOOKUP_ONLYCONVERTING); |
44210 | this_pre_body = pop_stmt_list (sl); |
44211 | sl = NULL_TREE; |
44212 | } |
44213 | |
44214 | if (pushed_scope) |
44215 | pop_scope (pushed_scope); |
44216 | } |
44217 | } |
44218 | else |
44219 | { |
44220 | cp_id_kind idk; |
44221 | /* If parsing a type specifier sequence failed, then |
44222 | this MUST be a simple expression. */ |
44223 | cp_parser_parse_tentatively (parser); |
44224 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, |
44225 | template_arg_p: false, idk: &idk); |
44226 | cp_token *last_tok = cp_lexer_peek_token (lexer: parser->lexer); |
44227 | if (!cp_parser_error_occurred (parser) |
44228 | && decl |
44229 | && (TREE_CODE (decl) == COMPONENT_REF |
44230 | || (TREE_CODE (decl) == SCOPE_REF && TREE_TYPE (decl)))) |
44231 | { |
44232 | cp_parser_abort_tentative_parse (parser); |
44233 | cp_parser_parse_tentatively (parser); |
44234 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
44235 | tree name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
44236 | /*check_dependency_p=*/true, |
44237 | /*template_p=*/NULL, |
44238 | /*declarator_p=*/false, |
44239 | /*optional_p=*/false); |
44240 | if (name != error_mark_node |
44241 | && last_tok == cp_lexer_peek_token (lexer: parser->lexer)) |
44242 | { |
44243 | decl = cp_parser_lookup_name_simple (parser, name, |
44244 | location: token->location); |
44245 | if (TREE_CODE (decl) == FIELD_DECL) |
44246 | add_private_clause = omp_privatize_field (decl, false); |
44247 | } |
44248 | cp_parser_abort_tentative_parse (parser); |
44249 | cp_parser_parse_tentatively (parser); |
44250 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, |
44251 | template_arg_p: false, idk: &idk); |
44252 | } |
44253 | if (!cp_parser_error_occurred (parser) |
44254 | && decl |
44255 | && DECL_P (decl) |
44256 | && CLASS_TYPE_P (TREE_TYPE (decl))) |
44257 | { |
44258 | tree rhs; |
44259 | |
44260 | cp_parser_parse_definitely (parser); |
44261 | cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ); |
44262 | rhs = cp_parser_assignment_expression (parser); |
44263 | orig_init = rhs; |
44264 | finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs), |
44265 | decl, NOP_EXPR, |
44266 | rhs, NULL_TREE, |
44267 | tf_warning_or_error)); |
44268 | if (!add_private_clause) |
44269 | add_private_clause = decl; |
44270 | } |
44271 | else |
44272 | { |
44273 | decl = NULL; |
44274 | cp_parser_abort_tentative_parse (parser); |
44275 | init = cp_parser_expression (parser); |
44276 | if (init) |
44277 | { |
44278 | if (TREE_CODE (init) == MODIFY_EXPR |
44279 | || TREE_CODE (init) == MODOP_EXPR) |
44280 | real_decl = TREE_OPERAND (init, 0); |
44281 | } |
44282 | } |
44283 | this_pre_body = pop_stmt_list (sl); |
44284 | sl = NULL_TREE; |
44285 | } |
44286 | return add_private_clause; |
44287 | } |
44288 | |
44289 | /* Helper for cp_parser_omp_loop_nest, handle one range-for loop |
44290 | including introducing new temporaries for the range start and end, |
44291 | doing auto deduction, and processing decomposition variables. |
44292 | |
44293 | This function is also called from pt.cc during template instantiation. |
44294 | In that case SL is NULL_TREE, otherwise it is the current statement |
44295 | list. */ |
44296 | void |
44297 | cp_convert_omp_range_for (tree &this_pre_body, tree &sl, |
44298 | tree &decl, tree &orig_decl, tree &init, |
44299 | tree &orig_init, tree &cond, tree &incr) |
44300 | { |
44301 | tree begin, end, range_temp_decl = NULL_TREE; |
44302 | tree iter_type, begin_expr, end_expr; |
44303 | bool clear_has_value_expr = false; |
44304 | |
44305 | if (processing_template_decl) |
44306 | { |
44307 | if (check_for_bare_parameter_packs (init)) |
44308 | init = error_mark_node; |
44309 | if (!type_dependent_expression_p (init) |
44310 | /* do_auto_deduction doesn't mess with template init-lists. */ |
44311 | && !BRACE_ENCLOSED_INITIALIZER_P (init)) |
44312 | { |
44313 | tree d = decl; |
44314 | cp_decomp decomp_d, *decomp = NULL; |
44315 | if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl)) |
44316 | { |
44317 | tree v = DECL_VALUE_EXPR (decl); |
44318 | if (TREE_CODE (v) == ARRAY_REF |
44319 | && VAR_P (TREE_OPERAND (v, 0)) |
44320 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
44321 | { |
44322 | d = TREE_OPERAND (v, 0); |
44323 | decomp = &decomp_d; |
44324 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
44325 | decomp->decl = decl; |
44326 | } |
44327 | } |
44328 | do_range_for_auto_deduction (decl: d, range_expr: init, decomp); |
44329 | } |
44330 | cond = global_namespace; |
44331 | incr = NULL_TREE; |
44332 | orig_init = init; |
44333 | if (sl) |
44334 | { |
44335 | this_pre_body = pop_stmt_list (sl); |
44336 | sl = NULL_TREE; |
44337 | } |
44338 | return; |
44339 | } |
44340 | |
44341 | init = mark_lvalue_use (init); |
44342 | |
44343 | if (decl == error_mark_node || init == error_mark_node) |
44344 | /* If an error happened previously do nothing or else a lot of |
44345 | unhelpful errors would be issued. */ |
44346 | begin_expr = end_expr = iter_type = error_mark_node; |
44347 | else |
44348 | { |
44349 | tree range_temp; |
44350 | |
44351 | if (VAR_P (init) |
44352 | && array_of_runtime_bound_p (TREE_TYPE (init))) |
44353 | /* Can't bind a reference to an array of runtime bound. */ |
44354 | range_temp = init; |
44355 | else |
44356 | { |
44357 | range_temp = build_range_temp (range_expr: init); |
44358 | DECL_NAME (range_temp) = NULL_TREE; |
44359 | pushdecl (range_temp); |
44360 | cp_finish_decl (range_temp, init, |
44361 | /*is_constant_init*/false, NULL_TREE, |
44362 | LOOKUP_ONLYCONVERTING); |
44363 | range_temp_decl = range_temp; |
44364 | range_temp = convert_from_reference (range_temp); |
44365 | } |
44366 | iter_type = cp_parser_perform_range_for_lookup (range: range_temp, |
44367 | begin: &begin_expr, end: &end_expr); |
44368 | } |
44369 | |
44370 | tree end_iter_type = iter_type; |
44371 | if (cxx_dialect >= cxx17) |
44372 | end_iter_type = cv_unqualified (TREE_TYPE (end_expr)); |
44373 | end = build_decl (input_location, VAR_DECL, NULL_TREE, end_iter_type); |
44374 | TREE_USED (end) = 1; |
44375 | DECL_ARTIFICIAL (end) = 1; |
44376 | pushdecl (end); |
44377 | cp_finish_decl (end, end_expr, |
44378 | /*is_constant_init*/false, NULL_TREE, |
44379 | LOOKUP_ONLYCONVERTING); |
44380 | |
44381 | /* The new for initialization statement. */ |
44382 | begin = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type); |
44383 | TREE_USED (begin) = 1; |
44384 | DECL_ARTIFICIAL (begin) = 1; |
44385 | pushdecl (begin); |
44386 | orig_init = init; |
44387 | if (CLASS_TYPE_P (iter_type)) |
44388 | init = NULL_TREE; |
44389 | else |
44390 | { |
44391 | init = begin_expr; |
44392 | begin_expr = NULL_TREE; |
44393 | } |
44394 | cp_finish_decl (begin, begin_expr, |
44395 | /*is_constant_init*/false, NULL_TREE, |
44396 | LOOKUP_ONLYCONVERTING); |
44397 | |
44398 | /* The new for condition. */ |
44399 | if (CLASS_TYPE_P (iter_type)) |
44400 | cond = build2 (NE_EXPR, boolean_type_node, begin, end); |
44401 | else |
44402 | cond = build_x_binary_op (input_location, NE_EXPR, |
44403 | begin, ERROR_MARK, |
44404 | end, ERROR_MARK, |
44405 | NULL_TREE, NULL, tf_warning_or_error); |
44406 | |
44407 | /* The new increment expression. */ |
44408 | if (CLASS_TYPE_P (iter_type)) |
44409 | incr = build2 (PREINCREMENT_EXPR, iter_type, begin, NULL_TREE); |
44410 | else |
44411 | incr = finish_unary_op_expr (input_location, |
44412 | PREINCREMENT_EXPR, begin, |
44413 | tf_warning_or_error); |
44414 | |
44415 | orig_decl = decl; |
44416 | decl = begin; |
44417 | /* Defer popping sl here. */ |
44418 | |
44419 | cp_decomp decomp_d, *decomp = NULL; |
44420 | if (orig_decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (orig_decl)) |
44421 | { |
44422 | tree v = DECL_VALUE_EXPR (orig_decl); |
44423 | if (TREE_CODE (v) == ARRAY_REF |
44424 | && VAR_P (TREE_OPERAND (v, 0)) |
44425 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
44426 | { |
44427 | tree d = orig_decl; |
44428 | orig_decl = TREE_OPERAND (v, 0); |
44429 | decomp = &decomp_d; |
44430 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
44431 | decomp->decl = d; |
44432 | } |
44433 | } |
44434 | |
44435 | tree auto_node = type_uses_auto (TREE_TYPE (orig_decl)); |
44436 | if (auto_node) |
44437 | { |
44438 | tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
44439 | NULL_TREE, tf_none); |
44440 | if (!error_operand_p (t)) |
44441 | { |
44442 | TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl), |
44443 | t, auto_node); |
44444 | if (decomp) |
44445 | { |
44446 | ++processing_template_decl; |
44447 | cp_finish_decomp (orig_decl, decomp); |
44448 | --processing_template_decl; |
44449 | if (!processing_template_decl) |
44450 | clear_has_value_expr = true; |
44451 | } |
44452 | } |
44453 | } |
44454 | |
44455 | /* The output ORIG_DECL is not a decl. Instead, it is a tree structure |
44456 | that holds decls for variables implementing the iterator, represented |
44457 | as a TREE_LIST whose TREE_CHAIN is a vector. The first two elements |
44458 | of the vector are decls of scratch variables for the range start and |
44459 | end that will eventually be bound in the implicit scope surrounding |
44460 | the whole loop nest. The remaining elements are decls of derived |
44461 | decomposition variables that are bound inside the loop body. This |
44462 | structure is further mangled by finish_omp_for into the form required |
44463 | for the OMP_FOR_ORIG_DECLS field of the OMP_FOR tree node. */\ |
44464 | unsigned decomp_cnt = decomp ? decomp->count : 0; |
44465 | tree v = make_tree_vec (decomp_cnt + 3); |
44466 | TREE_VEC_ELT (v, 0) = range_temp_decl; |
44467 | TREE_VEC_ELT (v, 1) = end; |
44468 | TREE_VEC_ELT (v, 2) = orig_decl; |
44469 | if (clear_has_value_expr) |
44470 | TREE_PUBLIC (v) = 1; |
44471 | for (unsigned i = 0; i < decomp_cnt; i++) |
44472 | { |
44473 | if (clear_has_value_expr) |
44474 | { |
44475 | /* If cp_finish_decomp was called with processing_template_decl |
44476 | temporarily set to 1, then decomp names will have deduced |
44477 | name but the DECL_VALUE_EXPR will be dependent. Hide those |
44478 | from folding of other loop initializers e.g. for warning |
44479 | purposes until cp_finish_omp_range_for. */ |
44480 | gcc_checking_assert (DECL_HAS_VALUE_EXPR_P (decomp->decl) |
44481 | || (TREE_TYPE (decomp->decl) |
44482 | == error_mark_node)); |
44483 | DECL_HAS_VALUE_EXPR_P (decomp->decl) = 0; |
44484 | } |
44485 | TREE_VEC_ELT (v, i + 3) = decomp->decl; |
44486 | decomp->decl = DECL_CHAIN (decomp->decl); |
44487 | } |
44488 | orig_decl = tree_cons (NULL_TREE, NULL_TREE, v); |
44489 | } |
44490 | |
44491 | /* Helper for cp_parser_omp_for_loop, finalize part of range for |
44492 | inside of the collapsed body. */ |
44493 | |
44494 | void |
44495 | cp_finish_omp_range_for (tree orig, tree begin) |
44496 | { |
44497 | gcc_assert (TREE_CODE (orig) == TREE_LIST |
44498 | && TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC); |
44499 | tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2); |
44500 | cp_decomp decomp_d, *decomp = NULL; |
44501 | |
44502 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
44503 | { |
44504 | decomp = &decomp_d; |
44505 | decomp_d.decl = TREE_VEC_ELT (TREE_CHAIN (orig), 3); |
44506 | decomp_d.count = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3; |
44507 | if (TREE_PUBLIC (TREE_CHAIN (orig))) |
44508 | { |
44509 | /* Undo temporary clearing of DECL_HAS_VALUE_EXPR_P done |
44510 | by cp_convert_omp_range_for above. */ |
44511 | TREE_PUBLIC (TREE_CHAIN (orig)) = 0; |
44512 | tree d = decomp_d.decl; |
44513 | for (unsigned i = 0; i < decomp_d.count; i++) |
44514 | { |
44515 | if (TREE_TYPE (d) != error_mark_node) |
44516 | DECL_HAS_VALUE_EXPR_P (d) = 1; |
44517 | d = DECL_CHAIN (d); |
44518 | } |
44519 | } |
44520 | } |
44521 | |
44522 | /* The declaration is initialized with *__begin inside the loop body. */ |
44523 | cp_finish_decl (decl, |
44524 | build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
44525 | NULL_TREE, tf_warning_or_error), |
44526 | /*is_constant_init*/false, NULL_TREE, |
44527 | LOOKUP_ONLYCONVERTING, decomp); |
44528 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
44529 | cp_finish_decomp (decl, decomp); |
44530 | } |
44531 | |
44532 | /* Return true if next tokens contain a standard attribute that contains |
44533 | omp::directive (DIRECTIVE). */ |
44534 | |
44535 | static bool |
44536 | cp_parser_omp_section_scan (cp_parser *parser, const char *directive, |
44537 | bool tentative) |
44538 | { |
44539 | size_t n = cp_parser_skip_attributes_opt (parser, n: 1), i; |
44540 | if (n < 10) |
44541 | return false; |
44542 | for (i = 5; i < n - 4; i++) |
44543 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i, type: CPP_NAME) |
44544 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, type: CPP_OPEN_PAREN) |
44545 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 2, type: CPP_NAME)) |
44546 | { |
44547 | tree first = cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->u.value; |
44548 | tree second = cp_lexer_peek_nth_token (lexer: parser->lexer, n: i + 2)->u.value; |
44549 | if (strcmp (IDENTIFIER_POINTER (first), s2: "directive" ) |
44550 | && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__" )) |
44551 | continue; |
44552 | if (strcmp (IDENTIFIER_POINTER (second), s2: directive) == 0) |
44553 | break; |
44554 | } |
44555 | if (i == n - 4) |
44556 | return false; |
44557 | cp_parser_parse_tentatively (parser); |
44558 | location_t first_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
44559 | location_t last_loc |
44560 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n - 1)->location; |
44561 | location_t middle_loc = UNKNOWN_LOCATION; |
44562 | tree std_attrs = cp_parser_std_attribute_spec_seq (parser); |
44563 | int cnt = 0; |
44564 | bool seen = false; |
44565 | for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr)) |
44566 | if (get_attribute_namespace (attr) == omp_identifier |
44567 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (attr))) |
44568 | { |
44569 | for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a)) |
44570 | { |
44571 | tree d = TREE_VALUE (a); |
44572 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
44573 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
44574 | cnt++; |
44575 | if (first->type == CPP_NAME |
44576 | && strcmp (IDENTIFIER_POINTER (first->u.value), |
44577 | s2: directive) == 0) |
44578 | { |
44579 | seen = true; |
44580 | if (middle_loc == UNKNOWN_LOCATION) |
44581 | middle_loc = first->location; |
44582 | } |
44583 | } |
44584 | } |
44585 | if (!seen || tentative) |
44586 | { |
44587 | cp_parser_abort_tentative_parse (parser); |
44588 | return seen; |
44589 | } |
44590 | if (cnt != 1 || TREE_CHAIN (std_attrs)) |
44591 | { |
44592 | error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc), |
44593 | "%<[[omp::directive(%s)]]%> must be the only specified " |
44594 | "attribute on a statement" , directive); |
44595 | cp_parser_abort_tentative_parse (parser); |
44596 | return false; |
44597 | } |
44598 | if (!cp_parser_parse_definitely (parser)) |
44599 | return false; |
44600 | cp_parser_handle_statement_omp_attributes (parser, attrs: std_attrs); |
44601 | return true; |
44602 | } |
44603 | |
44604 | /* Parse an OpenMP structured block sequence. KIND is the corresponding |
44605 | separating directive. */ |
44606 | |
44607 | static tree |
44608 | cp_parser_omp_structured_block_sequence (cp_parser *parser, |
44609 | enum pragma_kind kind) |
44610 | { |
44611 | tree stmt = begin_omp_structured_block (); |
44612 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
44613 | |
44614 | cp_parser_statement (parser, NULL_TREE, in_compound: false, NULL); |
44615 | while (true) |
44616 | { |
44617 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
44618 | |
44619 | if (token->type == CPP_CLOSE_BRACE |
44620 | || token->type == CPP_EOF |
44621 | || token->type == CPP_PRAGMA_EOL |
44622 | || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END) |
44623 | || (kind != PRAGMA_NONE |
44624 | && cp_parser_pragma_kind (token) == kind)) |
44625 | break; |
44626 | |
44627 | if (kind != PRAGMA_NONE |
44628 | && cp_parser_omp_section_scan (parser, |
44629 | directive: kind == PRAGMA_OMP_SCAN |
44630 | ? "scan" : "section" , tentative: false)) |
44631 | break; |
44632 | |
44633 | cp_parser_statement (parser, NULL_TREE, in_compound: false, NULL); |
44634 | } |
44635 | |
44636 | cp_parser_end_omp_structured_block (parser, save); |
44637 | return finish_omp_structured_block (stmt); |
44638 | } |
44639 | |
44640 | |
44641 | /* OpenMP 5.0: |
44642 | |
44643 | scan-loop-body: |
44644 | { structured-block scan-directive structured-block } */ |
44645 | |
44646 | static void |
44647 | cp_parser_omp_scan_loop_body (cp_parser *parser) |
44648 | { |
44649 | tree substmt, clauses = NULL_TREE; |
44650 | bool found_scan = false; |
44651 | |
44652 | matching_braces braces; |
44653 | if (!braces.require_open (parser)) |
44654 | return; |
44655 | |
44656 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
44657 | if (cp_parser_pragma_kind (token: tok) != PRAGMA_OMP_SCAN) |
44658 | substmt = cp_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN); |
44659 | else |
44660 | { |
44661 | warning_at (tok->location, OPT_Wopenmp, |
44662 | "%<#pragma omp scan%> with zero preceding executable " |
44663 | "statements" ); |
44664 | substmt = build_empty_stmt (tok->location); |
44665 | } |
44666 | substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); |
44667 | add_stmt (substmt); |
44668 | |
44669 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
44670 | if (cp_parser_pragma_kind (token: tok) == PRAGMA_OMP_SCAN) |
44671 | { |
44672 | enum omp_clause_code clause = OMP_CLAUSE_ERROR; |
44673 | found_scan = true; |
44674 | |
44675 | cp_lexer_consume_token (lexer: parser->lexer); |
44676 | |
44677 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
44678 | cp_lexer_consume_token (lexer: parser->lexer); |
44679 | |
44680 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
44681 | { |
44682 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
44683 | const char *p = IDENTIFIER_POINTER (id); |
44684 | if (strcmp (s1: p, s2: "inclusive" ) == 0) |
44685 | clause = OMP_CLAUSE_INCLUSIVE; |
44686 | else if (strcmp (s1: p, s2: "exclusive" ) == 0) |
44687 | clause = OMP_CLAUSE_EXCLUSIVE; |
44688 | } |
44689 | if (clause != OMP_CLAUSE_ERROR) |
44690 | { |
44691 | cp_lexer_consume_token (lexer: parser->lexer); |
44692 | clauses = cp_parser_omp_var_list (parser, kind: clause, NULL_TREE); |
44693 | } |
44694 | else |
44695 | cp_parser_error (parser, gmsgid: "expected %<inclusive%> or " |
44696 | "%<exclusive%> clause" ); |
44697 | |
44698 | cp_parser_require_pragma_eol (parser, pragma_tok: tok); |
44699 | } |
44700 | else |
44701 | error ("expected %<#pragma omp scan%>" ); |
44702 | |
44703 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
44704 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
44705 | substmt = cp_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE); |
44706 | else |
44707 | { |
44708 | if (found_scan) |
44709 | warning_at (tok->location, OPT_Wopenmp, |
44710 | "%<#pragma omp scan%> with zero succeeding executable " |
44711 | "statements" ); |
44712 | substmt = build_empty_stmt (tok->location); |
44713 | } |
44714 | substmt = build2_loc (loc: tok->location, code: OMP_SCAN, void_type_node, arg0: substmt, |
44715 | arg1: clauses); |
44716 | add_stmt (substmt); |
44717 | |
44718 | braces.require_close (parser); |
44719 | } |
44720 | |
44721 | |
44722 | /* This function parses a single level of a loop nest, invoking itself |
44723 | recursively if necessary. |
44724 | |
44725 | loop-nest :: for (...) loop-body |
44726 | loop-body :: loop-nest |
44727 | | { [intervening-code] loop-body [intervening-code] } |
44728 | | final-loop-body |
44729 | intervening-code :: structured-block-sequence |
44730 | final-loop-body :: structured-block |
44731 | |
44732 | For a collapsed loop nest, only a single OMP_FOR is built, pulling out |
44733 | all the iterator information from the inner loops into vectors in the |
44734 | parser->omp_for_parse_state structure. |
44735 | |
44736 | In the "range for" case, it is transformed into a regular "for" iterator |
44737 | by introducing some temporary variables for the begin/end, |
44738 | as well as bindings of the actual iteration variables which are |
44739 | injected into the body of the loop. |
44740 | |
44741 | Initialization code for iterator variables may end up either in the |
44742 | init vector (simple assignments), in omp_for_parse_state->pre_body |
44743 | (decl_exprs for iterators bound in the for statement), or in the |
44744 | scope surrounding this level of loop initialization. |
44745 | |
44746 | The scopes of class iterator variables and their finalizers need to |
44747 | be adjusted after parsing so that all of the initialization happens |
44748 | in a scope surrounding all of the intervening and body code. For |
44749 | this reason we separately store the initialization and body blocks |
44750 | for each level of loops in the omp_for_parse_state structure and |
44751 | reassemble/reorder them in cp_parser_omp_for. See additional |
44752 | comments there about the use of placeholders, etc. */ |
44753 | |
44754 | static tree |
44755 | cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) |
44756 | { |
44757 | tree decl, cond, incr, init; |
44758 | tree orig_init, real_decl, orig_decl; |
44759 | tree init_block, body_block; |
44760 | tree init_placeholder, body_placeholder; |
44761 | tree init_scope; |
44762 | tree this_pre_body = NULL_TREE; |
44763 | bool moreloops; |
44764 | unsigned char save_in_statement; |
44765 | tree add_private_clause = NULL_TREE; |
44766 | location_t loc; |
44767 | bool is_range_for = false; |
44768 | tree sl = NULL_TREE; |
44769 | struct omp_for_parse_data *omp_for_parse_state |
44770 | = parser->omp_for_parse_state; |
44771 | gcc_assert (omp_for_parse_state); |
44772 | int depth = omp_for_parse_state->depth; |
44773 | |
44774 | /* We have already matched the FOR token but not consumed it yet. */ |
44775 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)); |
44776 | loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
44777 | |
44778 | /* Forbid break/continue in the loop initializer, condition, and |
44779 | increment expressions. */ |
44780 | save_in_statement = parser->in_statement; |
44781 | parser->in_statement = IN_OMP_BLOCK; |
44782 | |
44783 | /* We are not in intervening code now. */ |
44784 | omp_for_parse_state->in_intervening_code = false; |
44785 | |
44786 | /* Don't create location wrapper nodes within an OpenMP "for" |
44787 | statement. */ |
44788 | auto_suppress_location_wrappers sentinel; |
44789 | |
44790 | matching_parens parens; |
44791 | if (!parens.require_open (parser)) |
44792 | return NULL; |
44793 | |
44794 | init = orig_init = decl = real_decl = orig_decl = NULL_TREE; |
44795 | |
44796 | init_placeholder = build_stmt (input_location, EXPR_STMT, |
44797 | integer_zero_node); |
44798 | vec_safe_push (r&: omp_for_parse_state->init_placeholderv, t: init_placeholder); |
44799 | |
44800 | /* The init_block acts as a container for this level of loop goo. */ |
44801 | init_block = push_stmt_list (); |
44802 | vec_safe_push (r&: omp_for_parse_state->init_blockv, t: init_block); |
44803 | |
44804 | /* Wrap a scope around this entire level of loop to hold bindings |
44805 | of loop iteration variables. We can't insert them directly |
44806 | in the containing scope because that would cause their visibility to |
44807 | be incorrect with respect to intervening code after this loop. |
44808 | We will combine the nested init_scopes in postprocessing after the |
44809 | entire loop is parsed. */ |
44810 | init_scope = begin_compound_stmt (0); |
44811 | |
44812 | /* Now we need another level of statement list container to capture the |
44813 | initialization (and possible finalization) bits. In some cases this |
44814 | container may be popped off during initializer parsing to store code in |
44815 | INIT or THIS_PRE_BODY, depending on the form of initialization. If |
44816 | we have a class iterator we will pop it at the end of parsing this |
44817 | level, so the cleanups are handled correctly. */ |
44818 | sl = push_stmt_list (); |
44819 | |
44820 | if (omp_for_parse_state->code != OACC_LOOP && cxx_dialect >= cxx11) |
44821 | { |
44822 | /* Save tokens so that we can put them back. */ |
44823 | cp_lexer_save_tokens (lexer: parser->lexer); |
44824 | |
44825 | /* Look for ':' that is not nested in () or {}. */ |
44826 | is_range_for |
44827 | = (cp_parser_skip_to_closing_parenthesis_1 (parser, |
44828 | /*recovering=*/false, |
44829 | or_ttype: CPP_COLON, |
44830 | /*consume_paren=*/ |
44831 | false) == -1); |
44832 | |
44833 | /* Roll back the tokens we skipped. */ |
44834 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
44835 | |
44836 | if (is_range_for) |
44837 | { |
44838 | bool saved_colon_corrects_to_scope_p |
44839 | = parser->colon_corrects_to_scope_p; |
44840 | |
44841 | /* A colon is used in range-based for. */ |
44842 | parser->colon_corrects_to_scope_p = false; |
44843 | |
44844 | /* Parse the declaration. */ |
44845 | cp_parser_simple_declaration (parser, |
44846 | /*function_definition_allowed_p=*/ |
44847 | false, maybe_range_for_decl: &decl); |
44848 | parser->colon_corrects_to_scope_p |
44849 | = saved_colon_corrects_to_scope_p; |
44850 | |
44851 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
44852 | |
44853 | init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, range_decl: decl, |
44854 | ivdep: false, NULL_TREE, novector: false, is_omp: true); |
44855 | |
44856 | cp_convert_omp_range_for (this_pre_body, sl, decl, |
44857 | orig_decl, init, orig_init, |
44858 | cond, incr); |
44859 | |
44860 | if (omp_for_parse_state->ordered_cl) |
44861 | error_at (OMP_CLAUSE_LOCATION (omp_for_parse_state->ordered_cl), |
44862 | "%<ordered%> clause with parameter on " |
44863 | "range-based %<for%> loop" ); |
44864 | |
44865 | goto parse_close_paren; |
44866 | } |
44867 | } |
44868 | |
44869 | add_private_clause |
44870 | = cp_parser_omp_for_loop_init (parser, this_pre_body, sl, |
44871 | init, orig_init, decl, real_decl); |
44872 | |
44873 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
44874 | |
44875 | /* If the iteration variable was introduced via a declaration in the |
44876 | for statement, DECL points at it. Otherwise DECL is null and |
44877 | REAL_DECL is a variable previously declared in an outer scope. |
44878 | Make REAL_DECL point at the iteration variable no matter where it |
44879 | was introduced. */ |
44880 | if (decl) |
44881 | real_decl = decl; |
44882 | |
44883 | /* Some clauses treat iterator variables specially. */ |
44884 | if (omp_for_parse_state->cclauses != NULL |
44885 | && omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL |
44886 | && real_decl != NULL_TREE |
44887 | && omp_for_parse_state->code != OMP_LOOP) |
44888 | { |
44889 | tree *c; |
44890 | for (c = &(omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]); |
44891 | *c ; ) |
44892 | if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE |
44893 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44894 | { |
44895 | error_at (loc, "iteration variable %qD" |
44896 | " should not be firstprivate" , real_decl); |
44897 | *c = OMP_CLAUSE_CHAIN (*c); |
44898 | } |
44899 | else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE |
44900 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44901 | { |
44902 | /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ |
44903 | tree l = *c; |
44904 | *c = OMP_CLAUSE_CHAIN (*c); |
44905 | if (omp_for_parse_state->code == OMP_SIMD) |
44906 | { |
44907 | OMP_CLAUSE_CHAIN (l) |
44908 | = omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
44909 | omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l; |
44910 | } |
44911 | else |
44912 | { |
44913 | OMP_CLAUSE_CHAIN (l) = omp_for_parse_state->clauses; |
44914 | omp_for_parse_state->clauses = l; |
44915 | } |
44916 | add_private_clause = NULL_TREE; |
44917 | } |
44918 | else |
44919 | { |
44920 | if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE |
44921 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44922 | add_private_clause = NULL_TREE; |
44923 | c = &OMP_CLAUSE_CHAIN (*c); |
44924 | } |
44925 | } |
44926 | |
44927 | if (add_private_clause) |
44928 | { |
44929 | tree c; |
44930 | for (c = omp_for_parse_state->clauses; c ; c = OMP_CLAUSE_CHAIN (c)) |
44931 | { |
44932 | if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE |
44933 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) |
44934 | && OMP_CLAUSE_DECL (c) == decl) |
44935 | break; |
44936 | else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE |
44937 | && OMP_CLAUSE_DECL (c) == decl) |
44938 | error_at (loc, "iteration variable %qD " |
44939 | "should not be firstprivate" , |
44940 | decl); |
44941 | else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION |
44942 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) |
44943 | && OMP_CLAUSE_DECL (c) == decl) |
44944 | error_at (loc, "iteration variable %qD should not be reduction" , |
44945 | decl); |
44946 | } |
44947 | if (c == NULL) |
44948 | { |
44949 | if ((omp_for_parse_state->code == OMP_SIMD |
44950 | && omp_for_parse_state->count != 1) |
44951 | || omp_for_parse_state->code == OMP_LOOP) |
44952 | c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE); |
44953 | else if (omp_for_parse_state->code != OMP_SIMD) |
44954 | c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE); |
44955 | else |
44956 | c = build_omp_clause (loc, OMP_CLAUSE_LINEAR); |
44957 | OMP_CLAUSE_DECL (c) = add_private_clause; |
44958 | c = finish_omp_clauses (c, C_ORT_OMP); |
44959 | if (c) |
44960 | { |
44961 | OMP_CLAUSE_CHAIN (c) = omp_for_parse_state->clauses; |
44962 | omp_for_parse_state->clauses = c; |
44963 | /* For linear, signal that we need to fill up |
44964 | the so far unknown linear step. */ |
44965 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR) |
44966 | OMP_CLAUSE_LINEAR_STEP (c) = NULL_TREE; |
44967 | } |
44968 | } |
44969 | } |
44970 | |
44971 | cond = NULL; |
44972 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
44973 | cond = cp_parser_omp_for_cond (parser, decl, code: omp_for_parse_state->code); |
44974 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
44975 | |
44976 | incr = NULL; |
44977 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
44978 | { |
44979 | /* If decl is an iterator, preserve the operator on decl |
44980 | until finish_omp_for. */ |
44981 | if (real_decl |
44982 | && ((processing_template_decl |
44983 | && (TREE_TYPE (real_decl) == NULL_TREE |
44984 | || !INDIRECT_TYPE_P (TREE_TYPE (real_decl)))) |
44985 | || CLASS_TYPE_P (TREE_TYPE (real_decl)))) |
44986 | incr = cp_parser_omp_for_incr (parser, decl: real_decl); |
44987 | else |
44988 | incr = cp_parser_expression (parser); |
44989 | protected_set_expr_location_if_unset (incr, input_location); |
44990 | } |
44991 | |
44992 | parse_close_paren: |
44993 | if (!parens.require_close (parser)) |
44994 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
44995 | /*or_comma=*/false, |
44996 | /*consume_paren=*/true); |
44997 | |
44998 | /* We've parsed all the for (...) stuff now. Store the bits. */ |
44999 | TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl; |
45000 | TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init; |
45001 | TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond; |
45002 | TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr; |
45003 | if (orig_init) |
45004 | { |
45005 | omp_for_parse_state->orig_inits.safe_grow_cleared (len: depth + 1, exact: true); |
45006 | omp_for_parse_state->orig_inits[depth] = orig_init; |
45007 | } |
45008 | if (orig_decl) |
45009 | { |
45010 | if (!omp_for_parse_state->orig_declv) |
45011 | omp_for_parse_state->orig_declv |
45012 | = copy_node (omp_for_parse_state->declv); |
45013 | TREE_VEC_ELT (omp_for_parse_state->orig_declv, depth) = orig_decl; |
45014 | } |
45015 | else if (omp_for_parse_state->orig_declv) |
45016 | TREE_VEC_ELT (omp_for_parse_state->orig_declv, depth) = decl; |
45017 | if (this_pre_body) |
45018 | append_to_statement_list_force (this_pre_body, |
45019 | &(omp_for_parse_state->pre_body)); |
45020 | |
45021 | /* Start a nested block for the loop body. */ |
45022 | body_placeholder = build_stmt (input_location, EXPR_STMT, |
45023 | integer_zero_node); |
45024 | vec_safe_push (r&: omp_for_parse_state->body_placeholderv, t: body_placeholder); |
45025 | body_block = push_stmt_list (); |
45026 | vec_safe_push (r&: omp_for_parse_state->body_blockv, t: body_block); |
45027 | |
45028 | moreloops = depth < omp_for_parse_state->count - 1; |
45029 | omp_for_parse_state->want_nested_loop = moreloops; |
45030 | if (moreloops && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
45031 | { |
45032 | omp_for_parse_state->depth++; |
45033 | add_stmt (cp_parser_omp_loop_nest (parser, if_p)); |
45034 | omp_for_parse_state->depth--; |
45035 | } |
45036 | else if (moreloops |
45037 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
45038 | { |
45039 | /* This is the open brace in the loop-body grammar production. Rather |
45040 | than trying to special-case braces, just parse it as a compound |
45041 | statement and handle the nested loop-body case there. Note that |
45042 | when we see a further open brace inside the compound statement |
45043 | loop-body, we don't know whether it is the start of intervening |
45044 | code that is a compound statement, or a level of braces |
45045 | surrounding a nested loop-body. Use the WANT_NESTED_LOOP state |
45046 | bit to ensure we have only one nested loop at each level. */ |
45047 | |
45048 | omp_for_parse_state->in_intervening_code = true; |
45049 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
45050 | omp_for_parse_state->in_intervening_code = false; |
45051 | |
45052 | if (omp_for_parse_state->want_nested_loop) |
45053 | { |
45054 | /* We have already parsed the whole loop body and not found a |
45055 | nested loop. */ |
45056 | error_at (omp_for_parse_state->for_loc, |
45057 | "not enough nested loops" ); |
45058 | omp_for_parse_state->fail = true; |
45059 | } |
45060 | if_p = NULL; |
45061 | } |
45062 | else |
45063 | { |
45064 | /* This is the final-loop-body case in the grammar: we have something |
45065 | that is not a FOR and not an open brace. */ |
45066 | if (moreloops) |
45067 | { |
45068 | /* If we were expecting a nested loop, give an error and mark |
45069 | that parsing has failed, and try to recover by parsing the |
45070 | body as regular code without further collapsing. */ |
45071 | error_at (omp_for_parse_state->for_loc, |
45072 | "not enough nested loops" ); |
45073 | omp_for_parse_state->fail = true; |
45074 | } |
45075 | parser->in_statement = IN_OMP_FOR; |
45076 | |
45077 | /* Generate the parts of range for that belong in the loop body, |
45078 | to be executed on every iteration. This includes setting the |
45079 | user-declared decomposition variables from the compiler-generated |
45080 | temporaries that are the real iteration variables for OMP_FOR. |
45081 | FIXME: Not sure if this is correct with respect to visibility |
45082 | of the variables from intervening code. However, putting this |
45083 | code in each level of loop instead of all around the innermost |
45084 | body also makes the decomposition variables visible to the |
45085 | inner for init/bound/step exressions, which is not supposed to |
45086 | happen and causes test failures. */ |
45087 | if (omp_for_parse_state->orig_declv) |
45088 | for (int i = 0; i < omp_for_parse_state->count; i++) |
45089 | { |
45090 | tree o = TREE_VEC_ELT (omp_for_parse_state->orig_declv, i); |
45091 | tree d = TREE_VEC_ELT (omp_for_parse_state->declv, i); |
45092 | if (o != d) |
45093 | cp_finish_omp_range_for (orig: o, begin: d); |
45094 | } |
45095 | |
45096 | /* Now parse the final-loop-body for the innermost loop. */ |
45097 | parser->omp_for_parse_state = NULL; |
45098 | if (omp_for_parse_state->inscan) |
45099 | cp_parser_omp_scan_loop_body (parser); |
45100 | else |
45101 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
45102 | parser->omp_for_parse_state = omp_for_parse_state; |
45103 | } |
45104 | parser->in_statement = save_in_statement; |
45105 | omp_for_parse_state->want_nested_loop = false; |
45106 | omp_for_parse_state->in_intervening_code = true; |
45107 | |
45108 | /* Pop and remember the body block. Add the body placeholder |
45109 | to the surrounding statement list instead. This is just a unique |
45110 | token that will be replaced when we reassemble the generated |
45111 | code for the entire omp for statement. */ |
45112 | body_block = pop_stmt_list (body_block); |
45113 | omp_for_parse_state->body_blockv[depth] = body_block; |
45114 | add_stmt (body_placeholder); |
45115 | |
45116 | /* Pop and remember the init block. */ |
45117 | if (sl) |
45118 | add_stmt (pop_stmt_list (sl)); |
45119 | finish_compound_stmt (init_scope); |
45120 | init_block = pop_stmt_list (init_block); |
45121 | omp_for_parse_state->init_blockv[depth] = init_block; |
45122 | |
45123 | /* Return the init placeholder rather than the remembered init block. |
45124 | Again, this is just a unique cookie that will be used to reassemble |
45125 | code pieces when the entire omp for statement has been parsed. */ |
45126 | return init_placeholder; |
45127 | } |
45128 | |
45129 | /* Worker for find_structured_blocks. *TP points to a STATEMENT_LIST |
45130 | and ITER is the element that is or contains a nested loop. This |
45131 | function moves the statements before and after ITER into |
45132 | OMP_STRUCTURED_BLOCKs and modifies *TP. */ |
45133 | static void |
45134 | insert_structured_blocks (tree *tp, tree_stmt_iterator iter) |
45135 | { |
45136 | tree sl = push_stmt_list (); |
45137 | for (tree_stmt_iterator i = tsi_start (t: *tp); !tsi_end_p (i); ) |
45138 | if (i == iter) |
45139 | { |
45140 | sl = pop_stmt_list (sl); |
45141 | if (TREE_CODE (sl) != STATEMENT_LIST || !tsi_end_p (i: tsi_start (t: sl))) |
45142 | tsi_link_before (&i, |
45143 | build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl), |
45144 | TSI_SAME_STMT); |
45145 | i++; |
45146 | sl = push_stmt_list (); |
45147 | } |
45148 | else |
45149 | { |
45150 | tree s = tsi_stmt (i); |
45151 | tsi_delink (&i); /* Advances i to next statement. */ |
45152 | add_stmt (s); |
45153 | } |
45154 | sl = pop_stmt_list (sl); |
45155 | if (TREE_CODE (sl) != STATEMENT_LIST || !tsi_end_p (i: tsi_start (t: sl))) |
45156 | tsi_link_after (&iter, |
45157 | build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl), |
45158 | TSI_SAME_STMT); |
45159 | } |
45160 | |
45161 | /* Helper to find and mark structured blocks in intervening code for a |
45162 | single loop level with markers for later error checking. *TP is the |
45163 | piece of code to be marked and INNER is the inner loop placeholder. |
45164 | Returns true if INNER was found (recursively) in *TP. */ |
45165 | static bool |
45166 | find_structured_blocks (tree *tp, tree inner) |
45167 | { |
45168 | if (*tp == inner) |
45169 | return true; |
45170 | else if (TREE_CODE (*tp) == BIND_EXPR) |
45171 | return find_structured_blocks (tp: &(BIND_EXPR_BODY (*tp)), inner); |
45172 | else if (TREE_CODE (*tp) == STATEMENT_LIST) |
45173 | { |
45174 | for (tree_stmt_iterator i = tsi_start (t: *tp); !tsi_end_p (i); ++i) |
45175 | { |
45176 | tree *p = tsi_stmt_ptr (i); |
45177 | /* The normal case is that there is no intervening code and we |
45178 | do not have to insert any OMP_STRUCTURED_BLOCK markers. */ |
45179 | if (find_structured_blocks (tp: p, inner)) |
45180 | { |
45181 | if (!(i == tsi_start (t: *tp) && i == tsi_last (t: *tp))) |
45182 | insert_structured_blocks (tp, iter: i); |
45183 | return true; |
45184 | } |
45185 | } |
45186 | return false; |
45187 | } |
45188 | else if (TREE_CODE (*tp) == TRY_FINALLY_EXPR) |
45189 | return find_structured_blocks (tp: &(TREE_OPERAND (*tp, 0)), inner); |
45190 | else if (TREE_CODE (*tp) == CLEANUP_STMT) |
45191 | return find_structured_blocks (tp: &(CLEANUP_BODY (*tp)), inner); |
45192 | else |
45193 | return false; |
45194 | } |
45195 | |
45196 | /* Helpers used for relinking tree structures: In tree rooted at |
45197 | CONTEXT, replace ORIG with REPLACEMENT. If FLATTEN is true, try to combine |
45198 | nested BIND_EXPRs. Gives an assertion if it fails to find ORIG. */ |
45199 | |
45200 | struct sit_data { |
45201 | tree orig; |
45202 | tree repl; |
45203 | bool flatten; |
45204 | }; |
45205 | |
45206 | static tree |
45207 | substitute_in_tree_walker (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, |
45208 | void *dp) |
45209 | { |
45210 | struct sit_data *sit = (struct sit_data *)dp; |
45211 | if (*tp == sit->orig) |
45212 | { |
45213 | *tp = sit->repl; |
45214 | return *tp; |
45215 | } |
45216 | /* Remove redundant BIND_EXPRs with no bindings even when not specifically |
45217 | trying to flatten. */ |
45218 | else if (TREE_CODE (*tp) == BIND_EXPR |
45219 | && BIND_EXPR_BODY (*tp) == sit->orig |
45220 | && !BIND_EXPR_VARS (*tp) |
45221 | && (sit->flatten || TREE_CODE (sit->repl) == BIND_EXPR)) |
45222 | { |
45223 | *tp = sit->repl; |
45224 | return *tp; |
45225 | } |
45226 | else if (sit->flatten |
45227 | && TREE_CODE (*tp) == BIND_EXPR |
45228 | && TREE_CODE (sit->repl) == BIND_EXPR) |
45229 | { |
45230 | if (BIND_EXPR_BODY (*tp) == sit->orig) |
45231 | { |
45232 | /* Merge binding lists for two directly nested BIND_EXPRs, |
45233 | keeping the outer one. */ |
45234 | BIND_EXPR_VARS (*tp) = chainon (BIND_EXPR_VARS (*tp), |
45235 | BIND_EXPR_VARS (sit->repl)); |
45236 | BIND_EXPR_BODY (*tp) = BIND_EXPR_BODY (sit->repl); |
45237 | return *tp; |
45238 | } |
45239 | else if (TREE_CODE (BIND_EXPR_BODY (*tp)) == STATEMENT_LIST) |
45240 | /* There might be a statement list containing cleanup_points |
45241 | etc between the two levels of BIND_EXPR. We can still merge |
45242 | them, again keeping the outer BIND_EXPR. */ |
45243 | for (tree_stmt_iterator i = tsi_start (BIND_EXPR_BODY (*tp)); |
45244 | !tsi_end_p (i); ++i) |
45245 | { |
45246 | tree *p = tsi_stmt_ptr (i); |
45247 | if (*p == sit->orig) |
45248 | { |
45249 | BIND_EXPR_VARS (*tp) = chainon (BIND_EXPR_VARS (*tp), |
45250 | BIND_EXPR_VARS (sit->repl)); |
45251 | *p = BIND_EXPR_BODY (sit->repl); |
45252 | return *tp; |
45253 | } |
45254 | } |
45255 | } |
45256 | return NULL; |
45257 | } |
45258 | |
45259 | static void |
45260 | substitute_in_tree (tree *context, tree orig, tree repl, bool flatten) |
45261 | { |
45262 | struct sit_data data; |
45263 | |
45264 | gcc_assert (*context && orig && repl); |
45265 | if (TREE_CODE (repl) == BIND_EXPR && !BIND_EXPR_VARS (repl)) |
45266 | repl = BIND_EXPR_BODY (repl); |
45267 | data.orig = orig; |
45268 | data.repl = repl; |
45269 | data.flatten = flatten; |
45270 | |
45271 | tree result = cp_walk_tree (context, substitute_in_tree_walker, |
45272 | (void *)&data, NULL); |
45273 | gcc_assert (result != NULL_TREE); |
45274 | } |
45275 | |
45276 | /* Walker to patch up the BLOCK_NODE hierarchy after the above surgery. |
45277 | *DP is the parent block. */ |
45278 | |
45279 | static tree |
45280 | fixup_blocks_walker (tree *tp, int *walk_subtrees, void *dp) |
45281 | { |
45282 | tree superblock = *(tree *)dp; |
45283 | |
45284 | /* BIND_EXPR_BLOCK may be null if the expression is not a |
45285 | full-expression; if there's no block, no patching is necessary |
45286 | for this node. */ |
45287 | if (TREE_CODE (*tp) == BIND_EXPR && BIND_EXPR_BLOCK (*tp)) |
45288 | { |
45289 | tree block = BIND_EXPR_BLOCK (*tp); |
45290 | if (superblock) |
45291 | { |
45292 | BLOCK_SUPERCONTEXT (block) = superblock; |
45293 | BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (superblock); |
45294 | BLOCK_SUBBLOCKS (superblock) = block; |
45295 | } |
45296 | BLOCK_SUBBLOCKS (block) = NULL_TREE; |
45297 | cp_walk_tree (&BIND_EXPR_BODY (*tp), fixup_blocks_walker, |
45298 | (void *)&block, NULL); |
45299 | *walk_subtrees = 0; |
45300 | } |
45301 | |
45302 | return NULL; |
45303 | } |
45304 | |
45305 | /* Parse the restricted form of the for statement allowed by OpenMP. */ |
45306 | |
45307 | static tree |
45308 | cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, |
45309 | tree *cclauses, bool *if_p) |
45310 | { |
45311 | tree ret; |
45312 | tree cl, ordered_cl = NULL_TREE; |
45313 | int collapse = 1, ordered = 0; |
45314 | unsigned int count; |
45315 | bool tiling = false; |
45316 | bool inscan = false; |
45317 | struct omp_for_parse_data data; |
45318 | struct omp_for_parse_data *save_data = parser->omp_for_parse_state; |
45319 | tree result; |
45320 | location_t loc_first = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45321 | |
45322 | for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) |
45323 | if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) |
45324 | collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); |
45325 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE) |
45326 | { |
45327 | tiling = true; |
45328 | collapse = list_length (OMP_CLAUSE_TILE_LIST (cl)); |
45329 | } |
45330 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED |
45331 | && OMP_CLAUSE_ORDERED_EXPR (cl)) |
45332 | { |
45333 | ordered_cl = cl; |
45334 | ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); |
45335 | } |
45336 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION |
45337 | && OMP_CLAUSE_REDUCTION_INSCAN (cl) |
45338 | && (code == OMP_SIMD || code == OMP_FOR)) |
45339 | inscan = true; |
45340 | |
45341 | if (ordered && ordered < collapse) |
45342 | { |
45343 | error_at (OMP_CLAUSE_LOCATION (ordered_cl), |
45344 | "%<ordered%> clause parameter is less than %<collapse%>" ); |
45345 | OMP_CLAUSE_ORDERED_EXPR (ordered_cl) |
45346 | = build_int_cst (NULL_TREE, collapse); |
45347 | ordered = collapse; |
45348 | } |
45349 | |
45350 | gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); |
45351 | count = ordered ? ordered : collapse; |
45352 | |
45353 | if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
45354 | { |
45355 | cp_parser_error (parser, gmsgid: "for statement expected" ); |
45356 | return NULL; |
45357 | } |
45358 | |
45359 | /* Initialize parse state for recursive descent. */ |
45360 | data.declv = make_tree_vec (count); |
45361 | data.initv = make_tree_vec (count); |
45362 | data.condv = make_tree_vec (count); |
45363 | data.incrv = make_tree_vec (count); |
45364 | data.pre_body = NULL_TREE; |
45365 | data.for_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45366 | data.count = count; |
45367 | data.depth = 0; |
45368 | data.want_nested_loop = true; |
45369 | data.ordered = ordered > 0; |
45370 | data.in_intervening_code = false; |
45371 | data.perfect_nesting_fail = false; |
45372 | data.fail = false; |
45373 | data.inscan = inscan; |
45374 | data.saw_intervening_code = false; |
45375 | data.code = code; |
45376 | data.orig_declv = NULL_TREE; |
45377 | data.clauses = clauses; |
45378 | data.cclauses = cclauses; |
45379 | data.ordered_cl = ordered_cl; |
45380 | parser->omp_for_parse_state = &data; |
45381 | |
45382 | cp_parser_omp_loop_nest (parser, if_p); |
45383 | |
45384 | /* Bomb out early if there was an error (not enough loops, etc). */ |
45385 | if (data.fail || data.declv == NULL_TREE) |
45386 | { |
45387 | parser->omp_for_parse_state = save_data; |
45388 | return NULL_TREE; |
45389 | } |
45390 | |
45391 | /* Relink the init and body blocks that were built during parsing. At |
45392 | this point we have a structure nested like |
45393 | init 0 |
45394 | body 0 |
45395 | init 1 |
45396 | body 1 |
45397 | init 2 |
45398 | body 2 |
45399 | and we want to turn it into |
45400 | init 0 |
45401 | init 1 |
45402 | init 2 |
45403 | omp_for |
45404 | body 0 |
45405 | body 1 |
45406 | body 2 |
45407 | We also need to flatten the init blocks, as some code for later |
45408 | processing of combined directives gets confused otherwise. */ |
45409 | |
45410 | gcc_assert (vec_safe_length (data.init_blockv) == count); |
45411 | gcc_assert (vec_safe_length (data.body_blockv) == count); |
45412 | gcc_assert (vec_safe_length (data.init_placeholderv) == count); |
45413 | gcc_assert (vec_safe_length (data.body_placeholderv) == count); |
45414 | |
45415 | /* First insert markers for structured blocks for intervening code in |
45416 | the loop bodies. */ |
45417 | for (unsigned int i = 0; i < count - 1; i++) |
45418 | { |
45419 | bool good = find_structured_blocks (tp: &(data.body_blockv[i]), |
45420 | inner: data.init_placeholderv[i+1]); |
45421 | gcc_assert (good); |
45422 | } |
45423 | |
45424 | /* Do the substitution from the inside out. */ |
45425 | for (unsigned int i = count - 1; i > 0; i--) |
45426 | { |
45427 | substitute_in_tree (context: &(data.body_blockv[i-1]), |
45428 | orig: data.init_placeholderv[i], |
45429 | repl: data.body_blockv[i], flatten: false); |
45430 | substitute_in_tree (context: &(data.init_blockv[i-1]), |
45431 | orig: data.body_placeholderv[i-1], |
45432 | repl: data.init_blockv[i], flatten: true); |
45433 | } |
45434 | |
45435 | /* Generate the OMP_FOR. Note finish_omp_for adds the OMP_FOR |
45436 | (and possibly other stuff) to the current statement list but |
45437 | returns a pointer to the OMP_FOR itself, or null in case of error. */ |
45438 | result = push_stmt_list (); |
45439 | ret = finish_omp_for (loc_first, code, data.declv, data.orig_declv, |
45440 | data.initv, data.condv, data.incrv, |
45441 | data.body_blockv[0], |
45442 | data.pre_body, &data.orig_inits, data.clauses); |
45443 | result = pop_stmt_list (result); |
45444 | |
45445 | /* Check for errors involving lb/ub/incr expressions referencing |
45446 | variables declared in intervening code. */ |
45447 | if (data.saw_intervening_code |
45448 | && !c_omp_check_loop_binding_exprs (ret, &data.orig_inits)) |
45449 | ret = NULL_TREE; |
45450 | |
45451 | if (ret) |
45452 | { |
45453 | /* Splice the omp_for into the nest of init blocks. */ |
45454 | substitute_in_tree (context: &(data.init_blockv[0]), |
45455 | orig: data.body_placeholderv[count - 1], |
45456 | repl: result, flatten: true); |
45457 | |
45458 | /* Some later processing for combined directives assumes |
45459 | that the BIND_EXPR containing range for variables appears |
45460 | at top level in the OMP_FOR body. Fix that up if it's |
45461 | not the case, e.g. because there is intervening code. */ |
45462 | if (code != OACC_LOOP) |
45463 | finish_omp_for_block (data.init_blockv[0], ret); |
45464 | |
45465 | /* Clean up the block subblock/superblock links. Per comment in |
45466 | begin_compound_stmt, "we don't build BLOCK nodes when processing |
45467 | templates", so skip this step in that case. */ |
45468 | if (!processing_template_decl) |
45469 | { |
45470 | tree superblock = NULL_TREE; |
45471 | cp_walk_tree (&data.init_blockv[0], fixup_blocks_walker, |
45472 | (void *)&superblock, NULL); |
45473 | } |
45474 | |
45475 | /* Finally record the result. */ |
45476 | add_stmt (data.init_blockv[0]); |
45477 | } |
45478 | |
45479 | parser->omp_for_parse_state = save_data; |
45480 | return ret; |
45481 | } |
45482 | |
45483 | /* Helper function for OpenMP parsing, split clauses and call |
45484 | finish_omp_clauses on each of the set of clauses afterwards. */ |
45485 | |
45486 | static void |
45487 | cp_omp_split_clauses (location_t loc, enum tree_code code, |
45488 | omp_clause_mask mask, tree clauses, tree *cclauses) |
45489 | { |
45490 | int i; |
45491 | c_omp_split_clauses (loc, code, mask, clauses, cclauses); |
45492 | for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) |
45493 | if (cclauses[i]) |
45494 | cclauses[i] = finish_omp_clauses (cclauses[i], |
45495 | i == C_OMP_CLAUSE_SPLIT_TARGET |
45496 | ? C_ORT_OMP_TARGET : C_ORT_OMP); |
45497 | } |
45498 | |
45499 | /* OpenMP 5.0: |
45500 | #pragma omp loop loop-clause[optseq] new-line |
45501 | for-loop */ |
45502 | |
45503 | #define OMP_LOOP_CLAUSE_MASK \ |
45504 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45505 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45506 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45507 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
45508 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \ |
45509 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
45510 | |
45511 | static tree |
45512 | cp_parser_omp_loop (cp_parser *parser, cp_token *pragma_tok, |
45513 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45514 | bool *if_p) |
45515 | { |
45516 | tree clauses, sb, ret; |
45517 | unsigned int save; |
45518 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45519 | |
45520 | strcat (dest: p_name, src: " loop" ); |
45521 | mask |= OMP_LOOP_CLAUSE_MASK; |
45522 | |
45523 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45524 | finish_p: cclauses == NULL); |
45525 | if (cclauses) |
45526 | { |
45527 | cp_omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses); |
45528 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP]; |
45529 | } |
45530 | |
45531 | keep_next_level (true); |
45532 | sb = begin_omp_structured_block (); |
45533 | save = cp_parser_begin_omp_structured_block (parser); |
45534 | |
45535 | ret = cp_parser_omp_for_loop (parser, code: OMP_LOOP, clauses, cclauses, if_p); |
45536 | |
45537 | cp_parser_end_omp_structured_block (parser, save); |
45538 | add_stmt (finish_omp_structured_block (sb)); |
45539 | |
45540 | return ret; |
45541 | } |
45542 | |
45543 | /* OpenMP 4.0: |
45544 | #pragma omp simd simd-clause[optseq] new-line |
45545 | for-loop */ |
45546 | |
45547 | #define OMP_SIMD_CLAUSE_MASK \ |
45548 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \ |
45549 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ |
45550 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
45551 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ |
45552 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45553 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45554 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45555 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
45556 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
45557 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \ |
45558 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
45559 | |
45560 | static tree |
45561 | cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, |
45562 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45563 | bool *if_p) |
45564 | { |
45565 | tree clauses, sb, ret; |
45566 | unsigned int save; |
45567 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45568 | |
45569 | strcat (dest: p_name, src: " simd" ); |
45570 | mask |= OMP_SIMD_CLAUSE_MASK; |
45571 | |
45572 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45573 | finish_p: cclauses == NULL); |
45574 | if (cclauses) |
45575 | { |
45576 | cp_omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses); |
45577 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; |
45578 | } |
45579 | |
45580 | keep_next_level (true); |
45581 | sb = begin_omp_structured_block (); |
45582 | save = cp_parser_begin_omp_structured_block (parser); |
45583 | |
45584 | ret = cp_parser_omp_for_loop (parser, code: OMP_SIMD, clauses, cclauses, if_p); |
45585 | |
45586 | cp_parser_end_omp_structured_block (parser, save); |
45587 | add_stmt (finish_omp_structured_block (sb)); |
45588 | |
45589 | return ret; |
45590 | } |
45591 | |
45592 | /* OpenMP 2.5: |
45593 | #pragma omp for for-clause[optseq] new-line |
45594 | for-loop |
45595 | |
45596 | OpenMP 4.0: |
45597 | #pragma omp for simd for-simd-clause[optseq] new-line |
45598 | for-loop */ |
45599 | |
45600 | #define OMP_FOR_CLAUSE_MASK \ |
45601 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45602 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45603 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45604 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
45605 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45606 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ |
45607 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ |
45608 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ |
45609 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
45610 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45611 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
45612 | |
45613 | static tree |
45614 | cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok, |
45615 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45616 | bool *if_p) |
45617 | { |
45618 | tree clauses, sb, ret; |
45619 | unsigned int save; |
45620 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45621 | |
45622 | strcat (dest: p_name, src: " for" ); |
45623 | mask |= OMP_FOR_CLAUSE_MASK; |
45624 | /* parallel for{, simd} disallows nowait clause, but for |
45625 | target {teams distribute ,}parallel for{, simd} it should be accepted. */ |
45626 | if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0) |
45627 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); |
45628 | /* Composite distribute parallel for{, simd} disallows ordered clause. */ |
45629 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
45630 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED); |
45631 | |
45632 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45633 | { |
45634 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45635 | const char *p = IDENTIFIER_POINTER (id); |
45636 | |
45637 | if (strcmp (s1: p, s2: "simd" ) == 0) |
45638 | { |
45639 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45640 | if (cclauses == NULL) |
45641 | cclauses = cclauses_buf; |
45642 | |
45643 | cp_lexer_consume_token (lexer: parser->lexer); |
45644 | if (!flag_openmp) /* flag_openmp_simd */ |
45645 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45646 | cclauses, if_p); |
45647 | sb = begin_omp_structured_block (); |
45648 | save = cp_parser_begin_omp_structured_block (parser); |
45649 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45650 | cclauses, if_p); |
45651 | cp_parser_end_omp_structured_block (parser, save); |
45652 | tree body = finish_omp_structured_block (sb); |
45653 | if (ret == NULL) |
45654 | return ret; |
45655 | ret = make_node (OMP_FOR); |
45656 | TREE_TYPE (ret) = void_type_node; |
45657 | OMP_FOR_BODY (ret) = body; |
45658 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
45659 | SET_EXPR_LOCATION (ret, loc); |
45660 | add_stmt (ret); |
45661 | return ret; |
45662 | } |
45663 | } |
45664 | if (!flag_openmp) /* flag_openmp_simd */ |
45665 | { |
45666 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45667 | return NULL_TREE; |
45668 | } |
45669 | |
45670 | /* Composite distribute parallel for disallows linear clause. */ |
45671 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
45672 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR); |
45673 | |
45674 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45675 | finish_p: cclauses == NULL); |
45676 | if (cclauses) |
45677 | { |
45678 | cp_omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses); |
45679 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
45680 | } |
45681 | |
45682 | keep_next_level (true); |
45683 | sb = begin_omp_structured_block (); |
45684 | save = cp_parser_begin_omp_structured_block (parser); |
45685 | |
45686 | ret = cp_parser_omp_for_loop (parser, code: OMP_FOR, clauses, cclauses, if_p); |
45687 | |
45688 | cp_parser_end_omp_structured_block (parser, save); |
45689 | add_stmt (finish_omp_structured_block (sb)); |
45690 | |
45691 | return ret; |
45692 | } |
45693 | |
45694 | static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *, |
45695 | omp_clause_mask, tree *, bool *); |
45696 | |
45697 | /* OpenMP 2.5: |
45698 | # pragma omp master new-line |
45699 | structured-block */ |
45700 | |
45701 | static tree |
45702 | cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, |
45703 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45704 | bool *if_p) |
45705 | { |
45706 | tree clauses, sb, ret; |
45707 | unsigned int save; |
45708 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45709 | |
45710 | strcat (dest: p_name, src: " master" ); |
45711 | |
45712 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45713 | { |
45714 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45715 | const char *p = IDENTIFIER_POINTER (id); |
45716 | |
45717 | if (strcmp (s1: p, s2: "taskloop" ) == 0) |
45718 | { |
45719 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45720 | if (cclauses == NULL) |
45721 | cclauses = cclauses_buf; |
45722 | |
45723 | cp_lexer_consume_token (lexer: parser->lexer); |
45724 | if (!flag_openmp) /* flag_openmp_simd */ |
45725 | return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45726 | cclauses, if_p); |
45727 | sb = begin_omp_structured_block (); |
45728 | save = cp_parser_begin_omp_structured_block (parser); |
45729 | ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45730 | cclauses, if_p); |
45731 | cp_parser_end_omp_structured_block (parser, save); |
45732 | tree body = finish_omp_structured_block (sb); |
45733 | if (ret == NULL) |
45734 | return ret; |
45735 | ret = c_finish_omp_master (loc, body); |
45736 | OMP_MASTER_COMBINED (ret) = 1; |
45737 | return ret; |
45738 | } |
45739 | } |
45740 | if (!flag_openmp) /* flag_openmp_simd */ |
45741 | { |
45742 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45743 | return NULL_TREE; |
45744 | } |
45745 | |
45746 | if (cclauses) |
45747 | { |
45748 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45749 | finish_p: false); |
45750 | cp_omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses); |
45751 | } |
45752 | else |
45753 | cp_parser_require_pragma_eol (parser, pragma_tok); |
45754 | |
45755 | return c_finish_omp_master (loc, |
45756 | cp_parser_omp_structured_block (parser, if_p)); |
45757 | } |
45758 | |
45759 | /* OpenMP 5.1: |
45760 | # pragma omp masked masked-clauses new-line |
45761 | structured-block */ |
45762 | |
45763 | #define OMP_MASKED_CLAUSE_MASK \ |
45764 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER) |
45765 | |
45766 | static tree |
45767 | cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok, |
45768 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45769 | bool *if_p) |
45770 | { |
45771 | tree clauses, sb, ret; |
45772 | unsigned int save; |
45773 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45774 | |
45775 | strcat (dest: p_name, src: " masked" ); |
45776 | mask |= OMP_MASKED_CLAUSE_MASK; |
45777 | |
45778 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45779 | { |
45780 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45781 | const char *p = IDENTIFIER_POINTER (id); |
45782 | |
45783 | if (strcmp (s1: p, s2: "taskloop" ) == 0) |
45784 | { |
45785 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45786 | if (cclauses == NULL) |
45787 | cclauses = cclauses_buf; |
45788 | |
45789 | cp_lexer_consume_token (lexer: parser->lexer); |
45790 | if (!flag_openmp) /* flag_openmp_simd */ |
45791 | return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45792 | cclauses, if_p); |
45793 | sb = begin_omp_structured_block (); |
45794 | save = cp_parser_begin_omp_structured_block (parser); |
45795 | ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45796 | cclauses, if_p); |
45797 | cp_parser_end_omp_structured_block (parser, save); |
45798 | tree body = finish_omp_structured_block (sb); |
45799 | if (ret == NULL) |
45800 | return ret; |
45801 | ret = c_finish_omp_masked (loc, body, |
45802 | cclauses[C_OMP_CLAUSE_SPLIT_MASKED]); |
45803 | OMP_MASKED_COMBINED (ret) = 1; |
45804 | return ret; |
45805 | } |
45806 | } |
45807 | if (!flag_openmp) /* flag_openmp_simd */ |
45808 | { |
45809 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45810 | return NULL_TREE; |
45811 | } |
45812 | |
45813 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45814 | finish_p: cclauses == NULL); |
45815 | if (cclauses) |
45816 | { |
45817 | cp_omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses); |
45818 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED]; |
45819 | } |
45820 | |
45821 | return c_finish_omp_masked (loc, |
45822 | cp_parser_omp_structured_block (parser, if_p), |
45823 | clauses); |
45824 | } |
45825 | |
45826 | /* OpenMP 2.5: |
45827 | # pragma omp ordered new-line |
45828 | structured-block |
45829 | |
45830 | OpenMP 4.5: |
45831 | # pragma omp ordered ordered-clauses new-line |
45832 | structured-block */ |
45833 | |
45834 | #define OMP_ORDERED_CLAUSE_MASK \ |
45835 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ |
45836 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) |
45837 | |
45838 | #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ |
45839 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
45840 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) |
45841 | |
45842 | static bool |
45843 | cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, |
45844 | enum pragma_context context, bool *if_p) |
45845 | { |
45846 | location_t loc = pragma_tok->location; |
45847 | int n = 1; |
45848 | |
45849 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
45850 | n = 2; |
45851 | |
45852 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_NAME)) |
45853 | { |
45854 | tree id = cp_lexer_peek_nth_token (lexer: parser->lexer, n)->u.value; |
45855 | const char *p = IDENTIFIER_POINTER (id); |
45856 | |
45857 | if (strcmp (s1: p, s2: "depend" ) == 0 || strcmp (s1: p, s2: "doacross" ) == 0) |
45858 | { |
45859 | if (!flag_openmp) /* flag_openmp_simd */ |
45860 | { |
45861 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45862 | return false; |
45863 | } |
45864 | if (context == pragma_stmt) |
45865 | { |
45866 | error_at (pragma_tok->location, "%<#pragma omp ordered%> with " |
45867 | "%qs clause may only be used in compound " |
45868 | "statements" , p); |
45869 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45870 | return true; |
45871 | } |
45872 | tree clauses |
45873 | = cp_parser_omp_all_clauses (parser, |
45874 | OMP_ORDERED_DEPEND_CLAUSE_MASK, |
45875 | where: "#pragma omp ordered" , pragma_tok); |
45876 | c_finish_omp_ordered (loc, clauses, NULL_TREE); |
45877 | return false; |
45878 | } |
45879 | } |
45880 | |
45881 | tree clauses |
45882 | = cp_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK, |
45883 | where: "#pragma omp ordered" , pragma_tok); |
45884 | |
45885 | if (!flag_openmp /* flag_openmp_simd */ |
45886 | && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE) |
45887 | return false; |
45888 | |
45889 | c_finish_omp_ordered (loc, clauses, |
45890 | cp_parser_omp_structured_block (parser, if_p)); |
45891 | return true; |
45892 | } |
45893 | |
45894 | /* OpenMP 2.5: |
45895 | |
45896 | section-scope: |
45897 | { section-sequence } |
45898 | |
45899 | section-sequence: |
45900 | section-directive[opt] structured-block |
45901 | section-sequence section-directive structured-block */ |
45902 | |
45903 | static tree |
45904 | cp_parser_omp_sections_scope (cp_parser *parser) |
45905 | { |
45906 | tree stmt, substmt; |
45907 | bool error_suppress = false; |
45908 | cp_token *tok; |
45909 | |
45910 | matching_braces braces; |
45911 | if (!braces.require_open (parser)) |
45912 | return NULL_TREE; |
45913 | |
45914 | stmt = push_stmt_list (); |
45915 | |
45916 | if (cp_parser_pragma_kind (token: cp_lexer_peek_token (lexer: parser->lexer)) |
45917 | != PRAGMA_OMP_SECTION |
45918 | && !cp_parser_omp_section_scan (parser, directive: "section" , tentative: true)) |
45919 | { |
45920 | substmt = cp_parser_omp_structured_block_sequence (parser, |
45921 | kind: PRAGMA_OMP_SECTION); |
45922 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
45923 | add_stmt (substmt); |
45924 | } |
45925 | |
45926 | while (1) |
45927 | { |
45928 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
45929 | if (tok->type == CPP_CLOSE_BRACE) |
45930 | break; |
45931 | if (tok->type == CPP_EOF) |
45932 | break; |
45933 | |
45934 | if (cp_parser_omp_section_scan (parser, directive: "section" , tentative: false)) |
45935 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
45936 | if (cp_parser_pragma_kind (token: tok) == PRAGMA_OMP_SECTION) |
45937 | { |
45938 | cp_lexer_consume_token (lexer: parser->lexer); |
45939 | cp_parser_require_pragma_eol (parser, pragma_tok: tok); |
45940 | error_suppress = false; |
45941 | } |
45942 | else if (!error_suppress) |
45943 | { |
45944 | cp_parser_error (parser, gmsgid: "expected %<#pragma omp section%> or %<}%>" ); |
45945 | error_suppress = true; |
45946 | } |
45947 | |
45948 | substmt = cp_parser_omp_structured_block_sequence (parser, |
45949 | kind: PRAGMA_OMP_SECTION); |
45950 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
45951 | add_stmt (substmt); |
45952 | } |
45953 | braces.require_close (parser); |
45954 | |
45955 | substmt = pop_stmt_list (stmt); |
45956 | |
45957 | stmt = make_node (OMP_SECTIONS); |
45958 | TREE_TYPE (stmt) = void_type_node; |
45959 | OMP_SECTIONS_BODY (stmt) = substmt; |
45960 | |
45961 | add_stmt (stmt); |
45962 | return stmt; |
45963 | } |
45964 | |
45965 | /* OpenMP 2.5: |
45966 | # pragma omp sections sections-clause[optseq] newline |
45967 | sections-scope */ |
45968 | |
45969 | #define OMP_SECTIONS_CLAUSE_MASK \ |
45970 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45971 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45972 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45973 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45974 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45975 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
45976 | |
45977 | static tree |
45978 | cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok, |
45979 | char *p_name, omp_clause_mask mask, tree *cclauses) |
45980 | { |
45981 | tree clauses, ret; |
45982 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45983 | |
45984 | strcat (dest: p_name, src: " sections" ); |
45985 | mask |= OMP_SECTIONS_CLAUSE_MASK; |
45986 | if (cclauses) |
45987 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); |
45988 | |
45989 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45990 | finish_p: cclauses == NULL); |
45991 | if (cclauses) |
45992 | { |
45993 | cp_omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses); |
45994 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]; |
45995 | } |
45996 | |
45997 | ret = cp_parser_omp_sections_scope (parser); |
45998 | if (ret) |
45999 | OMP_SECTIONS_CLAUSES (ret) = clauses; |
46000 | |
46001 | return ret; |
46002 | } |
46003 | |
46004 | /* OpenMP 2.5: |
46005 | # pragma omp parallel parallel-clause[optseq] new-line |
46006 | structured-block |
46007 | # pragma omp parallel for parallel-for-clause[optseq] new-line |
46008 | structured-block |
46009 | # pragma omp parallel sections parallel-sections-clause[optseq] new-line |
46010 | structured-block |
46011 | |
46012 | OpenMP 4.0: |
46013 | # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line |
46014 | structured-block */ |
46015 | |
46016 | #define OMP_PARALLEL_CLAUSE_MASK \ |
46017 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46018 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46019 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46020 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
46021 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
46022 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \ |
46023 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
46024 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \ |
46025 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46026 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) |
46027 | |
46028 | static tree |
46029 | cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, |
46030 | char *p_name, omp_clause_mask mask, tree *cclauses, |
46031 | bool *if_p) |
46032 | { |
46033 | tree stmt, clauses, block; |
46034 | unsigned int save; |
46035 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
46036 | |
46037 | strcat (dest: p_name, src: " parallel" ); |
46038 | mask |= OMP_PARALLEL_CLAUSE_MASK; |
46039 | /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */ |
46040 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0 |
46041 | && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0) |
46042 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN); |
46043 | |
46044 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
46045 | { |
46046 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46047 | if (cclauses == NULL) |
46048 | cclauses = cclauses_buf; |
46049 | |
46050 | cp_lexer_consume_token (lexer: parser->lexer); |
46051 | if (!flag_openmp) /* flag_openmp_simd */ |
46052 | return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses, |
46053 | if_p); |
46054 | block = begin_omp_parallel (); |
46055 | save = cp_parser_begin_omp_structured_block (parser); |
46056 | tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses, |
46057 | if_p); |
46058 | cp_parser_end_omp_structured_block (parser, save); |
46059 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
46060 | block); |
46061 | if (ret == NULL_TREE) |
46062 | return ret; |
46063 | OMP_PARALLEL_COMBINED (stmt) = 1; |
46064 | return stmt; |
46065 | } |
46066 | /* When combined with distribute, parallel has to be followed by for. |
46067 | #pragma omp target parallel is allowed though. */ |
46068 | else if (cclauses |
46069 | && (mask & (OMP_CLAUSE_MASK_1 |
46070 | << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
46071 | { |
46072 | error_at (loc, "expected %<for%> after %qs" , p_name); |
46073 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46074 | return NULL_TREE; |
46075 | } |
46076 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46077 | { |
46078 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46079 | const char *p = IDENTIFIER_POINTER (id); |
46080 | if (cclauses == NULL && strcmp (s1: p, s2: "masked" ) == 0) |
46081 | { |
46082 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46083 | cclauses = cclauses_buf; |
46084 | |
46085 | cp_lexer_consume_token (lexer: parser->lexer); |
46086 | if (!flag_openmp) /* flag_openmp_simd */ |
46087 | return cp_parser_omp_masked (parser, pragma_tok, p_name, mask, |
46088 | cclauses, if_p); |
46089 | block = begin_omp_parallel (); |
46090 | save = cp_parser_begin_omp_structured_block (parser); |
46091 | tree ret = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, |
46092 | cclauses, if_p); |
46093 | cp_parser_end_omp_structured_block (parser, save); |
46094 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
46095 | block); |
46096 | if (ret == NULL_TREE) |
46097 | return ret; |
46098 | /* masked does have just filter clause, but during gimplification |
46099 | isn't represented by a gimplification omp context, so for |
46100 | #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED, |
46101 | so that |
46102 | #pragma omp parallel masked |
46103 | #pragma omp taskloop simd lastprivate (x) |
46104 | isn't confused with |
46105 | #pragma omp parallel masked taskloop simd lastprivate (x) */ |
46106 | if (OMP_MASKED_COMBINED (ret)) |
46107 | OMP_PARALLEL_COMBINED (stmt) = 1; |
46108 | return stmt; |
46109 | } |
46110 | else if (cclauses == NULL && strcmp (s1: p, s2: "master" ) == 0) |
46111 | { |
46112 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46113 | cclauses = cclauses_buf; |
46114 | |
46115 | cp_lexer_consume_token (lexer: parser->lexer); |
46116 | if (!flag_openmp) /* flag_openmp_simd */ |
46117 | return cp_parser_omp_master (parser, pragma_tok, p_name, mask, |
46118 | cclauses, if_p); |
46119 | block = begin_omp_parallel (); |
46120 | save = cp_parser_begin_omp_structured_block (parser); |
46121 | tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask, |
46122 | cclauses, if_p); |
46123 | cp_parser_end_omp_structured_block (parser, save); |
46124 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
46125 | block); |
46126 | if (ret == NULL_TREE) |
46127 | return ret; |
46128 | /* master doesn't have any clauses and during gimplification |
46129 | isn't represented by a gimplification omp context, so for |
46130 | #pragma omp parallel master don't set OMP_PARALLEL_COMBINED, |
46131 | so that |
46132 | #pragma omp parallel master |
46133 | #pragma omp taskloop simd lastprivate (x) |
46134 | isn't confused with |
46135 | #pragma omp parallel master taskloop simd lastprivate (x) */ |
46136 | if (OMP_MASTER_COMBINED (ret)) |
46137 | OMP_PARALLEL_COMBINED (stmt) = 1; |
46138 | return stmt; |
46139 | } |
46140 | else if (strcmp (s1: p, s2: "loop" ) == 0) |
46141 | { |
46142 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46143 | if (cclauses == NULL) |
46144 | cclauses = cclauses_buf; |
46145 | |
46146 | cp_lexer_consume_token (lexer: parser->lexer); |
46147 | if (!flag_openmp) /* flag_openmp_simd */ |
46148 | return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
46149 | cclauses, if_p); |
46150 | block = begin_omp_parallel (); |
46151 | save = cp_parser_begin_omp_structured_block (parser); |
46152 | tree ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
46153 | cclauses, if_p); |
46154 | cp_parser_end_omp_structured_block (parser, save); |
46155 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
46156 | block); |
46157 | if (ret == NULL_TREE) |
46158 | return ret; |
46159 | OMP_PARALLEL_COMBINED (stmt) = 1; |
46160 | return stmt; |
46161 | } |
46162 | else if (!flag_openmp) /* flag_openmp_simd */ |
46163 | { |
46164 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46165 | return NULL_TREE; |
46166 | } |
46167 | else if (cclauses == NULL && strcmp (s1: p, s2: "sections" ) == 0) |
46168 | { |
46169 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46170 | cclauses = cclauses_buf; |
46171 | |
46172 | cp_lexer_consume_token (lexer: parser->lexer); |
46173 | block = begin_omp_parallel (); |
46174 | save = cp_parser_begin_omp_structured_block (parser); |
46175 | cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses); |
46176 | cp_parser_end_omp_structured_block (parser, save); |
46177 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
46178 | block); |
46179 | OMP_PARALLEL_COMBINED (stmt) = 1; |
46180 | return stmt; |
46181 | } |
46182 | } |
46183 | else if (!flag_openmp) /* flag_openmp_simd */ |
46184 | { |
46185 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46186 | return NULL_TREE; |
46187 | } |
46188 | |
46189 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
46190 | finish_p: cclauses == NULL); |
46191 | if (cclauses) |
46192 | { |
46193 | cp_omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses); |
46194 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; |
46195 | } |
46196 | |
46197 | block = begin_omp_parallel (); |
46198 | save = cp_parser_begin_omp_structured_block (parser); |
46199 | parser->omp_attrs_forbidden_p = true; |
46200 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
46201 | cp_parser_end_omp_structured_block (parser, save); |
46202 | stmt = finish_omp_parallel (clauses, block); |
46203 | return stmt; |
46204 | } |
46205 | |
46206 | /* OpenMP 2.5: |
46207 | # pragma omp single single-clause[optseq] new-line |
46208 | structured-block */ |
46209 | |
46210 | #define OMP_SINGLE_CLAUSE_MASK \ |
46211 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46212 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46213 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ |
46214 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46215 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46216 | |
46217 | static tree |
46218 | cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46219 | { |
46220 | tree stmt = make_node (OMP_SINGLE); |
46221 | TREE_TYPE (stmt) = void_type_node; |
46222 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46223 | |
46224 | OMP_SINGLE_CLAUSES (stmt) |
46225 | = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, |
46226 | where: "#pragma omp single" , pragma_tok); |
46227 | OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46228 | |
46229 | return add_stmt (stmt); |
46230 | } |
46231 | |
46232 | /* OpenMP 5.1: |
46233 | # pragma omp scope scope-clause[optseq] new-line |
46234 | structured-block */ |
46235 | |
46236 | #define OMP_SCOPE_CLAUSE_MASK \ |
46237 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46238 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46239 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
46240 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46241 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46242 | |
46243 | static tree |
46244 | cp_parser_omp_scope (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46245 | { |
46246 | tree stmt = make_node (OMP_SCOPE); |
46247 | TREE_TYPE (stmt) = void_type_node; |
46248 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46249 | |
46250 | OMP_SCOPE_CLAUSES (stmt) |
46251 | = cp_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK, |
46252 | where: "#pragma omp scope" , pragma_tok); |
46253 | OMP_SCOPE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46254 | |
46255 | return add_stmt (stmt); |
46256 | } |
46257 | |
46258 | /* OpenMP 3.0: |
46259 | # pragma omp task task-clause[optseq] new-line |
46260 | structured-block */ |
46261 | |
46262 | #define OMP_TASK_CLAUSE_MASK \ |
46263 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46264 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ |
46265 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
46266 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46267 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46268 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
46269 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ |
46270 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ |
46271 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46272 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ |
46273 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46274 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ |
46275 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \ |
46276 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY)) |
46277 | |
46278 | static tree |
46279 | cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46280 | { |
46281 | tree clauses, block; |
46282 | unsigned int save; |
46283 | |
46284 | clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK, |
46285 | where: "#pragma omp task" , pragma_tok); |
46286 | block = begin_omp_task (); |
46287 | save = cp_parser_begin_omp_structured_block (parser); |
46288 | parser->omp_attrs_forbidden_p = true; |
46289 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
46290 | cp_parser_end_omp_structured_block (parser, save); |
46291 | return finish_omp_task (clauses, block); |
46292 | } |
46293 | |
46294 | /* OpenMP 3.0: |
46295 | # pragma omp taskwait new-line |
46296 | |
46297 | OpenMP 5.0: |
46298 | # pragma omp taskwait taskwait-clause[opt] new-line */ |
46299 | |
46300 | #define OMP_TASKWAIT_CLAUSE_MASK \ |
46301 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46302 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46303 | |
46304 | static void |
46305 | cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok) |
46306 | { |
46307 | tree clauses |
46308 | = cp_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK, |
46309 | where: "#pragma omp taskwait" , pragma_tok); |
46310 | |
46311 | if (clauses) |
46312 | { |
46313 | tree stmt = make_node (OMP_TASK); |
46314 | TREE_TYPE (stmt) = void_node; |
46315 | OMP_TASK_CLAUSES (stmt) = clauses; |
46316 | OMP_TASK_BODY (stmt) = NULL_TREE; |
46317 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46318 | add_stmt (stmt); |
46319 | } |
46320 | else |
46321 | finish_omp_taskwait (); |
46322 | } |
46323 | |
46324 | /* OpenMP 3.1: |
46325 | # pragma omp taskyield new-line */ |
46326 | |
46327 | static void |
46328 | cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok) |
46329 | { |
46330 | cp_parser_require_pragma_eol (parser, pragma_tok); |
46331 | finish_omp_taskyield (); |
46332 | } |
46333 | |
46334 | /* OpenMP 4.0: |
46335 | # pragma omp taskgroup new-line |
46336 | structured-block |
46337 | |
46338 | OpenMP 5.0: |
46339 | # pragma omp taskgroup taskgroup-clause[optseq] new-line */ |
46340 | |
46341 | #define OMP_TASKGROUP_CLAUSE_MASK \ |
46342 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46343 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION)) |
46344 | |
46345 | static tree |
46346 | cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46347 | { |
46348 | tree clauses |
46349 | = cp_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK, |
46350 | where: "#pragma omp taskgroup" , pragma_tok); |
46351 | return c_finish_omp_taskgroup (input_location, |
46352 | cp_parser_omp_structured_block (parser, |
46353 | if_p), |
46354 | clauses); |
46355 | } |
46356 | |
46357 | |
46358 | /* OpenMP 2.5: |
46359 | # pragma omp threadprivate (variable-list) */ |
46360 | |
46361 | static void |
46362 | cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok) |
46363 | { |
46364 | tree vars; |
46365 | |
46366 | vars = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
46367 | cp_parser_require_pragma_eol (parser, pragma_tok); |
46368 | |
46369 | finish_omp_threadprivate (vars); |
46370 | } |
46371 | |
46372 | /* OpenMP 4.0: |
46373 | # pragma omp cancel cancel-clause[optseq] new-line */ |
46374 | |
46375 | #define OMP_CANCEL_CLAUSE_MASK \ |
46376 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ |
46377 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ |
46378 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ |
46379 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \ |
46380 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) |
46381 | |
46382 | static void |
46383 | cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok) |
46384 | { |
46385 | tree clauses = cp_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK, |
46386 | where: "#pragma omp cancel" , pragma_tok); |
46387 | finish_omp_cancel (clauses); |
46388 | } |
46389 | |
46390 | /* OpenMP 4.0: |
46391 | # pragma omp cancellation point cancelpt-clause[optseq] new-line */ |
46392 | |
46393 | #define OMP_CANCELLATION_POINT_CLAUSE_MASK \ |
46394 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ |
46395 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ |
46396 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ |
46397 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP)) |
46398 | |
46399 | static bool |
46400 | cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, |
46401 | enum pragma_context context) |
46402 | { |
46403 | tree clauses; |
46404 | bool point_seen = false; |
46405 | |
46406 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46407 | { |
46408 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46409 | const char *p = IDENTIFIER_POINTER (id); |
46410 | |
46411 | if (strcmp (s1: p, s2: "point" ) == 0) |
46412 | { |
46413 | cp_lexer_consume_token (lexer: parser->lexer); |
46414 | point_seen = true; |
46415 | } |
46416 | } |
46417 | if (!point_seen) |
46418 | { |
46419 | cp_parser_error (parser, gmsgid: "expected %<point%>" ); |
46420 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46421 | return false; |
46422 | } |
46423 | |
46424 | if (context != pragma_compound) |
46425 | { |
46426 | if (context == pragma_stmt) |
46427 | error_at (pragma_tok->location, |
46428 | "%<#pragma %s%> may only be used in compound statements" , |
46429 | "omp cancellation point" ); |
46430 | else |
46431 | cp_parser_error (parser, gmsgid: "expected declaration specifiers" ); |
46432 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46433 | return true; |
46434 | } |
46435 | |
46436 | clauses = cp_parser_omp_all_clauses (parser, |
46437 | OMP_CANCELLATION_POINT_CLAUSE_MASK, |
46438 | where: "#pragma omp cancellation point" , |
46439 | pragma_tok); |
46440 | finish_omp_cancellation_point (clauses); |
46441 | return true; |
46442 | } |
46443 | |
46444 | /* OpenMP 4.0: |
46445 | #pragma omp distribute distribute-clause[optseq] new-line |
46446 | for-loop */ |
46447 | |
46448 | #define OMP_DISTRIBUTE_CLAUSE_MASK \ |
46449 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46450 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46451 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
46452 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ |
46453 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46454 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
46455 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
46456 | |
46457 | static tree |
46458 | cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok, |
46459 | char *p_name, omp_clause_mask mask, tree *cclauses, |
46460 | bool *if_p) |
46461 | { |
46462 | tree clauses, sb, ret; |
46463 | unsigned int save; |
46464 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
46465 | |
46466 | strcat (dest: p_name, src: " distribute" ); |
46467 | mask |= OMP_DISTRIBUTE_CLAUSE_MASK; |
46468 | |
46469 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46470 | { |
46471 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46472 | const char *p = IDENTIFIER_POINTER (id); |
46473 | bool simd = false; |
46474 | bool parallel = false; |
46475 | |
46476 | if (strcmp (s1: p, s2: "simd" ) == 0) |
46477 | simd = true; |
46478 | else |
46479 | parallel = strcmp (s1: p, s2: "parallel" ) == 0; |
46480 | if (parallel || simd) |
46481 | { |
46482 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46483 | if (cclauses == NULL) |
46484 | cclauses = cclauses_buf; |
46485 | cp_lexer_consume_token (lexer: parser->lexer); |
46486 | if (!flag_openmp) /* flag_openmp_simd */ |
46487 | { |
46488 | if (simd) |
46489 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
46490 | cclauses, if_p); |
46491 | else |
46492 | return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, |
46493 | cclauses, if_p); |
46494 | } |
46495 | sb = begin_omp_structured_block (); |
46496 | save = cp_parser_begin_omp_structured_block (parser); |
46497 | if (simd) |
46498 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
46499 | cclauses, if_p); |
46500 | else |
46501 | ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, |
46502 | cclauses, if_p); |
46503 | cp_parser_end_omp_structured_block (parser, save); |
46504 | tree body = finish_omp_structured_block (sb); |
46505 | if (ret == NULL) |
46506 | return ret; |
46507 | ret = make_node (OMP_DISTRIBUTE); |
46508 | TREE_TYPE (ret) = void_type_node; |
46509 | OMP_FOR_BODY (ret) = body; |
46510 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; |
46511 | SET_EXPR_LOCATION (ret, loc); |
46512 | add_stmt (ret); |
46513 | return ret; |
46514 | } |
46515 | } |
46516 | if (!flag_openmp) /* flag_openmp_simd */ |
46517 | { |
46518 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46519 | return NULL_TREE; |
46520 | } |
46521 | |
46522 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
46523 | finish_p: cclauses == NULL); |
46524 | if (cclauses) |
46525 | { |
46526 | cp_omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses); |
46527 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; |
46528 | } |
46529 | |
46530 | keep_next_level (true); |
46531 | sb = begin_omp_structured_block (); |
46532 | save = cp_parser_begin_omp_structured_block (parser); |
46533 | |
46534 | ret = cp_parser_omp_for_loop (parser, code: OMP_DISTRIBUTE, clauses, NULL, if_p); |
46535 | |
46536 | cp_parser_end_omp_structured_block (parser, save); |
46537 | add_stmt (finish_omp_structured_block (sb)); |
46538 | |
46539 | return ret; |
46540 | } |
46541 | |
46542 | /* OpenMP 4.0: |
46543 | # pragma omp teams teams-clause[optseq] new-line |
46544 | structured-block */ |
46545 | |
46546 | #define OMP_TEAMS_CLAUSE_MASK \ |
46547 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46548 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46549 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
46550 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
46551 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \ |
46552 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ |
46553 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46554 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)) |
46555 | |
46556 | static tree |
46557 | cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok, |
46558 | char *p_name, omp_clause_mask mask, tree *cclauses, |
46559 | bool *if_p) |
46560 | { |
46561 | tree clauses, sb, ret; |
46562 | unsigned int save; |
46563 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
46564 | |
46565 | strcat (dest: p_name, src: " teams" ); |
46566 | mask |= OMP_TEAMS_CLAUSE_MASK; |
46567 | |
46568 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46569 | { |
46570 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46571 | const char *p = IDENTIFIER_POINTER (id); |
46572 | if (strcmp (s1: p, s2: "distribute" ) == 0) |
46573 | { |
46574 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46575 | if (cclauses == NULL) |
46576 | cclauses = cclauses_buf; |
46577 | |
46578 | cp_lexer_consume_token (lexer: parser->lexer); |
46579 | if (!flag_openmp) /* flag_openmp_simd */ |
46580 | return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, |
46581 | cclauses, if_p); |
46582 | keep_next_level (true); |
46583 | sb = begin_omp_structured_block (); |
46584 | save = cp_parser_begin_omp_structured_block (parser); |
46585 | ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, |
46586 | cclauses, if_p); |
46587 | cp_parser_end_omp_structured_block (parser, save); |
46588 | tree body = finish_omp_structured_block (sb); |
46589 | if (ret == NULL) |
46590 | return ret; |
46591 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46592 | ret = make_node (OMP_TEAMS); |
46593 | TREE_TYPE (ret) = void_type_node; |
46594 | OMP_TEAMS_CLAUSES (ret) = clauses; |
46595 | OMP_TEAMS_BODY (ret) = body; |
46596 | OMP_TEAMS_COMBINED (ret) = 1; |
46597 | SET_EXPR_LOCATION (ret, loc); |
46598 | return add_stmt (ret); |
46599 | } |
46600 | else if (strcmp (s1: p, s2: "loop" ) == 0) |
46601 | { |
46602 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
46603 | if (cclauses == NULL) |
46604 | cclauses = cclauses_buf; |
46605 | |
46606 | cp_lexer_consume_token (lexer: parser->lexer); |
46607 | if (!flag_openmp) /* flag_openmp_simd */ |
46608 | return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
46609 | cclauses, if_p); |
46610 | keep_next_level (true); |
46611 | sb = begin_omp_structured_block (); |
46612 | save = cp_parser_begin_omp_structured_block (parser); |
46613 | ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
46614 | cclauses, if_p); |
46615 | cp_parser_end_omp_structured_block (parser, save); |
46616 | tree body = finish_omp_structured_block (sb); |
46617 | if (ret == NULL) |
46618 | return ret; |
46619 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46620 | ret = make_node (OMP_TEAMS); |
46621 | TREE_TYPE (ret) = void_type_node; |
46622 | OMP_TEAMS_CLAUSES (ret) = clauses; |
46623 | OMP_TEAMS_BODY (ret) = body; |
46624 | OMP_TEAMS_COMBINED (ret) = 1; |
46625 | SET_EXPR_LOCATION (ret, loc); |
46626 | return add_stmt (ret); |
46627 | } |
46628 | } |
46629 | if (!flag_openmp) /* flag_openmp_simd */ |
46630 | { |
46631 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46632 | return NULL_TREE; |
46633 | } |
46634 | |
46635 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
46636 | finish_p: cclauses == NULL); |
46637 | if (cclauses) |
46638 | { |
46639 | cp_omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses); |
46640 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46641 | } |
46642 | |
46643 | tree stmt = make_node (OMP_TEAMS); |
46644 | TREE_TYPE (stmt) = void_type_node; |
46645 | OMP_TEAMS_CLAUSES (stmt) = clauses; |
46646 | keep_next_level (true); |
46647 | OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46648 | SET_EXPR_LOCATION (stmt, loc); |
46649 | |
46650 | return add_stmt (stmt); |
46651 | } |
46652 | |
46653 | /* OpenMP 4.0: |
46654 | # pragma omp target data target-data-clause[optseq] new-line |
46655 | structured-block */ |
46656 | |
46657 | #define OMP_TARGET_DATA_CLAUSE_MASK \ |
46658 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46659 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46660 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46661 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \ |
46662 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR)) |
46663 | |
46664 | static tree |
46665 | cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46666 | { |
46667 | if (flag_openmp) |
46668 | omp_requires_mask |
46669 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46670 | |
46671 | tree clauses |
46672 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, |
46673 | where: "#pragma omp target data" , pragma_tok); |
46674 | c_omp_adjust_map_clauses (clauses, false); |
46675 | int map_seen = 0; |
46676 | for (tree *pc = &clauses; *pc;) |
46677 | { |
46678 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46679 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46680 | { |
46681 | case GOMP_MAP_TO: |
46682 | case GOMP_MAP_ALWAYS_TO: |
46683 | case GOMP_MAP_PRESENT_TO: |
46684 | case GOMP_MAP_ALWAYS_PRESENT_TO: |
46685 | case GOMP_MAP_FROM: |
46686 | case GOMP_MAP_ALWAYS_FROM: |
46687 | case GOMP_MAP_PRESENT_FROM: |
46688 | case GOMP_MAP_ALWAYS_PRESENT_FROM: |
46689 | case GOMP_MAP_TOFROM: |
46690 | case GOMP_MAP_ALWAYS_TOFROM: |
46691 | case GOMP_MAP_PRESENT_TOFROM: |
46692 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46693 | case GOMP_MAP_ALLOC: |
46694 | case GOMP_MAP_PRESENT_ALLOC: |
46695 | map_seen = 3; |
46696 | break; |
46697 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46698 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46699 | case GOMP_MAP_ALWAYS_POINTER: |
46700 | case GOMP_MAP_ATTACH_DETACH: |
46701 | case GOMP_MAP_ATTACH: |
46702 | break; |
46703 | default: |
46704 | map_seen |= 1; |
46705 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46706 | "%<#pragma omp target data%> with map-type other " |
46707 | "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> " |
46708 | "on %<map%> clause" ); |
46709 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46710 | continue; |
46711 | } |
46712 | else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR |
46713 | || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR) |
46714 | map_seen = 3; |
46715 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46716 | } |
46717 | |
46718 | if (map_seen != 3) |
46719 | { |
46720 | if (map_seen == 0) |
46721 | error_at (pragma_tok->location, |
46722 | "%<#pragma omp target data%> must contain at least " |
46723 | "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> " |
46724 | "clause" ); |
46725 | return NULL_TREE; |
46726 | } |
46727 | |
46728 | tree stmt = make_node (OMP_TARGET_DATA); |
46729 | TREE_TYPE (stmt) = void_type_node; |
46730 | OMP_TARGET_DATA_CLAUSES (stmt) = clauses; |
46731 | |
46732 | keep_next_level (true); |
46733 | OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46734 | |
46735 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46736 | return add_stmt (stmt); |
46737 | } |
46738 | |
46739 | /* OpenMP 4.5: |
46740 | # pragma omp target enter data target-enter-data-clause[optseq] new-line |
46741 | structured-block */ |
46742 | |
46743 | #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \ |
46744 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46745 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46746 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46747 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46748 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46749 | |
46750 | static bool |
46751 | cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, |
46752 | enum pragma_context context) |
46753 | { |
46754 | bool data_seen = false; |
46755 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46756 | { |
46757 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46758 | const char *p = IDENTIFIER_POINTER (id); |
46759 | |
46760 | if (strcmp (s1: p, s2: "data" ) == 0) |
46761 | { |
46762 | cp_lexer_consume_token (lexer: parser->lexer); |
46763 | data_seen = true; |
46764 | } |
46765 | } |
46766 | if (!data_seen) |
46767 | { |
46768 | cp_parser_error (parser, gmsgid: "expected %<data%>" ); |
46769 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46770 | return false; |
46771 | } |
46772 | |
46773 | if (context == pragma_stmt) |
46774 | { |
46775 | error_at (pragma_tok->location, |
46776 | "%<#pragma %s%> may only be used in compound statements" , |
46777 | "omp target enter data" ); |
46778 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46779 | return true; |
46780 | } |
46781 | |
46782 | if (flag_openmp) |
46783 | omp_requires_mask |
46784 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46785 | |
46786 | tree clauses |
46787 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK, |
46788 | where: "#pragma omp target enter data" , pragma_tok); |
46789 | c_omp_adjust_map_clauses (clauses, false); |
46790 | int map_seen = 0; |
46791 | for (tree *pc = &clauses; *pc;) |
46792 | { |
46793 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46794 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46795 | { |
46796 | case GOMP_MAP_TO: |
46797 | case GOMP_MAP_ALWAYS_TO: |
46798 | case GOMP_MAP_PRESENT_TO: |
46799 | case GOMP_MAP_ALWAYS_PRESENT_TO: |
46800 | case GOMP_MAP_ALLOC: |
46801 | case GOMP_MAP_PRESENT_ALLOC: |
46802 | map_seen = 3; |
46803 | break; |
46804 | case GOMP_MAP_TOFROM: |
46805 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO); |
46806 | map_seen = 3; |
46807 | break; |
46808 | case GOMP_MAP_ALWAYS_TOFROM: |
46809 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO); |
46810 | map_seen = 3; |
46811 | break; |
46812 | case GOMP_MAP_PRESENT_TOFROM: |
46813 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO); |
46814 | map_seen = 3; |
46815 | break; |
46816 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46817 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO); |
46818 | map_seen = 3; |
46819 | break; |
46820 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46821 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46822 | case GOMP_MAP_ALWAYS_POINTER: |
46823 | case GOMP_MAP_ATTACH_DETACH: |
46824 | case GOMP_MAP_ATTACH: |
46825 | break; |
46826 | default: |
46827 | map_seen |= 1; |
46828 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46829 | "%<#pragma omp target enter data%> with map-type other " |
46830 | "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause" ); |
46831 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46832 | continue; |
46833 | } |
46834 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46835 | } |
46836 | |
46837 | if (map_seen != 3) |
46838 | { |
46839 | if (map_seen == 0) |
46840 | error_at (pragma_tok->location, |
46841 | "%<#pragma omp target enter data%> must contain at least " |
46842 | "one %<map%> clause" ); |
46843 | return true; |
46844 | } |
46845 | |
46846 | tree stmt = make_node (OMP_TARGET_ENTER_DATA); |
46847 | TREE_TYPE (stmt) = void_type_node; |
46848 | OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses; |
46849 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46850 | add_stmt (stmt); |
46851 | return true; |
46852 | } |
46853 | |
46854 | /* OpenMP 4.5: |
46855 | # pragma omp target exit data target-enter-data-clause[optseq] new-line |
46856 | structured-block */ |
46857 | |
46858 | #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \ |
46859 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46860 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46861 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46862 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46863 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46864 | |
46865 | static bool |
46866 | cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, |
46867 | enum pragma_context context) |
46868 | { |
46869 | bool data_seen = false; |
46870 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46871 | { |
46872 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46873 | const char *p = IDENTIFIER_POINTER (id); |
46874 | |
46875 | if (strcmp (s1: p, s2: "data" ) == 0) |
46876 | { |
46877 | cp_lexer_consume_token (lexer: parser->lexer); |
46878 | data_seen = true; |
46879 | } |
46880 | } |
46881 | if (!data_seen) |
46882 | { |
46883 | cp_parser_error (parser, gmsgid: "expected %<data%>" ); |
46884 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46885 | return false; |
46886 | } |
46887 | |
46888 | if (context == pragma_stmt) |
46889 | { |
46890 | error_at (pragma_tok->location, |
46891 | "%<#pragma %s%> may only be used in compound statements" , |
46892 | "omp target exit data" ); |
46893 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46894 | return true; |
46895 | } |
46896 | |
46897 | if (flag_openmp) |
46898 | omp_requires_mask |
46899 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46900 | |
46901 | tree clauses |
46902 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK, |
46903 | where: "#pragma omp target exit data" , pragma_tok, |
46904 | finish_p: false); |
46905 | clauses = finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA); |
46906 | c_omp_adjust_map_clauses (clauses, false); |
46907 | int map_seen = 0; |
46908 | for (tree *pc = &clauses; *pc;) |
46909 | { |
46910 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46911 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46912 | { |
46913 | case GOMP_MAP_FROM: |
46914 | case GOMP_MAP_ALWAYS_FROM: |
46915 | case GOMP_MAP_PRESENT_FROM: |
46916 | case GOMP_MAP_ALWAYS_PRESENT_FROM: |
46917 | case GOMP_MAP_RELEASE: |
46918 | case GOMP_MAP_DELETE: |
46919 | map_seen = 3; |
46920 | break; |
46921 | case GOMP_MAP_TOFROM: |
46922 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM); |
46923 | map_seen = 3; |
46924 | break; |
46925 | case GOMP_MAP_ALWAYS_TOFROM: |
46926 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM); |
46927 | map_seen = 3; |
46928 | break; |
46929 | case GOMP_MAP_PRESENT_TOFROM: |
46930 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM); |
46931 | map_seen = 3; |
46932 | break; |
46933 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46934 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM); |
46935 | map_seen = 3; |
46936 | break; |
46937 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46938 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46939 | case GOMP_MAP_ALWAYS_POINTER: |
46940 | case GOMP_MAP_ATTACH_DETACH: |
46941 | case GOMP_MAP_DETACH: |
46942 | break; |
46943 | default: |
46944 | map_seen |= 1; |
46945 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46946 | "%<#pragma omp target exit data%> with map-type other " |
46947 | "than %<from%>, %<tofrom%>, %<release%> or %<delete%> " |
46948 | "on %<map%> clause" ); |
46949 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46950 | continue; |
46951 | } |
46952 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46953 | } |
46954 | |
46955 | if (map_seen != 3) |
46956 | { |
46957 | if (map_seen == 0) |
46958 | error_at (pragma_tok->location, |
46959 | "%<#pragma omp target exit data%> must contain at least " |
46960 | "one %<map%> clause" ); |
46961 | return true; |
46962 | } |
46963 | |
46964 | tree stmt = make_node (OMP_TARGET_EXIT_DATA); |
46965 | TREE_TYPE (stmt) = void_type_node; |
46966 | OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses; |
46967 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46968 | add_stmt (stmt); |
46969 | return true; |
46970 | } |
46971 | |
46972 | /* OpenMP 4.0: |
46973 | # pragma omp target update target-update-clause[optseq] new-line */ |
46974 | |
46975 | #define OMP_TARGET_UPDATE_CLAUSE_MASK \ |
46976 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \ |
46977 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ |
46978 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46979 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46980 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46981 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46982 | |
46983 | static bool |
46984 | cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, |
46985 | enum pragma_context context) |
46986 | { |
46987 | if (context == pragma_stmt) |
46988 | { |
46989 | error_at (pragma_tok->location, |
46990 | "%<#pragma %s%> may only be used in compound statements" , |
46991 | "omp target update" ); |
46992 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46993 | return true; |
46994 | } |
46995 | |
46996 | tree clauses |
46997 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK, |
46998 | where: "#pragma omp target update" , pragma_tok); |
46999 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE |
47000 | && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE) |
47001 | { |
47002 | error_at (pragma_tok->location, |
47003 | "%<#pragma omp target update%> must contain at least one " |
47004 | "%<from%> or %<to%> clauses" ); |
47005 | return true; |
47006 | } |
47007 | |
47008 | if (flag_openmp) |
47009 | omp_requires_mask |
47010 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
47011 | |
47012 | tree stmt = make_node (OMP_TARGET_UPDATE); |
47013 | TREE_TYPE (stmt) = void_type_node; |
47014 | OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses; |
47015 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
47016 | add_stmt (stmt); |
47017 | return true; |
47018 | } |
47019 | |
47020 | /* OpenMP 4.0: |
47021 | # pragma omp target target-clause[optseq] new-line |
47022 | structured-block */ |
47023 | |
47024 | #define OMP_TARGET_CLAUSE_MASK \ |
47025 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
47026 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
47027 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
47028 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
47029 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ |
47030 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
47031 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
47032 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \ |
47033 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
47034 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ |
47035 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ |
47036 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\ |
47037 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR)) |
47038 | |
47039 | static bool |
47040 | cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, |
47041 | enum pragma_context context, bool *if_p) |
47042 | { |
47043 | if (flag_openmp) |
47044 | omp_requires_mask |
47045 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
47046 | |
47047 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47048 | { |
47049 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47050 | const char *p = IDENTIFIER_POINTER (id); |
47051 | enum tree_code ccode = ERROR_MARK; |
47052 | |
47053 | if (strcmp (s1: p, s2: "teams" ) == 0) |
47054 | ccode = OMP_TEAMS; |
47055 | else if (strcmp (s1: p, s2: "parallel" ) == 0) |
47056 | ccode = OMP_PARALLEL; |
47057 | else if (strcmp (s1: p, s2: "simd" ) == 0) |
47058 | ccode = OMP_SIMD; |
47059 | if (ccode != ERROR_MARK) |
47060 | { |
47061 | tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT]; |
47062 | char p_name[sizeof ("#pragma omp target teams distribute " |
47063 | "parallel for simd" )]; |
47064 | |
47065 | cp_lexer_consume_token (lexer: parser->lexer); |
47066 | strcpy (dest: p_name, src: "#pragma omp target" ); |
47067 | if (!flag_openmp) /* flag_openmp_simd */ |
47068 | { |
47069 | tree stmt; |
47070 | switch (ccode) |
47071 | { |
47072 | case OMP_TEAMS: |
47073 | stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, |
47074 | OMP_TARGET_CLAUSE_MASK, |
47075 | cclauses, if_p); |
47076 | break; |
47077 | case OMP_PARALLEL: |
47078 | stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, |
47079 | OMP_TARGET_CLAUSE_MASK, |
47080 | cclauses, if_p); |
47081 | break; |
47082 | case OMP_SIMD: |
47083 | stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, |
47084 | OMP_TARGET_CLAUSE_MASK, |
47085 | cclauses, if_p); |
47086 | break; |
47087 | default: |
47088 | gcc_unreachable (); |
47089 | } |
47090 | return stmt != NULL_TREE; |
47091 | } |
47092 | keep_next_level (true); |
47093 | tree sb = begin_omp_structured_block (), ret; |
47094 | unsigned save = cp_parser_begin_omp_structured_block (parser); |
47095 | switch (ccode) |
47096 | { |
47097 | case OMP_TEAMS: |
47098 | ret = cp_parser_omp_teams (parser, pragma_tok, p_name, |
47099 | OMP_TARGET_CLAUSE_MASK, cclauses, |
47100 | if_p); |
47101 | break; |
47102 | case OMP_PARALLEL: |
47103 | ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, |
47104 | OMP_TARGET_CLAUSE_MASK, cclauses, |
47105 | if_p); |
47106 | break; |
47107 | case OMP_SIMD: |
47108 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, |
47109 | OMP_TARGET_CLAUSE_MASK, cclauses, |
47110 | if_p); |
47111 | break; |
47112 | default: |
47113 | gcc_unreachable (); |
47114 | } |
47115 | cp_parser_end_omp_structured_block (parser, save); |
47116 | tree body = finish_omp_structured_block (sb); |
47117 | if (ret == NULL_TREE) |
47118 | return false; |
47119 | if (ccode == OMP_TEAMS && !processing_template_decl) |
47120 | /* For combined target teams, ensure the num_teams and |
47121 | thread_limit clause expressions are evaluated on the host, |
47122 | before entering the target construct. */ |
47123 | for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
47124 | c; c = OMP_CLAUSE_CHAIN (c)) |
47125 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS |
47126 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT) |
47127 | for (int i = 0; |
47128 | i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i) |
47129 | if (OMP_CLAUSE_OPERAND (c, i) |
47130 | && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST) |
47131 | { |
47132 | tree expr = OMP_CLAUSE_OPERAND (c, i); |
47133 | expr = force_target_expr (TREE_TYPE (expr), expr, |
47134 | tf_none); |
47135 | if (expr == error_mark_node) |
47136 | continue; |
47137 | tree tmp = TARGET_EXPR_SLOT (expr); |
47138 | add_stmt (expr); |
47139 | OMP_CLAUSE_OPERAND (c, i) = expr; |
47140 | tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c), |
47141 | OMP_CLAUSE_FIRSTPRIVATE); |
47142 | OMP_CLAUSE_DECL (tc) = tmp; |
47143 | OMP_CLAUSE_CHAIN (tc) |
47144 | = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; |
47145 | cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc; |
47146 | } |
47147 | c_omp_adjust_map_clauses (cclauses[C_OMP_CLAUSE_SPLIT_TARGET], true); |
47148 | finish_omp_target (pragma_tok->location, |
47149 | cclauses[C_OMP_CLAUSE_SPLIT_TARGET], body, true); |
47150 | return true; |
47151 | } |
47152 | else if (!flag_openmp) /* flag_openmp_simd */ |
47153 | { |
47154 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47155 | return false; |
47156 | } |
47157 | else if (strcmp (s1: p, s2: "data" ) == 0) |
47158 | { |
47159 | cp_lexer_consume_token (lexer: parser->lexer); |
47160 | cp_parser_omp_target_data (parser, pragma_tok, if_p); |
47161 | return true; |
47162 | } |
47163 | else if (strcmp (s1: p, s2: "enter" ) == 0) |
47164 | { |
47165 | cp_lexer_consume_token (lexer: parser->lexer); |
47166 | return cp_parser_omp_target_enter_data (parser, pragma_tok, context); |
47167 | } |
47168 | else if (strcmp (s1: p, s2: "exit" ) == 0) |
47169 | { |
47170 | cp_lexer_consume_token (lexer: parser->lexer); |
47171 | return cp_parser_omp_target_exit_data (parser, pragma_tok, context); |
47172 | } |
47173 | else if (strcmp (s1: p, s2: "update" ) == 0) |
47174 | { |
47175 | cp_lexer_consume_token (lexer: parser->lexer); |
47176 | return cp_parser_omp_target_update (parser, pragma_tok, context); |
47177 | } |
47178 | } |
47179 | if (!flag_openmp) /* flag_openmp_simd */ |
47180 | { |
47181 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47182 | return false; |
47183 | } |
47184 | |
47185 | tree clauses = cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK, |
47186 | where: "#pragma omp target" , pragma_tok, |
47187 | finish_p: false); |
47188 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
47189 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) |
47190 | { |
47191 | tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); |
47192 | OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c); |
47193 | OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM); |
47194 | OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c); |
47195 | OMP_CLAUSE_CHAIN (c) = nc; |
47196 | } |
47197 | clauses = finish_omp_clauses (clauses, C_ORT_OMP_TARGET); |
47198 | |
47199 | c_omp_adjust_map_clauses (clauses, true); |
47200 | keep_next_level (true); |
47201 | tree body = cp_parser_omp_structured_block (parser, if_p); |
47202 | |
47203 | finish_omp_target (pragma_tok->location, clauses, body, false); |
47204 | return true; |
47205 | } |
47206 | |
47207 | /* OpenACC 2.0: |
47208 | # pragma acc cache (variable-list) new-line |
47209 | |
47210 | OpenACC 2.7: |
47211 | # pragma acc cache (readonly: variable-list) new-line |
47212 | */ |
47213 | |
47214 | static tree |
47215 | cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok) |
47216 | { |
47217 | /* Don't create location wrapper nodes within 'OMP_CLAUSE__CACHE_' |
47218 | clauses. */ |
47219 | auto_suppress_location_wrappers sentinel; |
47220 | |
47221 | tree stmt, clauses = NULL_TREE; |
47222 | bool readonly = false; |
47223 | |
47224 | if (cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
47225 | { |
47226 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
47227 | if (token->type == CPP_NAME |
47228 | && !strcmp (IDENTIFIER_POINTER (token->u.value), s2: "readonly" ) |
47229 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
47230 | { |
47231 | cp_lexer_consume_token (lexer: parser->lexer); |
47232 | cp_lexer_consume_token (lexer: parser->lexer); |
47233 | readonly = true; |
47234 | } |
47235 | clauses = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE__CACHE_, |
47236 | NULL, NULL); |
47237 | } |
47238 | |
47239 | if (readonly) |
47240 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
47241 | OMP_CLAUSE__CACHE__READONLY (c) = 1; |
47242 | |
47243 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
47244 | |
47245 | cp_parser_require_pragma_eol (parser, pragma_tok: cp_lexer_peek_token (lexer: parser->lexer)); |
47246 | |
47247 | stmt = make_node (OACC_CACHE); |
47248 | TREE_TYPE (stmt) = void_type_node; |
47249 | OACC_CACHE_CLAUSES (stmt) = clauses; |
47250 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
47251 | add_stmt (stmt); |
47252 | |
47253 | return stmt; |
47254 | } |
47255 | |
47256 | /* OpenACC 2.0: |
47257 | # pragma acc data oacc-data-clause[optseq] new-line |
47258 | structured-block */ |
47259 | |
47260 | #define OACC_DATA_CLAUSE_MASK \ |
47261 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47262 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47263 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47264 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47265 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47266 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47267 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \ |
47268 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47269 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47270 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47271 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) ) |
47272 | |
47273 | static tree |
47274 | cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
47275 | { |
47276 | tree stmt, clauses, block; |
47277 | unsigned int save; |
47278 | |
47279 | clauses = cp_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK, |
47280 | where: "#pragma acc data" , pragma_tok); |
47281 | |
47282 | block = begin_omp_parallel (); |
47283 | save = cp_parser_begin_omp_structured_block (parser); |
47284 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
47285 | cp_parser_end_omp_structured_block (parser, save); |
47286 | stmt = finish_oacc_data (clauses, block); |
47287 | return stmt; |
47288 | } |
47289 | |
47290 | /* OpenACC 2.0: |
47291 | # pragma acc host_data <clauses> new-line |
47292 | structured-block */ |
47293 | |
47294 | #define OACC_HOST_DATA_CLAUSE_MASK \ |
47295 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \ |
47296 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47297 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) ) |
47298 | |
47299 | static tree |
47300 | cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
47301 | { |
47302 | tree stmt, clauses, block; |
47303 | unsigned int save; |
47304 | |
47305 | clauses = cp_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK, |
47306 | where: "#pragma acc host_data" , pragma_tok, |
47307 | finish_p: false); |
47308 | if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR)) |
47309 | { |
47310 | error_at (pragma_tok->location, |
47311 | "%<host_data%> construct requires %<use_device%> clause" ); |
47312 | return error_mark_node; |
47313 | } |
47314 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
47315 | block = begin_omp_parallel (); |
47316 | save = cp_parser_begin_omp_structured_block (parser); |
47317 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
47318 | cp_parser_end_omp_structured_block (parser, save); |
47319 | stmt = finish_oacc_host_data (clauses, block); |
47320 | return stmt; |
47321 | } |
47322 | |
47323 | /* OpenACC 2.0: |
47324 | # pragma acc declare oacc-data-clause[optseq] new-line |
47325 | */ |
47326 | |
47327 | #define OACC_DECLARE_CLAUSE_MASK \ |
47328 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47329 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47330 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47331 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47332 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47333 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \ |
47334 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \ |
47335 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) ) |
47336 | |
47337 | static tree |
47338 | cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) |
47339 | { |
47340 | tree clauses, stmt; |
47341 | bool error = false; |
47342 | bool found_in_scope = global_bindings_p (); |
47343 | |
47344 | clauses = cp_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK, |
47345 | where: "#pragma acc declare" , pragma_tok); |
47346 | |
47347 | |
47348 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
47349 | { |
47350 | error_at (pragma_tok->location, |
47351 | "no valid clauses specified in %<#pragma acc declare%>" ); |
47352 | return NULL_TREE; |
47353 | } |
47354 | |
47355 | for (tree t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) |
47356 | { |
47357 | location_t loc = OMP_CLAUSE_LOCATION (t); |
47358 | tree decl = OMP_CLAUSE_DECL (t); |
47359 | if (!DECL_P (decl)) |
47360 | { |
47361 | error_at (loc, "array section in %<#pragma acc declare%>" ); |
47362 | error = true; |
47363 | continue; |
47364 | } |
47365 | gcc_assert (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_MAP); |
47366 | switch (OMP_CLAUSE_MAP_KIND (t)) |
47367 | { |
47368 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
47369 | case GOMP_MAP_ALLOC: |
47370 | case GOMP_MAP_TO: |
47371 | case GOMP_MAP_FORCE_DEVICEPTR: |
47372 | case GOMP_MAP_DEVICE_RESIDENT: |
47373 | break; |
47374 | |
47375 | case GOMP_MAP_LINK: |
47376 | if (!global_bindings_p () |
47377 | && (TREE_STATIC (decl) |
47378 | || !DECL_EXTERNAL (decl))) |
47379 | { |
47380 | error_at (loc, |
47381 | "%qD must be a global variable in " |
47382 | "%<#pragma acc declare link%>" , |
47383 | decl); |
47384 | error = true; |
47385 | continue; |
47386 | } |
47387 | break; |
47388 | |
47389 | default: |
47390 | if (global_bindings_p ()) |
47391 | { |
47392 | error_at (loc, "invalid OpenACC clause at file scope" ); |
47393 | error = true; |
47394 | continue; |
47395 | } |
47396 | if (DECL_EXTERNAL (decl)) |
47397 | { |
47398 | error_at (loc, |
47399 | "invalid use of %<extern%> variable %qD " |
47400 | "in %<#pragma acc declare%>" , decl); |
47401 | error = true; |
47402 | continue; |
47403 | } |
47404 | else if (TREE_PUBLIC (decl)) |
47405 | { |
47406 | error_at (loc, |
47407 | "invalid use of %<global%> variable %qD " |
47408 | "in %<#pragma acc declare%>" , decl); |
47409 | error = true; |
47410 | continue; |
47411 | } |
47412 | break; |
47413 | } |
47414 | |
47415 | if (!found_in_scope) |
47416 | /* This seems to ignore the existence of cleanup scopes? |
47417 | What is the meaning for local extern decls? The local |
47418 | extern is in this scope, but it is referring to a decl that |
47419 | is namespace scope. */ |
47420 | for (tree d = current_binding_level->names; d; d = TREE_CHAIN (d)) |
47421 | if (d == decl) |
47422 | { |
47423 | found_in_scope = true; |
47424 | break; |
47425 | } |
47426 | if (!found_in_scope) |
47427 | { |
47428 | error_at (loc, |
47429 | "%qD must be a variable declared in the same scope as " |
47430 | "%<#pragma acc declare%>" , decl); |
47431 | error = true; |
47432 | continue; |
47433 | } |
47434 | |
47435 | if (!error) |
47436 | { |
47437 | if (DECL_LOCAL_DECL_P (decl)) |
47438 | /* We need to mark the aliased decl, as that is the entity |
47439 | that is being referred to. This won't work for |
47440 | dependent variables, but it didn't work for them before |
47441 | DECL_LOCAL_DECL_P was a thing either. But then |
47442 | dependent local extern variable decls are as rare as |
47443 | hen's teeth. */ |
47444 | if (auto alias = DECL_LOCAL_DECL_ALIAS (decl)) |
47445 | if (alias != error_mark_node) |
47446 | decl = alias; |
47447 | |
47448 | if (lookup_attribute (attr_name: "omp declare target" , DECL_ATTRIBUTES (decl)) |
47449 | || lookup_attribute (attr_name: "omp declare target link" , |
47450 | DECL_ATTRIBUTES (decl))) |
47451 | { |
47452 | error_at (loc, "variable %qD used more than once with " |
47453 | "%<#pragma acc declare%>" , decl); |
47454 | error = true; |
47455 | continue; |
47456 | } |
47457 | |
47458 | tree id; |
47459 | if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK) |
47460 | id = get_identifier ("omp declare target link" ); |
47461 | else |
47462 | id = get_identifier ("omp declare target" ); |
47463 | |
47464 | DECL_ATTRIBUTES (decl) |
47465 | = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl)); |
47466 | if (current_binding_level->kind == sk_namespace) |
47467 | { |
47468 | symtab_node *node = symtab_node::get (decl); |
47469 | if (node != NULL) |
47470 | { |
47471 | node->offloadable = 1; |
47472 | if (ENABLE_OFFLOADING) |
47473 | { |
47474 | g->have_offload = true; |
47475 | if (is_a <varpool_node *> (p: node)) |
47476 | vec_safe_push (v&: offload_vars, obj: decl); |
47477 | } |
47478 | } |
47479 | } |
47480 | } |
47481 | } |
47482 | |
47483 | if (error || current_binding_level->kind == sk_namespace) |
47484 | return NULL_TREE; |
47485 | |
47486 | stmt = make_node (OACC_DECLARE); |
47487 | TREE_TYPE (stmt) = void_type_node; |
47488 | OACC_DECLARE_CLAUSES (stmt) = clauses; |
47489 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
47490 | |
47491 | add_stmt (stmt); |
47492 | |
47493 | return NULL_TREE; |
47494 | } |
47495 | |
47496 | /* OpenACC 2.0: |
47497 | # pragma acc enter data oacc-enter-data-clause[optseq] new-line |
47498 | |
47499 | or |
47500 | |
47501 | # pragma acc exit data oacc-exit-data-clause[optseq] new-line |
47502 | |
47503 | LOC is the location of the #pragma token. |
47504 | */ |
47505 | |
47506 | #define OACC_ENTER_DATA_CLAUSE_MASK \ |
47507 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47508 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47509 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47510 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47511 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47512 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47513 | |
47514 | #define OACC_EXIT_DATA_CLAUSE_MASK \ |
47515 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47516 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47517 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47518 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \ |
47519 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \ |
47520 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \ |
47521 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47522 | |
47523 | static tree |
47524 | cp_parser_oacc_enter_exit_data (cp_parser *parser, cp_token *pragma_tok, |
47525 | bool enter) |
47526 | { |
47527 | location_t loc = pragma_tok->location; |
47528 | tree stmt, clauses; |
47529 | const char *p = "" ; |
47530 | |
47531 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47532 | p = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47533 | |
47534 | if (strcmp (s1: p, s2: "data" ) != 0) |
47535 | { |
47536 | error_at (loc, "expected %<data%> after %<#pragma acc %s%>" , |
47537 | enter ? "enter" : "exit" ); |
47538 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47539 | return NULL_TREE; |
47540 | } |
47541 | |
47542 | cp_lexer_consume_token (lexer: parser->lexer); |
47543 | |
47544 | if (enter) |
47545 | clauses = cp_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK, |
47546 | where: "#pragma acc enter data" , pragma_tok); |
47547 | else |
47548 | clauses = cp_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK, |
47549 | where: "#pragma acc exit data" , pragma_tok); |
47550 | |
47551 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
47552 | { |
47553 | error_at (loc, "%<#pragma acc %s data%> has no data movement clause" , |
47554 | enter ? "enter" : "exit" ); |
47555 | return NULL_TREE; |
47556 | } |
47557 | |
47558 | stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA); |
47559 | TREE_TYPE (stmt) = void_type_node; |
47560 | OMP_STANDALONE_CLAUSES (stmt) = clauses; |
47561 | SET_EXPR_LOCATION (stmt, loc); |
47562 | add_stmt (stmt); |
47563 | return stmt; |
47564 | } |
47565 | |
47566 | /* OpenACC 2.0: |
47567 | # pragma acc loop oacc-loop-clause[optseq] new-line |
47568 | structured-block */ |
47569 | |
47570 | #define OACC_LOOP_CLAUSE_MASK \ |
47571 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \ |
47572 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
47573 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
47574 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ |
47575 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ |
47576 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ |
47577 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \ |
47578 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \ |
47579 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ |
47580 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE)) |
47581 | |
47582 | static tree |
47583 | cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name, |
47584 | omp_clause_mask mask, tree *cclauses, bool *if_p) |
47585 | { |
47586 | bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1; |
47587 | |
47588 | strcat (dest: p_name, src: " loop" ); |
47589 | mask |= OACC_LOOP_CLAUSE_MASK; |
47590 | |
47591 | tree clauses = cp_parser_oacc_all_clauses (parser, mask, where: p_name, pragma_tok, |
47592 | /*finish_p=*/cclauses == NULL, |
47593 | /*target=*/target_p: is_parallel); |
47594 | if (cclauses) |
47595 | { |
47596 | clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel); |
47597 | if (*cclauses) |
47598 | *cclauses = finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET); |
47599 | if (clauses) |
47600 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
47601 | } |
47602 | |
47603 | tree block = begin_omp_structured_block (); |
47604 | int save = cp_parser_begin_omp_structured_block (parser); |
47605 | tree stmt = cp_parser_omp_for_loop (parser, code: OACC_LOOP, clauses, NULL, if_p); |
47606 | cp_parser_end_omp_structured_block (parser, save); |
47607 | |
47608 | /* Later processing of combined acc loop constructs gets confused |
47609 | by an extra level of empty nested BIND_EXPRs, so flatten them. */ |
47610 | block = finish_omp_structured_block (block); |
47611 | if (TREE_CODE (block) == BIND_EXPR |
47612 | && TREE_CODE (BIND_EXPR_BODY (block)) == BIND_EXPR |
47613 | && !BIND_EXPR_VARS (block)) |
47614 | block = BIND_EXPR_BODY (block); |
47615 | add_stmt (block); |
47616 | |
47617 | return stmt; |
47618 | } |
47619 | |
47620 | /* OpenACC 2.0: |
47621 | # pragma acc kernels oacc-kernels-clause[optseq] new-line |
47622 | structured-block |
47623 | |
47624 | or |
47625 | |
47626 | # pragma acc parallel oacc-parallel-clause[optseq] new-line |
47627 | structured-block |
47628 | |
47629 | OpenACC 2.6: |
47630 | |
47631 | # pragma acc serial oacc-serial-clause[optseq] new-line |
47632 | */ |
47633 | |
47634 | #define OACC_KERNELS_CLAUSE_MASK \ |
47635 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47636 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47637 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47638 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47639 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47640 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47641 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47642 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47643 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47644 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47645 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
47646 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ |
47647 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47648 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47649 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ |
47650 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47651 | |
47652 | #define OACC_PARALLEL_CLAUSE_MASK \ |
47653 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47654 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47655 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47656 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47657 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47658 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47659 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47660 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47661 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \ |
47662 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47663 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47664 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
47665 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ |
47666 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47667 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
47668 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
47669 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47670 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ |
47671 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47672 | |
47673 | #define OACC_SERIAL_CLAUSE_MASK \ |
47674 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47675 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47676 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47677 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47678 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47679 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47680 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47681 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47682 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47683 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47684 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
47685 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \ |
47686 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47687 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
47688 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47689 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47690 | |
47691 | static tree |
47692 | cp_parser_oacc_compute (cp_parser *parser, cp_token *pragma_tok, |
47693 | char *p_name, bool *if_p) |
47694 | { |
47695 | omp_clause_mask mask; |
47696 | enum tree_code code; |
47697 | switch (cp_parser_pragma_kind (token: pragma_tok)) |
47698 | { |
47699 | case PRAGMA_OACC_KERNELS: |
47700 | strcat (dest: p_name, src: " kernels" ); |
47701 | mask = OACC_KERNELS_CLAUSE_MASK; |
47702 | code = OACC_KERNELS; |
47703 | break; |
47704 | case PRAGMA_OACC_PARALLEL: |
47705 | strcat (dest: p_name, src: " parallel" ); |
47706 | mask = OACC_PARALLEL_CLAUSE_MASK; |
47707 | code = OACC_PARALLEL; |
47708 | break; |
47709 | case PRAGMA_OACC_SERIAL: |
47710 | strcat (dest: p_name, src: " serial" ); |
47711 | mask = OACC_SERIAL_CLAUSE_MASK; |
47712 | code = OACC_SERIAL; |
47713 | break; |
47714 | default: |
47715 | gcc_unreachable (); |
47716 | } |
47717 | |
47718 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47719 | { |
47720 | const char *p |
47721 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47722 | if (strcmp (s1: p, s2: "loop" ) == 0) |
47723 | { |
47724 | cp_lexer_consume_token (lexer: parser->lexer); |
47725 | tree block = begin_omp_parallel (); |
47726 | tree clauses; |
47727 | tree stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, |
47728 | cclauses: &clauses, if_p); |
47729 | protected_set_expr_location (stmt, pragma_tok->location); |
47730 | return finish_omp_construct (code, block, clauses); |
47731 | } |
47732 | } |
47733 | |
47734 | tree clauses = cp_parser_oacc_all_clauses (parser, mask, where: p_name, pragma_tok, |
47735 | /*finish_p=*/true, |
47736 | /*target=*/target_p: true); |
47737 | |
47738 | tree block = begin_omp_parallel (); |
47739 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
47740 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
47741 | cp_parser_end_omp_structured_block (parser, save); |
47742 | return finish_omp_construct (code, block, clauses); |
47743 | } |
47744 | |
47745 | /* OpenACC 2.0: |
47746 | # pragma acc update oacc-update-clause[optseq] new-line |
47747 | */ |
47748 | |
47749 | #define OACC_UPDATE_CLAUSE_MASK \ |
47750 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47751 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \ |
47752 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \ |
47753 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47754 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \ |
47755 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47756 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT)) |
47757 | |
47758 | static tree |
47759 | cp_parser_oacc_update (cp_parser *parser, cp_token *pragma_tok) |
47760 | { |
47761 | tree stmt, clauses; |
47762 | |
47763 | clauses = cp_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK, |
47764 | where: "#pragma acc update" , pragma_tok); |
47765 | |
47766 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
47767 | { |
47768 | error_at (pragma_tok->location, |
47769 | "%<#pragma acc update%> must contain at least one " |
47770 | "%<device%> or %<host%> or %<self%> clause" ); |
47771 | return NULL_TREE; |
47772 | } |
47773 | |
47774 | stmt = make_node (OACC_UPDATE); |
47775 | TREE_TYPE (stmt) = void_type_node; |
47776 | OACC_UPDATE_CLAUSES (stmt) = clauses; |
47777 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
47778 | add_stmt (stmt); |
47779 | return stmt; |
47780 | } |
47781 | |
47782 | /* OpenACC 2.0: |
47783 | # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line |
47784 | |
47785 | LOC is the location of the #pragma token. |
47786 | */ |
47787 | |
47788 | #define OACC_WAIT_CLAUSE_MASK \ |
47789 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)) |
47790 | |
47791 | static tree |
47792 | cp_parser_oacc_wait (cp_parser *parser, cp_token *pragma_tok) |
47793 | { |
47794 | tree clauses, list = NULL_TREE, stmt = NULL_TREE; |
47795 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47796 | |
47797 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
47798 | list = cp_parser_oacc_wait_list (parser, clause_loc: loc, list); |
47799 | |
47800 | clauses = cp_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, |
47801 | where: "#pragma acc wait" , pragma_tok); |
47802 | |
47803 | stmt = c_finish_oacc_wait (loc, list, clauses); |
47804 | stmt = finish_expr_stmt (stmt); |
47805 | |
47806 | return stmt; |
47807 | } |
47808 | |
47809 | /* OpenMP 4.0: |
47810 | # pragma omp declare simd declare-simd-clauses[optseq] new-line */ |
47811 | |
47812 | #define OMP_DECLARE_SIMD_CLAUSE_MASK \ |
47813 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ |
47814 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
47815 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ |
47816 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ |
47817 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ |
47818 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) |
47819 | |
47820 | static void |
47821 | cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, |
47822 | enum pragma_context context, |
47823 | bool variant_p) |
47824 | { |
47825 | bool first_p = parser->omp_declare_simd == NULL; |
47826 | cp_omp_declare_simd_data data; |
47827 | if (first_p) |
47828 | { |
47829 | data.error_seen = false; |
47830 | data.fndecl_seen = false; |
47831 | data.variant_p = variant_p; |
47832 | data.tokens = vNULL; |
47833 | data.attribs[0] = NULL; |
47834 | data.attribs[1] = NULL; |
47835 | data.loc = UNKNOWN_LOCATION; |
47836 | /* It is safe to take the address of a local variable; it will only be |
47837 | used while this scope is live. */ |
47838 | parser->omp_declare_simd = &data; |
47839 | } |
47840 | else if (parser->omp_declare_simd->variant_p != variant_p) |
47841 | { |
47842 | error_at (pragma_tok->location, |
47843 | "%<#pragma omp declare %s%> followed by " |
47844 | "%<#pragma omp declare %s%>" , |
47845 | parser->omp_declare_simd->variant_p ? "variant" : "simd" , |
47846 | parser->omp_declare_simd->variant_p ? "simd" : "variant" ); |
47847 | parser->omp_declare_simd->error_seen = true; |
47848 | } |
47849 | |
47850 | /* Store away all pragma tokens. */ |
47851 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
47852 | cp_lexer_consume_token (lexer: parser->lexer); |
47853 | cp_parser_require_pragma_eol (parser, pragma_tok); |
47854 | struct cp_token_cache *cp |
47855 | = cp_token_cache_new (first: pragma_tok, last: cp_lexer_peek_token (lexer: parser->lexer)); |
47856 | parser->omp_declare_simd->tokens.safe_push (obj: cp); |
47857 | |
47858 | if (first_p) |
47859 | { |
47860 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
47861 | cp_parser_pragma (parser, context, NULL); |
47862 | switch (context) |
47863 | { |
47864 | case pragma_external: |
47865 | cp_parser_declaration (parser, NULL_TREE); |
47866 | break; |
47867 | case pragma_member: |
47868 | cp_parser_member_declaration (parser); |
47869 | break; |
47870 | case pragma_objc_icode: |
47871 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
47872 | break; |
47873 | default: |
47874 | cp_parser_declaration_statement (parser); |
47875 | break; |
47876 | } |
47877 | if (parser->omp_declare_simd |
47878 | && !parser->omp_declare_simd->error_seen |
47879 | && !parser->omp_declare_simd->fndecl_seen) |
47880 | error_at (pragma_tok->location, |
47881 | "%<#pragma omp declare %s%> not immediately followed by " |
47882 | "function declaration or definition" , |
47883 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
47884 | data.tokens.release (); |
47885 | parser->omp_declare_simd = NULL; |
47886 | } |
47887 | } |
47888 | |
47889 | /* OpenMP 5.0: |
47890 | |
47891 | trait-selector: |
47892 | trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])] |
47893 | |
47894 | trait-score: |
47895 | score(score-expression) |
47896 | |
47897 | Note that this function returns a list of trait selectors for the |
47898 | trait-selector-set SET. */ |
47899 | |
47900 | static tree |
47901 | cp_parser_omp_context_selector (cp_parser *parser, enum omp_tss_code set, |
47902 | bool has_parms_p) |
47903 | { |
47904 | tree ret = NULL_TREE; |
47905 | do |
47906 | { |
47907 | tree selector; |
47908 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
47909 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47910 | selector = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47911 | else |
47912 | { |
47913 | cp_parser_error (parser, gmsgid: "expected trait selector name" ); |
47914 | return error_mark_node; |
47915 | } |
47916 | |
47917 | enum omp_ts_code sel |
47918 | = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector)); |
47919 | |
47920 | if (sel == OMP_TRAIT_INVALID) |
47921 | { |
47922 | /* Per the spec, "Implementations can ignore specified selectors |
47923 | that are not those described in this section"; however, we |
47924 | must record such selectors because they cause match failures. */ |
47925 | warning_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
47926 | OPT_Wopenmp, |
47927 | "unknown selector %qs for context selector set %qs" , |
47928 | IDENTIFIER_POINTER (selector), omp_tss_map[set]); |
47929 | cp_lexer_consume_token (lexer: parser->lexer); |
47930 | ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret); |
47931 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
47932 | for (size_t n = cp_parser_skip_balanced_tokens (parser, n: 1) - 1; |
47933 | n; --n) |
47934 | cp_lexer_consume_token (lexer: parser->lexer); |
47935 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47936 | { |
47937 | cp_lexer_consume_token (lexer: parser->lexer); |
47938 | continue; |
47939 | } |
47940 | else |
47941 | break; |
47942 | } |
47943 | |
47944 | cp_lexer_consume_token (lexer: parser->lexer); |
47945 | |
47946 | tree properties = NULL_TREE; |
47947 | tree scoreval = NULL_TREE; |
47948 | enum omp_tp_type property_kind = omp_ts_map[sel].tp_type; |
47949 | bool allow_score = omp_ts_map[sel].allow_score; |
47950 | tree t; |
47951 | |
47952 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
47953 | { |
47954 | if (property_kind == OMP_TRAIT_PROPERTY_NONE) |
47955 | { |
47956 | error ("selector %qs does not accept any properties" , |
47957 | IDENTIFIER_POINTER (selector)); |
47958 | return error_mark_node; |
47959 | } |
47960 | |
47961 | matching_parens parens; |
47962 | parens.consume_open (parser); |
47963 | |
47964 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
47965 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
47966 | && strcmp (IDENTIFIER_POINTER (token->u.value), s2: "score" ) == 0 |
47967 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
47968 | { |
47969 | cp_lexer_save_tokens (lexer: parser->lexer); |
47970 | cp_lexer_consume_token (lexer: parser->lexer); |
47971 | cp_lexer_consume_token (lexer: parser->lexer); |
47972 | if (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
47973 | consume_paren: true) |
47974 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
47975 | { |
47976 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
47977 | cp_lexer_consume_token (lexer: parser->lexer); |
47978 | |
47979 | matching_parens parens2; |
47980 | parens2.require_open (parser); |
47981 | tree score = cp_parser_constant_expression (parser); |
47982 | if (!parens2.require_close (parser)) |
47983 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, |
47984 | or_comma: false, consume_paren: true); |
47985 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
47986 | if (!allow_score) |
47987 | error_at (token->location, |
47988 | "%<score%> cannot be specified in traits " |
47989 | "in the %qs trait-selector-set" , |
47990 | omp_tss_map[set]); |
47991 | else if (score != error_mark_node) |
47992 | { |
47993 | score = fold_non_dependent_expr (score); |
47994 | if (value_dependent_expression_p (score)) |
47995 | scoreval = score; |
47996 | else if (!INTEGRAL_TYPE_P (TREE_TYPE (score)) |
47997 | || TREE_CODE (score) != INTEGER_CST) |
47998 | error_at (token->location, "%<score%> argument must " |
47999 | "be constant integer expression" ); |
48000 | else if (tree_int_cst_sgn (score) < 0) |
48001 | error_at (token->location, "%<score%> argument must " |
48002 | "be non-negative" ); |
48003 | else |
48004 | scoreval = score; |
48005 | } |
48006 | } |
48007 | else |
48008 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
48009 | |
48010 | token = cp_lexer_peek_token (lexer: parser->lexer); |
48011 | } |
48012 | |
48013 | switch (property_kind) |
48014 | { |
48015 | case OMP_TRAIT_PROPERTY_ID: |
48016 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
48017 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48018 | { |
48019 | tree prop = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48020 | cp_lexer_consume_token (lexer: parser->lexer); |
48021 | properties = make_trait_property (prop, NULL_TREE, |
48022 | properties); |
48023 | } |
48024 | else |
48025 | { |
48026 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
48027 | return error_mark_node; |
48028 | } |
48029 | break; |
48030 | case OMP_TRAIT_PROPERTY_NAME_LIST: |
48031 | do |
48032 | { |
48033 | tree prop = OMP_TP_NAMELIST_NODE; |
48034 | tree value = NULL_TREE; |
48035 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
48036 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48037 | { |
48038 | value = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48039 | cp_lexer_consume_token (lexer: parser->lexer); |
48040 | } |
48041 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_STRING)) |
48042 | value = cp_parser_string_literal (parser, |
48043 | /*translate=*/false, |
48044 | /*wide_ok=*/false); |
48045 | else |
48046 | { |
48047 | cp_parser_error (parser, gmsgid: "expected identifier or " |
48048 | "string literal" ); |
48049 | return error_mark_node; |
48050 | } |
48051 | |
48052 | properties = make_trait_property (prop, value, properties); |
48053 | |
48054 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
48055 | cp_lexer_consume_token (lexer: parser->lexer); |
48056 | else |
48057 | break; |
48058 | } |
48059 | while (1); |
48060 | break; |
48061 | case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR: |
48062 | case OMP_TRAIT_PROPERTY_BOOL_EXPR: |
48063 | /* FIXME: this is bogus, the expression need |
48064 | not be constant. */ |
48065 | t = cp_parser_constant_expression (parser); |
48066 | if (t != error_mark_node) |
48067 | { |
48068 | t = fold_non_dependent_expr (t); |
48069 | if (!value_dependent_expression_p (t) |
48070 | && (!INTEGRAL_TYPE_P (TREE_TYPE (t)) |
48071 | || !tree_fits_shwi_p (t))) |
48072 | error_at (token->location, "property must be " |
48073 | "constant integer expression" ); |
48074 | else |
48075 | properties = make_trait_property (NULL_TREE, t, |
48076 | properties); |
48077 | } |
48078 | else |
48079 | return error_mark_node; |
48080 | break; |
48081 | case OMP_TRAIT_PROPERTY_CLAUSE_LIST: |
48082 | if (sel == OMP_TRAIT_CONSTRUCT_SIMD) |
48083 | { |
48084 | if (!has_parms_p) |
48085 | { |
48086 | error_at (token->location, "properties for %<simd%> " |
48087 | "selector may not be specified in " |
48088 | "%<metadirective%>" ); |
48089 | return error_mark_node; |
48090 | } |
48091 | properties |
48092 | = cp_parser_omp_all_clauses (parser, |
48093 | OMP_DECLARE_SIMD_CLAUSE_MASK, |
48094 | where: "simd" , NULL, finish_p: true, nested: 2); |
48095 | } |
48096 | else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES) |
48097 | { |
48098 | /* FIXME: The "requires" selector was added in OpenMP 5.1. |
48099 | Currently only the now-deprecated syntax |
48100 | from OpenMP 5.0 is supported. */ |
48101 | sorry_at (token->location, |
48102 | "%<requires%> selector is not supported yet" ); |
48103 | return error_mark_node; |
48104 | } |
48105 | else |
48106 | gcc_unreachable (); |
48107 | break; |
48108 | default: |
48109 | gcc_unreachable (); |
48110 | } |
48111 | |
48112 | if (!parens.require_close (parser)) |
48113 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
48114 | |
48115 | properties = nreverse (properties); |
48116 | } |
48117 | else if (property_kind != OMP_TRAIT_PROPERTY_NONE |
48118 | && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST |
48119 | && property_kind != OMP_TRAIT_PROPERTY_EXTENSION) |
48120 | { |
48121 | cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN); |
48122 | return error_mark_node; |
48123 | } |
48124 | |
48125 | ret = make_trait_selector (sel, scoreval, properties, ret); |
48126 | |
48127 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
48128 | cp_lexer_consume_token (lexer: parser->lexer); |
48129 | else |
48130 | break; |
48131 | } |
48132 | while (1); |
48133 | |
48134 | return nreverse (ret); |
48135 | } |
48136 | |
48137 | /* OpenMP 5.0: |
48138 | |
48139 | trait-set-selector[,trait-set-selector[,...]] |
48140 | |
48141 | trait-set-selector: |
48142 | trait-set-selector-name = { trait-selector[, trait-selector[, ...]] } |
48143 | |
48144 | trait-set-selector-name: |
48145 | constructor |
48146 | device |
48147 | implementation |
48148 | user */ |
48149 | |
48150 | static tree |
48151 | cp_parser_omp_context_selector_specification (cp_parser *parser, |
48152 | bool has_parms_p) |
48153 | { |
48154 | tree ret = NULL_TREE; |
48155 | do |
48156 | { |
48157 | const char *setp = "" ; |
48158 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48159 | setp |
48160 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
48161 | enum omp_tss_code set = omp_lookup_tss_code (setp); |
48162 | |
48163 | if (set == OMP_TRAIT_SET_INVALID) |
48164 | { |
48165 | cp_parser_error (parser, gmsgid: "expected context selector set name" ); |
48166 | return error_mark_node; |
48167 | } |
48168 | |
48169 | cp_lexer_consume_token (lexer: parser->lexer); |
48170 | |
48171 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
48172 | return error_mark_node; |
48173 | |
48174 | matching_braces braces; |
48175 | if (!braces.require_open (parser)) |
48176 | return error_mark_node; |
48177 | |
48178 | tree selectors |
48179 | = cp_parser_omp_context_selector (parser, set, has_parms_p); |
48180 | if (selectors == error_mark_node) |
48181 | { |
48182 | cp_parser_skip_to_closing_brace (parser); |
48183 | ret = error_mark_node; |
48184 | } |
48185 | else if (ret != error_mark_node) |
48186 | ret = make_trait_set_selector (set, selectors, ret); |
48187 | |
48188 | braces.require_close (parser); |
48189 | |
48190 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
48191 | cp_lexer_consume_token (lexer: parser->lexer); |
48192 | else |
48193 | break; |
48194 | } |
48195 | while (1); |
48196 | |
48197 | if (ret == error_mark_node) |
48198 | return ret; |
48199 | return nreverse (ret); |
48200 | } |
48201 | |
48202 | /* Assumption clauses: |
48203 | OpenMP 5.1 |
48204 | absent (directive-name-list) |
48205 | contains (directive-name-list) |
48206 | holds (expression) |
48207 | no_openmp |
48208 | no_openmp_routines |
48209 | no_parallelism */ |
48210 | |
48211 | static void |
48212 | cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, |
48213 | bool is_assume) |
48214 | { |
48215 | bool no_openmp = false; |
48216 | bool no_openmp_routines = false; |
48217 | bool no_parallelism = false; |
48218 | bitmap_head absent_head, contains_head; |
48219 | |
48220 | bitmap_obstack_initialize (NULL); |
48221 | bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack); |
48222 | bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack); |
48223 | |
48224 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
48225 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
48226 | "expected at least one assumption clause" ); |
48227 | |
48228 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
48229 | { |
48230 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48231 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
48232 | cp_lexer_consume_token (lexer: parser->lexer); |
48233 | |
48234 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48235 | break; |
48236 | |
48237 | const char *p |
48238 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
48239 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
48240 | |
48241 | if (!strcmp (s1: p, s2: "no_openmp" )) |
48242 | { |
48243 | cp_lexer_consume_token (lexer: parser->lexer); |
48244 | if (no_openmp) |
48245 | error_at (cloc, "too many %qs clauses" , "no_openmp" ); |
48246 | no_openmp = true; |
48247 | } |
48248 | else if (!strcmp (s1: p, s2: "no_openmp_routines" )) |
48249 | { |
48250 | cp_lexer_consume_token (lexer: parser->lexer); |
48251 | if (no_openmp_routines) |
48252 | error_at (cloc, "too many %qs clauses" , "no_openmp_routines" ); |
48253 | no_openmp_routines = true; |
48254 | } |
48255 | else if (!strcmp (s1: p, s2: "no_parallelism" )) |
48256 | { |
48257 | cp_lexer_consume_token (lexer: parser->lexer); |
48258 | if (no_parallelism) |
48259 | error_at (cloc, "too many %qs clauses" , "no_parallelism" ); |
48260 | no_parallelism = true; |
48261 | } |
48262 | else if (!strcmp (s1: p, s2: "holds" )) |
48263 | { |
48264 | cp_lexer_consume_token (lexer: parser->lexer); |
48265 | matching_parens parens; |
48266 | if (parens.require_open (parser)) |
48267 | { |
48268 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
48269 | tree t = cp_parser_assignment_expression (parser); |
48270 | if (!type_dependent_expression_p (t)) |
48271 | t = contextual_conv_bool (t, tf_warning_or_error); |
48272 | if (is_assume && !error_operand_p (t)) |
48273 | finish_expr_stmt (build_assume_call (eloc, t)); |
48274 | if (!parens.require_close (parser)) |
48275 | cp_parser_skip_to_closing_parenthesis (parser, |
48276 | /*recovering=*/true, |
48277 | /*or_comma=*/false, |
48278 | /*consume_paren=*/true); |
48279 | } |
48280 | } |
48281 | else if (!strcmp (s1: p, s2: "absent" ) || !strcmp (s1: p, s2: "contains" )) |
48282 | { |
48283 | cp_lexer_consume_token (lexer: parser->lexer); |
48284 | matching_parens parens; |
48285 | if (parens.require_open (parser)) |
48286 | { |
48287 | do |
48288 | { |
48289 | const char *directive[3] = {}; |
48290 | int i; |
48291 | location_t dloc |
48292 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
48293 | for (i = 0; i < 3; i++) |
48294 | { |
48295 | tree id; |
48296 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, type: CPP_NAME)) |
48297 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, |
48298 | n: i + 1)->u.value; |
48299 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, |
48300 | type: CPP_KEYWORD)) |
48301 | { |
48302 | enum rid rid |
48303 | = cp_lexer_peek_nth_token (lexer: parser->lexer, |
48304 | n: i + 1)->keyword; |
48305 | id = ridpointers[rid]; |
48306 | } |
48307 | else |
48308 | break; |
48309 | directive[i] = IDENTIFIER_POINTER (id); |
48310 | } |
48311 | if (i == 0) |
48312 | error_at (dloc, "expected directive name" ); |
48313 | else |
48314 | { |
48315 | const struct c_omp_directive *dir |
48316 | = c_omp_categorize_directive (directive[0], |
48317 | directive[1], |
48318 | directive[2]); |
48319 | if (dir == NULL |
48320 | || dir->kind == C_OMP_DIR_DECLARATIVE |
48321 | || dir->kind == C_OMP_DIR_INFORMATIONAL |
48322 | || dir->id == PRAGMA_OMP_END |
48323 | || (!dir->second && directive[1]) |
48324 | || (!dir->third && directive[2])) |
48325 | error_at (dloc, "unknown OpenMP directive name in " |
48326 | "%qs clause argument" , p); |
48327 | else |
48328 | { |
48329 | int id = dir - c_omp_directives; |
48330 | if (bitmap_bit_p (p[0] == 'a' ? &contains_head |
48331 | : &absent_head, id)) |
48332 | error_at (dloc, "%<%s%s%s%s%s%> directive " |
48333 | "mentioned in both %<absent%> and " |
48334 | "%<contains%> clauses" , |
48335 | directive[0], |
48336 | directive[1] ? " " : "" , |
48337 | directive[1] ? directive[1] : "" , |
48338 | directive[2] ? " " : "" , |
48339 | directive[2] ? directive[2] : "" ); |
48340 | else if (!bitmap_set_bit (p[0] == 'a' |
48341 | ? &absent_head |
48342 | : &contains_head, id)) |
48343 | error_at (dloc, "%<%s%s%s%s%s%> directive " |
48344 | "mentioned multiple times in %qs " |
48345 | "clauses" , |
48346 | directive[0], |
48347 | directive[1] ? " " : "" , |
48348 | directive[1] ? directive[1] : "" , |
48349 | directive[2] ? " " : "" , |
48350 | directive[2] ? directive[2] : "" , p); |
48351 | } |
48352 | for (; i; --i) |
48353 | cp_lexer_consume_token (lexer: parser->lexer); |
48354 | } |
48355 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
48356 | cp_lexer_consume_token (lexer: parser->lexer); |
48357 | else |
48358 | break; |
48359 | } |
48360 | while (1); |
48361 | if (!parens.require_close (parser)) |
48362 | cp_parser_skip_to_closing_parenthesis (parser, |
48363 | /*recovering=*/true, |
48364 | /*or_comma=*/false, |
48365 | /*consume_paren=*/true); |
48366 | } |
48367 | } |
48368 | else if (startswith (str: p, prefix: "ext_" )) |
48369 | { |
48370 | warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs" , p); |
48371 | cp_lexer_consume_token (lexer: parser->lexer); |
48372 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
48373 | for (size_t n = cp_parser_skip_balanced_tokens (parser, n: 1) - 1; |
48374 | n; --n) |
48375 | cp_lexer_consume_token (lexer: parser->lexer); |
48376 | } |
48377 | else |
48378 | { |
48379 | cp_lexer_consume_token (lexer: parser->lexer); |
48380 | error_at (cloc, "expected assumption clause" ); |
48381 | break; |
48382 | } |
48383 | } |
48384 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48385 | } |
48386 | |
48387 | /* OpenMP 5.1 |
48388 | # pragma omp assume clauses[optseq] new-line */ |
48389 | |
48390 | static void |
48391 | cp_parser_omp_assume (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
48392 | { |
48393 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: true); |
48394 | add_stmt (cp_parser_omp_structured_block (parser, if_p)); |
48395 | } |
48396 | |
48397 | /* OpenMP 5.1 |
48398 | # pragma omp assumes clauses[optseq] new-line */ |
48399 | |
48400 | static bool |
48401 | cp_parser_omp_assumes (cp_parser *parser, cp_token *pragma_tok) |
48402 | { |
48403 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: false); |
48404 | return false; |
48405 | } |
48406 | |
48407 | /* Finalize #pragma omp declare variant after a fndecl has been parsed, and put |
48408 | that into "omp declare variant base" attribute. */ |
48409 | |
48410 | static tree |
48411 | cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, |
48412 | tree attrs) |
48413 | { |
48414 | matching_parens parens; |
48415 | if (!parens.require_open (parser)) |
48416 | { |
48417 | fail: |
48418 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48419 | return attrs; |
48420 | } |
48421 | |
48422 | bool template_p; |
48423 | cp_id_kind idk = CP_ID_KIND_NONE; |
48424 | cp_token *varid_token = cp_lexer_peek_token (lexer: parser->lexer); |
48425 | cp_expr varid |
48426 | = cp_parser_id_expression (parser, /*template_keyword_p=*/false, |
48427 | /*check_dependency_p=*/true, |
48428 | /*template_p=*/&template_p, |
48429 | /*declarator_p=*/false, |
48430 | /*optional_p=*/false); |
48431 | parens.require_close (parser); |
48432 | |
48433 | tree variant; |
48434 | if (TREE_CODE (varid) == TEMPLATE_ID_EXPR |
48435 | || TREE_CODE (varid) == TYPE_DECL |
48436 | || varid == error_mark_node) |
48437 | variant = varid; |
48438 | else if (varid_token->type == CPP_NAME && varid_token->error_reported) |
48439 | variant = NULL_TREE; |
48440 | else |
48441 | { |
48442 | tree ambiguous_decls; |
48443 | variant = cp_parser_lookup_name (parser, name: varid, tag_type: none_type, |
48444 | is_template: template_p, /*is_namespace=*/false, |
48445 | /*check_dependency=*/true, |
48446 | ambiguous_decls: &ambiguous_decls, |
48447 | name_location: varid.get_location ()); |
48448 | if (ambiguous_decls) |
48449 | variant = NULL_TREE; |
48450 | } |
48451 | if (variant == NULL_TREE) |
48452 | variant = error_mark_node; |
48453 | else if (TREE_CODE (variant) != SCOPE_REF) |
48454 | { |
48455 | const char *error_msg; |
48456 | variant |
48457 | = finish_id_expression (varid, variant, parser->scope, |
48458 | &idk, false, true, |
48459 | &parser->non_integral_constant_expression_p, |
48460 | template_p, true, false, false, &error_msg, |
48461 | varid.get_location ()); |
48462 | if (error_msg) |
48463 | cp_parser_error (parser, gmsgid: error_msg); |
48464 | } |
48465 | location_t caret_loc = get_pure_location (loc: varid.get_location ()); |
48466 | location_t start_loc = get_start (loc: varid_token->location); |
48467 | location_t finish_loc = get_finish (loc: varid.get_location ()); |
48468 | location_t varid_loc = make_location (caret: caret_loc, start: start_loc, finish: finish_loc); |
48469 | |
48470 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48471 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
48472 | cp_lexer_consume_token (lexer: parser->lexer); |
48473 | |
48474 | const char *clause = "" ; |
48475 | location_t match_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
48476 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48477 | clause = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
48478 | if (strcmp (s1: clause, s2: "match" )) |
48479 | { |
48480 | cp_parser_error (parser, gmsgid: "expected %<match%>" ); |
48481 | goto fail; |
48482 | } |
48483 | |
48484 | cp_lexer_consume_token (lexer: parser->lexer); |
48485 | |
48486 | if (!parens.require_open (parser)) |
48487 | goto fail; |
48488 | |
48489 | tree ctx = cp_parser_omp_context_selector_specification (parser, has_parms_p: true); |
48490 | if (ctx == error_mark_node) |
48491 | goto fail; |
48492 | ctx = omp_check_context_selector (loc: match_loc, ctx); |
48493 | if (ctx != error_mark_node && variant != error_mark_node) |
48494 | { |
48495 | tree match_loc_node = maybe_wrap_with_location (integer_zero_node, |
48496 | match_loc); |
48497 | tree loc_node = maybe_wrap_with_location (integer_zero_node, varid_loc); |
48498 | loc_node = tree_cons (match_loc_node, |
48499 | build_int_cst (integer_type_node, idk), |
48500 | build_tree_list (loc_node, integer_zero_node)); |
48501 | attrs = tree_cons (get_identifier ("omp declare variant base" ), |
48502 | tree_cons (variant, ctx, loc_node), attrs); |
48503 | if (processing_template_decl) |
48504 | ATTR_IS_DEPENDENT (attrs) = 1; |
48505 | } |
48506 | |
48507 | parens.require_close (parser); |
48508 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48509 | return attrs; |
48510 | } |
48511 | |
48512 | |
48513 | /* Finalize #pragma omp declare simd clauses after direct declarator has |
48514 | been parsed, and put that into "omp declare simd" attribute. */ |
48515 | |
48516 | static tree |
48517 | cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) |
48518 | { |
48519 | struct cp_token_cache *ce; |
48520 | cp_omp_declare_simd_data *data = parser->omp_declare_simd; |
48521 | int i; |
48522 | |
48523 | if (!data->error_seen && data->fndecl_seen) |
48524 | { |
48525 | error ("%<#pragma omp declare %s%> not immediately followed by " |
48526 | "a single function declaration or definition" , |
48527 | data->variant_p ? "variant" : "simd" ); |
48528 | data->error_seen = true; |
48529 | } |
48530 | if (data->error_seen) |
48531 | return attrs; |
48532 | |
48533 | FOR_EACH_VEC_ELT (data->tokens, i, ce) |
48534 | { |
48535 | tree c, cl; |
48536 | |
48537 | cp_parser_push_lexer_for_tokens (parser, cache: ce); |
48538 | parser->lexer->in_pragma = true; |
48539 | gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA); |
48540 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
48541 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48542 | const char *kind = IDENTIFIER_POINTER (id); |
48543 | cp_lexer_consume_token (lexer: parser->lexer); |
48544 | if (strcmp (s1: kind, s2: "simd" ) == 0) |
48545 | { |
48546 | cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, |
48547 | where: "#pragma omp declare simd" , |
48548 | pragma_tok); |
48549 | if (cl) |
48550 | cl = tree_cons (NULL_TREE, cl, NULL_TREE); |
48551 | c = build_tree_list (get_identifier ("omp declare simd" ), cl); |
48552 | TREE_CHAIN (c) = attrs; |
48553 | if (processing_template_decl) |
48554 | ATTR_IS_DEPENDENT (c) = 1; |
48555 | attrs = c; |
48556 | } |
48557 | else |
48558 | { |
48559 | gcc_assert (strcmp (kind, "variant" ) == 0); |
48560 | attrs |
48561 | = cp_finish_omp_declare_variant (parser, pragma_tok, attrs); |
48562 | } |
48563 | cp_parser_pop_lexer (parser); |
48564 | } |
48565 | |
48566 | cp_lexer *lexer = NULL; |
48567 | for (int i = 0; i < 2; i++) |
48568 | { |
48569 | if (data->attribs[i] == NULL) |
48570 | continue; |
48571 | for (tree *pa = data->attribs[i]; *pa; ) |
48572 | if (get_attribute_namespace (*pa) == omp_identifier |
48573 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
48574 | { |
48575 | for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) |
48576 | { |
48577 | tree d = TREE_VALUE (a); |
48578 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
48579 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
48580 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
48581 | const char *directive[3] = {}; |
48582 | for (int j = 0; j < 3; j++) |
48583 | { |
48584 | tree id = NULL_TREE; |
48585 | if (first + j == last) |
48586 | break; |
48587 | if (first[j].type == CPP_NAME) |
48588 | id = first[j].u.value; |
48589 | else if (first[j].type == CPP_KEYWORD) |
48590 | id = ridpointers[(int) first[j].keyword]; |
48591 | else |
48592 | break; |
48593 | directive[j] = IDENTIFIER_POINTER (id); |
48594 | } |
48595 | const c_omp_directive *dir = NULL; |
48596 | if (directive[0]) |
48597 | dir = c_omp_categorize_directive (directive[0], directive[1], |
48598 | directive[2]); |
48599 | if (dir == NULL) |
48600 | { |
48601 | error_at (first->location, |
48602 | "unknown OpenMP directive name in " |
48603 | "%qs attribute argument" , |
48604 | TREE_PUBLIC (d) |
48605 | ? "omp::decl" : "omp::directive" ); |
48606 | continue; |
48607 | } |
48608 | if (dir->id != PRAGMA_OMP_DECLARE |
48609 | || (strcmp (s1: directive[1], s2: "simd" ) != 0 |
48610 | && strcmp (s1: directive[1], s2: "variant" ) != 0)) |
48611 | { |
48612 | error_at (first->location, |
48613 | "OpenMP directive other than %<declare simd%> " |
48614 | "or %<declare variant%> appertains to a " |
48615 | "declaration" ); |
48616 | continue; |
48617 | } |
48618 | |
48619 | if (parser->omp_attrs_forbidden_p) |
48620 | { |
48621 | error_at (first->location, |
48622 | "mixing OpenMP directives with attribute and " |
48623 | "pragma syntax on the same statement" ); |
48624 | parser->omp_attrs_forbidden_p = false; |
48625 | } |
48626 | |
48627 | if (!flag_openmp && strcmp (s1: directive[1], s2: "simd" ) != 0) |
48628 | continue; |
48629 | if (lexer == NULL) |
48630 | { |
48631 | lexer = cp_lexer_alloc (); |
48632 | lexer->debugging_p = parser->lexer->debugging_p; |
48633 | } |
48634 | vec_safe_reserve (v&: lexer->buffer, nelems: (last - first) + 2); |
48635 | cp_token tok = {}; |
48636 | tok.type = CPP_PRAGMA; |
48637 | tok.keyword = RID_MAX; |
48638 | tok.u.value = build_int_cst (NULL, PRAGMA_OMP_DECLARE); |
48639 | tok.location = first->location; |
48640 | lexer->buffer->quick_push (obj: tok); |
48641 | while (++first < last) |
48642 | lexer->buffer->quick_push (obj: *first); |
48643 | tok = {}; |
48644 | tok.type = CPP_PRAGMA_EOL; |
48645 | tok.keyword = RID_MAX; |
48646 | tok.location = last->location; |
48647 | lexer->buffer->quick_push (obj: tok); |
48648 | tok = {}; |
48649 | tok.type = CPP_EOF; |
48650 | tok.keyword = RID_MAX; |
48651 | tok.location = last->location; |
48652 | lexer->buffer->quick_push (obj: tok); |
48653 | lexer->next = parser->lexer; |
48654 | lexer->next_token = lexer->buffer->address (); |
48655 | lexer->last_token = lexer->next_token |
48656 | + lexer->buffer->length () |
48657 | - 1; |
48658 | lexer->in_omp_attribute_pragma = true; |
48659 | parser->lexer = lexer; |
48660 | /* Move the current source position to that of the first token |
48661 | in the new lexer. */ |
48662 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
48663 | |
48664 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
48665 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48666 | const char *kind = IDENTIFIER_POINTER (id); |
48667 | cp_lexer_consume_token (lexer: parser->lexer); |
48668 | |
48669 | tree c, cl; |
48670 | if (strcmp (s1: kind, s2: "simd" ) == 0) |
48671 | { |
48672 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48673 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
48674 | cp_lexer_consume_token (lexer: parser->lexer); |
48675 | |
48676 | omp_clause_mask mask = OMP_DECLARE_SIMD_CLAUSE_MASK; |
48677 | cl = cp_parser_omp_all_clauses (parser, mask, |
48678 | where: "#pragma omp declare simd" , |
48679 | pragma_tok); |
48680 | if (cl) |
48681 | cl = tree_cons (NULL_TREE, cl, NULL_TREE); |
48682 | c = build_tree_list (get_identifier ("omp declare simd" ), |
48683 | cl); |
48684 | TREE_CHAIN (c) = attrs; |
48685 | if (processing_template_decl) |
48686 | ATTR_IS_DEPENDENT (c) = 1; |
48687 | attrs = c; |
48688 | } |
48689 | else |
48690 | { |
48691 | gcc_assert (strcmp (kind, "variant" ) == 0); |
48692 | attrs |
48693 | = cp_finish_omp_declare_variant (parser, pragma_tok, |
48694 | attrs); |
48695 | } |
48696 | gcc_assert (parser->lexer != lexer); |
48697 | vec_safe_truncate (v: lexer->buffer, size: 0); |
48698 | } |
48699 | *pa = TREE_CHAIN (*pa); |
48700 | } |
48701 | else |
48702 | pa = &TREE_CHAIN (*pa); |
48703 | } |
48704 | if (lexer) |
48705 | cp_lexer_destroy (lexer); |
48706 | |
48707 | data->fndecl_seen = true; |
48708 | return attrs; |
48709 | } |
48710 | |
48711 | /* D should be DEFERRED_PARSE from omp::decl attribute. If it contains |
48712 | a threadprivate, groupprivate, allocate or declare target directive, |
48713 | return true and parse it for DECL. */ |
48714 | |
48715 | bool |
48716 | cp_maybe_parse_omp_decl (tree decl, tree d) |
48717 | { |
48718 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
48719 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
48720 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
48721 | const char *directive[3] = {}; |
48722 | for (int j = 0; j < 3; j++) |
48723 | { |
48724 | tree id = NULL_TREE; |
48725 | if (first + j == last) |
48726 | break; |
48727 | if (first[j].type == CPP_NAME) |
48728 | id = first[j].u.value; |
48729 | else if (first[j].type == CPP_KEYWORD) |
48730 | id = ridpointers[(int) first[j].keyword]; |
48731 | else |
48732 | break; |
48733 | directive[j] = IDENTIFIER_POINTER (id); |
48734 | } |
48735 | const c_omp_directive *dir = NULL; |
48736 | if (directive[0]) |
48737 | dir = c_omp_categorize_directive (directive[0], directive[1], |
48738 | directive[2]); |
48739 | if (dir == NULL) |
48740 | { |
48741 | error_at (first->location, |
48742 | "unknown OpenMP directive name in " |
48743 | "%qs attribute argument" , "omp::decl" ); |
48744 | return false; |
48745 | } |
48746 | if (dir->id != PRAGMA_OMP_THREADPRIVATE |
48747 | /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */ |
48748 | && dir->id != PRAGMA_OMP_ALLOCATE |
48749 | && (dir->id != PRAGMA_OMP_DECLARE |
48750 | || strcmp (s1: directive[1], s2: "target" ) != 0)) |
48751 | return false; |
48752 | |
48753 | if (!flag_openmp && !dir->simd) |
48754 | return true; |
48755 | |
48756 | cp_parser *parser = the_parser; |
48757 | cp_lexer *lexer = cp_lexer_alloc (); |
48758 | lexer->debugging_p = parser->lexer->debugging_p; |
48759 | lexer->in_omp_decl_attribute = decl; |
48760 | vec_safe_reserve (v&: lexer->buffer, nelems: last - first + 3, exact: true); |
48761 | cp_token tok = {}; |
48762 | tok.type = CPP_PRAGMA; |
48763 | tok.keyword = RID_MAX; |
48764 | tok.u.value = build_int_cst (NULL, dir->id); |
48765 | tok.location = first->location; |
48766 | lexer->buffer->quick_push (obj: tok); |
48767 | while (++first < last) |
48768 | lexer->buffer->quick_push (obj: *first); |
48769 | tok = {}; |
48770 | tok.type = CPP_PRAGMA_EOL; |
48771 | tok.keyword = RID_MAX; |
48772 | tok.location = last->location; |
48773 | lexer->buffer->quick_push (obj: tok); |
48774 | tok = {}; |
48775 | tok.type = CPP_EOF; |
48776 | tok.keyword = RID_MAX; |
48777 | tok.location = last->location; |
48778 | lexer->buffer->quick_push (obj: tok); |
48779 | lexer->next = parser->lexer; |
48780 | lexer->next_token = lexer->buffer->address (); |
48781 | lexer->last_token = lexer->next_token |
48782 | + lexer->buffer->length () |
48783 | - 1; |
48784 | lexer->in_omp_attribute_pragma = true; |
48785 | parser->lexer = lexer; |
48786 | /* Move the current source position to that of the first token in the |
48787 | new lexer. */ |
48788 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
48789 | cp_parser_pragma (parser, pragma_external, NULL); |
48790 | |
48791 | return true; |
48792 | } |
48793 | |
48794 | /* Helper for cp_parser_omp_declare_target, handle one to or link clause |
48795 | on #pragma omp declare target. Return false if errors were reported. */ |
48796 | |
48797 | static bool |
48798 | handle_omp_declare_target_clause (tree c, tree t, int device_type, |
48799 | bool indirect) |
48800 | { |
48801 | tree at1 = lookup_attribute (attr_name: "omp declare target" , DECL_ATTRIBUTES (t)); |
48802 | tree at2 = lookup_attribute (attr_name: "omp declare target link" , DECL_ATTRIBUTES (t)); |
48803 | tree id; |
48804 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK) |
48805 | { |
48806 | id = get_identifier ("omp declare target link" ); |
48807 | std::swap (a&: at1, b&: at2); |
48808 | } |
48809 | else |
48810 | id = get_identifier ("omp declare target" ); |
48811 | if (at2) |
48812 | { |
48813 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER) |
48814 | error_at (OMP_CLAUSE_LOCATION (c), |
48815 | "%qD specified both in declare target %<link%> and %qs" |
48816 | " clauses" , t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter" ); |
48817 | else |
48818 | error_at (OMP_CLAUSE_LOCATION (c), |
48819 | "%qD specified both in declare target %<link%> and " |
48820 | "%<to%> or %<enter%> clauses" , t); |
48821 | return false; |
48822 | } |
48823 | if (!at1) |
48824 | { |
48825 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48826 | if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t)) |
48827 | return true; |
48828 | |
48829 | symtab_node *node = symtab_node::get (decl: t); |
48830 | if (node != NULL) |
48831 | { |
48832 | node->offloadable = 1; |
48833 | if (ENABLE_OFFLOADING) |
48834 | { |
48835 | g->have_offload = true; |
48836 | if (is_a <varpool_node *> (p: node)) |
48837 | vec_safe_push (v&: offload_vars, obj: t); |
48838 | } |
48839 | } |
48840 | } |
48841 | if (TREE_CODE (t) != FUNCTION_DECL) |
48842 | return true; |
48843 | if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0) |
48844 | { |
48845 | tree at3 = lookup_attribute (attr_name: "omp declare target host" , |
48846 | DECL_ATTRIBUTES (t)); |
48847 | if (at3 == NULL_TREE) |
48848 | { |
48849 | id = get_identifier ("omp declare target host" ); |
48850 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48851 | } |
48852 | } |
48853 | if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0) |
48854 | { |
48855 | tree at3 = lookup_attribute (attr_name: "omp declare target nohost" , |
48856 | DECL_ATTRIBUTES (t)); |
48857 | if (at3 == NULL_TREE) |
48858 | { |
48859 | id = get_identifier ("omp declare target nohost" ); |
48860 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48861 | } |
48862 | } |
48863 | if (indirect) |
48864 | { |
48865 | tree at4 = lookup_attribute (attr_name: "omp declare target indirect" , |
48866 | DECL_ATTRIBUTES (t)); |
48867 | if (at4 == NULL_TREE) |
48868 | { |
48869 | id = get_identifier ("omp declare target indirect" ); |
48870 | DECL_ATTRIBUTES (t) |
48871 | = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48872 | } |
48873 | } |
48874 | return true; |
48875 | } |
48876 | |
48877 | /* OpenMP 4.0: |
48878 | # pragma omp declare target new-line |
48879 | declarations and definitions |
48880 | # pragma omp end declare target new-line |
48881 | |
48882 | OpenMP 4.5: |
48883 | # pragma omp declare target ( extended-list ) new-line |
48884 | |
48885 | # pragma omp declare target declare-target-clauses[seq] new-line */ |
48886 | |
48887 | #define OMP_DECLARE_TARGET_CLAUSE_MASK \ |
48888 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ |
48889 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \ |
48890 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \ |
48891 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ |
48892 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT)) |
48893 | |
48894 | static void |
48895 | cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) |
48896 | { |
48897 | tree clauses = NULL_TREE; |
48898 | int device_type = 0; |
48899 | bool indirect = false; |
48900 | bool only_device_type_or_indirect = true; |
48901 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
48902 | || (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48903 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME))) |
48904 | clauses |
48905 | = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, |
48906 | where: "#pragma omp declare target" , pragma_tok); |
48907 | else if (parser->lexer->in_omp_decl_attribute |
48908 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
48909 | { |
48910 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
48911 | list: clauses); |
48912 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
48913 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48914 | } |
48915 | else |
48916 | { |
48917 | cp_omp_declare_target_attr a |
48918 | = { .attr_syntax: parser->lexer->in_omp_attribute_pragma, .device_type: -1, .indirect: false }; |
48919 | vec_safe_push (v&: scope_chain->omp_declare_target_attribute, obj: a); |
48920 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48921 | return; |
48922 | } |
48923 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48924 | { |
48925 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE) |
48926 | device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c); |
48927 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48928 | indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c)); |
48929 | } |
48930 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48931 | { |
48932 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE |
48933 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48934 | continue; |
48935 | tree t = OMP_CLAUSE_DECL (c); |
48936 | only_device_type_or_indirect = false; |
48937 | if (!handle_omp_declare_target_clause (c, t, device_type, indirect)) |
48938 | continue; |
48939 | if (VAR_OR_FUNCTION_DECL_P (t) |
48940 | && DECL_LOCAL_DECL_P (t) |
48941 | && DECL_LANG_SPECIFIC (t) |
48942 | && DECL_LOCAL_DECL_ALIAS (t) |
48943 | && DECL_LOCAL_DECL_ALIAS (t) != error_mark_node) |
48944 | handle_omp_declare_target_clause (c, DECL_LOCAL_DECL_ALIAS (t), |
48945 | device_type, indirect); |
48946 | } |
48947 | if ((device_type || indirect) && only_device_type_or_indirect) |
48948 | error_at (OMP_CLAUSE_LOCATION (clauses), |
48949 | "directive with only %<device_type%> or %<indirect%> clauses" ); |
48950 | if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY) |
48951 | error_at (OMP_CLAUSE_LOCATION (clauses), |
48952 | "%<device_type%> clause must specify 'any' when used with " |
48953 | "an %<indirect%> clause" ); |
48954 | } |
48955 | |
48956 | /* OpenMP 5.1 |
48957 | # pragma omp begin assumes clauses[optseq] new-line |
48958 | |
48959 | # pragma omp begin declare target clauses[optseq] new-line */ |
48960 | |
48961 | #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \ |
48962 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ |
48963 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT)) |
48964 | |
48965 | static void |
48966 | cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) |
48967 | { |
48968 | const char *p = "" ; |
48969 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
48970 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48971 | { |
48972 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48973 | p = IDENTIFIER_POINTER (id); |
48974 | } |
48975 | if (strcmp (s1: p, s2: "declare" ) == 0) |
48976 | { |
48977 | cp_lexer_consume_token (lexer: parser->lexer); |
48978 | p = "" ; |
48979 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48980 | { |
48981 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48982 | p = IDENTIFIER_POINTER (id); |
48983 | } |
48984 | if (strcmp (s1: p, s2: "target" ) == 0) |
48985 | { |
48986 | cp_lexer_consume_token (lexer: parser->lexer); |
48987 | tree clauses |
48988 | = cp_parser_omp_all_clauses (parser, |
48989 | OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK, |
48990 | where: "#pragma omp begin declare target" , |
48991 | pragma_tok); |
48992 | int device_type = 0; |
48993 | bool indirect = 0; |
48994 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48995 | { |
48996 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE) |
48997 | device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c); |
48998 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48999 | indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c)); |
49000 | } |
49001 | cp_omp_declare_target_attr a |
49002 | = { .attr_syntax: in_omp_attribute_pragma, .device_type: device_type, .indirect: indirect }; |
49003 | vec_safe_push (v&: scope_chain->omp_declare_target_attribute, obj: a); |
49004 | } |
49005 | else |
49006 | { |
49007 | cp_parser_error (parser, gmsgid: "expected %<target%>" ); |
49008 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49009 | } |
49010 | } |
49011 | else if (strcmp (s1: p, s2: "assumes" ) == 0) |
49012 | { |
49013 | cp_lexer_consume_token (lexer: parser->lexer); |
49014 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: false); |
49015 | cp_omp_begin_assumes_data a = { .attr_syntax: in_omp_attribute_pragma }; |
49016 | vec_safe_push (v&: scope_chain->omp_begin_assumes, obj: a); |
49017 | } |
49018 | else |
49019 | { |
49020 | cp_parser_error (parser, gmsgid: "expected %<declare target%> or %<assumes%>" ); |
49021 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49022 | } |
49023 | } |
49024 | |
49025 | /* OpenMP 4.0: |
49026 | # pragma omp end declare target new-line |
49027 | |
49028 | OpenMP 5.1: |
49029 | # pragma omp end assumes new-line */ |
49030 | |
49031 | static void |
49032 | cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok) |
49033 | { |
49034 | const char *p = "" ; |
49035 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
49036 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49037 | { |
49038 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49039 | p = IDENTIFIER_POINTER (id); |
49040 | } |
49041 | if (strcmp (s1: p, s2: "declare" ) == 0) |
49042 | { |
49043 | cp_lexer_consume_token (lexer: parser->lexer); |
49044 | p = "" ; |
49045 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49046 | { |
49047 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49048 | p = IDENTIFIER_POINTER (id); |
49049 | } |
49050 | if (strcmp (s1: p, s2: "target" ) == 0) |
49051 | cp_lexer_consume_token (lexer: parser->lexer); |
49052 | else |
49053 | { |
49054 | cp_parser_error (parser, gmsgid: "expected %<target%>" ); |
49055 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49056 | return; |
49057 | } |
49058 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49059 | if (!vec_safe_length (v: scope_chain->omp_declare_target_attribute)) |
49060 | error_at (pragma_tok->location, |
49061 | "%<#pragma omp end declare target%> without corresponding " |
49062 | "%<#pragma omp declare target%> or " |
49063 | "%<#pragma omp begin declare target%>" ); |
49064 | else |
49065 | { |
49066 | cp_omp_declare_target_attr |
49067 | a = scope_chain->omp_declare_target_attribute->pop (); |
49068 | if (a.attr_syntax != in_omp_attribute_pragma) |
49069 | { |
49070 | if (a.attr_syntax) |
49071 | error_at (pragma_tok->location, |
49072 | "%qs in attribute syntax terminated " |
49073 | "with %qs in pragma syntax" , |
49074 | a.device_type >= 0 ? "begin declare target" |
49075 | : "declare target" , |
49076 | "end declare target" ); |
49077 | else |
49078 | error_at (pragma_tok->location, |
49079 | "%qs in pragma syntax terminated " |
49080 | "with %qs in attribute syntax" , |
49081 | a.device_type >= 0 ? "begin declare target" |
49082 | : "declare target" , |
49083 | "end declare target" ); |
49084 | } |
49085 | } |
49086 | } |
49087 | else if (strcmp (s1: p, s2: "assumes" ) == 0) |
49088 | { |
49089 | cp_lexer_consume_token (lexer: parser->lexer); |
49090 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49091 | if (!vec_safe_length (v: scope_chain->omp_begin_assumes)) |
49092 | error_at (pragma_tok->location, |
49093 | "%qs without corresponding %qs" , |
49094 | "#pragma omp end assumes" , "#pragma omp begin assumes" ); |
49095 | else |
49096 | { |
49097 | cp_omp_begin_assumes_data |
49098 | a = scope_chain->omp_begin_assumes->pop (); |
49099 | if (a.attr_syntax != in_omp_attribute_pragma) |
49100 | { |
49101 | if (a.attr_syntax) |
49102 | error_at (pragma_tok->location, |
49103 | "%qs in attribute syntax terminated " |
49104 | "with %qs in pragma syntax" , |
49105 | "begin assumes" , "end assumes" ); |
49106 | else |
49107 | error_at (pragma_tok->location, |
49108 | "%qs in pragma syntax terminated " |
49109 | "with %qs in attribute syntax" , |
49110 | "begin assumes" , "end assumes" ); |
49111 | } |
49112 | } |
49113 | } |
49114 | else |
49115 | { |
49116 | cp_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>" ); |
49117 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49118 | return; |
49119 | } |
49120 | } |
49121 | |
49122 | /* Helper function of cp_parser_omp_declare_reduction. Parse the combiner |
49123 | expression and optional initializer clause of |
49124 | #pragma omp declare reduction. We store the expression(s) as |
49125 | either 3, 6 or 7 special statements inside of the artificial function's |
49126 | body. The first two statements are DECL_EXPRs for the artificial |
49127 | OMP_OUT resp. OMP_IN variables, followed by a statement with the combiner |
49128 | expression that uses those variables. |
49129 | If there was any INITIALIZER clause, this is followed by further statements, |
49130 | the fourth and fifth statements are DECL_EXPRs for the artificial |
49131 | OMP_PRIV resp. OMP_ORIG variables. If the INITIALIZER clause wasn't the |
49132 | constructor variant (first token after open paren is not omp_priv), |
49133 | then the sixth statement is a statement with the function call expression |
49134 | that uses the OMP_PRIV and optionally OMP_ORIG variable. |
49135 | Otherwise, the sixth statement is whatever statement cp_finish_decl emits |
49136 | to initialize the OMP_PRIV artificial variable and there is seventh |
49137 | statement, a DECL_EXPR of the OMP_PRIV statement again. */ |
49138 | |
49139 | static bool |
49140 | cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) |
49141 | { |
49142 | tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); |
49143 | gcc_assert (TYPE_REF_P (type)); |
49144 | type = TREE_TYPE (type); |
49145 | tree omp_out = build_lang_decl (VAR_DECL, get_identifier ("omp_out" ), type); |
49146 | DECL_ARTIFICIAL (omp_out) = 1; |
49147 | pushdecl (omp_out); |
49148 | add_decl_expr (omp_out); |
49149 | tree omp_in = build_lang_decl (VAR_DECL, get_identifier ("omp_in" ), type); |
49150 | DECL_ARTIFICIAL (omp_in) = 1; |
49151 | pushdecl (omp_in); |
49152 | add_decl_expr (omp_in); |
49153 | tree combiner; |
49154 | tree omp_priv = NULL_TREE, omp_orig = NULL_TREE, initializer = NULL_TREE; |
49155 | |
49156 | keep_next_level (true); |
49157 | tree block = begin_omp_structured_block (); |
49158 | combiner = cp_parser_expression (parser); |
49159 | finish_expr_stmt (combiner); |
49160 | block = finish_omp_structured_block (block); |
49161 | if (processing_template_decl) |
49162 | block = build_stmt (input_location, EXPR_STMT, block); |
49163 | add_stmt (block); |
49164 | |
49165 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_CLOSE_PAREN)) |
49166 | return false; |
49167 | |
49168 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
49169 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
49170 | cp_lexer_consume_token (lexer: parser->lexer); |
49171 | |
49172 | const char *p = "" ; |
49173 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49174 | { |
49175 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49176 | p = IDENTIFIER_POINTER (id); |
49177 | } |
49178 | |
49179 | if (strcmp (s1: p, s2: "initializer" ) == 0) |
49180 | { |
49181 | cp_lexer_consume_token (lexer: parser->lexer); |
49182 | matching_parens parens; |
49183 | if (!parens.require_open (parser)) |
49184 | return false; |
49185 | |
49186 | p = "" ; |
49187 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49188 | { |
49189 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49190 | p = IDENTIFIER_POINTER (id); |
49191 | } |
49192 | |
49193 | omp_priv = build_lang_decl (VAR_DECL, get_identifier ("omp_priv" ), type); |
49194 | DECL_ARTIFICIAL (omp_priv) = 1; |
49195 | pushdecl (omp_priv); |
49196 | add_decl_expr (omp_priv); |
49197 | omp_orig = build_lang_decl (VAR_DECL, get_identifier ("omp_orig" ), type); |
49198 | DECL_ARTIFICIAL (omp_orig) = 1; |
49199 | pushdecl (omp_orig); |
49200 | add_decl_expr (omp_orig); |
49201 | |
49202 | keep_next_level (true); |
49203 | block = begin_omp_structured_block (); |
49204 | |
49205 | bool ctor = false; |
49206 | if (strcmp (s1: p, s2: "omp_priv" ) == 0) |
49207 | { |
49208 | bool is_non_constant_init; |
49209 | ctor = true; |
49210 | cp_lexer_consume_token (lexer: parser->lexer); |
49211 | /* Reject initializer (omp_priv) and initializer (omp_priv ()). */ |
49212 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
49213 | || (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
49214 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
49215 | == CPP_CLOSE_PAREN |
49216 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
49217 | == CPP_CLOSE_PAREN)) |
49218 | { |
49219 | finish_omp_structured_block (block); |
49220 | error ("invalid initializer clause" ); |
49221 | return false; |
49222 | } |
49223 | initializer = cp_parser_initializer (parser, |
49224 | /*is_direct_init=*/nullptr, |
49225 | non_constant_p: &is_non_constant_init); |
49226 | cp_finish_decl (omp_priv, initializer, !is_non_constant_init, |
49227 | NULL_TREE, LOOKUP_ONLYCONVERTING); |
49228 | } |
49229 | else |
49230 | { |
49231 | cp_parser_parse_tentatively (parser); |
49232 | /* Don't create location wrapper nodes here. */ |
49233 | auto_suppress_location_wrappers sentinel; |
49234 | tree fn_name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
49235 | /*check_dependency_p=*/true, |
49236 | /*template_p=*/NULL, |
49237 | /*declarator_p=*/false, |
49238 | /*optional_p=*/false); |
49239 | vec<tree, va_gc> *args; |
49240 | if (fn_name == error_mark_node |
49241 | || cp_parser_error_occurred (parser) |
49242 | || !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
49243 | || ((args = cp_parser_parenthesized_expression_list |
49244 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
49245 | /*allow_expansion_p=*/true, |
49246 | /*non_constant_p=*/NULL)), |
49247 | cp_parser_error_occurred (parser))) |
49248 | { |
49249 | finish_omp_structured_block (block); |
49250 | cp_parser_abort_tentative_parse (parser); |
49251 | cp_parser_error (parser, gmsgid: "expected id-expression (arguments)" ); |
49252 | return false; |
49253 | } |
49254 | unsigned int i; |
49255 | tree arg; |
49256 | FOR_EACH_VEC_SAFE_ELT (args, i, arg) |
49257 | if (arg == omp_priv |
49258 | || (TREE_CODE (arg) == ADDR_EXPR |
49259 | && TREE_OPERAND (arg, 0) == omp_priv)) |
49260 | break; |
49261 | cp_parser_abort_tentative_parse (parser); |
49262 | if (arg == NULL_TREE) |
49263 | error ("one of the initializer call arguments should be %<omp_priv%>" |
49264 | " or %<&omp_priv%>" ); |
49265 | initializer = cp_parser_postfix_expression (parser, address_p: false, cast_p: false, member_access_only_p: false, |
49266 | decltype_p: false, NULL); |
49267 | finish_expr_stmt (initializer); |
49268 | } |
49269 | |
49270 | block = finish_omp_structured_block (block); |
49271 | cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL); |
49272 | if (processing_template_decl) |
49273 | block = build_stmt (input_location, EXPR_STMT, block); |
49274 | add_stmt (block); |
49275 | |
49276 | if (ctor) |
49277 | add_decl_expr (omp_orig); |
49278 | |
49279 | if (!parens.require_close (parser)) |
49280 | return false; |
49281 | } |
49282 | |
49283 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49284 | cp_parser_required_error (parser, token_desc: RT_PRAGMA_EOL, /*keyword=*/false, |
49285 | UNKNOWN_LOCATION); |
49286 | |
49287 | return true; |
49288 | } |
49289 | |
49290 | /* OpenMP 4.0 |
49291 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ |
49292 | initializer-clause[opt] new-line |
49293 | |
49294 | initializer-clause: |
49295 | initializer (omp_priv initializer) |
49296 | initializer (function-name (argument-list)) */ |
49297 | |
49298 | static void |
49299 | cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, |
49300 | enum pragma_context) |
49301 | { |
49302 | auto_vec<tree> types; |
49303 | enum tree_code reduc_code = ERROR_MARK; |
49304 | tree reduc_id = NULL_TREE, orig_reduc_id = NULL_TREE, type; |
49305 | unsigned int i; |
49306 | cp_token *first_token; |
49307 | cp_token_cache *cp; |
49308 | int errs; |
49309 | void *p; |
49310 | |
49311 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
49312 | p = obstack_alloc (&declarator_obstack, 0); |
49313 | |
49314 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
49315 | goto fail; |
49316 | |
49317 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
49318 | { |
49319 | case CPP_PLUS: |
49320 | reduc_code = PLUS_EXPR; |
49321 | break; |
49322 | case CPP_MULT: |
49323 | reduc_code = MULT_EXPR; |
49324 | break; |
49325 | case CPP_MINUS: |
49326 | reduc_code = MINUS_EXPR; |
49327 | break; |
49328 | case CPP_AND: |
49329 | reduc_code = BIT_AND_EXPR; |
49330 | break; |
49331 | case CPP_XOR: |
49332 | reduc_code = BIT_XOR_EXPR; |
49333 | break; |
49334 | case CPP_OR: |
49335 | reduc_code = BIT_IOR_EXPR; |
49336 | break; |
49337 | case CPP_AND_AND: |
49338 | reduc_code = TRUTH_ANDIF_EXPR; |
49339 | break; |
49340 | case CPP_OR_OR: |
49341 | reduc_code = TRUTH_ORIF_EXPR; |
49342 | break; |
49343 | case CPP_NAME: |
49344 | reduc_id = orig_reduc_id = cp_parser_identifier (parser); |
49345 | break; |
49346 | default: |
49347 | cp_parser_error (parser, gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, " |
49348 | "%<|%>, %<&&%>, %<||%> or identifier" ); |
49349 | goto fail; |
49350 | } |
49351 | |
49352 | if (reduc_code != ERROR_MARK) |
49353 | cp_lexer_consume_token (lexer: parser->lexer); |
49354 | |
49355 | reduc_id = omp_reduction_id (reduc_code, reduc_id, NULL_TREE); |
49356 | if (reduc_id == error_mark_node) |
49357 | goto fail; |
49358 | |
49359 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
49360 | goto fail; |
49361 | |
49362 | /* Types may not be defined in declare reduction type list. */ |
49363 | const char *saved_message; |
49364 | saved_message = parser->type_definition_forbidden_message; |
49365 | parser->type_definition_forbidden_message |
49366 | = G_("types may not be defined in declare reduction type list" ); |
49367 | bool saved_colon_corrects_to_scope_p; |
49368 | saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
49369 | parser->colon_corrects_to_scope_p = false; |
49370 | bool saved_colon_doesnt_start_class_def_p; |
49371 | saved_colon_doesnt_start_class_def_p |
49372 | = parser->colon_doesnt_start_class_def_p; |
49373 | parser->colon_doesnt_start_class_def_p = true; |
49374 | |
49375 | while (true) |
49376 | { |
49377 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49378 | type = cp_parser_type_id (parser); |
49379 | if (type == error_mark_node) |
49380 | ; |
49381 | else if (ARITHMETIC_TYPE_P (type) |
49382 | && (orig_reduc_id == NULL_TREE |
49383 | || (TREE_CODE (type) != COMPLEX_TYPE |
49384 | && (id_equal (id: orig_reduc_id, str: "min" ) |
49385 | || id_equal (id: orig_reduc_id, str: "max" ))))) |
49386 | error_at (loc, "predeclared arithmetic type %qT in " |
49387 | "%<#pragma omp declare reduction%>" , type); |
49388 | else if (FUNC_OR_METHOD_TYPE_P (type) |
49389 | || TREE_CODE (type) == ARRAY_TYPE) |
49390 | error_at (loc, "function or array type %qT in " |
49391 | "%<#pragma omp declare reduction%>" , type); |
49392 | else if (TYPE_REF_P (type)) |
49393 | error_at (loc, "reference type %qT in " |
49394 | "%<#pragma omp declare reduction%>" , type); |
49395 | else if (TYPE_QUALS_NO_ADDR_SPACE (type)) |
49396 | error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified " |
49397 | "type %qT in %<#pragma omp declare reduction%>" , type); |
49398 | else |
49399 | types.safe_push (obj: type); |
49400 | |
49401 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
49402 | cp_lexer_consume_token (lexer: parser->lexer); |
49403 | else |
49404 | break; |
49405 | } |
49406 | |
49407 | /* Restore the saved message. */ |
49408 | parser->type_definition_forbidden_message = saved_message; |
49409 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
49410 | parser->colon_doesnt_start_class_def_p |
49411 | = saved_colon_doesnt_start_class_def_p; |
49412 | |
49413 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON) |
49414 | || types.is_empty ()) |
49415 | { |
49416 | fail: |
49417 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49418 | goto done; |
49419 | } |
49420 | |
49421 | first_token = cp_lexer_peek_token (lexer: parser->lexer); |
49422 | cp = NULL; |
49423 | errs = errorcount; |
49424 | FOR_EACH_VEC_ELT (types, i, type) |
49425 | { |
49426 | tree fntype |
49427 | = build_function_type_list (void_type_node, |
49428 | cp_build_reference_type (type, false), |
49429 | NULL_TREE); |
49430 | tree this_reduc_id = reduc_id; |
49431 | if (!dependent_type_p (type)) |
49432 | this_reduc_id = omp_reduction_id (ERROR_MARK, reduc_id, type); |
49433 | tree fndecl = build_lang_decl (FUNCTION_DECL, this_reduc_id, fntype); |
49434 | DECL_SOURCE_LOCATION (fndecl) = pragma_tok->location; |
49435 | DECL_ARTIFICIAL (fndecl) = 1; |
49436 | DECL_EXTERNAL (fndecl) = 1; |
49437 | DECL_DECLARED_INLINE_P (fndecl) = 1; |
49438 | DECL_IGNORED_P (fndecl) = 1; |
49439 | DECL_OMP_DECLARE_REDUCTION_P (fndecl) = 1; |
49440 | SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier ("<udr>" )); |
49441 | DECL_ATTRIBUTES (fndecl) |
49442 | = tree_cons (get_identifier ("gnu_inline" ), NULL_TREE, |
49443 | DECL_ATTRIBUTES (fndecl)); |
49444 | bool block_scope = false; |
49445 | if (current_function_decl) |
49446 | { |
49447 | block_scope = true; |
49448 | DECL_CONTEXT (fndecl) = current_function_decl; |
49449 | DECL_LOCAL_DECL_P (fndecl) = true; |
49450 | } |
49451 | |
49452 | if (processing_template_decl) |
49453 | fndecl = push_template_decl (fndecl); |
49454 | |
49455 | if (block_scope) |
49456 | { |
49457 | if (!processing_template_decl) |
49458 | pushdecl (fndecl); |
49459 | } |
49460 | else if (current_class_type) |
49461 | { |
49462 | if (cp == NULL) |
49463 | { |
49464 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49465 | cp_lexer_consume_token (lexer: parser->lexer); |
49466 | cp = cp_token_cache_new (first: first_token, |
49467 | last: cp_lexer_peek_nth_token (lexer: parser->lexer, |
49468 | n: 2)); |
49469 | } |
49470 | DECL_STATIC_FUNCTION_P (fndecl) = 1; |
49471 | finish_member_declaration (fndecl); |
49472 | DECL_PENDING_INLINE_INFO (fndecl) = cp; |
49473 | DECL_PENDING_INLINE_P (fndecl) = 1; |
49474 | vec_safe_push (unparsed_funs_with_definitions, obj: fndecl); |
49475 | continue; |
49476 | } |
49477 | else |
49478 | { |
49479 | DECL_CONTEXT (fndecl) = current_namespace; |
49480 | tree d = pushdecl (fndecl); |
49481 | /* We should never meet a matched duplicate decl. */ |
49482 | gcc_checking_assert (d == error_mark_node || d == fndecl); |
49483 | } |
49484 | |
49485 | tree block = NULL_TREE; |
49486 | if (!block_scope) |
49487 | start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED); |
49488 | else |
49489 | block = begin_omp_structured_block (); |
49490 | if (cp) |
49491 | { |
49492 | cp_parser_push_lexer_for_tokens (parser, cache: cp); |
49493 | parser->lexer->in_pragma = true; |
49494 | } |
49495 | |
49496 | bool ok = cp_parser_omp_declare_reduction_exprs (fndecl, parser); |
49497 | |
49498 | if (cp) |
49499 | cp_parser_pop_lexer (parser); |
49500 | if (!block_scope) |
49501 | finish_function (/*inline_p=*/false); |
49502 | else |
49503 | { |
49504 | DECL_CONTEXT (fndecl) = current_function_decl; |
49505 | if (DECL_TEMPLATE_INFO (fndecl)) |
49506 | DECL_CONTEXT (DECL_TI_TEMPLATE (fndecl)) = current_function_decl; |
49507 | } |
49508 | if (!ok) |
49509 | goto fail; |
49510 | |
49511 | if (block_scope) |
49512 | { |
49513 | block = finish_omp_structured_block (block); |
49514 | if (TREE_CODE (block) == BIND_EXPR) |
49515 | DECL_SAVED_TREE (fndecl) = BIND_EXPR_BODY (block); |
49516 | else if (TREE_CODE (block) == STATEMENT_LIST) |
49517 | DECL_SAVED_TREE (fndecl) = block; |
49518 | if (processing_template_decl) |
49519 | add_decl_expr (fndecl); |
49520 | } |
49521 | |
49522 | cp_check_omp_declare_reduction (fndecl); |
49523 | if (cp == NULL && types.length () > 1) |
49524 | cp = cp_token_cache_new (first: first_token, |
49525 | last: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
49526 | if (errs != errorcount) |
49527 | break; |
49528 | } |
49529 | |
49530 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49531 | |
49532 | done: |
49533 | /* Free any declarators allocated. */ |
49534 | obstack_free (&declarator_obstack, p); |
49535 | } |
49536 | |
49537 | /* OpenMP 4.0 |
49538 | #pragma omp declare simd declare-simd-clauses[optseq] new-line |
49539 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ |
49540 | initializer-clause[opt] new-line |
49541 | #pragma omp declare target new-line |
49542 | |
49543 | OpenMP 5.0 |
49544 | #pragma omp declare variant (identifier) match (context-selector) */ |
49545 | |
49546 | static bool |
49547 | cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok, |
49548 | enum pragma_context context) |
49549 | { |
49550 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49551 | { |
49552 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49553 | const char *p = IDENTIFIER_POINTER (id); |
49554 | |
49555 | if (strcmp (s1: p, s2: "simd" ) == 0) |
49556 | { |
49557 | cp_lexer_consume_token (lexer: parser->lexer); |
49558 | cp_parser_omp_declare_simd (parser, pragma_tok, |
49559 | context, variant_p: false); |
49560 | return true; |
49561 | } |
49562 | if (flag_openmp && strcmp (s1: p, s2: "variant" ) == 0) |
49563 | { |
49564 | cp_lexer_consume_token (lexer: parser->lexer); |
49565 | cp_parser_omp_declare_simd (parser, pragma_tok, |
49566 | context, variant_p: true); |
49567 | return true; |
49568 | } |
49569 | cp_ensure_no_omp_declare_simd (parser); |
49570 | if (strcmp (s1: p, s2: "reduction" ) == 0) |
49571 | { |
49572 | cp_lexer_consume_token (lexer: parser->lexer); |
49573 | cp_parser_omp_declare_reduction (parser, pragma_tok, |
49574 | context); |
49575 | return false; |
49576 | } |
49577 | if (!flag_openmp) /* flag_openmp_simd */ |
49578 | { |
49579 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49580 | return false; |
49581 | } |
49582 | if (strcmp (s1: p, s2: "target" ) == 0) |
49583 | { |
49584 | cp_lexer_consume_token (lexer: parser->lexer); |
49585 | cp_parser_omp_declare_target (parser, pragma_tok); |
49586 | return false; |
49587 | } |
49588 | } |
49589 | cp_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, " |
49590 | "%<target%> or %<variant%>" ); |
49591 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49592 | return false; |
49593 | } |
49594 | |
49595 | /* OpenMP 5.0 |
49596 | #pragma omp requires clauses[optseq] new-line */ |
49597 | |
49598 | static bool |
49599 | cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) |
49600 | { |
49601 | enum omp_requires new_req = (enum omp_requires) 0; |
49602 | |
49603 | location_t loc = pragma_tok->location; |
49604 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49605 | { |
49606 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
49607 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
49608 | cp_lexer_consume_token (lexer: parser->lexer); |
49609 | |
49610 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49611 | { |
49612 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49613 | const char *p = IDENTIFIER_POINTER (id); |
49614 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49615 | enum omp_requires this_req = (enum omp_requires) 0; |
49616 | |
49617 | if (!strcmp (s1: p, s2: "unified_address" )) |
49618 | this_req = OMP_REQUIRES_UNIFIED_ADDRESS; |
49619 | else if (!strcmp (s1: p, s2: "unified_shared_memory" )) |
49620 | this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY; |
49621 | else if (!strcmp (s1: p, s2: "dynamic_allocators" )) |
49622 | this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS; |
49623 | else if (!strcmp (s1: p, s2: "reverse_offload" )) |
49624 | this_req = OMP_REQUIRES_REVERSE_OFFLOAD; |
49625 | else if (!strcmp (s1: p, s2: "atomic_default_mem_order" )) |
49626 | { |
49627 | cp_lexer_consume_token (lexer: parser->lexer); |
49628 | |
49629 | matching_parens parens; |
49630 | if (parens.require_open (parser)) |
49631 | { |
49632 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49633 | { |
49634 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49635 | p = IDENTIFIER_POINTER (id); |
49636 | |
49637 | if (!strcmp (s1: p, s2: "seq_cst" )) |
49638 | this_req |
49639 | = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST; |
49640 | else if (!strcmp (s1: p, s2: "relaxed" )) |
49641 | this_req |
49642 | = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED; |
49643 | else if (!strcmp (s1: p, s2: "release" )) |
49644 | this_req |
49645 | = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE; |
49646 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
49647 | this_req |
49648 | = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL; |
49649 | else if (!strcmp (s1: p, s2: "acquire" )) |
49650 | this_req |
49651 | = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE; |
49652 | } |
49653 | if (this_req == 0) |
49654 | { |
49655 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
49656 | "expected %<acq_rel%>, %<acquire%>, " |
49657 | "%<relaxed%>, %<release%> or %<seq_cst%>" ); |
49658 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
49659 | { |
49660 | case CPP_EOF: |
49661 | case CPP_PRAGMA_EOL: |
49662 | case CPP_CLOSE_PAREN: |
49663 | break; |
49664 | default: |
49665 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
49666 | type: CPP_CLOSE_PAREN)) |
49667 | cp_lexer_consume_token (lexer: parser->lexer); |
49668 | break; |
49669 | } |
49670 | } |
49671 | else |
49672 | cp_lexer_consume_token (lexer: parser->lexer); |
49673 | |
49674 | if (!parens.require_close (parser)) |
49675 | cp_parser_skip_to_closing_parenthesis (parser, |
49676 | /*recovering=*/true, |
49677 | /*or_comma=*/false, |
49678 | /*consume_paren=*/ |
49679 | true); |
49680 | |
49681 | if (this_req == 0) |
49682 | { |
49683 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49684 | return false; |
49685 | } |
49686 | } |
49687 | p = NULL; |
49688 | } |
49689 | else |
49690 | { |
49691 | error_at (cloc, "expected %<unified_address%>, " |
49692 | "%<unified_shared_memory%>, " |
49693 | "%<dynamic_allocators%>, " |
49694 | "%<reverse_offload%> " |
49695 | "or %<atomic_default_mem_order%> clause" ); |
49696 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49697 | return false; |
49698 | } |
49699 | if (p) |
49700 | cp_lexer_consume_token (lexer: parser->lexer); |
49701 | if (this_req) |
49702 | { |
49703 | if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49704 | { |
49705 | if ((this_req & new_req) != 0) |
49706 | error_at (cloc, "too many %qs clauses" , p); |
49707 | if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS |
49708 | && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0) |
49709 | error_at (cloc, "%qs clause used lexically after first " |
49710 | "target construct or offloading API" , p); |
49711 | } |
49712 | else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49713 | { |
49714 | error_at (cloc, "too many %qs clauses" , |
49715 | "atomic_default_mem_order" ); |
49716 | this_req = (enum omp_requires) 0; |
49717 | } |
49718 | else if ((omp_requires_mask |
49719 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49720 | { |
49721 | error_at (cloc, "more than one %<atomic_default_mem_order%>" |
49722 | " clause in a single compilation unit" ); |
49723 | this_req |
49724 | = (enum omp_requires) |
49725 | (omp_requires_mask |
49726 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER); |
49727 | } |
49728 | else if ((omp_requires_mask |
49729 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0) |
49730 | error_at (cloc, "%<atomic_default_mem_order%> clause used " |
49731 | "lexically after first %<atomic%> construct " |
49732 | "without memory order clause" ); |
49733 | new_req = (enum omp_requires) (new_req | this_req); |
49734 | omp_requires_mask |
49735 | = (enum omp_requires) (omp_requires_mask | this_req); |
49736 | continue; |
49737 | } |
49738 | } |
49739 | break; |
49740 | } |
49741 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49742 | |
49743 | if (new_req == 0) |
49744 | error_at (loc, "%<pragma omp requires%> requires at least one clause" ); |
49745 | return false; |
49746 | } |
49747 | |
49748 | |
49749 | /* OpenMP 5.1: |
49750 | #pragma omp nothing new-line */ |
49751 | |
49752 | static void |
49753 | cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok) |
49754 | { |
49755 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49756 | } |
49757 | |
49758 | |
49759 | /* OpenMP 5.1 |
49760 | #pragma omp error clauses[optseq] new-line */ |
49761 | |
49762 | static bool |
49763 | cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, |
49764 | enum pragma_context context) |
49765 | { |
49766 | int at_compilation = -1; |
49767 | int severity_fatal = -1; |
49768 | tree message = NULL_TREE; |
49769 | bool bad = false; |
49770 | location_t loc = pragma_tok->location; |
49771 | |
49772 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49773 | { |
49774 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
49775 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
49776 | cp_lexer_consume_token (lexer: parser->lexer); |
49777 | |
49778 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
49779 | break; |
49780 | |
49781 | const char *p |
49782 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
49783 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49784 | static const char *args[] = { |
49785 | "execution" , "compilation" , "warning" , "fatal" |
49786 | }; |
49787 | int *v = NULL; |
49788 | int idx = 0, n = -1; |
49789 | tree m = NULL_TREE; |
49790 | |
49791 | if (!strcmp (s1: p, s2: "at" )) |
49792 | v = &at_compilation; |
49793 | else if (!strcmp (s1: p, s2: "severity" )) |
49794 | { |
49795 | v = &severity_fatal; |
49796 | idx += 2; |
49797 | } |
49798 | else if (strcmp (s1: p, s2: "message" )) |
49799 | { |
49800 | error_at (cloc, |
49801 | "expected %<at%>, %<severity%> or %<message%> clause" ); |
49802 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49803 | return false; |
49804 | } |
49805 | |
49806 | cp_lexer_consume_token (lexer: parser->lexer); |
49807 | |
49808 | matching_parens parens; |
49809 | if (parens.require_open (parser)) |
49810 | { |
49811 | if (v == NULL) |
49812 | { |
49813 | m = cp_parser_assignment_expression (parser); |
49814 | if (type_dependent_expression_p (m)) |
49815 | m = build1 (IMPLICIT_CONV_EXPR, const_string_type_node, m); |
49816 | else |
49817 | m = perform_implicit_conversion_flags (const_string_type_node, m, |
49818 | tf_warning_or_error, |
49819 | LOOKUP_NORMAL); |
49820 | } |
49821 | else |
49822 | { |
49823 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49824 | { |
49825 | tree val = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49826 | const char *q = IDENTIFIER_POINTER (val); |
49827 | |
49828 | if (!strcmp (s1: q, s2: args[idx])) |
49829 | n = 0; |
49830 | else if (!strcmp (s1: q, s2: args[idx + 1])) |
49831 | n = 1; |
49832 | } |
49833 | if (n == -1) |
49834 | { |
49835 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
49836 | "expected %qs or %qs" , args[idx], args[idx + 1]); |
49837 | bad = true; |
49838 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
49839 | { |
49840 | case CPP_EOF: |
49841 | case CPP_PRAGMA_EOL: |
49842 | case CPP_CLOSE_PAREN: |
49843 | break; |
49844 | default: |
49845 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
49846 | type: CPP_CLOSE_PAREN)) |
49847 | cp_lexer_consume_token (lexer: parser->lexer); |
49848 | break; |
49849 | } |
49850 | } |
49851 | else |
49852 | cp_lexer_consume_token (lexer: parser->lexer); |
49853 | } |
49854 | |
49855 | if (!parens.require_close (parser)) |
49856 | cp_parser_skip_to_closing_parenthesis (parser, |
49857 | /*recovering=*/true, |
49858 | /*or_comma=*/false, |
49859 | /*consume_paren=*/ |
49860 | true); |
49861 | |
49862 | if (v == NULL) |
49863 | { |
49864 | if (message) |
49865 | { |
49866 | error_at (cloc, "too many %qs clauses" , p); |
49867 | bad = true; |
49868 | } |
49869 | else |
49870 | message = m; |
49871 | } |
49872 | else if (n != -1) |
49873 | { |
49874 | if (*v != -1) |
49875 | { |
49876 | error_at (cloc, "too many %qs clauses" , p); |
49877 | bad = true; |
49878 | } |
49879 | else |
49880 | *v = n; |
49881 | } |
49882 | } |
49883 | else |
49884 | bad = true; |
49885 | } |
49886 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49887 | if (bad) |
49888 | return true; |
49889 | |
49890 | if (at_compilation == -1) |
49891 | at_compilation = 1; |
49892 | if (severity_fatal == -1) |
49893 | severity_fatal = 1; |
49894 | if (!at_compilation) |
49895 | { |
49896 | if (context != pragma_compound) |
49897 | { |
49898 | error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause " |
49899 | "may only be used in compound statements" ); |
49900 | return true; |
49901 | } |
49902 | tree fndecl |
49903 | = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR |
49904 | : BUILT_IN_GOMP_WARNING); |
49905 | if (!message) |
49906 | message = build_zero_cst (const_string_type_node); |
49907 | tree stmt = build_call_expr_loc (loc, fndecl, 2, message, |
49908 | build_all_ones_cst (size_type_node)); |
49909 | add_stmt (stmt); |
49910 | return true; |
49911 | } |
49912 | |
49913 | if (in_discarded_stmt) |
49914 | return false; |
49915 | |
49916 | const char *msg = NULL; |
49917 | if (message) |
49918 | { |
49919 | msg = c_getstr (fold_for_warn (message)); |
49920 | if (msg == NULL) |
49921 | msg = _("<message unknown at compile time>" ); |
49922 | } |
49923 | if (msg) |
49924 | emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, |
49925 | "%<pragma omp error%> encountered: %s" , msg); |
49926 | else |
49927 | emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, |
49928 | "%<pragma omp error%> encountered" ); |
49929 | return false; |
49930 | } |
49931 | |
49932 | /* OpenMP 4.5: |
49933 | #pragma omp taskloop taskloop-clause[optseq] new-line |
49934 | for-loop |
49935 | |
49936 | #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line |
49937 | for-loop */ |
49938 | |
49939 | #define OMP_TASKLOOP_CLAUSE_MASK \ |
49940 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
49941 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
49942 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
49943 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
49944 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
49945 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \ |
49946 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \ |
49947 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
49948 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ |
49949 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
49950 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ |
49951 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ |
49952 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \ |
49953 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ |
49954 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
49955 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
49956 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION)) |
49957 | |
49958 | static tree |
49959 | cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok, |
49960 | char *p_name, omp_clause_mask mask, tree *cclauses, |
49961 | bool *if_p) |
49962 | { |
49963 | tree clauses, sb, ret; |
49964 | unsigned int save; |
49965 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49966 | |
49967 | strcat (dest: p_name, src: " taskloop" ); |
49968 | mask |= OMP_TASKLOOP_CLAUSE_MASK; |
49969 | /* #pragma omp parallel master taskloop{, simd} disallow in_reduction |
49970 | clause. */ |
49971 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) |
49972 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION); |
49973 | |
49974 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49975 | { |
49976 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49977 | const char *p = IDENTIFIER_POINTER (id); |
49978 | |
49979 | if (strcmp (s1: p, s2: "simd" ) == 0) |
49980 | { |
49981 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
49982 | if (cclauses == NULL) |
49983 | cclauses = cclauses_buf; |
49984 | |
49985 | cp_lexer_consume_token (lexer: parser->lexer); |
49986 | if (!flag_openmp) /* flag_openmp_simd */ |
49987 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
49988 | cclauses, if_p); |
49989 | sb = begin_omp_structured_block (); |
49990 | save = cp_parser_begin_omp_structured_block (parser); |
49991 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
49992 | cclauses, if_p); |
49993 | cp_parser_end_omp_structured_block (parser, save); |
49994 | tree body = finish_omp_structured_block (sb); |
49995 | if (ret == NULL) |
49996 | return ret; |
49997 | ret = make_node (OMP_TASKLOOP); |
49998 | TREE_TYPE (ret) = void_type_node; |
49999 | OMP_FOR_BODY (ret) = body; |
50000 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; |
50001 | SET_EXPR_LOCATION (ret, loc); |
50002 | add_stmt (ret); |
50003 | return ret; |
50004 | } |
50005 | } |
50006 | if (!flag_openmp) /* flag_openmp_simd */ |
50007 | { |
50008 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50009 | return NULL_TREE; |
50010 | } |
50011 | |
50012 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
50013 | finish_p: cclauses == NULL); |
50014 | if (cclauses) |
50015 | { |
50016 | cp_omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses); |
50017 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; |
50018 | } |
50019 | |
50020 | keep_next_level (true); |
50021 | sb = begin_omp_structured_block (); |
50022 | save = cp_parser_begin_omp_structured_block (parser); |
50023 | |
50024 | ret = cp_parser_omp_for_loop (parser, code: OMP_TASKLOOP, clauses, cclauses, |
50025 | if_p); |
50026 | |
50027 | cp_parser_end_omp_structured_block (parser, save); |
50028 | add_stmt (finish_omp_structured_block (sb)); |
50029 | |
50030 | return ret; |
50031 | } |
50032 | |
50033 | |
50034 | /* OpenACC 2.0: |
50035 | # pragma acc routine oacc-routine-clause[optseq] new-line |
50036 | function-definition |
50037 | |
50038 | # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line |
50039 | */ |
50040 | |
50041 | #define OACC_ROUTINE_CLAUSE_MASK \ |
50042 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ |
50043 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ |
50044 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ |
50045 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ |
50046 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) ) |
50047 | |
50048 | /* Parse the OpenACC routine pragma. This has an optional '( name )' |
50049 | component, which must resolve to a declared namespace-scope |
50050 | function. The clauses are either processed directly (for a named |
50051 | function), or defered until the immediatley following declaration |
50052 | is parsed. */ |
50053 | |
50054 | static void |
50055 | cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, |
50056 | enum pragma_context context) |
50057 | { |
50058 | gcc_checking_assert (context == pragma_external); |
50059 | /* The checking for "another pragma following this one" in the "no optional |
50060 | '( name )'" case makes sure that we dont re-enter. */ |
50061 | gcc_checking_assert (parser->oacc_routine == NULL); |
50062 | |
50063 | cp_oacc_routine_data data; |
50064 | data.error_seen = false; |
50065 | data.fndecl_seen = false; |
50066 | data.tokens = vNULL; |
50067 | data.clauses = NULL_TREE; |
50068 | data.loc = pragma_tok->location; |
50069 | /* It is safe to take the address of a local variable; it will only be |
50070 | used while this scope is live. */ |
50071 | parser->oacc_routine = &data; |
50072 | |
50073 | /* Look for optional '( name )'. */ |
50074 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
50075 | { |
50076 | matching_parens parens; |
50077 | parens.consume_open (parser); /* '(' */ |
50078 | |
50079 | /* We parse the name as an id-expression. If it resolves to |
50080 | anything other than a non-overloaded function at namespace |
50081 | scope, it's an error. */ |
50082 | location_t name_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
50083 | tree name = cp_parser_id_expression (parser, |
50084 | /*template_keyword_p=*/false, |
50085 | /*check_dependency_p=*/false, |
50086 | /*template_p=*/NULL, |
50087 | /*declarator_p=*/false, |
50088 | /*optional_p=*/false); |
50089 | tree decl = (identifier_p (t: name) |
50090 | ? cp_parser_lookup_name_simple (parser, name, location: name_loc) |
50091 | : name); |
50092 | if (name != error_mark_node && decl == error_mark_node) |
50093 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, location: name_loc); |
50094 | |
50095 | if (decl == error_mark_node |
50096 | || !parens.require_close (parser)) |
50097 | { |
50098 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50099 | parser->oacc_routine = NULL; |
50100 | return; |
50101 | } |
50102 | |
50103 | data.clauses |
50104 | = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, |
50105 | where: "#pragma acc routine" , |
50106 | pragma_tok: cp_lexer_peek_token (lexer: parser->lexer)); |
50107 | /* The clauses are in reverse order; fix that to make later diagnostic |
50108 | emission easier. */ |
50109 | data.clauses = nreverse (data.clauses); |
50110 | |
50111 | if (decl && is_overloaded_fn (decl) |
50112 | && (TREE_CODE (decl) != FUNCTION_DECL |
50113 | || DECL_FUNCTION_TEMPLATE_P (decl))) |
50114 | { |
50115 | error_at (name_loc, |
50116 | "%<#pragma acc routine%> names a set of overloads" ); |
50117 | parser->oacc_routine = NULL; |
50118 | return; |
50119 | } |
50120 | |
50121 | /* Perhaps we should use the same rule as declarations in different |
50122 | namespaces? */ |
50123 | if (!DECL_NAMESPACE_SCOPE_P (decl)) |
50124 | { |
50125 | error_at (name_loc, |
50126 | "%qD does not refer to a namespace scope function" , decl); |
50127 | parser->oacc_routine = NULL; |
50128 | return; |
50129 | } |
50130 | |
50131 | if (TREE_CODE (decl) != FUNCTION_DECL) |
50132 | { |
50133 | error_at (name_loc, "%qD does not refer to a function" , decl); |
50134 | parser->oacc_routine = NULL; |
50135 | return; |
50136 | } |
50137 | |
50138 | cp_finalize_oacc_routine (parser, decl, false); |
50139 | parser->oacc_routine = NULL; |
50140 | } |
50141 | else /* No optional '( name )'. */ |
50142 | { |
50143 | /* Store away all pragma tokens. */ |
50144 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
50145 | cp_lexer_consume_token (lexer: parser->lexer); |
50146 | cp_parser_require_pragma_eol (parser, pragma_tok); |
50147 | struct cp_token_cache *cp |
50148 | = cp_token_cache_new (first: pragma_tok, last: cp_lexer_peek_token (lexer: parser->lexer)); |
50149 | parser->oacc_routine->tokens.safe_push (obj: cp); |
50150 | |
50151 | /* Emit a helpful diagnostic if there's another pragma following this |
50152 | one. */ |
50153 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
50154 | { |
50155 | cp_ensure_no_oacc_routine (parser); |
50156 | data.tokens.release (); |
50157 | /* ..., and then just keep going. */ |
50158 | return; |
50159 | } |
50160 | |
50161 | /* We only have to consider the pragma_external case here. */ |
50162 | cp_parser_declaration (parser, NULL_TREE); |
50163 | if (parser->oacc_routine |
50164 | && !parser->oacc_routine->fndecl_seen) |
50165 | cp_ensure_no_oacc_routine (parser); |
50166 | else |
50167 | parser->oacc_routine = NULL; |
50168 | data.tokens.release (); |
50169 | } |
50170 | } |
50171 | |
50172 | /* Finalize #pragma acc routine clauses after direct declarator has |
50173 | been parsed. */ |
50174 | |
50175 | static tree |
50176 | cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs) |
50177 | { |
50178 | struct cp_token_cache *ce; |
50179 | cp_oacc_routine_data *data = parser->oacc_routine; |
50180 | |
50181 | if (!data->error_seen && data->fndecl_seen) |
50182 | { |
50183 | error_at (data->loc, |
50184 | "%<#pragma acc routine%> not immediately followed by " |
50185 | "a single function declaration or definition" ); |
50186 | data->error_seen = true; |
50187 | } |
50188 | if (data->error_seen) |
50189 | return attrs; |
50190 | |
50191 | gcc_checking_assert (data->tokens.length () == 1); |
50192 | ce = data->tokens[0]; |
50193 | |
50194 | cp_parser_push_lexer_for_tokens (parser, cache: ce); |
50195 | parser->lexer->in_pragma = true; |
50196 | gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA); |
50197 | |
50198 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
50199 | gcc_checking_assert (parser->oacc_routine->clauses == NULL_TREE); |
50200 | parser->oacc_routine->clauses |
50201 | = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, |
50202 | where: "#pragma acc routine" , pragma_tok); |
50203 | /* The clauses are in reverse order; fix that to make later diagnostic |
50204 | emission easier. */ |
50205 | parser->oacc_routine->clauses = nreverse (parser->oacc_routine->clauses); |
50206 | cp_parser_pop_lexer (parser); |
50207 | /* Later, cp_finalize_oacc_routine will process the clauses. */ |
50208 | parser->oacc_routine->fndecl_seen = true; |
50209 | |
50210 | return attrs; |
50211 | } |
50212 | |
50213 | /* Apply any saved OpenACC routine clauses to a just-parsed |
50214 | declaration. */ |
50215 | |
50216 | static void |
50217 | cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn) |
50218 | { |
50219 | if (UNLIKELY (parser->oacc_routine != NULL)) |
50220 | { |
50221 | /* Keep going if we're in error reporting mode. */ |
50222 | if (parser->oacc_routine->error_seen |
50223 | || fndecl == error_mark_node) |
50224 | return; |
50225 | |
50226 | if (TREE_CODE (fndecl) != FUNCTION_DECL) |
50227 | { |
50228 | if (parser->oacc_routine->fndecl_seen) |
50229 | { |
50230 | error_at (parser->oacc_routine->loc, |
50231 | "%<#pragma acc routine%> not immediately followed by" |
50232 | " a single function declaration or definition" ); |
50233 | parser->oacc_routine = NULL; |
50234 | return; |
50235 | } |
50236 | |
50237 | cp_ensure_no_oacc_routine (parser); |
50238 | return; |
50239 | } |
50240 | |
50241 | int compatible |
50242 | = oacc_verify_routine_clauses (fndecl, &parser->oacc_routine->clauses, |
50243 | parser->oacc_routine->loc, |
50244 | "#pragma acc routine" ); |
50245 | if (compatible < 0) |
50246 | { |
50247 | parser->oacc_routine = NULL; |
50248 | return; |
50249 | } |
50250 | if (compatible > 0) |
50251 | { |
50252 | } |
50253 | else |
50254 | { |
50255 | if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl))) |
50256 | { |
50257 | error_at (parser->oacc_routine->loc, |
50258 | TREE_USED (fndecl) |
50259 | ? G_("%<#pragma acc routine%> must be applied before" |
50260 | " use" ) |
50261 | : G_("%<#pragma acc routine%> must be applied before" |
50262 | " definition" )); |
50263 | parser->oacc_routine = NULL; |
50264 | return; |
50265 | } |
50266 | |
50267 | /* Set the routine's level of parallelism. */ |
50268 | tree dims = oacc_build_routine_dims (clauses: parser->oacc_routine->clauses); |
50269 | oacc_replace_fn_attrib (fn: fndecl, dims); |
50270 | |
50271 | /* Add an "omp declare target" attribute. */ |
50272 | DECL_ATTRIBUTES (fndecl) |
50273 | = tree_cons (get_identifier ("omp declare target" ), |
50274 | parser->oacc_routine->clauses, |
50275 | DECL_ATTRIBUTES (fndecl)); |
50276 | } |
50277 | } |
50278 | } |
50279 | |
50280 | /* Main entry point to OpenMP statement pragmas. */ |
50281 | |
50282 | static void |
50283 | cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
50284 | { |
50285 | tree stmt; |
50286 | char p_name[sizeof "#pragma omp teams distribute parallel for simd" ]; |
50287 | omp_clause_mask mask (0); |
50288 | |
50289 | switch (cp_parser_pragma_kind (token: pragma_tok)) |
50290 | { |
50291 | case PRAGMA_OACC_ATOMIC: |
50292 | cp_parser_omp_atomic (parser, pragma_tok, openacc: true); |
50293 | return; |
50294 | case PRAGMA_OACC_CACHE: |
50295 | stmt = cp_parser_oacc_cache (parser, pragma_tok); |
50296 | break; |
50297 | case PRAGMA_OACC_DATA: |
50298 | stmt = cp_parser_oacc_data (parser, pragma_tok, if_p); |
50299 | break; |
50300 | case PRAGMA_OACC_ENTER_DATA: |
50301 | stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, enter: true); |
50302 | break; |
50303 | case PRAGMA_OACC_EXIT_DATA: |
50304 | stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, enter: false); |
50305 | break; |
50306 | case PRAGMA_OACC_HOST_DATA: |
50307 | stmt = cp_parser_oacc_host_data (parser, pragma_tok, if_p); |
50308 | break; |
50309 | case PRAGMA_OACC_KERNELS: |
50310 | case PRAGMA_OACC_PARALLEL: |
50311 | case PRAGMA_OACC_SERIAL: |
50312 | strcpy (dest: p_name, src: "#pragma acc" ); |
50313 | stmt = cp_parser_oacc_compute (parser, pragma_tok, p_name, if_p); |
50314 | break; |
50315 | case PRAGMA_OACC_LOOP: |
50316 | strcpy (dest: p_name, src: "#pragma acc" ); |
50317 | stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL, |
50318 | if_p); |
50319 | break; |
50320 | case PRAGMA_OACC_UPDATE: |
50321 | stmt = cp_parser_oacc_update (parser, pragma_tok); |
50322 | break; |
50323 | case PRAGMA_OACC_WAIT: |
50324 | stmt = cp_parser_oacc_wait (parser, pragma_tok); |
50325 | break; |
50326 | case PRAGMA_OMP_ALLOCATE: |
50327 | cp_parser_omp_allocate (parser, pragma_tok); |
50328 | return; |
50329 | case PRAGMA_OMP_ATOMIC: |
50330 | cp_parser_omp_atomic (parser, pragma_tok, openacc: false); |
50331 | return; |
50332 | case PRAGMA_OMP_CRITICAL: |
50333 | stmt = cp_parser_omp_critical (parser, pragma_tok, if_p); |
50334 | break; |
50335 | case PRAGMA_OMP_DISTRIBUTE: |
50336 | strcpy (dest: p_name, src: "#pragma omp" ); |
50337 | stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL, |
50338 | if_p); |
50339 | break; |
50340 | case PRAGMA_OMP_FOR: |
50341 | strcpy (dest: p_name, src: "#pragma omp" ); |
50342 | stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL, |
50343 | if_p); |
50344 | break; |
50345 | case PRAGMA_OMP_LOOP: |
50346 | strcpy (dest: p_name, src: "#pragma omp" ); |
50347 | stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL, |
50348 | if_p); |
50349 | break; |
50350 | case PRAGMA_OMP_MASKED: |
50351 | strcpy (dest: p_name, src: "#pragma omp" ); |
50352 | stmt = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, NULL, |
50353 | if_p); |
50354 | break; |
50355 | case PRAGMA_OMP_MASTER: |
50356 | strcpy (dest: p_name, src: "#pragma omp" ); |
50357 | stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, |
50358 | if_p); |
50359 | break; |
50360 | case PRAGMA_OMP_PARALLEL: |
50361 | strcpy (dest: p_name, src: "#pragma omp" ); |
50362 | stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL, |
50363 | if_p); |
50364 | break; |
50365 | case PRAGMA_OMP_SCOPE: |
50366 | stmt = cp_parser_omp_scope (parser, pragma_tok, if_p); |
50367 | break; |
50368 | case PRAGMA_OMP_SECTIONS: |
50369 | strcpy (dest: p_name, src: "#pragma omp" ); |
50370 | stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL); |
50371 | break; |
50372 | case PRAGMA_OMP_SIMD: |
50373 | strcpy (dest: p_name, src: "#pragma omp" ); |
50374 | stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL, |
50375 | if_p); |
50376 | break; |
50377 | case PRAGMA_OMP_SINGLE: |
50378 | stmt = cp_parser_omp_single (parser, pragma_tok, if_p); |
50379 | break; |
50380 | case PRAGMA_OMP_TASK: |
50381 | stmt = cp_parser_omp_task (parser, pragma_tok, if_p); |
50382 | break; |
50383 | case PRAGMA_OMP_TASKGROUP: |
50384 | stmt = cp_parser_omp_taskgroup (parser, pragma_tok, if_p); |
50385 | break; |
50386 | case PRAGMA_OMP_TASKLOOP: |
50387 | strcpy (dest: p_name, src: "#pragma omp" ); |
50388 | stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL, |
50389 | if_p); |
50390 | break; |
50391 | case PRAGMA_OMP_TEAMS: |
50392 | strcpy (dest: p_name, src: "#pragma omp" ); |
50393 | stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL, |
50394 | if_p); |
50395 | break; |
50396 | case PRAGMA_OMP_ASSUME: |
50397 | cp_parser_omp_assume (parser, pragma_tok, if_p); |
50398 | return; |
50399 | default: |
50400 | gcc_unreachable (); |
50401 | } |
50402 | |
50403 | protected_set_expr_location (stmt, pragma_tok->location); |
50404 | } |
50405 | |
50406 | /* Transactional Memory parsing routines. */ |
50407 | |
50408 | /* Parse a transaction attribute. |
50409 | |
50410 | txn-attribute: |
50411 | attribute |
50412 | [ [ identifier ] ] |
50413 | |
50414 | We use this instead of cp_parser_attributes_opt for transactions to avoid |
50415 | the pedwarn in C++98 mode. */ |
50416 | |
50417 | static tree |
50418 | cp_parser_txn_attribute_opt (cp_parser *parser) |
50419 | { |
50420 | cp_token *token; |
50421 | tree attr_name, attr = NULL; |
50422 | |
50423 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ATTRIBUTE)) |
50424 | return cp_parser_attributes_opt (parser); |
50425 | |
50426 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
50427 | return NULL_TREE; |
50428 | cp_lexer_consume_token (lexer: parser->lexer); |
50429 | if (!cp_parser_require (parser, type: CPP_OPEN_SQUARE, token_desc: RT_OPEN_SQUARE)) |
50430 | goto error1; |
50431 | |
50432 | token = cp_lexer_peek_token (lexer: parser->lexer); |
50433 | if (token->type == CPP_NAME || token->type == CPP_KEYWORD) |
50434 | { |
50435 | token = cp_lexer_consume_token (lexer: parser->lexer); |
50436 | |
50437 | attr_name = (token->type == CPP_KEYWORD |
50438 | /* For keywords, use the canonical spelling, |
50439 | not the parsed identifier. */ |
50440 | ? ridpointers[(int) token->keyword] |
50441 | : token->u.value); |
50442 | attr = build_tree_list (attr_name, NULL_TREE); |
50443 | } |
50444 | else |
50445 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
50446 | |
50447 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
50448 | error1: |
50449 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
50450 | return attr; |
50451 | } |
50452 | |
50453 | /* Parse a __transaction_atomic or __transaction_relaxed statement. |
50454 | |
50455 | transaction-statement: |
50456 | __transaction_atomic txn-attribute[opt] txn-noexcept-spec[opt] |
50457 | compound-statement |
50458 | __transaction_relaxed txn-noexcept-spec[opt] compound-statement |
50459 | */ |
50460 | |
50461 | static tree |
50462 | cp_parser_transaction (cp_parser *parser, cp_token *token) |
50463 | { |
50464 | unsigned char old_in = parser->in_transaction; |
50465 | unsigned char this_in = 1, new_in; |
50466 | enum rid keyword = token->keyword; |
50467 | tree stmt, attrs, noex; |
50468 | |
50469 | cp_lexer_consume_token (lexer: parser->lexer); |
50470 | |
50471 | if (keyword == RID_TRANSACTION_RELAXED |
50472 | || keyword == RID_SYNCHRONIZED) |
50473 | this_in |= TM_STMT_ATTR_RELAXED; |
50474 | else |
50475 | { |
50476 | attrs = cp_parser_txn_attribute_opt (parser); |
50477 | if (attrs) |
50478 | this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); |
50479 | } |
50480 | |
50481 | /* Parse a noexcept specification. */ |
50482 | if (keyword == RID_ATOMIC_NOEXCEPT) |
50483 | noex = boolean_true_node; |
50484 | else if (keyword == RID_ATOMIC_CANCEL) |
50485 | { |
50486 | /* cancel-and-throw is unimplemented. */ |
50487 | sorry ("%<atomic_cancel%>" ); |
50488 | noex = NULL_TREE; |
50489 | } |
50490 | else |
50491 | noex = cp_parser_noexcept_specification_opt (parser, |
50492 | flags: CP_PARSER_FLAGS_NONE, |
50493 | /*require_constexpr=*/true, |
50494 | /*consumed_expr=*/NULL, |
50495 | /*return_cond=*/true); |
50496 | |
50497 | /* Keep track if we're in the lexical scope of an outer transaction. */ |
50498 | new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); |
50499 | |
50500 | stmt = begin_transaction_stmt (token->location, NULL, this_in); |
50501 | |
50502 | parser->in_transaction = new_in; |
50503 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_TRANSACTION, function_body: false); |
50504 | parser->in_transaction = old_in; |
50505 | |
50506 | finish_transaction_stmt (stmt, NULL, this_in, noex); |
50507 | |
50508 | return stmt; |
50509 | } |
50510 | |
50511 | /* Parse a __transaction_atomic or __transaction_relaxed expression. |
50512 | |
50513 | transaction-expression: |
50514 | __transaction_atomic txn-noexcept-spec[opt] ( expression ) |
50515 | __transaction_relaxed txn-noexcept-spec[opt] ( expression ) |
50516 | */ |
50517 | |
50518 | static tree |
50519 | cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) |
50520 | { |
50521 | unsigned char old_in = parser->in_transaction; |
50522 | unsigned char this_in = 1; |
50523 | cp_token *token; |
50524 | tree expr, noex; |
50525 | bool noex_expr; |
50526 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
50527 | |
50528 | gcc_assert (keyword == RID_TRANSACTION_ATOMIC |
50529 | || keyword == RID_TRANSACTION_RELAXED); |
50530 | |
50531 | if (!flag_tm) |
50532 | error_at (loc, |
50533 | keyword == RID_TRANSACTION_RELAXED |
50534 | ? G_("%<__transaction_relaxed%> without transactional memory " |
50535 | "support enabled" ) |
50536 | : G_("%<__transaction_atomic%> without transactional memory " |
50537 | "support enabled" )); |
50538 | |
50539 | token = cp_parser_require_keyword (parser, keyword, |
50540 | token_desc: (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC |
50541 | : RT_TRANSACTION_RELAXED)); |
50542 | gcc_assert (token != NULL); |
50543 | |
50544 | if (keyword == RID_TRANSACTION_RELAXED) |
50545 | this_in |= TM_STMT_ATTR_RELAXED; |
50546 | |
50547 | /* Set this early. This might mean that we allow transaction_cancel in |
50548 | an expression that we find out later actually has to be a constexpr. |
50549 | However, we expect that cxx_constant_value will be able to deal with |
50550 | this; also, if the noexcept has no constexpr, then what we parse next |
50551 | really is a transaction's body. */ |
50552 | parser->in_transaction = this_in; |
50553 | |
50554 | /* Parse a noexcept specification. */ |
50555 | noex = cp_parser_noexcept_specification_opt (parser, |
50556 | flags: CP_PARSER_FLAGS_NONE, |
50557 | /*require_constexpr=*/false, |
50558 | consumed_expr: &noex_expr, |
50559 | /*return_cond=*/true); |
50560 | |
50561 | if (!noex || !noex_expr |
50562 | || cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
50563 | { |
50564 | matching_parens parens; |
50565 | parens.require_open (parser); |
50566 | |
50567 | expr = cp_parser_expression (parser); |
50568 | expr = finish_parenthesized_expr (expr); |
50569 | |
50570 | parens.require_close (parser); |
50571 | } |
50572 | else |
50573 | { |
50574 | /* The only expression that is available got parsed for the noexcept |
50575 | already. noexcept is true then. */ |
50576 | expr = noex; |
50577 | noex = boolean_true_node; |
50578 | } |
50579 | |
50580 | expr = build_transaction_expr (token->location, expr, this_in, noex); |
50581 | parser->in_transaction = old_in; |
50582 | |
50583 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_TRANSACTION)) |
50584 | return error_mark_node; |
50585 | |
50586 | return (flag_tm ? expr : error_mark_node); |
50587 | } |
50588 | |
50589 | /* Parse a function-transaction-block. |
50590 | |
50591 | function-transaction-block: |
50592 | __transaction_atomic txn-attribute[opt] ctor-initializer[opt] |
50593 | function-body |
50594 | __transaction_atomic txn-attribute[opt] function-try-block |
50595 | __transaction_relaxed ctor-initializer[opt] function-body |
50596 | __transaction_relaxed function-try-block |
50597 | */ |
50598 | |
50599 | static void |
50600 | cp_parser_function_transaction (cp_parser *parser, enum rid keyword) |
50601 | { |
50602 | unsigned char old_in = parser->in_transaction; |
50603 | unsigned char new_in = 1; |
50604 | tree compound_stmt, stmt, attrs; |
50605 | cp_token *token; |
50606 | |
50607 | gcc_assert (keyword == RID_TRANSACTION_ATOMIC |
50608 | || keyword == RID_TRANSACTION_RELAXED); |
50609 | token = cp_parser_require_keyword (parser, keyword, |
50610 | token_desc: (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC |
50611 | : RT_TRANSACTION_RELAXED)); |
50612 | gcc_assert (token != NULL); |
50613 | |
50614 | if (keyword == RID_TRANSACTION_RELAXED) |
50615 | new_in |= TM_STMT_ATTR_RELAXED; |
50616 | else |
50617 | { |
50618 | attrs = cp_parser_txn_attribute_opt (parser); |
50619 | if (attrs) |
50620 | new_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); |
50621 | } |
50622 | |
50623 | stmt = begin_transaction_stmt (token->location, &compound_stmt, new_in); |
50624 | |
50625 | parser->in_transaction = new_in; |
50626 | |
50627 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
50628 | cp_parser_function_try_block (parser); |
50629 | else |
50630 | cp_parser_ctor_initializer_opt_and_function_body |
50631 | (parser, /*in_function_try_block=*/false); |
50632 | |
50633 | parser->in_transaction = old_in; |
50634 | |
50635 | finish_transaction_stmt (stmt, compound_stmt, new_in, NULL_TREE); |
50636 | } |
50637 | |
50638 | /* Parse a __transaction_cancel statement. |
50639 | |
50640 | cancel-statement: |
50641 | __transaction_cancel txn-attribute[opt] ; |
50642 | __transaction_cancel txn-attribute[opt] throw-expression ; |
50643 | |
50644 | ??? Cancel and throw is not yet implemented. */ |
50645 | |
50646 | static tree |
50647 | cp_parser_transaction_cancel (cp_parser *parser) |
50648 | { |
50649 | cp_token *token; |
50650 | bool is_outer = false; |
50651 | tree stmt, attrs; |
50652 | |
50653 | token = cp_parser_require_keyword (parser, keyword: RID_TRANSACTION_CANCEL, |
50654 | token_desc: RT_TRANSACTION_CANCEL); |
50655 | gcc_assert (token != NULL); |
50656 | |
50657 | attrs = cp_parser_txn_attribute_opt (parser); |
50658 | if (attrs) |
50659 | is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0); |
50660 | |
50661 | /* ??? Parse cancel-and-throw here. */ |
50662 | |
50663 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
50664 | |
50665 | if (!flag_tm) |
50666 | { |
50667 | error_at (token->location, "%<__transaction_cancel%> without " |
50668 | "transactional memory support enabled" ); |
50669 | return error_mark_node; |
50670 | } |
50671 | else if (parser->in_transaction & TM_STMT_ATTR_RELAXED) |
50672 | { |
50673 | error_at (token->location, "%<__transaction_cancel%> within a " |
50674 | "%<__transaction_relaxed%>" ); |
50675 | return error_mark_node; |
50676 | } |
50677 | else if (is_outer) |
50678 | { |
50679 | if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0 |
50680 | && !is_tm_may_cancel_outer (current_function_decl)) |
50681 | { |
50682 | error_at (token->location, "outer %<__transaction_cancel%> not " |
50683 | "within outer %<__transaction_atomic%>" ); |
50684 | error_at (token->location, |
50685 | " or a %<transaction_may_cancel_outer%> function" ); |
50686 | return error_mark_node; |
50687 | } |
50688 | } |
50689 | else if (parser->in_transaction == 0) |
50690 | { |
50691 | error_at (token->location, "%<__transaction_cancel%> not within " |
50692 | "%<__transaction_atomic%>" ); |
50693 | return error_mark_node; |
50694 | } |
50695 | |
50696 | stmt = build_tm_abort_call (token->location, is_outer); |
50697 | add_stmt (stmt); |
50698 | |
50699 | return stmt; |
50700 | } |
50701 | |
50702 | |
50703 | /* Special handling for the first token or line in the file. The first |
50704 | thing in the file might be #pragma GCC pch_preprocess, which loads a |
50705 | PCH file, which is a GC collection point. So we need to handle this |
50706 | first pragma without benefit of an existing lexer structure. |
50707 | |
50708 | Always returns one token to the caller in *FIRST_TOKEN. This is |
50709 | either the true first token of the file, or the first token after |
50710 | the initial pragma. */ |
50711 | |
50712 | static void |
50713 | cp_parser_initial_pragma (cp_token *first_token) |
50714 | { |
50715 | if (cp_parser_pragma_kind (token: first_token) != PRAGMA_GCC_PCH_PREPROCESS) |
50716 | return; |
50717 | |
50718 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50719 | |
50720 | tree name = NULL; |
50721 | if (first_token->type == CPP_STRING) |
50722 | { |
50723 | name = first_token->u.value; |
50724 | |
50725 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50726 | } |
50727 | |
50728 | /* Skip to the end of the pragma. */ |
50729 | if (first_token->type != CPP_PRAGMA_EOL) |
50730 | { |
50731 | error_at (first_token->location, |
50732 | "malformed %<#pragma GCC pch_preprocess%>" ); |
50733 | do |
50734 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50735 | while (first_token->type != CPP_PRAGMA_EOL); |
50736 | } |
50737 | |
50738 | /* Now actually load the PCH file. */ |
50739 | if (name) |
50740 | c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name)); |
50741 | |
50742 | /* Read one more token to return to our caller. We have to do this |
50743 | after reading the PCH file in, since its pointers have to be |
50744 | live. */ |
50745 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50746 | } |
50747 | |
50748 | /* Parse a pragma GCC ivdep. */ |
50749 | |
50750 | static bool |
50751 | cp_parser_pragma_ivdep (cp_parser *parser, cp_token *pragma_tok) |
50752 | { |
50753 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50754 | return true; |
50755 | } |
50756 | |
50757 | /* Parse a pragma GCC unroll. */ |
50758 | |
50759 | static tree |
50760 | cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok) |
50761 | { |
50762 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
50763 | tree unroll = cp_parser_constant_expression (parser); |
50764 | unroll = cp_check_pragma_unroll (location, fold_non_dependent_expr (unroll)); |
50765 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50766 | return unroll; |
50767 | } |
50768 | |
50769 | /* Parse a pragma GCC novector. */ |
50770 | |
50771 | static bool |
50772 | cp_parser_pragma_novector (cp_parser *parser, cp_token *pragma_tok) |
50773 | { |
50774 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50775 | return true; |
50776 | } |
50777 | |
50778 | /* Normal parsing of a pragma token. Here we can (and must) use the |
50779 | regular lexer. */ |
50780 | |
50781 | static bool |
50782 | cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) |
50783 | { |
50784 | cp_token *pragma_tok; |
50785 | unsigned int id; |
50786 | tree stmt; |
50787 | bool ret = false; |
50788 | |
50789 | pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
50790 | gcc_assert (pragma_tok->type == CPP_PRAGMA); |
50791 | parser->lexer->in_pragma = true; |
50792 | |
50793 | id = cp_parser_pragma_kind (token: pragma_tok); |
50794 | if (parser->omp_for_parse_state |
50795 | && parser->omp_for_parse_state->in_intervening_code |
50796 | && id >= PRAGMA_OMP__START_ |
50797 | && id <= PRAGMA_OMP__LAST_) |
50798 | { |
50799 | error_at (pragma_tok->location, |
50800 | "intervening code must not contain OpenMP directives" ); |
50801 | parser->omp_for_parse_state->fail = true; |
50802 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50803 | return false; |
50804 | } |
50805 | if (id != PRAGMA_OMP_DECLARE && id != PRAGMA_OACC_ROUTINE) |
50806 | cp_ensure_no_omp_declare_simd (parser); |
50807 | switch (id) |
50808 | { |
50809 | case PRAGMA_GCC_PCH_PREPROCESS: |
50810 | error_at (pragma_tok->location, |
50811 | "%<#pragma GCC pch_preprocess%> must be first" ); |
50812 | break; |
50813 | |
50814 | case PRAGMA_OMP_BARRIER: |
50815 | switch (context) |
50816 | { |
50817 | case pragma_compound: |
50818 | cp_parser_omp_barrier (parser, pragma_tok); |
50819 | return false; |
50820 | case pragma_stmt: |
50821 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50822 | "used in compound statements" , "omp barrier" ); |
50823 | ret = true; |
50824 | break; |
50825 | default: |
50826 | goto bad_stmt; |
50827 | } |
50828 | break; |
50829 | |
50830 | case PRAGMA_OMP_DEPOBJ: |
50831 | switch (context) |
50832 | { |
50833 | case pragma_compound: |
50834 | cp_parser_omp_depobj (parser, pragma_tok); |
50835 | return false; |
50836 | case pragma_stmt: |
50837 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50838 | "used in compound statements" , "omp depobj" ); |
50839 | ret = true; |
50840 | break; |
50841 | default: |
50842 | goto bad_stmt; |
50843 | } |
50844 | break; |
50845 | |
50846 | case PRAGMA_OMP_FLUSH: |
50847 | switch (context) |
50848 | { |
50849 | case pragma_compound: |
50850 | cp_parser_omp_flush (parser, pragma_tok); |
50851 | return false; |
50852 | case pragma_stmt: |
50853 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50854 | "used in compound statements" , "omp flush" ); |
50855 | ret = true; |
50856 | break; |
50857 | default: |
50858 | goto bad_stmt; |
50859 | } |
50860 | break; |
50861 | |
50862 | case PRAGMA_OMP_TASKWAIT: |
50863 | switch (context) |
50864 | { |
50865 | case pragma_compound: |
50866 | cp_parser_omp_taskwait (parser, pragma_tok); |
50867 | return false; |
50868 | case pragma_stmt: |
50869 | error_at (pragma_tok->location, |
50870 | "%<#pragma %s%> may only be used in compound statements" , |
50871 | "omp taskwait" ); |
50872 | ret = true; |
50873 | break; |
50874 | default: |
50875 | goto bad_stmt; |
50876 | } |
50877 | break; |
50878 | |
50879 | case PRAGMA_OMP_TASKYIELD: |
50880 | switch (context) |
50881 | { |
50882 | case pragma_compound: |
50883 | cp_parser_omp_taskyield (parser, pragma_tok); |
50884 | return false; |
50885 | case pragma_stmt: |
50886 | error_at (pragma_tok->location, |
50887 | "%<#pragma %s%> may only be used in compound statements" , |
50888 | "omp taskyield" ); |
50889 | ret = true; |
50890 | break; |
50891 | default: |
50892 | goto bad_stmt; |
50893 | } |
50894 | break; |
50895 | |
50896 | case PRAGMA_OMP_CANCEL: |
50897 | switch (context) |
50898 | { |
50899 | case pragma_compound: |
50900 | cp_parser_omp_cancel (parser, pragma_tok); |
50901 | return false; |
50902 | case pragma_stmt: |
50903 | error_at (pragma_tok->location, |
50904 | "%<#pragma %s%> may only be used in compound statements" , |
50905 | "omp cancel" ); |
50906 | ret = true; |
50907 | break; |
50908 | default: |
50909 | goto bad_stmt; |
50910 | } |
50911 | break; |
50912 | |
50913 | case PRAGMA_OMP_CANCELLATION_POINT: |
50914 | return cp_parser_omp_cancellation_point (parser, pragma_tok, context); |
50915 | |
50916 | case PRAGMA_OMP_THREADPRIVATE: |
50917 | cp_parser_omp_threadprivate (parser, pragma_tok); |
50918 | return false; |
50919 | |
50920 | case PRAGMA_OMP_DECLARE: |
50921 | return cp_parser_omp_declare (parser, pragma_tok, context); |
50922 | |
50923 | case PRAGMA_OACC_DECLARE: |
50924 | cp_parser_oacc_declare (parser, pragma_tok); |
50925 | return false; |
50926 | |
50927 | case PRAGMA_OACC_ENTER_DATA: |
50928 | if (context == pragma_stmt) |
50929 | { |
50930 | error_at (pragma_tok->location, |
50931 | "%<#pragma %s%> may only be used in compound statements" , |
50932 | "acc enter data" ); |
50933 | ret = true; |
50934 | break; |
50935 | } |
50936 | else if (context != pragma_compound) |
50937 | goto bad_stmt; |
50938 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50939 | return true; |
50940 | |
50941 | case PRAGMA_OACC_EXIT_DATA: |
50942 | if (context == pragma_stmt) |
50943 | { |
50944 | error_at (pragma_tok->location, |
50945 | "%<#pragma %s%> may only be used in compound statements" , |
50946 | "acc exit data" ); |
50947 | ret = true; |
50948 | break; |
50949 | } |
50950 | else if (context != pragma_compound) |
50951 | goto bad_stmt; |
50952 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50953 | return true; |
50954 | |
50955 | case PRAGMA_OACC_ROUTINE: |
50956 | if (context != pragma_external) |
50957 | { |
50958 | error_at (pragma_tok->location, |
50959 | "%<#pragma acc routine%> must be at file scope" ); |
50960 | ret = true; |
50961 | break; |
50962 | } |
50963 | cp_parser_oacc_routine (parser, pragma_tok, context); |
50964 | return false; |
50965 | |
50966 | case PRAGMA_OACC_UPDATE: |
50967 | if (context == pragma_stmt) |
50968 | { |
50969 | error_at (pragma_tok->location, |
50970 | "%<#pragma %s%> may only be used in compound statements" , |
50971 | "acc update" ); |
50972 | ret = true; |
50973 | break; |
50974 | } |
50975 | else if (context != pragma_compound) |
50976 | goto bad_stmt; |
50977 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50978 | return true; |
50979 | |
50980 | case PRAGMA_OACC_WAIT: |
50981 | if (context == pragma_stmt) |
50982 | { |
50983 | error_at (pragma_tok->location, |
50984 | "%<#pragma %s%> may only be used in compound statements" , |
50985 | "acc wait" ); |
50986 | ret = true; |
50987 | break; |
50988 | } |
50989 | else if (context != pragma_compound) |
50990 | goto bad_stmt; |
50991 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50992 | return true; |
50993 | case PRAGMA_OMP_ALLOCATE: |
50994 | cp_parser_omp_allocate (parser, pragma_tok); |
50995 | return false; |
50996 | case PRAGMA_OACC_ATOMIC: |
50997 | case PRAGMA_OACC_CACHE: |
50998 | case PRAGMA_OACC_DATA: |
50999 | case PRAGMA_OACC_HOST_DATA: |
51000 | case PRAGMA_OACC_KERNELS: |
51001 | case PRAGMA_OACC_LOOP: |
51002 | case PRAGMA_OACC_PARALLEL: |
51003 | case PRAGMA_OACC_SERIAL: |
51004 | case PRAGMA_OMP_ASSUME: |
51005 | case PRAGMA_OMP_ATOMIC: |
51006 | case PRAGMA_OMP_CRITICAL: |
51007 | case PRAGMA_OMP_DISTRIBUTE: |
51008 | case PRAGMA_OMP_FOR: |
51009 | case PRAGMA_OMP_LOOP: |
51010 | case PRAGMA_OMP_MASKED: |
51011 | case PRAGMA_OMP_MASTER: |
51012 | case PRAGMA_OMP_PARALLEL: |
51013 | case PRAGMA_OMP_SCOPE: |
51014 | case PRAGMA_OMP_SECTIONS: |
51015 | case PRAGMA_OMP_SIMD: |
51016 | case PRAGMA_OMP_SINGLE: |
51017 | case PRAGMA_OMP_TASK: |
51018 | case PRAGMA_OMP_TASKGROUP: |
51019 | case PRAGMA_OMP_TASKLOOP: |
51020 | case PRAGMA_OMP_TEAMS: |
51021 | if (context != pragma_stmt && context != pragma_compound) |
51022 | goto bad_stmt; |
51023 | stmt = push_omp_privatization_clauses (false); |
51024 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
51025 | pop_omp_privatization_clauses (stmt); |
51026 | return true; |
51027 | |
51028 | case PRAGMA_OMP_REQUIRES: |
51029 | if (context != pragma_external) |
51030 | { |
51031 | error_at (pragma_tok->location, |
51032 | "%<#pragma omp requires%> may only be used at file or " |
51033 | "namespace scope" ); |
51034 | ret = true; |
51035 | break; |
51036 | } |
51037 | return cp_parser_omp_requires (parser, pragma_tok); |
51038 | |
51039 | case PRAGMA_OMP_ASSUMES: |
51040 | if (context != pragma_external) |
51041 | { |
51042 | error_at (pragma_tok->location, |
51043 | "%<#pragma omp assumes%> may only be used at file or " |
51044 | "namespace scope" ); |
51045 | ret = true; |
51046 | break; |
51047 | } |
51048 | return cp_parser_omp_assumes (parser, pragma_tok); |
51049 | |
51050 | case PRAGMA_OMP_NOTHING: |
51051 | cp_parser_omp_nothing (parser, pragma_tok); |
51052 | return false; |
51053 | |
51054 | case PRAGMA_OMP_ERROR: |
51055 | return cp_parser_omp_error (parser, pragma_tok, context); |
51056 | |
51057 | case PRAGMA_OMP_ORDERED: |
51058 | if (context != pragma_stmt && context != pragma_compound) |
51059 | goto bad_stmt; |
51060 | stmt = push_omp_privatization_clauses (false); |
51061 | ret = cp_parser_omp_ordered (parser, pragma_tok, context, if_p); |
51062 | pop_omp_privatization_clauses (stmt); |
51063 | return ret; |
51064 | |
51065 | case PRAGMA_OMP_TARGET: |
51066 | if (context != pragma_stmt && context != pragma_compound) |
51067 | goto bad_stmt; |
51068 | stmt = push_omp_privatization_clauses (false); |
51069 | ret = cp_parser_omp_target (parser, pragma_tok, context, if_p); |
51070 | pop_omp_privatization_clauses (stmt); |
51071 | return ret; |
51072 | |
51073 | case PRAGMA_OMP_BEGIN: |
51074 | cp_parser_omp_begin (parser, pragma_tok); |
51075 | return false; |
51076 | |
51077 | case PRAGMA_OMP_END: |
51078 | cp_parser_omp_end (parser, pragma_tok); |
51079 | return false; |
51080 | |
51081 | case PRAGMA_OMP_SCAN: |
51082 | error_at (pragma_tok->location, |
51083 | "%<#pragma omp scan%> may only be used in " |
51084 | "a loop construct with %<inscan%> %<reduction%> clause" ); |
51085 | break; |
51086 | |
51087 | case PRAGMA_OMP_SECTION: |
51088 | error_at (pragma_tok->location, |
51089 | "%<#pragma omp section%> may only be used in " |
51090 | "%<#pragma omp sections%> construct" ); |
51091 | break; |
51092 | |
51093 | case PRAGMA_IVDEP: |
51094 | case PRAGMA_UNROLL: |
51095 | case PRAGMA_NOVECTOR: |
51096 | { |
51097 | bool ivdep = false; |
51098 | tree unroll = NULL_TREE; |
51099 | bool novector = false; |
51100 | const char *pragma_str; |
51101 | |
51102 | switch (id) |
51103 | { |
51104 | case PRAGMA_IVDEP: |
51105 | pragma_str = "ivdep" ; |
51106 | break; |
51107 | case PRAGMA_UNROLL: |
51108 | pragma_str = "unroll" ; |
51109 | break; |
51110 | case PRAGMA_NOVECTOR: |
51111 | pragma_str = "novector" ; |
51112 | break; |
51113 | default: |
51114 | gcc_unreachable (); |
51115 | } |
51116 | |
51117 | if (context == pragma_external) |
51118 | { |
51119 | error_at (pragma_tok->location, |
51120 | "%<#pragma GCC %s%> must be inside a function" , |
51121 | pragma_str); |
51122 | break; |
51123 | } |
51124 | |
51125 | cp_token *tok = pragma_tok; |
51126 | bool has_more = true; |
51127 | do |
51128 | { |
51129 | switch (cp_parser_pragma_kind (token: tok)) |
51130 | { |
51131 | case PRAGMA_IVDEP: |
51132 | { |
51133 | if (tok != pragma_tok) |
51134 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
51135 | ivdep = cp_parser_pragma_ivdep (parser, pragma_tok: tok); |
51136 | break; |
51137 | } |
51138 | case PRAGMA_UNROLL: |
51139 | { |
51140 | if (tok != pragma_tok) |
51141 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
51142 | unroll = cp_parser_pragma_unroll (parser, pragma_tok: tok); |
51143 | break; |
51144 | } |
51145 | case PRAGMA_NOVECTOR: |
51146 | { |
51147 | if (tok != pragma_tok) |
51148 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
51149 | novector = cp_parser_pragma_novector (parser, pragma_tok: tok); |
51150 | break; |
51151 | } |
51152 | default: |
51153 | has_more = false; |
51154 | break; |
51155 | } |
51156 | tok = cp_lexer_peek_token (lexer: the_parser->lexer); |
51157 | has_more = has_more && tok->type == CPP_PRAGMA; |
51158 | } |
51159 | while (has_more); |
51160 | |
51161 | if (tok->type != CPP_KEYWORD |
51162 | || (tok->keyword != RID_FOR |
51163 | && tok->keyword != RID_WHILE |
51164 | && tok->keyword != RID_DO)) |
51165 | { |
51166 | cp_parser_error (parser, gmsgid: "for, while or do statement expected" ); |
51167 | return false; |
51168 | } |
51169 | cp_parser_iteration_statement (parser, if_p, ivdep, unroll, novector); |
51170 | return true; |
51171 | } |
51172 | |
51173 | default: |
51174 | gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); |
51175 | c_invoke_pragma_handler (id); |
51176 | break; |
51177 | |
51178 | bad_stmt: |
51179 | cp_parser_error (parser, gmsgid: "expected declaration specifiers" ); |
51180 | break; |
51181 | } |
51182 | |
51183 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
51184 | return ret; |
51185 | } |
51186 | |
51187 | /* Helper for pragma_lex in preprocess-only mode; in this mode, we have not |
51188 | populated the lexer with any tokens (the tokens rather being read by |
51189 | c-ppoutput.c's machinery), so we need to read enough tokens now to handle |
51190 | a pragma. */ |
51191 | static void |
51192 | maybe_read_tokens_for_pragma_lex () |
51193 | { |
51194 | const auto lexer = the_parser->lexer; |
51195 | if (!lexer->buffer->is_empty ()) |
51196 | return; |
51197 | |
51198 | /* Read the rest of the tokens comprising the pragma line. */ |
51199 | cp_token *tok; |
51200 | do |
51201 | { |
51202 | tok = vec_safe_push (v&: lexer->buffer, obj: cp_token ()); |
51203 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, token: tok); |
51204 | gcc_assert (tok->type != CPP_EOF); |
51205 | } while (tok->type != CPP_PRAGMA_EOL); |
51206 | lexer->next_token = lexer->buffer->address (); |
51207 | lexer->last_token = lexer->next_token + lexer->buffer->length () - 1; |
51208 | } |
51209 | |
51210 | /* The interface the pragma parsers have to the lexer. */ |
51211 | |
51212 | enum cpp_ttype |
51213 | pragma_lex (tree *value, location_t *loc) |
51214 | { |
51215 | if (flag_preprocess_only) |
51216 | maybe_read_tokens_for_pragma_lex (); |
51217 | |
51218 | cp_token *tok = cp_lexer_peek_token (lexer: the_parser->lexer); |
51219 | enum cpp_ttype ret = tok->type; |
51220 | |
51221 | *value = tok->u.value; |
51222 | if (loc) |
51223 | *loc = tok->location; |
51224 | |
51225 | if (ret == CPP_PRAGMA_EOL) |
51226 | ret = CPP_EOF; |
51227 | else if (ret == CPP_STRING) |
51228 | *value = cp_parser_string_literal (parser: the_parser, /*translate=*/false, |
51229 | /*wide_ok=*/false); |
51230 | else |
51231 | { |
51232 | if (ret == CPP_KEYWORD) |
51233 | ret = CPP_NAME; |
51234 | cp_lexer_consume_token (lexer: the_parser->lexer); |
51235 | } |
51236 | |
51237 | return ret; |
51238 | } |
51239 | |
51240 | void |
51241 | pragma_lex_discard_to_eol () |
51242 | { |
51243 | /* We have already read all the tokens, so we just need to discard |
51244 | them here. */ |
51245 | const auto lexer = the_parser->lexer; |
51246 | lexer->next_token = lexer->last_token; |
51247 | lexer->buffer->truncate (size: 0); |
51248 | } |
51249 | |
51250 | |
51251 | /* External interface. */ |
51252 | |
51253 | /* Parse one entire translation unit. */ |
51254 | |
51255 | void |
51256 | c_parse_file (void) |
51257 | { |
51258 | static bool already_called = false; |
51259 | |
51260 | if (already_called) |
51261 | fatal_error (input_location, |
51262 | "multi-source compilation not implemented for C++" ); |
51263 | already_called = true; |
51264 | |
51265 | /* cp_lexer_new_main is called before doing any GC allocation |
51266 | because tokenization might load a PCH file. */ |
51267 | cp_lexer_new_main (); |
51268 | |
51269 | cp_parser_translation_unit (parser: the_parser); |
51270 | class_decl_loc_t::diag_mismatched_tags (); |
51271 | |
51272 | the_parser = NULL; |
51273 | |
51274 | finish_translation_unit (); |
51275 | } |
51276 | |
51277 | /* Create an identifier for a generic parameter type (a synthesized |
51278 | template parameter implied by `auto' or a concept identifier). */ |
51279 | |
51280 | static GTY(()) int generic_parm_count; |
51281 | static tree |
51282 | make_generic_type_name () |
51283 | { |
51284 | char buf[32]; |
51285 | sprintf (s: buf, format: "auto:%d" , ++generic_parm_count); |
51286 | return get_identifier (buf); |
51287 | } |
51288 | |
51289 | /* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS |
51290 | (creating a new template parameter list if necessary). Returns the newly |
51291 | created template type parm. */ |
51292 | |
51293 | static tree |
51294 | synthesize_implicit_template_parm (cp_parser *parser, tree constr) |
51295 | { |
51296 | /* A requires-clause is not a function and cannot have placeholders. */ |
51297 | if (current_binding_level->requires_expression) |
51298 | { |
51299 | error ("placeholder type not allowed in this context" ); |
51300 | return error_mark_node; |
51301 | } |
51302 | |
51303 | gcc_assert (current_binding_level->kind == sk_function_parms); |
51304 | |
51305 | /* We are either continuing a function template that already contains implicit |
51306 | template parameters, creating a new fully-implicit function template, or |
51307 | extending an existing explicit function template with implicit template |
51308 | parameters. */ |
51309 | |
51310 | cp_binding_level *const entry_scope = current_binding_level; |
51311 | |
51312 | bool become_template = false; |
51313 | cp_binding_level *parent_scope = 0; |
51314 | |
51315 | if (parser->implicit_template_scope) |
51316 | { |
51317 | gcc_assert (parser->implicit_template_parms); |
51318 | |
51319 | current_binding_level = parser->implicit_template_scope; |
51320 | } |
51321 | else |
51322 | { |
51323 | /* Roll back to the existing template parameter scope (in the case of |
51324 | extending an explicit function template) or introduce a new template |
51325 | parameter scope ahead of the function parameter scope (or class scope |
51326 | in the case of out-of-line member definitions). The function scope is |
51327 | added back after template parameter synthesis below. */ |
51328 | |
51329 | cp_binding_level *scope = entry_scope; |
51330 | |
51331 | while (scope->kind == sk_function_parms) |
51332 | { |
51333 | parent_scope = scope; |
51334 | scope = scope->level_chain; |
51335 | } |
51336 | if (current_class_type && !LAMBDA_TYPE_P (current_class_type)) |
51337 | { |
51338 | /* If not defining a class, then any class scope is a scope level in |
51339 | an out-of-line member definition. In this case simply wind back |
51340 | beyond the first such scope to inject the template parameter list. |
51341 | Otherwise wind back to the class being defined. The latter can |
51342 | occur in class member friend declarations such as: |
51343 | |
51344 | class A { |
51345 | void foo (auto); |
51346 | }; |
51347 | class B { |
51348 | friend void A::foo (auto); |
51349 | }; |
51350 | |
51351 | The template parameter list synthesized for the friend declaration |
51352 | must be injected in the scope of 'B'. This can also occur in |
51353 | erroneous cases such as: |
51354 | |
51355 | struct A { |
51356 | struct B { |
51357 | void foo (auto); |
51358 | }; |
51359 | void B::foo (auto) {} |
51360 | }; |
51361 | |
51362 | Here the attempted definition of 'B::foo' within 'A' is ill-formed |
51363 | but, nevertheless, the template parameter list synthesized for the |
51364 | declarator should be injected into the scope of 'A' as if the |
51365 | ill-formed template was specified explicitly. */ |
51366 | |
51367 | while (scope->kind == sk_class && !scope->defining_class_p) |
51368 | { |
51369 | parent_scope = scope; |
51370 | scope = scope->level_chain; |
51371 | } |
51372 | } |
51373 | |
51374 | current_binding_level = scope; |
51375 | |
51376 | if (scope->kind != sk_template_parms |
51377 | || !function_being_declared_is_template_p (parser)) |
51378 | { |
51379 | /* Introduce a new template parameter list for implicit template |
51380 | parameters. */ |
51381 | |
51382 | become_template = true; |
51383 | |
51384 | parser->implicit_template_scope |
51385 | = begin_scope (sk_template_parms, NULL); |
51386 | |
51387 | ++processing_template_decl; |
51388 | |
51389 | parser->fully_implicit_function_template_p = true; |
51390 | ++parser->num_template_parameter_lists; |
51391 | } |
51392 | else |
51393 | { |
51394 | /* Synthesize implicit template parameters at the end of the explicit |
51395 | template parameter list. */ |
51396 | |
51397 | gcc_assert (current_template_parms); |
51398 | |
51399 | parser->implicit_template_scope = scope; |
51400 | |
51401 | tree v = INNERMOST_TEMPLATE_PARMS (current_template_parms); |
51402 | parser->implicit_template_parms |
51403 | = TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1); |
51404 | } |
51405 | } |
51406 | |
51407 | /* Synthesize a new template parameter and track the current template |
51408 | parameter chain with implicit_template_parms. */ |
51409 | |
51410 | tree proto = constr ? DECL_INITIAL (constr) : NULL_TREE; |
51411 | tree synth_id = make_generic_type_name (); |
51412 | bool non_type = false; |
51413 | |
51414 | /* Synthesize the type template parameter. */ |
51415 | gcc_assert(!proto || TREE_CODE (proto) == TYPE_DECL); |
51416 | tree synth_tmpl_parm = finish_template_type_parm (class_type_node, synth_id); |
51417 | |
51418 | if (become_template) |
51419 | current_template_parms = tree_cons (size_int (current_template_depth + 1), |
51420 | NULL_TREE, current_template_parms); |
51421 | |
51422 | /* Attach the constraint to the parm before processing. */ |
51423 | tree node = build_tree_list (NULL_TREE, synth_tmpl_parm); |
51424 | TREE_TYPE (node) = constr; |
51425 | tree new_parm |
51426 | = process_template_parm (parser->implicit_template_parms, |
51427 | input_location, |
51428 | node, |
51429 | /*non_type=*/non_type, |
51430 | /*param_pack=*/false); |
51431 | // Process_template_parm returns the list of parms, and |
51432 | // parser->implicit_template_parms holds the final node of the parm |
51433 | // list. We really want to manipulate the newly appended element. |
51434 | gcc_checking_assert (!parser->implicit_template_parms |
51435 | || parser->implicit_template_parms == new_parm); |
51436 | if (parser->implicit_template_parms) |
51437 | new_parm = TREE_CHAIN (new_parm); |
51438 | gcc_checking_assert (!TREE_CHAIN (new_parm)); |
51439 | |
51440 | // Record the last implicit parm node |
51441 | parser->implicit_template_parms = new_parm; |
51442 | |
51443 | /* Mark the synthetic declaration "virtual". This is used when |
51444 | comparing template-heads to determine if whether an abbreviated |
51445 | function template is equivalent to an explicit template. |
51446 | |
51447 | Note that DECL_ARTIFICIAL is used elsewhere for template |
51448 | parameters. */ |
51449 | if (TREE_VALUE (new_parm) != error_mark_node) |
51450 | DECL_IMPLICIT_TEMPLATE_PARM_P (TREE_VALUE (new_parm)) = true; |
51451 | |
51452 | tree new_decl = get_local_decls (); |
51453 | if (non_type) |
51454 | /* Return the TEMPLATE_PARM_INDEX, not the PARM_DECL. */ |
51455 | new_decl = DECL_INITIAL (new_decl); |
51456 | |
51457 | /* If creating a fully implicit function template, start the new implicit |
51458 | template parameter list with this synthesized type, otherwise grow the |
51459 | current template parameter list. */ |
51460 | |
51461 | if (become_template) |
51462 | { |
51463 | parent_scope->level_chain = current_binding_level; |
51464 | |
51465 | tree new_parms = make_tree_vec (1); |
51466 | TREE_VEC_ELT (new_parms, 0) = parser->implicit_template_parms; |
51467 | TREE_VALUE (current_template_parms) = new_parms; |
51468 | } |
51469 | else |
51470 | { |
51471 | tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); |
51472 | int new_parm_idx = TREE_VEC_LENGTH (new_parms); |
51473 | new_parms = grow_tree_vec (v: new_parms, new_parm_idx + 1); |
51474 | TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms; |
51475 | } |
51476 | |
51477 | /* If the new parameter was constrained, we need to add that to the |
51478 | constraints in the template parameter list. */ |
51479 | if (tree req = TEMPLATE_PARM_CONSTRAINTS (new_parm)) |
51480 | { |
51481 | tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); |
51482 | reqs = combine_constraint_expressions (reqs, req); |
51483 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
51484 | } |
51485 | |
51486 | current_binding_level = entry_scope; |
51487 | |
51488 | return new_decl; |
51489 | } |
51490 | |
51491 | /* Finish the declaration of a fully implicit function template. Such a |
51492 | template has no explicit template parameter list so has not been through the |
51493 | normal template head and tail processing. synthesize_implicit_template_parm |
51494 | tries to do the head; this tries to do the tail. MEMBER_DECL_OPT should be |
51495 | provided if the declaration is a class member such that its template |
51496 | declaration can be completed. If MEMBER_DECL_OPT is provided the finished |
51497 | form is returned. Otherwise NULL_TREE is returned. */ |
51498 | |
51499 | static tree |
51500 | finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt) |
51501 | { |
51502 | gcc_assert (parser->fully_implicit_function_template_p); |
51503 | |
51504 | if (member_decl_opt && member_decl_opt != error_mark_node |
51505 | && DECL_VIRTUAL_P (member_decl_opt)) |
51506 | { |
51507 | error_at (DECL_SOURCE_LOCATION (member_decl_opt), |
51508 | "implicit templates may not be %<virtual%>" ); |
51509 | DECL_VIRTUAL_P (member_decl_opt) = false; |
51510 | } |
51511 | |
51512 | if (member_decl_opt) |
51513 | member_decl_opt = finish_member_template_decl (member_decl_opt); |
51514 | end_template_decl (); |
51515 | |
51516 | parser->fully_implicit_function_template_p = false; |
51517 | parser->implicit_template_parms = 0; |
51518 | parser->implicit_template_scope = 0; |
51519 | --parser->num_template_parameter_lists; |
51520 | |
51521 | return member_decl_opt; |
51522 | } |
51523 | |
51524 | /* Like finish_fully_implicit_template, but to be used in error |
51525 | recovery, rearranging scopes so that we restore the state we had |
51526 | before synthesize_implicit_template_parm inserted the implement |
51527 | template parms scope. */ |
51528 | |
51529 | static void |
51530 | abort_fully_implicit_template (cp_parser *parser) |
51531 | { |
51532 | cp_binding_level *return_to_scope = current_binding_level; |
51533 | |
51534 | if (parser->implicit_template_scope |
51535 | && return_to_scope != parser->implicit_template_scope) |
51536 | { |
51537 | cp_binding_level *child = return_to_scope; |
51538 | for (cp_binding_level *scope = child->level_chain; |
51539 | scope != parser->implicit_template_scope; |
51540 | scope = child->level_chain) |
51541 | child = scope; |
51542 | child->level_chain = parser->implicit_template_scope->level_chain; |
51543 | parser->implicit_template_scope->level_chain = return_to_scope; |
51544 | current_binding_level = parser->implicit_template_scope; |
51545 | } |
51546 | else |
51547 | return_to_scope = return_to_scope->level_chain; |
51548 | |
51549 | finish_fully_implicit_template (parser, NULL); |
51550 | |
51551 | gcc_assert (current_binding_level == return_to_scope); |
51552 | } |
51553 | |
51554 | /* Helper function for diagnostics that have complained about things |
51555 | being used with 'extern "C"' linkage. |
51556 | |
51557 | Attempt to issue a note showing where the 'extern "C"' linkage began. */ |
51558 | |
51559 | void |
51560 | maybe_show_extern_c_location (void) |
51561 | { |
51562 | if (the_parser->innermost_linkage_specification_location != UNKNOWN_LOCATION) |
51563 | inform (the_parser->innermost_linkage_specification_location, |
51564 | "%<extern \"C\"%> linkage started here" ); |
51565 | } |
51566 | |
51567 | #include "gt-cp-parser.h" |
51568 | |