1 | /* -*- C++ -*- Parser. |
2 | Copyright (C) 2000-2023 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 | |
250 | static cp_token_cache *cp_token_cache_new |
251 | (cp_token *, cp_token *); |
252 | static tree cp_parser_late_noexcept_specifier |
253 | (cp_parser *, tree); |
254 | static void noexcept_override_late_checks |
255 | (tree); |
256 | |
257 | static void cp_parser_initial_pragma |
258 | (cp_token *); |
259 | |
260 | static bool cp_parser_omp_declare_reduction_exprs |
261 | (tree, cp_parser *); |
262 | static void cp_finalize_oacc_routine |
263 | (cp_parser *, tree, bool); |
264 | |
265 | static void check_omp_intervening_code |
266 | (cp_parser *); |
267 | |
268 | |
269 | /* Manifest constants. */ |
270 | #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) |
271 | #define CP_SAVED_TOKEN_STACK 5 |
272 | |
273 | /* Variables. */ |
274 | |
275 | /* The stream to which debugging output should be written. */ |
276 | static FILE *cp_lexer_debug_stream; |
277 | |
278 | /* Nonzero if we are parsing an unevaluated operand: an operand to |
279 | sizeof, typeof, or alignof. */ |
280 | int cp_unevaluated_operand; |
281 | |
282 | /* Dump up to NUM tokens in BUFFER to FILE starting with token |
283 | START_TOKEN. If START_TOKEN is NULL, the dump starts with the |
284 | first token in BUFFER. If NUM is 0, dump all the tokens. If |
285 | CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be |
286 | highlighted by surrounding it in [[ ]]. */ |
287 | |
288 | static void |
289 | cp_lexer_dump_tokens (FILE *file, vec<cp_token, va_gc> *buffer, |
290 | cp_token *start_token, unsigned num, |
291 | cp_token *curr_token) |
292 | { |
293 | unsigned i, nprinted; |
294 | cp_token *token; |
295 | bool do_print; |
296 | |
297 | fprintf (stream: file, format: "%u tokens\n" , vec_safe_length (v: buffer)); |
298 | |
299 | if (buffer == NULL) |
300 | return; |
301 | |
302 | if (num == 0) |
303 | num = buffer->length (); |
304 | |
305 | if (start_token == NULL) |
306 | start_token = buffer->address (); |
307 | |
308 | if (start_token > buffer->address ()) |
309 | { |
310 | cp_lexer_print_token (file, &(*buffer)[0]); |
311 | fprintf (stream: file, format: " ... " ); |
312 | } |
313 | |
314 | do_print = false; |
315 | nprinted = 0; |
316 | for (i = 0; buffer->iterate (ix: i, ptr: &token) && nprinted < num; i++) |
317 | { |
318 | if (token == start_token) |
319 | do_print = true; |
320 | |
321 | if (!do_print) |
322 | continue; |
323 | |
324 | nprinted++; |
325 | if (token == curr_token) |
326 | fprintf (stream: file, format: "[[" ); |
327 | |
328 | cp_lexer_print_token (file, token); |
329 | |
330 | if (token == curr_token) |
331 | fprintf (stream: file, format: "]]" ); |
332 | |
333 | switch (token->type) |
334 | { |
335 | case CPP_SEMICOLON: |
336 | case CPP_OPEN_BRACE: |
337 | case CPP_CLOSE_BRACE: |
338 | case CPP_EOF: |
339 | fputc (c: '\n', stream: file); |
340 | break; |
341 | |
342 | default: |
343 | fputc (c: ' ', stream: file); |
344 | } |
345 | } |
346 | |
347 | if (i == num && i < buffer->length ()) |
348 | { |
349 | fprintf (stream: file, format: " ... " ); |
350 | cp_lexer_print_token (file, &buffer->last ()); |
351 | } |
352 | |
353 | fprintf (stream: file, format: "\n" ); |
354 | } |
355 | |
356 | |
357 | /* Dump all tokens in BUFFER to stderr. */ |
358 | |
359 | void |
360 | cp_lexer_debug_tokens (vec<cp_token, va_gc> *buffer) |
361 | { |
362 | cp_lexer_dump_tokens (stderr, buffer, NULL, num: 0, NULL); |
363 | } |
364 | |
365 | DEBUG_FUNCTION void |
366 | debug (vec<cp_token, va_gc> &ref) |
367 | { |
368 | cp_lexer_dump_tokens (stderr, buffer: &ref, NULL, num: 0, NULL); |
369 | } |
370 | |
371 | DEBUG_FUNCTION void |
372 | debug (vec<cp_token, va_gc> *ptr) |
373 | { |
374 | if (ptr) |
375 | debug (ref&: *ptr); |
376 | else |
377 | fprintf (stderr, format: "<nil>\n" ); |
378 | } |
379 | |
380 | |
381 | /* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the |
382 | description for T. */ |
383 | |
384 | static void |
385 | cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t) |
386 | { |
387 | if (t) |
388 | { |
389 | fprintf (stream: file, format: "%s: " , desc); |
390 | print_node_brief (file, "" , t, 0); |
391 | } |
392 | } |
393 | |
394 | |
395 | /* Dump parser context C to FILE. */ |
396 | |
397 | static void |
398 | cp_debug_print_context (FILE *file, cp_parser_context *c) |
399 | { |
400 | const char *status_s[] = { "OK" , "ERROR" , "COMMITTED" }; |
401 | fprintf (stream: file, format: "{ status = %s, scope = " , status_s[c->status]); |
402 | print_node_brief (file, "" , c->object_type, 0); |
403 | fprintf (stream: file, format: "}\n" ); |
404 | } |
405 | |
406 | |
407 | /* Print the stack of parsing contexts to FILE starting with FIRST. */ |
408 | |
409 | static void |
410 | cp_debug_print_context_stack (FILE *file, cp_parser_context *first) |
411 | { |
412 | unsigned i; |
413 | cp_parser_context *c; |
414 | |
415 | fprintf (stream: file, format: "Parsing context stack:\n" ); |
416 | for (i = 0, c = first; c; c = c->next, i++) |
417 | { |
418 | fprintf (stream: file, format: "\t#%u: " , i); |
419 | cp_debug_print_context (file, c); |
420 | } |
421 | } |
422 | |
423 | |
424 | /* Print the value of FLAG to FILE. DESC is a string describing the flag. */ |
425 | |
426 | static void |
427 | cp_debug_print_flag (FILE *file, const char *desc, bool flag) |
428 | { |
429 | if (flag) |
430 | fprintf (stream: file, format: "%s: true\n" , desc); |
431 | } |
432 | |
433 | |
434 | /* Print an unparsed function entry UF to FILE. */ |
435 | |
436 | static void |
437 | cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf) |
438 | { |
439 | unsigned i; |
440 | cp_default_arg_entry *default_arg_fn; |
441 | tree fn; |
442 | |
443 | fprintf (stream: file, format: "\tFunctions with default args:\n" ); |
444 | for (i = 0; |
445 | vec_safe_iterate (v: uf->funs_with_default_args, ix: i, ptr: &default_arg_fn); |
446 | i++) |
447 | { |
448 | fprintf (stream: file, format: "\t\tClass type: " ); |
449 | print_node_brief (file, "" , default_arg_fn->class_type, 0); |
450 | fprintf (stream: file, format: "\t\tDeclaration: " ); |
451 | print_node_brief (file, "" , default_arg_fn->decl, 0); |
452 | fprintf (stream: file, format: "\n" ); |
453 | } |
454 | |
455 | fprintf (stream: file, format: "\n\tFunctions with definitions that require " |
456 | "post-processing\n\t\t" ); |
457 | for (i = 0; vec_safe_iterate (v: uf->funs_with_definitions, ix: i, ptr: &fn); i++) |
458 | { |
459 | print_node_brief (file, "" , fn, 0); |
460 | fprintf (stream: file, format: " " ); |
461 | } |
462 | fprintf (stream: file, format: "\n" ); |
463 | |
464 | fprintf (stream: file, format: "\n\tNon-static data members with initializers that require " |
465 | "post-processing\n\t\t" ); |
466 | for (i = 0; vec_safe_iterate (v: uf->nsdmis, ix: i, ptr: &fn); i++) |
467 | { |
468 | print_node_brief (file, "" , fn, 0); |
469 | fprintf (stream: file, format: " " ); |
470 | } |
471 | fprintf (stream: file, format: "\n" ); |
472 | } |
473 | |
474 | |
475 | /* Print the stack of unparsed member functions S to FILE. */ |
476 | |
477 | static void |
478 | cp_debug_print_unparsed_queues (FILE *file, |
479 | vec<cp_unparsed_functions_entry, va_gc> *s) |
480 | { |
481 | unsigned i; |
482 | cp_unparsed_functions_entry *uf; |
483 | |
484 | fprintf (stream: file, format: "Unparsed functions\n" ); |
485 | for (i = 0; vec_safe_iterate (v: s, ix: i, ptr: &uf); i++) |
486 | { |
487 | fprintf (stream: file, format: "#%u:\n" , i); |
488 | cp_debug_print_unparsed_function (file, uf); |
489 | } |
490 | } |
491 | |
492 | |
493 | /* Dump the tokens in a window of size WINDOW_SIZE around the next_token for |
494 | the given PARSER. If FILE is NULL, the output is printed on stderr. */ |
495 | |
496 | static void |
497 | cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size) |
498 | { |
499 | cp_token *next_token, *first_token, *start_token; |
500 | |
501 | if (file == NULL) |
502 | file = stderr; |
503 | |
504 | next_token = parser->lexer->next_token; |
505 | first_token = parser->lexer->buffer->address (); |
506 | start_token = (next_token > first_token + window_size / 2) |
507 | ? next_token - window_size / 2 |
508 | : first_token; |
509 | cp_lexer_dump_tokens (file, buffer: parser->lexer->buffer, start_token, num: window_size, |
510 | curr_token: next_token); |
511 | } |
512 | |
513 | |
514 | /* Dump debugging information for the given PARSER. If FILE is NULL, |
515 | the output is printed on stderr. */ |
516 | |
517 | void |
518 | cp_debug_parser (FILE *file, cp_parser *parser) |
519 | { |
520 | const size_t window_size = 20; |
521 | cp_token *token; |
522 | expanded_location eloc; |
523 | |
524 | if (file == NULL) |
525 | file = stderr; |
526 | |
527 | fprintf (stream: file, format: "Parser state\n\n" ); |
528 | fprintf (stream: file, format: "Number of tokens: %u\n" , |
529 | vec_safe_length (v: parser->lexer->buffer)); |
530 | cp_debug_print_tree_if_set (file, desc: "Lookup scope" , t: parser->scope); |
531 | cp_debug_print_tree_if_set (file, desc: "Object scope" , |
532 | t: parser->object_scope); |
533 | cp_debug_print_tree_if_set (file, desc: "Qualifying scope" , |
534 | t: parser->qualifying_scope); |
535 | cp_debug_print_context_stack (file, first: parser->context); |
536 | cp_debug_print_flag (file, desc: "Allow GNU extensions" , |
537 | flag: parser->allow_gnu_extensions_p); |
538 | cp_debug_print_flag (file, desc: "'>' token is greater-than" , |
539 | flag: parser->greater_than_is_operator_p); |
540 | cp_debug_print_flag (file, desc: "Default args allowed in current " |
541 | "parameter list" , flag: parser->default_arg_ok_p); |
542 | cp_debug_print_flag (file, desc: "Parsing integral constant-expression" , |
543 | flag: parser->integral_constant_expression_p); |
544 | cp_debug_print_flag (file, desc: "Allow non-constant expression in current " |
545 | "constant-expression" , |
546 | flag: parser->allow_non_integral_constant_expression_p); |
547 | cp_debug_print_flag (file, desc: "Seen non-constant expression" , |
548 | flag: parser->non_integral_constant_expression_p); |
549 | cp_debug_print_flag (file, desc: "Local names forbidden in current context" , |
550 | flag: (parser->local_variables_forbidden_p |
551 | & LOCAL_VARS_FORBIDDEN)); |
552 | cp_debug_print_flag (file, desc: "'this' forbidden in current context" , |
553 | flag: (parser->local_variables_forbidden_p |
554 | & THIS_FORBIDDEN)); |
555 | cp_debug_print_flag (file, desc: "In unbraced linkage specification" , |
556 | flag: parser->in_unbraced_linkage_specification_p); |
557 | cp_debug_print_flag (file, desc: "Parsing a declarator" , |
558 | flag: parser->in_declarator_p); |
559 | cp_debug_print_flag (file, desc: "In template argument list" , |
560 | flag: parser->in_template_argument_list_p); |
561 | cp_debug_print_flag (file, desc: "Parsing an iteration statement" , |
562 | flag: parser->in_statement & IN_ITERATION_STMT); |
563 | cp_debug_print_flag (file, desc: "Parsing a switch statement" , |
564 | flag: parser->in_statement & IN_SWITCH_STMT); |
565 | cp_debug_print_flag (file, desc: "Parsing a structured OpenMP block" , |
566 | flag: parser->in_statement & IN_OMP_BLOCK); |
567 | cp_debug_print_flag (file, desc: "Parsing an OpenMP loop" , |
568 | flag: parser->in_statement & IN_OMP_FOR); |
569 | cp_debug_print_flag (file, desc: "Parsing an if statement" , |
570 | flag: parser->in_statement & IN_IF_STMT); |
571 | cp_debug_print_flag (file, desc: "Parsing a type-id in an expression " |
572 | "context" , flag: parser->in_type_id_in_expr_p); |
573 | cp_debug_print_flag (file, desc: "String expressions should be translated " |
574 | "to execution character set" , |
575 | flag: parser->translate_strings_p); |
576 | cp_debug_print_flag (file, desc: "Parsing function body outside of a " |
577 | "local class" , flag: parser->in_function_body); |
578 | cp_debug_print_flag (file, desc: "Auto correct a colon to a scope operator" , |
579 | flag: parser->colon_corrects_to_scope_p); |
580 | cp_debug_print_flag (file, desc: "Colon doesn't start a class definition" , |
581 | flag: parser->colon_doesnt_start_class_def_p); |
582 | cp_debug_print_flag (file, desc: "Parsing an Objective-C++ message context" , |
583 | flag: parser->objective_c_message_context_p); |
584 | if (parser->type_definition_forbidden_message) |
585 | fprintf (stream: file, format: "Error message for forbidden type definitions: %s %s\n" , |
586 | parser->type_definition_forbidden_message, |
587 | parser->type_definition_forbidden_message_arg |
588 | ? parser->type_definition_forbidden_message_arg : "<none>" ); |
589 | cp_debug_print_unparsed_queues (file, s: parser->unparsed_queues); |
590 | fprintf (stream: file, format: "Number of class definitions in progress: %u\n" , |
591 | parser->num_classes_being_defined); |
592 | fprintf (stream: file, format: "Number of template parameter lists for the current " |
593 | "declaration: %u\n" , parser->num_template_parameter_lists); |
594 | cp_debug_parser_tokens (file, parser, window_size); |
595 | token = parser->lexer->next_token; |
596 | fprintf (stream: file, format: "Next token to parse:\n" ); |
597 | fprintf (stream: file, format: "\tToken: " ); |
598 | cp_lexer_print_token (file, token); |
599 | eloc = expand_location (token->location); |
600 | fprintf (stream: file, format: "\n\tFile: %s\n" , eloc.file); |
601 | fprintf (stream: file, format: "\tLine: %d\n" , eloc.line); |
602 | fprintf (stream: file, format: "\tColumn: %d\n" , eloc.column); |
603 | } |
604 | |
605 | DEBUG_FUNCTION void |
606 | debug (cp_parser &ref) |
607 | { |
608 | cp_debug_parser (stderr, parser: &ref); |
609 | } |
610 | |
611 | DEBUG_FUNCTION void |
612 | debug (cp_parser *ptr) |
613 | { |
614 | if (ptr) |
615 | debug (ref&: *ptr); |
616 | else |
617 | fprintf (stderr, format: "<nil>\n" ); |
618 | } |
619 | |
620 | /* Allocate memory for a new lexer object and return it. */ |
621 | |
622 | static cp_lexer * |
623 | cp_lexer_alloc (void) |
624 | { |
625 | /* Allocate the memory. */ |
626 | cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> (); |
627 | |
628 | /* Initially we are not debugging. */ |
629 | lexer->debugging_p = false; |
630 | |
631 | lexer->saved_tokens.create (CP_SAVED_TOKEN_STACK); |
632 | |
633 | /* Create the buffer. */ |
634 | vec_alloc (v&: lexer->buffer, CP_LEXER_BUFFER_SIZE); |
635 | |
636 | return lexer; |
637 | } |
638 | |
639 | /* Return TRUE if token is the start of a module declaration that will be |
640 | terminated by a CPP_PRAGMA_EOL token. */ |
641 | static inline bool |
642 | cp_token_is_module_directive (cp_token *token) |
643 | { |
644 | return token->keyword == RID__EXPORT |
645 | || token->keyword == RID__MODULE |
646 | || token->keyword == RID__IMPORT; |
647 | } |
648 | |
649 | /* Return TOKEN's pragma_kind if it is CPP_PRAGMA, otherwise |
650 | PRAGMA_NONE. */ |
651 | |
652 | static enum pragma_kind |
653 | cp_parser_pragma_kind (cp_token *token) |
654 | { |
655 | if (token->type != CPP_PRAGMA) |
656 | return PRAGMA_NONE; |
657 | /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ |
658 | return (enum pragma_kind) TREE_INT_CST_LOW (token->u.value); |
659 | } |
660 | |
661 | /* Handle early pragmas such as #pragma GCC diagnostic, which needs to be done |
662 | during preprocessing for the case of preprocessing-related diagnostics. This |
663 | is called immediately after pushing the CPP_PRAGMA_EOL token onto |
664 | lexer->buffer. */ |
665 | |
666 | static void |
667 | cp_lexer_handle_early_pragma (cp_lexer *lexer) |
668 | { |
669 | const auto first_token = lexer->buffer->address (); |
670 | const auto last_token = first_token + lexer->buffer->length () - 1; |
671 | |
672 | /* Back up to the start of the pragma so pragma_lex () can parse it when |
673 | c-pragma lib asks it to. */ |
674 | auto begin = last_token; |
675 | gcc_assert (begin->type == CPP_PRAGMA_EOL); |
676 | while (begin->type != CPP_PRAGMA) |
677 | { |
678 | if (cp_token_is_module_directive (token: begin)) |
679 | return; |
680 | gcc_assert (begin != first_token); |
681 | --begin; |
682 | } |
683 | gcc_assert (!lexer->next_token); |
684 | gcc_assert (!lexer->last_token); |
685 | lexer->next_token = begin; |
686 | lexer->last_token = last_token; |
687 | |
688 | /* Dispatch it. */ |
689 | const unsigned int id |
690 | = cp_parser_pragma_kind (token: cp_lexer_consume_token (lexer)); |
691 | if (id >= PRAGMA_FIRST_EXTERNAL) |
692 | c_invoke_early_pragma_handler (id); |
693 | |
694 | /* Reset to normal state. */ |
695 | lexer->next_token = lexer->last_token = nullptr; |
696 | } |
697 | |
698 | /* The parser. */ |
699 | static cp_parser *cp_parser_new (cp_lexer *); |
700 | static GTY (()) cp_parser *the_parser; |
701 | |
702 | /* Create a new main C++ lexer, the lexer that gets tokens from the |
703 | preprocessor, and also create the main parser. */ |
704 | |
705 | static cp_lexer * |
706 | cp_lexer_new_main (void) |
707 | { |
708 | cp_token token; |
709 | |
710 | /* It's possible that parsing the first pragma will load a PCH file, |
711 | which is a GC collection point. So we have to do that before |
712 | allocating any memory. */ |
713 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, &token); |
714 | cp_parser_initial_pragma (&token); |
715 | c_common_no_more_pch (); |
716 | |
717 | cp_lexer *lexer = cp_lexer_alloc (); |
718 | /* Put the first token in the buffer. */ |
719 | cp_token *tok = lexer->buffer->quick_push (obj: token); |
720 | |
721 | uintptr_t filter = 0; |
722 | if (modules_p ()) |
723 | filter = module_token_cdtor (parse_in, filter); |
724 | |
725 | /* Create the parser now, so we can use it to handle early pragmas. */ |
726 | gcc_assert (!the_parser); |
727 | the_parser = cp_parser_new (lexer); |
728 | |
729 | /* Get the remaining tokens from the preprocessor. */ |
730 | while (tok->type != CPP_EOF) |
731 | { |
732 | if (filter) |
733 | /* Process the previous token. */ |
734 | module_token_lang (type: tok->type, keyword: tok->keyword, value: tok->u.value, |
735 | tok->location, filter); |
736 | |
737 | /* Check for early pragmas that need to be handled now. */ |
738 | if (tok->type == CPP_PRAGMA_EOL) |
739 | cp_lexer_handle_early_pragma (lexer); |
740 | |
741 | tok = vec_safe_push (v&: lexer->buffer, obj: cp_token ()); |
742 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, tok); |
743 | } |
744 | |
745 | lexer->next_token = lexer->buffer->address (); |
746 | lexer->last_token = lexer->next_token |
747 | + lexer->buffer->length () |
748 | - 1; |
749 | |
750 | if (lexer->buffer->length () != 1) |
751 | { |
752 | /* Set the EOF token's location to be the just after the previous |
753 | token's range. That way 'at-eof' diagnostics point at something |
754 | meaninful. */ |
755 | auto range = get_range_from_loc (set: line_table, loc: tok[-1].location); |
756 | tok[0].location |
757 | = linemap_position_for_loc_and_offset (set: line_table, loc: range.m_finish, offset: 1); |
758 | } |
759 | |
760 | if (filter) |
761 | module_token_cdtor (parse_in, filter); |
762 | |
763 | /* Subsequent preprocessor diagnostics should use compiler |
764 | diagnostic functions to get the compiler source location. */ |
765 | override_libcpp_locations = true; |
766 | |
767 | maybe_check_all_macros (parse_in); |
768 | |
769 | /* If we processed any #pragma GCC target directives, we handled them early so |
770 | any macros they defined would be effective during preprocessing. Now, we |
771 | need to reset to the default state to begin compilation, and we will |
772 | process them again at the correct time as needed. */ |
773 | c_reset_target_pragmas (); |
774 | |
775 | gcc_assert (!lexer->next_token->purged_p); |
776 | return lexer; |
777 | } |
778 | |
779 | /* Create a lexer and parser to be used during preprocess-only mode. |
780 | This will be filled with tokens to parse when needed by pragma_lex (). */ |
781 | void |
782 | c_init_preprocess () |
783 | { |
784 | gcc_assert (!the_parser); |
785 | the_parser = cp_parser_new (cp_lexer_alloc ()); |
786 | } |
787 | |
788 | /* Create a new lexer whose token stream is primed with the tokens in |
789 | CACHE. When these tokens are exhausted, no new tokens will be read. */ |
790 | |
791 | static cp_lexer * |
792 | cp_lexer_new_from_tokens (cp_token_cache *cache) |
793 | { |
794 | cp_token *first = cache->first; |
795 | cp_token *last = cache->last; |
796 | cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> (); |
797 | |
798 | /* We do not own the buffer. */ |
799 | lexer->buffer = NULL; |
800 | |
801 | /* Insert an EOF token. */ |
802 | lexer->saved_type = last->type; |
803 | lexer->saved_keyword = last->keyword; |
804 | last->type = CPP_EOF; |
805 | last->keyword = RID_MAX; |
806 | |
807 | lexer->next_token = first; |
808 | lexer->last_token = last; |
809 | |
810 | lexer->saved_tokens.create (CP_SAVED_TOKEN_STACK); |
811 | |
812 | /* Initially we are not debugging. */ |
813 | lexer->debugging_p = false; |
814 | |
815 | gcc_assert (!lexer->next_token->purged_p |
816 | && !lexer->last_token->purged_p); |
817 | return lexer; |
818 | } |
819 | |
820 | /* Frees all resources associated with LEXER. */ |
821 | |
822 | static void |
823 | cp_lexer_destroy (cp_lexer *lexer) |
824 | { |
825 | if (lexer->buffer) |
826 | vec_free (v&: lexer->buffer); |
827 | else |
828 | { |
829 | /* Restore the token we overwrite with EOF. */ |
830 | lexer->last_token->type = lexer->saved_type; |
831 | lexer->last_token->keyword = lexer->saved_keyword; |
832 | } |
833 | lexer->saved_tokens.release (); |
834 | ggc_free (lexer); |
835 | } |
836 | |
837 | /* This needs to be set to TRUE before the lexer-debugging infrastructure can |
838 | be used. The point of this flag is to help the compiler to fold away calls |
839 | to cp_lexer_debugging_p within this source file at compile time, when the |
840 | lexer is not being debugged. */ |
841 | |
842 | #define LEXER_DEBUGGING_ENABLED_P false |
843 | |
844 | /* Returns nonzero if debugging information should be output. */ |
845 | |
846 | static inline bool |
847 | cp_lexer_debugging_p (cp_lexer *lexer) |
848 | { |
849 | if (!LEXER_DEBUGGING_ENABLED_P) |
850 | return false; |
851 | |
852 | return lexer->debugging_p; |
853 | } |
854 | |
855 | |
856 | static inline cp_token_position |
857 | cp_lexer_token_position (cp_lexer *lexer, bool previous_p) |
858 | { |
859 | return lexer->next_token - previous_p; |
860 | } |
861 | |
862 | static inline cp_token * |
863 | cp_lexer_token_at (cp_lexer * /*lexer*/, cp_token_position pos) |
864 | { |
865 | return pos; |
866 | } |
867 | |
868 | static inline void |
869 | cp_lexer_set_token_position (cp_lexer *lexer, cp_token_position pos) |
870 | { |
871 | lexer->next_token = cp_lexer_token_at (lexer, pos); |
872 | } |
873 | |
874 | static inline cp_token_position |
875 | cp_lexer_previous_token_position (cp_lexer *lexer) |
876 | { |
877 | return cp_lexer_token_position (lexer, previous_p: true); |
878 | } |
879 | |
880 | static inline cp_token * |
881 | cp_lexer_previous_token (cp_lexer *lexer) |
882 | { |
883 | cp_token_position tp = cp_lexer_previous_token_position (lexer); |
884 | |
885 | /* Skip past purged tokens. */ |
886 | while (tp->purged_p) |
887 | { |
888 | gcc_assert (tp != vec_safe_address (lexer->buffer)); |
889 | tp--; |
890 | } |
891 | |
892 | return cp_lexer_token_at (lexer, pos: tp); |
893 | } |
894 | |
895 | /* Same as above, but return NULL when the lexer doesn't own the token |
896 | buffer or if the next_token is at the start of the token |
897 | vector or if all previous tokens are purged. */ |
898 | |
899 | static cp_token * |
900 | cp_lexer_safe_previous_token (cp_lexer *lexer) |
901 | { |
902 | if (lexer->buffer |
903 | && lexer->next_token != lexer->buffer->address ()) |
904 | { |
905 | cp_token_position tp = cp_lexer_previous_token_position (lexer); |
906 | |
907 | /* Skip past purged tokens. */ |
908 | while (tp->purged_p) |
909 | { |
910 | if (tp == lexer->buffer->address ()) |
911 | return NULL; |
912 | tp--; |
913 | } |
914 | return cp_lexer_token_at (lexer, pos: tp); |
915 | } |
916 | |
917 | return NULL; |
918 | } |
919 | |
920 | /* Overload for make_location, taking the lexer to mean the location of the |
921 | previous token. */ |
922 | |
923 | static inline location_t |
924 | make_location (location_t caret, location_t start, cp_lexer *lexer) |
925 | { |
926 | cp_token *t = cp_lexer_previous_token (lexer); |
927 | return make_location (caret, start, finish: t->location); |
928 | } |
929 | |
930 | /* Overload for make_location taking tokens instead of locations. */ |
931 | |
932 | static inline location_t |
933 | make_location (cp_token *caret, cp_token *start, cp_token *end) |
934 | { |
935 | return make_location (caret: caret->location, start: start->location, finish: end->location); |
936 | } |
937 | |
938 | /* nonzero if we are presently saving tokens. */ |
939 | |
940 | static inline int |
941 | cp_lexer_saving_tokens (const cp_lexer* lexer) |
942 | { |
943 | return lexer->saved_tokens.length () != 0; |
944 | } |
945 | |
946 | /* Store the next token from the preprocessor in *TOKEN. Return true |
947 | if we reach EOF. If LEXER is NULL, assume we are handling an |
948 | initial #pragma pch_preprocess, and thus want the lexer to return |
949 | processed strings. |
950 | |
951 | Diagnostics issued from this function must have their controlling option (if |
952 | any) in c.opt annotated as a libcpp option via the CppReason property. */ |
953 | |
954 | static void |
955 | cp_lexer_get_preprocessor_token (unsigned flags, cp_token *token) |
956 | { |
957 | static int is_extern_c = 0; |
958 | |
959 | /* Get a new token from the preprocessor. */ |
960 | token->type |
961 | = c_lex_with_flags (&token->u.value, &token->location, &token->flags, |
962 | flags); |
963 | token->keyword = RID_MAX; |
964 | token->purged_p = false; |
965 | token->error_reported = false; |
966 | token->tree_check_p = false; |
967 | /* Usually never see a zero, but just in case ... */ |
968 | token->main_source_p = line_table->depth <= 1; |
969 | |
970 | /* On some systems, some header files are surrounded by an |
971 | implicit extern "C" block. Set a flag in the token if it |
972 | comes from such a header. */ |
973 | is_extern_c += pending_lang_change; |
974 | pending_lang_change = 0; |
975 | token->implicit_extern_c = is_extern_c > 0; |
976 | |
977 | /* Check to see if this token is a keyword. */ |
978 | if (token->type == CPP_NAME) |
979 | { |
980 | if (IDENTIFIER_KEYWORD_P (token->u.value)) |
981 | { |
982 | /* Mark this token as a keyword. */ |
983 | token->type = CPP_KEYWORD; |
984 | /* Record which keyword. */ |
985 | token->keyword = C_RID_CODE (token->u.value); |
986 | } |
987 | else |
988 | { |
989 | if (warn_cxx11_compat |
990 | && ((C_RID_CODE (token->u.value) >= RID_FIRST_CXX11 |
991 | && C_RID_CODE (token->u.value) <= RID_LAST_CXX11) |
992 | /* These are outside the CXX11 range. */ |
993 | || C_RID_CODE (token->u.value) == RID_ALIGNOF |
994 | || C_RID_CODE (token->u.value) == RID_ALIGNAS |
995 | || C_RID_CODE (token->u.value)== RID_THREAD)) |
996 | { |
997 | /* Warn about the C++11 keyword (but still treat it as |
998 | an identifier). */ |
999 | warning_at (token->location, OPT_Wc__11_compat, |
1000 | "identifier %qE is a keyword in C++11" , |
1001 | token->u.value); |
1002 | |
1003 | /* Clear out the C_RID_CODE so we don't warn about this |
1004 | particular identifier-turned-keyword again. */ |
1005 | C_SET_RID_CODE (token->u.value, RID_MAX); |
1006 | } |
1007 | if (warn_cxx20_compat |
1008 | && C_RID_CODE (token->u.value) >= RID_FIRST_CXX20 |
1009 | && C_RID_CODE (token->u.value) <= RID_LAST_CXX20) |
1010 | { |
1011 | /* Warn about the C++20 keyword (but still treat it as |
1012 | an identifier). */ |
1013 | warning_at (token->location, OPT_Wc__20_compat, |
1014 | "identifier %qE is a keyword in C++20" , |
1015 | token->u.value); |
1016 | |
1017 | /* Clear out the C_RID_CODE so we don't warn about this |
1018 | particular identifier-turned-keyword again. */ |
1019 | C_SET_RID_CODE (token->u.value, RID_MAX); |
1020 | } |
1021 | |
1022 | token->keyword = RID_MAX; |
1023 | } |
1024 | } |
1025 | else if (token->type == CPP_AT_NAME) |
1026 | { |
1027 | /* This only happens in Objective-C++; it must be a keyword. */ |
1028 | token->type = CPP_KEYWORD; |
1029 | switch (C_RID_CODE (token->u.value)) |
1030 | { |
1031 | /* Replace 'class' with '@class', 'private' with '@private', |
1032 | etc. This prevents confusion with the C++ keyword |
1033 | 'class', and makes the tokens consistent with other |
1034 | Objective-C 'AT' keywords. For example '@class' is |
1035 | reported as RID_AT_CLASS which is consistent with |
1036 | '@synchronized', which is reported as |
1037 | RID_AT_SYNCHRONIZED. |
1038 | */ |
1039 | case RID_CLASS: token->keyword = RID_AT_CLASS; break; |
1040 | case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break; |
1041 | case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break; |
1042 | case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break; |
1043 | case RID_THROW: token->keyword = RID_AT_THROW; break; |
1044 | case RID_TRY: token->keyword = RID_AT_TRY; break; |
1045 | case RID_CATCH: token->keyword = RID_AT_CATCH; break; |
1046 | case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break; |
1047 | default: token->keyword = C_RID_CODE (token->u.value); |
1048 | } |
1049 | } |
1050 | } |
1051 | |
1052 | /* Update the globals input_location and the input file stack from TOKEN. */ |
1053 | static inline void |
1054 | cp_lexer_set_source_position_from_token (cp_token *token) |
1055 | { |
1056 | input_location = token->location; |
1057 | } |
1058 | |
1059 | /* Update the globals input_location and the input file stack from LEXER. */ |
1060 | static inline void |
1061 | cp_lexer_set_source_position (cp_lexer *lexer) |
1062 | { |
1063 | cp_token *token = cp_lexer_peek_token (lexer); |
1064 | cp_lexer_set_source_position_from_token (token); |
1065 | } |
1066 | |
1067 | /* Return a pointer to the next token in the token stream, but do not |
1068 | consume it. */ |
1069 | |
1070 | static inline cp_token * |
1071 | cp_lexer_peek_token (cp_lexer *lexer) |
1072 | { |
1073 | if (cp_lexer_debugging_p (lexer)) |
1074 | { |
1075 | fputs (s: "cp_lexer: peeking at token: " , stream: cp_lexer_debug_stream); |
1076 | cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token); |
1077 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1078 | } |
1079 | return lexer->next_token; |
1080 | } |
1081 | |
1082 | /* Return true if the next token has the indicated TYPE. */ |
1083 | |
1084 | static inline bool |
1085 | cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type) |
1086 | { |
1087 | return cp_lexer_peek_token (lexer)->type == type; |
1088 | } |
1089 | |
1090 | /* Return true if the next token does not have the indicated TYPE. */ |
1091 | |
1092 | static inline bool |
1093 | cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type) |
1094 | { |
1095 | return !cp_lexer_next_token_is (lexer, type); |
1096 | } |
1097 | |
1098 | /* Return true if the next token is the indicated KEYWORD. */ |
1099 | |
1100 | static inline bool |
1101 | cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) |
1102 | { |
1103 | return cp_lexer_peek_token (lexer)->keyword == keyword; |
1104 | } |
1105 | |
1106 | static inline bool |
1107 | cp_lexer_nth_token_is (cp_lexer* lexer, size_t n, enum cpp_ttype type) |
1108 | { |
1109 | return cp_lexer_peek_nth_token (lexer, n)->type == type; |
1110 | } |
1111 | |
1112 | static inline bool |
1113 | cp_lexer_nth_token_is_keyword (cp_lexer* lexer, size_t n, enum rid keyword) |
1114 | { |
1115 | return cp_lexer_peek_nth_token (lexer, n)->keyword == keyword; |
1116 | } |
1117 | |
1118 | /* Return true if KEYWORD can start a decl-specifier. */ |
1119 | |
1120 | bool |
1121 | cp_keyword_starts_decl_specifier_p (enum rid keyword) |
1122 | { |
1123 | switch (keyword) |
1124 | { |
1125 | /* auto specifier: storage-class-specifier in C++, |
1126 | simple-type-specifier in C++0x. */ |
1127 | case RID_AUTO: |
1128 | /* Storage classes. */ |
1129 | case RID_REGISTER: |
1130 | case RID_STATIC: |
1131 | case RID_EXTERN: |
1132 | case RID_MUTABLE: |
1133 | case RID_THREAD: |
1134 | /* Elaborated type specifiers. */ |
1135 | case RID_ENUM: |
1136 | case RID_CLASS: |
1137 | case RID_STRUCT: |
1138 | case RID_UNION: |
1139 | case RID_TYPENAME: |
1140 | /* Simple type specifiers. */ |
1141 | case RID_CHAR: |
1142 | case RID_CHAR8: |
1143 | case RID_CHAR16: |
1144 | case RID_CHAR32: |
1145 | case RID_WCHAR: |
1146 | case RID_BOOL: |
1147 | case RID_SHORT: |
1148 | case RID_INT: |
1149 | case RID_LONG: |
1150 | case RID_SIGNED: |
1151 | case RID_UNSIGNED: |
1152 | case RID_FLOAT: |
1153 | case RID_DOUBLE: |
1154 | CASE_RID_FLOATN_NX: |
1155 | case RID_VOID: |
1156 | /* CV qualifiers. */ |
1157 | case RID_CONST: |
1158 | case RID_VOLATILE: |
1159 | /* Function specifiers. */ |
1160 | case RID_EXPLICIT: |
1161 | case RID_VIRTUAL: |
1162 | /* friend/typdef/inline specifiers. */ |
1163 | case RID_FRIEND: |
1164 | case RID_TYPEDEF: |
1165 | case RID_INLINE: |
1166 | /* GNU extensions. */ |
1167 | case RID_TYPEOF: |
1168 | /* C++11 extensions. */ |
1169 | case RID_DECLTYPE: |
1170 | case RID_CONSTEXPR: |
1171 | /* C++20 extensions. */ |
1172 | case RID_CONSTINIT: |
1173 | case RID_CONSTEVAL: |
1174 | return true; |
1175 | |
1176 | #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ |
1177 | case RID_##CODE: |
1178 | #include "cp-trait.def" |
1179 | #undef DEFTRAIT_TYPE |
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 | /* Return true if the next token is a keyword for a decl-specifier. */ |
1192 | |
1193 | static bool |
1194 | cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) |
1195 | { |
1196 | cp_token *token; |
1197 | |
1198 | token = cp_lexer_peek_token (lexer); |
1199 | return cp_keyword_starts_decl_specifier_p (keyword: token->keyword); |
1200 | } |
1201 | |
1202 | /* Returns TRUE iff the token T begins a decltype type. */ |
1203 | |
1204 | static bool |
1205 | token_is_decltype (cp_token *t) |
1206 | { |
1207 | return (t->keyword == RID_DECLTYPE |
1208 | || t->type == CPP_DECLTYPE); |
1209 | } |
1210 | |
1211 | /* Returns TRUE iff the next token begins a decltype type. */ |
1212 | |
1213 | static bool |
1214 | cp_lexer_next_token_is_decltype (cp_lexer *lexer) |
1215 | { |
1216 | cp_token *t = cp_lexer_peek_token (lexer); |
1217 | return token_is_decltype (t); |
1218 | } |
1219 | |
1220 | /* Called when processing a token with tree_check_value; perform or defer the |
1221 | associated checks and return the value. */ |
1222 | |
1223 | static tree |
1224 | saved_checks_value (struct tree_check *check_value) |
1225 | { |
1226 | /* Perform any access checks that were deferred. */ |
1227 | vec<deferred_access_check, va_gc> *checks; |
1228 | deferred_access_check *chk; |
1229 | checks = check_value->checks; |
1230 | if (checks) |
1231 | { |
1232 | int i; |
1233 | FOR_EACH_VEC_SAFE_ELT (checks, i, chk) |
1234 | perform_or_defer_access_check (chk->binfo, |
1235 | chk->decl, |
1236 | chk->diag_decl, tf_warning_or_error); |
1237 | } |
1238 | /* Return the stored value. */ |
1239 | return check_value->value; |
1240 | } |
1241 | |
1242 | /* Return a pointer to the Nth token in the token stream. If N is 1, |
1243 | then this is precisely equivalent to cp_lexer_peek_token (except |
1244 | that it is not inline). One would like to disallow that case, but |
1245 | there is one case (cp_parser_nth_token_starts_template_id) where |
1246 | the caller passes a variable for N and it might be 1. */ |
1247 | |
1248 | static cp_token * |
1249 | cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) |
1250 | { |
1251 | cp_token *token; |
1252 | |
1253 | /* N is 1-based, not zero-based. */ |
1254 | gcc_assert (n > 0); |
1255 | |
1256 | if (cp_lexer_debugging_p (lexer)) |
1257 | fprintf (stream: cp_lexer_debug_stream, |
1258 | format: "cp_lexer: peeking ahead %ld at token: " , (long)n); |
1259 | |
1260 | --n; |
1261 | token = lexer->next_token; |
1262 | while (n && token->type != CPP_EOF) |
1263 | { |
1264 | ++token; |
1265 | if (!token->purged_p) |
1266 | --n; |
1267 | } |
1268 | |
1269 | if (cp_lexer_debugging_p (lexer)) |
1270 | { |
1271 | cp_lexer_print_token (cp_lexer_debug_stream, token); |
1272 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1273 | } |
1274 | |
1275 | return token; |
1276 | } |
1277 | |
1278 | /* Return the next token, and advance the lexer's next_token pointer |
1279 | to point to the next non-purged token. */ |
1280 | |
1281 | static cp_token * |
1282 | cp_lexer_consume_token (cp_lexer* lexer) |
1283 | { |
1284 | cp_token *token = lexer->next_token; |
1285 | |
1286 | do |
1287 | { |
1288 | gcc_assert (token->type != CPP_EOF); |
1289 | lexer->next_token++; |
1290 | } |
1291 | while (lexer->next_token->purged_p); |
1292 | |
1293 | cp_lexer_set_source_position_from_token (token); |
1294 | |
1295 | /* Provide debugging output. */ |
1296 | if (cp_lexer_debugging_p (lexer)) |
1297 | { |
1298 | fputs (s: "cp_lexer: consuming token: " , stream: cp_lexer_debug_stream); |
1299 | cp_lexer_print_token (cp_lexer_debug_stream, token); |
1300 | putc (c: '\n', stream: cp_lexer_debug_stream); |
1301 | } |
1302 | |
1303 | return token; |
1304 | } |
1305 | |
1306 | /* Permanently remove the next token from the token stream, and |
1307 | advance the next_token pointer to refer to the next non-purged |
1308 | token. */ |
1309 | |
1310 | static void |
1311 | cp_lexer_purge_token (cp_lexer *lexer) |
1312 | { |
1313 | cp_token *tok = lexer->next_token; |
1314 | |
1315 | gcc_assert (tok->type != CPP_EOF); |
1316 | tok->purged_p = true; |
1317 | tok->location = UNKNOWN_LOCATION; |
1318 | tok->u.value = NULL_TREE; |
1319 | tok->keyword = RID_MAX; |
1320 | |
1321 | do |
1322 | tok++; |
1323 | while (tok->purged_p); |
1324 | lexer->next_token = tok; |
1325 | } |
1326 | |
1327 | /* Permanently remove all tokens after TOK, up to, but not |
1328 | including, the token that will be returned next by |
1329 | cp_lexer_peek_token. */ |
1330 | |
1331 | static void |
1332 | cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok) |
1333 | { |
1334 | cp_token *peek = lexer->next_token; |
1335 | |
1336 | gcc_assert (tok < peek); |
1337 | |
1338 | for (tok++; tok != peek; tok++) |
1339 | { |
1340 | tok->purged_p = true; |
1341 | tok->location = UNKNOWN_LOCATION; |
1342 | tok->u.value = NULL_TREE; |
1343 | tok->keyword = RID_MAX; |
1344 | } |
1345 | } |
1346 | |
1347 | /* Begin saving tokens. All tokens consumed after this point will be |
1348 | preserved. */ |
1349 | |
1350 | static void |
1351 | cp_lexer_save_tokens (cp_lexer* lexer) |
1352 | { |
1353 | /* Provide debugging output. */ |
1354 | if (cp_lexer_debugging_p (lexer)) |
1355 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: saving tokens\n" ); |
1356 | |
1357 | lexer->saved_tokens.safe_push (obj: lexer->next_token); |
1358 | } |
1359 | |
1360 | /* Commit to the portion of the token stream most recently saved. */ |
1361 | |
1362 | static void |
1363 | cp_lexer_commit_tokens (cp_lexer* lexer) |
1364 | { |
1365 | /* Provide debugging output. */ |
1366 | if (cp_lexer_debugging_p (lexer)) |
1367 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: committing tokens\n" ); |
1368 | |
1369 | lexer->saved_tokens.pop (); |
1370 | } |
1371 | |
1372 | /* Return all tokens saved since the last call to cp_lexer_save_tokens |
1373 | to the token stream. Stop saving tokens. */ |
1374 | |
1375 | static void |
1376 | cp_lexer_rollback_tokens (cp_lexer* lexer) |
1377 | { |
1378 | /* Provide debugging output. */ |
1379 | if (cp_lexer_debugging_p (lexer)) |
1380 | fprintf (stream: cp_lexer_debug_stream, format: "cp_lexer: restoring tokens\n" ); |
1381 | |
1382 | lexer->next_token = lexer->saved_tokens.pop (); |
1383 | } |
1384 | |
1385 | /* Determines what saved_token_sentinel does when going out of scope. */ |
1386 | |
1387 | enum saved_token_sentinel_mode { |
1388 | STS_COMMIT, |
1389 | STS_ROLLBACK, |
1390 | STS_DONOTHING |
1391 | }; |
1392 | |
1393 | /* RAII wrapper around the above functions, with sanity checking (the token |
1394 | stream should be the same at the point of instantiation as it is at the |
1395 | point of destruction). |
1396 | |
1397 | Creating a variable saves tokens. MODE determines what happens when the |
1398 | object is destroyed. STS_COMMIT commits tokens (default), |
1399 | STS_ROLLBACK rolls-back and STS_DONOTHING does nothing. Calling |
1400 | rollback() will immediately roll-back tokens and set MODE to |
1401 | STS_DONOTHING. */ |
1402 | |
1403 | struct saved_token_sentinel |
1404 | { |
1405 | cp_lexer *lexer; |
1406 | unsigned len; |
1407 | saved_token_sentinel_mode mode; |
1408 | saved_token_sentinel (cp_lexer *_lexer, |
1409 | saved_token_sentinel_mode _mode = STS_COMMIT) |
1410 | : lexer (_lexer), mode (_mode) |
1411 | { |
1412 | len = lexer->saved_tokens.length (); |
1413 | cp_lexer_save_tokens (lexer); |
1414 | } |
1415 | void rollback () |
1416 | { |
1417 | cp_lexer_rollback_tokens (lexer); |
1418 | cp_lexer_set_source_position_from_token |
1419 | (token: cp_lexer_previous_token (lexer)); |
1420 | mode = STS_DONOTHING; |
1421 | } |
1422 | ~saved_token_sentinel () |
1423 | { |
1424 | if (mode == STS_COMMIT) |
1425 | cp_lexer_commit_tokens (lexer); |
1426 | else if (mode == STS_ROLLBACK) |
1427 | rollback (); |
1428 | |
1429 | gcc_assert (lexer->saved_tokens.length () == len); |
1430 | } |
1431 | }; |
1432 | |
1433 | /* Print a representation of the TOKEN on the STREAM. */ |
1434 | |
1435 | static void |
1436 | cp_lexer_print_token (FILE * stream, cp_token *token) |
1437 | { |
1438 | /* We don't use cpp_type2name here because the parser defines |
1439 | a few tokens of its own. */ |
1440 | static const char *const token_names[] = { |
1441 | /* cpplib-defined token types */ |
1442 | #define OP(e, s) #e, |
1443 | #define TK(e, s) #e, |
1444 | TTYPE_TABLE |
1445 | #undef OP |
1446 | #undef TK |
1447 | /* C++ parser token types - see "Manifest constants", above. */ |
1448 | "KEYWORD" , |
1449 | "TEMPLATE_ID" , |
1450 | "NESTED_NAME_SPECIFIER" , |
1451 | }; |
1452 | |
1453 | /* For some tokens, print the associated data. */ |
1454 | switch (token->type) |
1455 | { |
1456 | case CPP_KEYWORD: |
1457 | /* Some keywords have a value that is not an IDENTIFIER_NODE. |
1458 | For example, `struct' is mapped to an INTEGER_CST. */ |
1459 | if (!identifier_p (t: token->u.value)) |
1460 | break; |
1461 | /* fall through */ |
1462 | case CPP_NAME: |
1463 | fputs (IDENTIFIER_POINTER (token->u.value), stream: stream); |
1464 | break; |
1465 | |
1466 | case CPP_STRING: |
1467 | case CPP_STRING16: |
1468 | case CPP_STRING32: |
1469 | case CPP_WSTRING: |
1470 | case CPP_UTF8STRING: |
1471 | fprintf (stream: stream, format: " \"%s\"" , TREE_STRING_POINTER (token->u.value)); |
1472 | break; |
1473 | |
1474 | case CPP_NUMBER: |
1475 | print_generic_expr (stream, token->u.value); |
1476 | break; |
1477 | |
1478 | default: |
1479 | /* If we have a name for the token, print it out. Otherwise, we |
1480 | simply give the numeric code. */ |
1481 | if (token->type < ARRAY_SIZE(token_names)) |
1482 | fputs (s: token_names[token->type], stream: stream); |
1483 | else |
1484 | fprintf (stream: stream, format: "[%d]" , token->type); |
1485 | break; |
1486 | } |
1487 | } |
1488 | |
1489 | DEBUG_FUNCTION void |
1490 | debug (cp_token &ref) |
1491 | { |
1492 | cp_lexer_print_token (stderr, token: &ref); |
1493 | fprintf (stderr, format: "\n" ); |
1494 | } |
1495 | |
1496 | DEBUG_FUNCTION void |
1497 | debug (cp_token *ptr) |
1498 | { |
1499 | if (ptr) |
1500 | debug (ref&: *ptr); |
1501 | else |
1502 | fprintf (stderr, format: "<nil>\n" ); |
1503 | } |
1504 | |
1505 | |
1506 | /* Start emitting debugging information. */ |
1507 | |
1508 | static void |
1509 | cp_lexer_start_debugging (cp_lexer* lexer) |
1510 | { |
1511 | if (!LEXER_DEBUGGING_ENABLED_P) |
1512 | fatal_error (input_location, |
1513 | "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true" ); |
1514 | |
1515 | lexer->debugging_p = true; |
1516 | cp_lexer_debug_stream = stderr; |
1517 | } |
1518 | |
1519 | /* Stop emitting debugging information. */ |
1520 | |
1521 | static void |
1522 | cp_lexer_stop_debugging (cp_lexer* lexer) |
1523 | { |
1524 | if (!LEXER_DEBUGGING_ENABLED_P) |
1525 | fatal_error (input_location, |
1526 | "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true" ); |
1527 | |
1528 | lexer->debugging_p = false; |
1529 | cp_lexer_debug_stream = NULL; |
1530 | } |
1531 | |
1532 | /* Create a new cp_token_cache, representing a range of tokens. */ |
1533 | |
1534 | static cp_token_cache * |
1535 | cp_token_cache_new (cp_token *first, cp_token *last) |
1536 | { |
1537 | cp_token_cache *cache = ggc_alloc<cp_token_cache> (); |
1538 | cache->first = first; |
1539 | cache->last = last; |
1540 | return cache; |
1541 | } |
1542 | |
1543 | /* Diagnose if #pragma omp declare simd isn't followed immediately |
1544 | by function declaration or definition. */ |
1545 | |
1546 | static inline void |
1547 | cp_ensure_no_omp_declare_simd (cp_parser *parser) |
1548 | { |
1549 | if (parser->omp_declare_simd && !parser->omp_declare_simd->error_seen) |
1550 | { |
1551 | error ("%<#pragma omp declare %s%> not immediately followed by " |
1552 | "function declaration or definition" , |
1553 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
1554 | parser->omp_declare_simd = NULL; |
1555 | } |
1556 | } |
1557 | |
1558 | /* Finalize #pragma omp declare simd clauses after FNDECL has been parsed, |
1559 | and put that into "omp declare simd" attribute. */ |
1560 | |
1561 | static inline void |
1562 | cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl) |
1563 | { |
1564 | if (UNLIKELY (parser->omp_declare_simd != NULL)) |
1565 | { |
1566 | if (fndecl == error_mark_node) |
1567 | { |
1568 | parser->omp_declare_simd = NULL; |
1569 | return; |
1570 | } |
1571 | if (TREE_CODE (fndecl) != FUNCTION_DECL) |
1572 | { |
1573 | cp_ensure_no_omp_declare_simd (parser); |
1574 | return; |
1575 | } |
1576 | } |
1577 | } |
1578 | |
1579 | /* Similarly, but for use in declaration parsing functions |
1580 | which call cp_parser_handle_directive_omp_attributes. */ |
1581 | |
1582 | static inline void |
1583 | cp_finalize_omp_declare_simd (cp_parser *parser, cp_omp_declare_simd_data *data) |
1584 | { |
1585 | if (parser->omp_declare_simd != data) |
1586 | return; |
1587 | |
1588 | if (!parser->omp_declare_simd->error_seen |
1589 | && !parser->omp_declare_simd->fndecl_seen) |
1590 | error_at (parser->omp_declare_simd->loc, |
1591 | "%<declare %s%> directive not immediately followed by " |
1592 | "function declaration or definition" , |
1593 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
1594 | parser->omp_declare_simd = NULL; |
1595 | } |
1596 | |
1597 | /* Diagnose if #pragma acc routine isn't followed immediately by function |
1598 | declaration or definition. */ |
1599 | |
1600 | static inline void |
1601 | cp_ensure_no_oacc_routine (cp_parser *parser) |
1602 | { |
1603 | if (parser->oacc_routine && !parser->oacc_routine->error_seen) |
1604 | { |
1605 | error_at (parser->oacc_routine->loc, |
1606 | "%<#pragma acc routine%> not immediately followed by " |
1607 | "function declaration or definition" ); |
1608 | parser->oacc_routine = NULL; |
1609 | } |
1610 | } |
1611 | |
1612 | /* Decl-specifiers. */ |
1613 | |
1614 | /* Set *DECL_SPECS to represent an empty decl-specifier-seq. */ |
1615 | |
1616 | static void |
1617 | clear_decl_specs (cp_decl_specifier_seq *decl_specs) |
1618 | { |
1619 | memset (s: decl_specs, c: 0, n: sizeof (cp_decl_specifier_seq)); |
1620 | } |
1621 | |
1622 | /* Declarators. */ |
1623 | |
1624 | /* Nothing other than the parser should be creating declarators; |
1625 | declarators are a semi-syntactic representation of C++ entities. |
1626 | Other parts of the front end that need to create entities (like |
1627 | VAR_DECLs or FUNCTION_DECLs) should do that directly. */ |
1628 | |
1629 | static cp_declarator *make_call_declarator |
1630 | (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, |
1631 | tree, tree, tree, tree, tree, location_t); |
1632 | static cp_declarator *make_array_declarator |
1633 | (cp_declarator *, tree); |
1634 | static cp_declarator *make_pointer_declarator |
1635 | (cp_cv_quals, cp_declarator *, tree); |
1636 | static cp_declarator *make_reference_declarator |
1637 | (cp_cv_quals, cp_declarator *, bool, tree); |
1638 | static cp_declarator *make_ptrmem_declarator |
1639 | (cp_cv_quals, tree, cp_declarator *, tree); |
1640 | |
1641 | /* An erroneous declarator. */ |
1642 | static cp_declarator *cp_error_declarator; |
1643 | |
1644 | /* The obstack on which declarators and related data structures are |
1645 | allocated. */ |
1646 | static struct obstack declarator_obstack; |
1647 | |
1648 | /* Alloc BYTES from the declarator memory pool. */ |
1649 | |
1650 | static inline void * |
1651 | alloc_declarator (size_t bytes) |
1652 | { |
1653 | return obstack_alloc (&declarator_obstack, bytes); |
1654 | } |
1655 | |
1656 | /* Allocate a declarator of the indicated KIND. Clear fields that are |
1657 | common to all declarators. */ |
1658 | |
1659 | static cp_declarator * |
1660 | make_declarator (cp_declarator_kind kind) |
1661 | { |
1662 | cp_declarator *declarator; |
1663 | |
1664 | declarator = (cp_declarator *) alloc_declarator (bytes: sizeof (cp_declarator)); |
1665 | declarator->kind = kind; |
1666 | declarator->parenthesized = UNKNOWN_LOCATION; |
1667 | declarator->attributes = NULL_TREE; |
1668 | declarator->std_attributes = NULL_TREE; |
1669 | declarator->declarator = NULL; |
1670 | declarator->parameter_pack_p = false; |
1671 | declarator->id_loc = UNKNOWN_LOCATION; |
1672 | declarator->init_loc = UNKNOWN_LOCATION; |
1673 | |
1674 | return declarator; |
1675 | } |
1676 | |
1677 | /* Make a declarator for a generalized identifier. If |
1678 | QUALIFYING_SCOPE is non-NULL, the identifier is |
1679 | QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is just |
1680 | UNQUALIFIED_NAME. SFK indicates the kind of special function this |
1681 | is, if any. */ |
1682 | |
1683 | static cp_declarator * |
1684 | make_id_declarator (tree qualifying_scope, tree unqualified_name, |
1685 | special_function_kind sfk, location_t id_location) |
1686 | { |
1687 | cp_declarator *declarator; |
1688 | |
1689 | /* It is valid to write: |
1690 | |
1691 | class C { void f(); }; |
1692 | typedef C D; |
1693 | void D::f(); |
1694 | |
1695 | The standard is not clear about whether `typedef const C D' is |
1696 | legal; as of 2002-09-15 the committee is considering that |
1697 | question. EDG 3.0 allows that syntax. Therefore, we do as |
1698 | well. */ |
1699 | if (qualifying_scope && TYPE_P (qualifying_scope)) |
1700 | qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope); |
1701 | |
1702 | gcc_assert (identifier_p (unqualified_name) |
1703 | || TREE_CODE (unqualified_name) == BIT_NOT_EXPR |
1704 | || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR); |
1705 | |
1706 | declarator = make_declarator (kind: cdk_id); |
1707 | declarator->u.id.qualifying_scope = qualifying_scope; |
1708 | declarator->u.id.unqualified_name = unqualified_name; |
1709 | declarator->u.id.sfk = sfk; |
1710 | declarator->id_loc = id_location; |
1711 | |
1712 | return declarator; |
1713 | } |
1714 | |
1715 | /* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list |
1716 | of modifiers such as const or volatile to apply to the pointer |
1717 | type, represented as identifiers. ATTRIBUTES represent the attributes that |
1718 | appertain to the pointer or reference. */ |
1719 | |
1720 | cp_declarator * |
1721 | make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, |
1722 | tree attributes) |
1723 | { |
1724 | cp_declarator *declarator; |
1725 | |
1726 | declarator = make_declarator (kind: cdk_pointer); |
1727 | declarator->declarator = target; |
1728 | declarator->u.pointer.qualifiers = cv_qualifiers; |
1729 | declarator->u.pointer.class_type = NULL_TREE; |
1730 | if (target) |
1731 | { |
1732 | declarator->id_loc = target->id_loc; |
1733 | declarator->parameter_pack_p = target->parameter_pack_p; |
1734 | target->parameter_pack_p = false; |
1735 | } |
1736 | else |
1737 | declarator->parameter_pack_p = false; |
1738 | |
1739 | declarator->std_attributes = attributes; |
1740 | |
1741 | return declarator; |
1742 | } |
1743 | |
1744 | /* Like make_pointer_declarator -- but for references. ATTRIBUTES |
1745 | represent the attributes that appertain to the pointer or |
1746 | reference. */ |
1747 | |
1748 | cp_declarator * |
1749 | make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, |
1750 | bool rvalue_ref, tree attributes) |
1751 | { |
1752 | cp_declarator *declarator; |
1753 | |
1754 | declarator = make_declarator (kind: cdk_reference); |
1755 | declarator->declarator = target; |
1756 | declarator->u.reference.qualifiers = cv_qualifiers; |
1757 | declarator->u.reference.rvalue_ref = rvalue_ref; |
1758 | if (target) |
1759 | { |
1760 | declarator->id_loc = target->id_loc; |
1761 | declarator->parameter_pack_p = target->parameter_pack_p; |
1762 | target->parameter_pack_p = false; |
1763 | } |
1764 | else |
1765 | declarator->parameter_pack_p = false; |
1766 | |
1767 | declarator->std_attributes = attributes; |
1768 | |
1769 | return declarator; |
1770 | } |
1771 | |
1772 | /* Like make_pointer_declarator -- but for a pointer to a non-static |
1773 | member of CLASS_TYPE. ATTRIBUTES represent the attributes that |
1774 | appertain to the pointer or reference. */ |
1775 | |
1776 | cp_declarator * |
1777 | make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, |
1778 | cp_declarator *pointee, |
1779 | tree attributes) |
1780 | { |
1781 | cp_declarator *declarator; |
1782 | |
1783 | declarator = make_declarator (kind: cdk_ptrmem); |
1784 | declarator->declarator = pointee; |
1785 | declarator->u.pointer.qualifiers = cv_qualifiers; |
1786 | declarator->u.pointer.class_type = class_type; |
1787 | |
1788 | if (pointee) |
1789 | { |
1790 | declarator->parameter_pack_p = pointee->parameter_pack_p; |
1791 | pointee->parameter_pack_p = false; |
1792 | } |
1793 | else |
1794 | declarator->parameter_pack_p = false; |
1795 | |
1796 | declarator->std_attributes = attributes; |
1797 | |
1798 | return declarator; |
1799 | } |
1800 | |
1801 | /* Make a declarator for the function given by TARGET, with the |
1802 | indicated PARMS. The CV_QUALIFIERS apply to the function, as in |
1803 | "const"-qualified member function. The EXCEPTION_SPECIFICATION |
1804 | indicates what exceptions can be thrown. STD_ATTRS contains |
1805 | attributes that appertain to the function type. */ |
1806 | |
1807 | cp_declarator * |
1808 | make_call_declarator (cp_declarator *target, |
1809 | tree parms, |
1810 | cp_cv_quals cv_qualifiers, |
1811 | cp_virt_specifiers virt_specifiers, |
1812 | cp_ref_qualifier ref_qualifier, |
1813 | tree tx_qualifier, |
1814 | tree exception_specification, |
1815 | tree late_return_type, |
1816 | tree requires_clause, |
1817 | tree std_attrs, |
1818 | location_t parens_loc) |
1819 | { |
1820 | cp_declarator *declarator; |
1821 | |
1822 | declarator = make_declarator (kind: cdk_function); |
1823 | declarator->declarator = target; |
1824 | declarator->u.function.parameters = parms; |
1825 | declarator->u.function.qualifiers = cv_qualifiers; |
1826 | declarator->u.function.virt_specifiers = virt_specifiers; |
1827 | declarator->u.function.ref_qualifier = ref_qualifier; |
1828 | declarator->u.function.tx_qualifier = tx_qualifier; |
1829 | declarator->u.function.exception_specification = exception_specification; |
1830 | declarator->u.function.late_return_type = late_return_type; |
1831 | declarator->u.function.requires_clause = requires_clause; |
1832 | declarator->u.function.parens_loc = parens_loc; |
1833 | if (target) |
1834 | { |
1835 | declarator->id_loc = target->id_loc; |
1836 | declarator->parameter_pack_p = target->parameter_pack_p; |
1837 | target->parameter_pack_p = false; |
1838 | } |
1839 | else |
1840 | declarator->parameter_pack_p = false; |
1841 | |
1842 | declarator->std_attributes = std_attrs; |
1843 | |
1844 | return declarator; |
1845 | } |
1846 | |
1847 | /* Make a declarator for an array of BOUNDS elements, each of which is |
1848 | defined by ELEMENT. */ |
1849 | |
1850 | cp_declarator * |
1851 | make_array_declarator (cp_declarator *element, tree bounds) |
1852 | { |
1853 | cp_declarator *declarator; |
1854 | |
1855 | declarator = make_declarator (kind: cdk_array); |
1856 | declarator->declarator = element; |
1857 | declarator->u.array.bounds = bounds; |
1858 | if (element) |
1859 | { |
1860 | declarator->id_loc = element->id_loc; |
1861 | declarator->parameter_pack_p = element->parameter_pack_p; |
1862 | element->parameter_pack_p = false; |
1863 | } |
1864 | else |
1865 | declarator->parameter_pack_p = false; |
1866 | |
1867 | return declarator; |
1868 | } |
1869 | |
1870 | /* Determine whether the declarator we've seen so far can be a |
1871 | parameter pack, when followed by an ellipsis. */ |
1872 | static bool |
1873 | declarator_can_be_parameter_pack (cp_declarator *declarator) |
1874 | { |
1875 | if (declarator && declarator->parameter_pack_p) |
1876 | /* We already saw an ellipsis. */ |
1877 | return false; |
1878 | |
1879 | /* Search for a declarator name, or any other declarator that goes |
1880 | after the point where the ellipsis could appear in a parameter |
1881 | pack. If we find any of these, then this declarator cannot be |
1882 | made into a parameter pack. */ |
1883 | bool found = false; |
1884 | while (declarator && !found) |
1885 | { |
1886 | switch ((int)declarator->kind) |
1887 | { |
1888 | case cdk_id: |
1889 | case cdk_array: |
1890 | case cdk_decomp: |
1891 | found = true; |
1892 | break; |
1893 | |
1894 | case cdk_error: |
1895 | return true; |
1896 | |
1897 | default: |
1898 | declarator = declarator->declarator; |
1899 | break; |
1900 | } |
1901 | } |
1902 | |
1903 | return !found; |
1904 | } |
1905 | |
1906 | cp_parameter_declarator *no_parameters; |
1907 | |
1908 | /* Create a parameter declarator with the indicated DECL_SPECIFIERS, |
1909 | DECLARATOR and DEFAULT_ARGUMENT. */ |
1910 | |
1911 | cp_parameter_declarator * |
1912 | make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, |
1913 | cp_declarator *declarator, |
1914 | tree default_argument, |
1915 | location_t loc, |
1916 | bool template_parameter_pack_p = false) |
1917 | { |
1918 | cp_parameter_declarator *parameter; |
1919 | |
1920 | parameter = ((cp_parameter_declarator *) |
1921 | alloc_declarator (bytes: sizeof (cp_parameter_declarator))); |
1922 | parameter->next = NULL; |
1923 | if (decl_specifiers) |
1924 | parameter->decl_specifiers = *decl_specifiers; |
1925 | else |
1926 | clear_decl_specs (decl_specs: ¶meter->decl_specifiers); |
1927 | parameter->declarator = declarator; |
1928 | parameter->default_argument = default_argument; |
1929 | parameter->template_parameter_pack_p = template_parameter_pack_p; |
1930 | parameter->loc = loc; |
1931 | |
1932 | return parameter; |
1933 | } |
1934 | |
1935 | /* Returns true iff DECLARATOR is a declaration for a function. */ |
1936 | |
1937 | static bool |
1938 | function_declarator_p (const cp_declarator *declarator) |
1939 | { |
1940 | while (declarator) |
1941 | { |
1942 | if (declarator->kind == cdk_function |
1943 | && declarator->declarator->kind == cdk_id) |
1944 | return true; |
1945 | if (declarator->kind == cdk_id |
1946 | || declarator->kind == cdk_decomp |
1947 | || declarator->kind == cdk_error) |
1948 | return false; |
1949 | declarator = declarator->declarator; |
1950 | } |
1951 | return false; |
1952 | } |
1953 | |
1954 | /* The parser. */ |
1955 | |
1956 | /* Overview |
1957 | -------- |
1958 | |
1959 | A cp_parser parses the token stream as specified by the C++ |
1960 | grammar. Its job is purely parsing, not semantic analysis. For |
1961 | example, the parser breaks the token stream into declarators, |
1962 | expressions, statements, and other similar syntactic constructs. |
1963 | It does not check that the types of the expressions on either side |
1964 | of an assignment-statement are compatible, or that a function is |
1965 | not declared with a parameter of type `void'. |
1966 | |
1967 | The parser invokes routines elsewhere in the compiler to perform |
1968 | semantic analysis and to build up the abstract syntax tree for the |
1969 | code processed. |
1970 | |
1971 | The parser (and the template instantiation code, which is, in a |
1972 | way, a close relative of parsing) are the only parts of the |
1973 | compiler that should be calling push_scope and pop_scope, or |
1974 | related functions. The parser (and template instantiation code) |
1975 | keeps track of what scope is presently active; everything else |
1976 | should simply honor that. (The code that generates static |
1977 | initializers may also need to set the scope, in order to check |
1978 | access control correctly when emitting the initializers.) |
1979 | |
1980 | Methodology |
1981 | ----------- |
1982 | |
1983 | The parser is of the standard recursive-descent variety. Upcoming |
1984 | tokens in the token stream are examined in order to determine which |
1985 | production to use when parsing a non-terminal. Some C++ constructs |
1986 | require arbitrary look ahead to disambiguate. For example, it is |
1987 | impossible, in the general case, to tell whether a statement is an |
1988 | expression or declaration without scanning the entire statement. |
1989 | Therefore, the parser is capable of "parsing tentatively." When the |
1990 | parser is not sure what construct comes next, it enters this mode. |
1991 | Then, while we attempt to parse the construct, the parser queues up |
1992 | error messages, rather than issuing them immediately, and saves the |
1993 | tokens it consumes. If the construct is parsed successfully, the |
1994 | parser "commits", i.e., it issues any queued error messages and |
1995 | the tokens that were being preserved are permanently discarded. |
1996 | If, however, the construct is not parsed successfully, the parser |
1997 | rolls back its state completely so that it can resume parsing using |
1998 | a different alternative. |
1999 | |
2000 | Future Improvements |
2001 | ------------------- |
2002 | |
2003 | The performance of the parser could probably be improved substantially. |
2004 | We could often eliminate the need to parse tentatively by looking ahead |
2005 | a little bit. In some places, this approach might not entirely eliminate |
2006 | the need to parse tentatively, but it might still speed up the average |
2007 | case. */ |
2008 | |
2009 | /* Flags that are passed to some parsing functions. These values can |
2010 | be bitwise-ored together. */ |
2011 | |
2012 | enum |
2013 | { |
2014 | /* No flags. */ |
2015 | CP_PARSER_FLAGS_NONE = 0x0, |
2016 | /* The construct is optional. If it is not present, then no error |
2017 | should be issued. */ |
2018 | CP_PARSER_FLAGS_OPTIONAL = 0x1, |
2019 | /* When parsing a type-specifier, treat user-defined type-names |
2020 | as non-type identifiers. */ |
2021 | CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2, |
2022 | /* When parsing a type-specifier, do not try to parse a class-specifier |
2023 | or enum-specifier. */ |
2024 | CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4, |
2025 | /* When parsing a decl-specifier-seq, only allow type-specifier or |
2026 | constexpr. */ |
2027 | CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8, |
2028 | /* When parsing a decl-specifier-seq, only allow mutable, constexpr or |
2029 | for C++20 consteval or for C++23 static. */ |
2030 | CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10, |
2031 | /* When parsing a decl-specifier-seq, allow missing typename. */ |
2032 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20, |
2033 | /* When parsing of the noexcept-specifier should be delayed. */ |
2034 | CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40, |
2035 | /* When parsing a consteval declarator. */ |
2036 | CP_PARSER_FLAGS_CONSTEVAL = 0x80 |
2037 | }; |
2038 | |
2039 | /* This type is used for parameters and variables which hold |
2040 | combinations of the above flags. */ |
2041 | typedef int cp_parser_flags; |
2042 | |
2043 | /* The different kinds of declarators we want to parse. */ |
2044 | |
2045 | enum cp_parser_declarator_kind |
2046 | { |
2047 | /* We want an abstract declarator. */ |
2048 | CP_PARSER_DECLARATOR_ABSTRACT, |
2049 | /* We want a named declarator. */ |
2050 | CP_PARSER_DECLARATOR_NAMED, |
2051 | /* We don't mind, but the name must be an unqualified-id. */ |
2052 | CP_PARSER_DECLARATOR_EITHER |
2053 | }; |
2054 | |
2055 | /* The precedence values used to parse binary expressions. The minimum value |
2056 | of PREC must be 1, because zero is reserved to quickly discriminate |
2057 | binary operators from other tokens. */ |
2058 | |
2059 | enum cp_parser_prec |
2060 | { |
2061 | PREC_NOT_OPERATOR, |
2062 | PREC_LOGICAL_OR_EXPRESSION, |
2063 | PREC_LOGICAL_AND_EXPRESSION, |
2064 | PREC_INCLUSIVE_OR_EXPRESSION, |
2065 | PREC_EXCLUSIVE_OR_EXPRESSION, |
2066 | PREC_AND_EXPRESSION, |
2067 | PREC_EQUALITY_EXPRESSION, |
2068 | PREC_RELATIONAL_EXPRESSION, |
2069 | PREC_SPACESHIP_EXPRESSION, |
2070 | PREC_SHIFT_EXPRESSION, |
2071 | PREC_ADDITIVE_EXPRESSION, |
2072 | PREC_MULTIPLICATIVE_EXPRESSION, |
2073 | PREC_PM_EXPRESSION, |
2074 | NUM_PREC_VALUES = PREC_PM_EXPRESSION |
2075 | }; |
2076 | |
2077 | /* A mapping from a token type to a corresponding tree node type, with a |
2078 | precedence value. */ |
2079 | |
2080 | struct cp_parser_binary_operations_map_node |
2081 | { |
2082 | /* The token type. */ |
2083 | enum cpp_ttype token_type; |
2084 | /* The corresponding tree code. */ |
2085 | enum tree_code tree_type; |
2086 | /* The precedence of this operator. */ |
2087 | enum cp_parser_prec prec; |
2088 | }; |
2089 | |
2090 | struct cp_parser_expression_stack_entry |
2091 | { |
2092 | /* Left hand side of the binary operation we are currently |
2093 | parsing. */ |
2094 | cp_expr lhs; |
2095 | /* Original tree code for left hand side, if it was a binary |
2096 | expression itself (used for -Wparentheses). */ |
2097 | enum tree_code lhs_type; |
2098 | /* Tree code for the binary operation we are parsing. */ |
2099 | enum tree_code tree_type; |
2100 | /* Precedence of the binary operation we are parsing. */ |
2101 | enum cp_parser_prec prec; |
2102 | /* Location of the binary operation we are parsing. */ |
2103 | location_t loc; |
2104 | /* Flags from the operator token. */ |
2105 | unsigned char flags; |
2106 | }; |
2107 | |
2108 | /* The stack for storing partial expressions. We only need NUM_PREC_VALUES |
2109 | entries because precedence levels on the stack are monotonically |
2110 | increasing. */ |
2111 | typedef struct cp_parser_expression_stack_entry |
2112 | cp_parser_expression_stack[NUM_PREC_VALUES]; |
2113 | |
2114 | /* Used for parsing OMP for loops. |
2115 | |
2116 | Some notes on flags used for context: |
2117 | parser->omp_for_parse_state is non-null anywhere inside the OMP FOR |
2118 | construct, except for the final-loop-body. |
2119 | The want_nested_loop flag is true if inside a {} sequence where |
2120 | a loop-nest (or another {} sequence containing a loop-nest) is expected, |
2121 | but has not yet been seen. It's false when parsing intervening code |
2122 | statements or their substatements that cannot contain a loop-nest. |
2123 | The in_intervening_code flag is true when parsing any intervening code, |
2124 | including substatements, and whether or not want_nested_loop is true. |
2125 | |
2126 | And, about error handling: |
2127 | The saw_intervening_code flag is set if the loop is not perfectly |
2128 | nested, even in the usual case where this is not an error. |
2129 | perfect_nesting_fail is set if an error has been diagnosed because an |
2130 | imperfectly-nested loop was found where a perfectly-nested one is |
2131 | required (we diagnose this only once). |
2132 | fail is set if any kind of structural error in the loop nest |
2133 | has been found and diagnosed. |
2134 | */ |
2135 | struct omp_for_parse_data { |
2136 | enum tree_code code; |
2137 | tree declv, condv, incrv, initv; |
2138 | tree pre_body; |
2139 | tree orig_declv; |
2140 | auto_vec<tree, 4> orig_inits; |
2141 | int count; /* Expected nesting depth. */ |
2142 | int depth; /* Current nesting depth. */ |
2143 | location_t for_loc; |
2144 | releasing_vec init_blockv; |
2145 | releasing_vec body_blockv; |
2146 | releasing_vec init_placeholderv; |
2147 | releasing_vec body_placeholderv; |
2148 | bool ordered : 1; |
2149 | bool inscan : 1; |
2150 | bool want_nested_loop : 1; |
2151 | bool in_intervening_code : 1; |
2152 | bool saw_intervening_code : 1; |
2153 | bool perfect_nesting_fail : 1; |
2154 | bool fail : 1; |
2155 | tree clauses; |
2156 | tree *cclauses; |
2157 | tree ordered_cl; |
2158 | }; |
2159 | |
2160 | /* Prototypes. */ |
2161 | |
2162 | /* Constructors and destructors. */ |
2163 | |
2164 | static cp_parser_context *cp_parser_context_new |
2165 | (cp_parser_context *); |
2166 | |
2167 | /* Class variables. */ |
2168 | |
2169 | static GTY((deletable)) cp_parser_context* cp_parser_context_free_list; |
2170 | |
2171 | /* The operator-precedence table used by cp_parser_binary_expression. |
2172 | Transformed into an associative array (binops_by_token) by |
2173 | cp_parser_new. */ |
2174 | |
2175 | static const cp_parser_binary_operations_map_node binops[] = { |
2176 | { .token_type: CPP_DEREF_STAR, .tree_type: MEMBER_REF, .prec: PREC_PM_EXPRESSION }, |
2177 | { .token_type: CPP_DOT_STAR, .tree_type: DOTSTAR_EXPR, .prec: PREC_PM_EXPRESSION }, |
2178 | |
2179 | { .token_type: CPP_MULT, .tree_type: MULT_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2180 | { .token_type: CPP_DIV, .tree_type: TRUNC_DIV_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2181 | { .token_type: CPP_MOD, .tree_type: TRUNC_MOD_EXPR, .prec: PREC_MULTIPLICATIVE_EXPRESSION }, |
2182 | |
2183 | { .token_type: CPP_PLUS, .tree_type: PLUS_EXPR, .prec: PREC_ADDITIVE_EXPRESSION }, |
2184 | { .token_type: CPP_MINUS, .tree_type: MINUS_EXPR, .prec: PREC_ADDITIVE_EXPRESSION }, |
2185 | |
2186 | { .token_type: CPP_LSHIFT, .tree_type: LSHIFT_EXPR, .prec: PREC_SHIFT_EXPRESSION }, |
2187 | { .token_type: CPP_RSHIFT, .tree_type: RSHIFT_EXPR, .prec: PREC_SHIFT_EXPRESSION }, |
2188 | |
2189 | { .token_type: CPP_SPACESHIP, .tree_type: SPACESHIP_EXPR, .prec: PREC_SPACESHIP_EXPRESSION }, |
2190 | |
2191 | { .token_type: CPP_LESS, .tree_type: LT_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2192 | { .token_type: CPP_GREATER, .tree_type: GT_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2193 | { .token_type: CPP_LESS_EQ, .tree_type: LE_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2194 | { .token_type: CPP_GREATER_EQ, .tree_type: GE_EXPR, .prec: PREC_RELATIONAL_EXPRESSION }, |
2195 | |
2196 | { .token_type: CPP_EQ_EQ, .tree_type: EQ_EXPR, .prec: PREC_EQUALITY_EXPRESSION }, |
2197 | { .token_type: CPP_NOT_EQ, .tree_type: NE_EXPR, .prec: PREC_EQUALITY_EXPRESSION }, |
2198 | |
2199 | { .token_type: CPP_AND, .tree_type: BIT_AND_EXPR, .prec: PREC_AND_EXPRESSION }, |
2200 | |
2201 | { .token_type: CPP_XOR, .tree_type: BIT_XOR_EXPR, .prec: PREC_EXCLUSIVE_OR_EXPRESSION }, |
2202 | |
2203 | { .token_type: CPP_OR, .tree_type: BIT_IOR_EXPR, .prec: PREC_INCLUSIVE_OR_EXPRESSION }, |
2204 | |
2205 | { .token_type: CPP_AND_AND, .tree_type: TRUTH_ANDIF_EXPR, .prec: PREC_LOGICAL_AND_EXPRESSION }, |
2206 | |
2207 | { .token_type: CPP_OR_OR, .tree_type: TRUTH_ORIF_EXPR, .prec: PREC_LOGICAL_OR_EXPRESSION } |
2208 | }; |
2209 | |
2210 | /* The same as binops, but initialized by cp_parser_new so that |
2211 | binops_by_token[N].token_type == N. Used in cp_parser_binary_expression |
2212 | for speed. */ |
2213 | static cp_parser_binary_operations_map_node binops_by_token[N_CP_TTYPES]; |
2214 | |
2215 | /* Constructors and destructors. */ |
2216 | |
2217 | /* Construct a new context. The context below this one on the stack |
2218 | is given by NEXT. */ |
2219 | |
2220 | static cp_parser_context * |
2221 | cp_parser_context_new (cp_parser_context* next) |
2222 | { |
2223 | cp_parser_context *context; |
2224 | |
2225 | /* Allocate the storage. */ |
2226 | if (cp_parser_context_free_list != NULL) |
2227 | { |
2228 | /* Pull the first entry from the free list. */ |
2229 | context = cp_parser_context_free_list; |
2230 | cp_parser_context_free_list = context->next; |
2231 | memset (s: context, c: 0, n: sizeof (*context)); |
2232 | } |
2233 | else |
2234 | context = ggc_cleared_alloc<cp_parser_context> (); |
2235 | |
2236 | /* No errors have occurred yet in this context. */ |
2237 | context->status = CP_PARSER_STATUS_KIND_NO_ERROR; |
2238 | /* If this is not the bottommost context, copy information that we |
2239 | need from the previous context. */ |
2240 | if (next) |
2241 | { |
2242 | /* If, in the NEXT context, we are parsing an `x->' or `x.' |
2243 | expression, then we are parsing one in this context, too. */ |
2244 | context->object_type = next->object_type; |
2245 | /* Thread the stack. */ |
2246 | context->next = next; |
2247 | } |
2248 | |
2249 | return context; |
2250 | } |
2251 | |
2252 | /* Managing the unparsed function queues. */ |
2253 | |
2254 | #define unparsed_funs_with_default_args \ |
2255 | parser->unparsed_queues->last ().funs_with_default_args |
2256 | #define unparsed_funs_with_definitions \ |
2257 | parser->unparsed_queues->last ().funs_with_definitions |
2258 | #define unparsed_nsdmis \ |
2259 | parser->unparsed_queues->last ().nsdmis |
2260 | #define unparsed_noexcepts \ |
2261 | parser->unparsed_queues->last ().noexcepts |
2262 | #define unparsed_contracts \ |
2263 | parser->unparsed_queues->last ().contracts |
2264 | |
2265 | static void |
2266 | push_unparsed_function_queues (cp_parser *parser) |
2267 | { |
2268 | cp_unparsed_functions_entry e |
2269 | = { NULL, .funs_with_definitions: make_tree_vector (), NULL, NULL, NULL }; |
2270 | vec_safe_push (v&: parser->unparsed_queues, obj: e); |
2271 | } |
2272 | |
2273 | static void |
2274 | pop_unparsed_function_queues (cp_parser *parser) |
2275 | { |
2276 | release_tree_vector (unparsed_funs_with_definitions); |
2277 | parser->unparsed_queues->pop (); |
2278 | } |
2279 | |
2280 | /* Prototypes. */ |
2281 | |
2282 | /* Routines to parse various constructs. |
2283 | |
2284 | Those that return `tree' will return the error_mark_node (rather |
2285 | than NULL_TREE) if a parse error occurs, unless otherwise noted. |
2286 | Sometimes, they will return an ordinary node if error-recovery was |
2287 | attempted, even though a parse error occurred. So, to check |
2288 | whether or not a parse error occurred, you should always use |
2289 | cp_parser_error_occurred. If the construct is optional (indicated |
2290 | either by an `_opt' in the name of the function that does the |
2291 | parsing or via a FLAGS parameter), then NULL_TREE is returned if |
2292 | the construct is not present. */ |
2293 | |
2294 | /* Lexical conventions [gram.lex] */ |
2295 | |
2296 | static tree finish_userdef_string_literal |
2297 | (tree); |
2298 | |
2299 | /* Basic concepts [gram.basic] */ |
2300 | |
2301 | static void cp_parser_translation_unit (cp_parser *); |
2302 | |
2303 | /* Expressions [gram.expr] */ |
2304 | |
2305 | static cp_expr cp_parser_primary_expression |
2306 | (cp_parser *, bool, bool, bool, cp_id_kind *); |
2307 | static cp_expr cp_parser_id_expression |
2308 | (cp_parser *, bool, bool, bool *, bool, bool); |
2309 | static cp_expr cp_parser_unqualified_id |
2310 | (cp_parser *, bool, bool, bool, bool); |
2311 | static tree cp_parser_nested_name_specifier_opt |
2312 | (cp_parser *, bool, bool, bool, bool, bool = false); |
2313 | static tree cp_parser_nested_name_specifier |
2314 | (cp_parser *, bool, bool, bool, bool); |
2315 | static tree cp_parser_qualifying_entity |
2316 | (cp_parser *, bool, bool, bool, bool, bool); |
2317 | static cp_expr cp_parser_postfix_expression |
2318 | (cp_parser *, bool, bool, bool, bool, cp_id_kind *); |
2319 | static tree cp_parser_postfix_open_square_expression |
2320 | (cp_parser *, tree, bool, bool); |
2321 | static tree cp_parser_postfix_dot_deref_expression |
2322 | (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t); |
2323 | static vec<tree, va_gc> *cp_parser_parenthesized_expression_list |
2324 | (cp_parser *, int, bool, bool, bool *, location_t * = NULL, |
2325 | bool = false); |
2326 | /* Values for the second parameter of cp_parser_parenthesized_expression_list. */ |
2327 | enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3, |
2328 | uneval_string_attr = 4 }; |
2329 | static void cp_parser_pseudo_destructor_name |
2330 | (cp_parser *, tree, tree *, tree *); |
2331 | static cp_expr cp_parser_unary_expression |
2332 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false); |
2333 | static enum tree_code cp_parser_unary_operator |
2334 | (cp_token *); |
2335 | static tree cp_parser_has_attribute_expression |
2336 | (cp_parser *); |
2337 | static tree cp_parser_new_expression |
2338 | (cp_parser *); |
2339 | static vec<tree, va_gc> *cp_parser_new_placement |
2340 | (cp_parser *); |
2341 | static tree cp_parser_new_type_id |
2342 | (cp_parser *, tree *); |
2343 | static cp_declarator *cp_parser_new_declarator_opt |
2344 | (cp_parser *); |
2345 | static cp_declarator *cp_parser_direct_new_declarator |
2346 | (cp_parser *); |
2347 | static vec<tree, va_gc> *cp_parser_new_initializer |
2348 | (cp_parser *); |
2349 | static tree cp_parser_delete_expression |
2350 | (cp_parser *); |
2351 | static cp_expr cp_parser_cast_expression |
2352 | (cp_parser *, bool, bool, bool, cp_id_kind *); |
2353 | static cp_expr cp_parser_binary_expression |
2354 | (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *); |
2355 | static tree cp_parser_question_colon_clause |
2356 | (cp_parser *, cp_expr); |
2357 | static cp_expr cp_parser_conditional_expression (cp_parser *); |
2358 | static cp_expr cp_parser_assignment_expression |
2359 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false); |
2360 | static enum tree_code cp_parser_assignment_operator_opt |
2361 | (cp_parser *); |
2362 | static cp_expr cp_parser_expression |
2363 | (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false); |
2364 | static cp_expr cp_parser_constant_expression |
2365 | (cp_parser *, int = 0, bool * = NULL, bool = false); |
2366 | static cp_expr cp_parser_builtin_offsetof |
2367 | (cp_parser *); |
2368 | static cp_expr cp_parser_lambda_expression |
2369 | (cp_parser *); |
2370 | static void cp_parser_lambda_introducer |
2371 | (cp_parser *, tree); |
2372 | static bool cp_parser_lambda_declarator_opt |
2373 | (cp_parser *, tree); |
2374 | static void cp_parser_lambda_body |
2375 | (cp_parser *, tree); |
2376 | |
2377 | /* Statements [gram.stmt.stmt] */ |
2378 | |
2379 | static void cp_parser_statement |
2380 | (cp_parser *, tree, bool, bool *, vec<tree> * = NULL, location_t * = NULL); |
2381 | static void cp_parser_label_for_labeled_statement |
2382 | (cp_parser *, tree); |
2383 | static tree cp_parser_expression_statement |
2384 | (cp_parser *, tree); |
2385 | static tree cp_parser_compound_statement |
2386 | (cp_parser *, tree, int, bool); |
2387 | static void cp_parser_statement_seq_opt |
2388 | (cp_parser *, tree); |
2389 | static tree cp_parser_selection_statement |
2390 | (cp_parser *, bool *, vec<tree> *); |
2391 | static tree cp_parser_condition |
2392 | (cp_parser *); |
2393 | static tree cp_parser_iteration_statement |
2394 | (cp_parser *, bool *, bool, unsigned short, bool); |
2395 | static bool cp_parser_init_statement |
2396 | (cp_parser *, tree *decl); |
2397 | static tree cp_parser_for |
2398 | (cp_parser *, bool, unsigned short, bool); |
2399 | static tree cp_parser_c_for |
2400 | (cp_parser *, tree, tree, bool, unsigned short, bool); |
2401 | static tree cp_parser_range_for |
2402 | (cp_parser *, tree, tree, tree, bool, unsigned short, bool, bool); |
2403 | static void do_range_for_auto_deduction |
2404 | (tree, tree, cp_decomp *); |
2405 | static tree cp_parser_perform_range_for_lookup |
2406 | (tree, tree *, tree *); |
2407 | static tree cp_parser_range_for_member_function |
2408 | (tree, tree); |
2409 | static tree cp_parser_jump_statement |
2410 | (cp_parser *); |
2411 | static void cp_parser_declaration_statement |
2412 | (cp_parser *); |
2413 | |
2414 | static tree cp_parser_implicitly_scoped_statement |
2415 | (cp_parser *, bool *, const token_indent_info &, vec<tree> * = NULL); |
2416 | static void cp_parser_already_scoped_statement |
2417 | (cp_parser *, bool *, const token_indent_info &); |
2418 | |
2419 | /* State of module-declaration parsing. */ |
2420 | enum module_parse |
2421 | { |
2422 | MP_NOT_MODULE, /* Not a module. */ |
2423 | |
2424 | _MP_UNUSED, |
2425 | |
2426 | MP_FIRST, /* First declaration of TU. */ |
2427 | MP_GLOBAL, /* Global Module Fragment. */ |
2428 | |
2429 | MP_PURVIEW_IMPORTS, /* Imports of a module. */ |
2430 | MP_PURVIEW, /* Purview of a named module. */ |
2431 | |
2432 | MP_PRIVATE_IMPORTS, /* Imports of a Private Module Fragment. */ |
2433 | MP_PRIVATE, /* Private Module Fragment. */ |
2434 | }; |
2435 | |
2436 | static module_parse cp_parser_module_declaration |
2437 | (cp_parser *parser, module_parse, bool exporting); |
2438 | static void cp_parser_import_declaration |
2439 | (cp_parser *parser, module_parse, bool exporting); |
2440 | |
2441 | /* Declarations [gram.dcl.dcl] */ |
2442 | |
2443 | static void cp_parser_declaration_seq_opt |
2444 | (cp_parser *); |
2445 | static void cp_parser_declaration |
2446 | (cp_parser *, tree); |
2447 | static void cp_parser_toplevel_declaration |
2448 | (cp_parser *); |
2449 | static void cp_parser_block_declaration |
2450 | (cp_parser *, bool); |
2451 | static void cp_parser_simple_declaration |
2452 | (cp_parser *, bool, tree *); |
2453 | static void cp_parser_decl_specifier_seq |
2454 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *); |
2455 | static tree cp_parser_storage_class_specifier_opt |
2456 | (cp_parser *); |
2457 | static tree cp_parser_function_specifier_opt |
2458 | (cp_parser *, cp_decl_specifier_seq *); |
2459 | static tree cp_parser_type_specifier |
2460 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool, |
2461 | int *, bool *); |
2462 | static tree cp_parser_simple_type_specifier |
2463 | (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags); |
2464 | static tree cp_parser_placeholder_type_specifier |
2465 | (cp_parser *, location_t, tree, bool); |
2466 | static tree cp_parser_type_name |
2467 | (cp_parser *, bool); |
2468 | static tree cp_parser_nonclass_name |
2469 | (cp_parser* parser); |
2470 | static tree cp_parser_elaborated_type_specifier |
2471 | (cp_parser *, bool, bool); |
2472 | static tree cp_parser_enum_specifier |
2473 | (cp_parser *); |
2474 | static void cp_parser_enumerator_list |
2475 | (cp_parser *, tree); |
2476 | static void cp_parser_enumerator_definition |
2477 | (cp_parser *, tree); |
2478 | static tree cp_parser_namespace_name |
2479 | (cp_parser *); |
2480 | static void cp_parser_namespace_definition |
2481 | (cp_parser *); |
2482 | static void cp_parser_namespace_body |
2483 | (cp_parser *); |
2484 | static tree cp_parser_qualified_namespace_specifier |
2485 | (cp_parser *); |
2486 | static void cp_parser_namespace_alias_definition |
2487 | (cp_parser *); |
2488 | static bool cp_parser_using_declaration |
2489 | (cp_parser *, bool); |
2490 | static void cp_parser_using_directive |
2491 | (cp_parser *); |
2492 | static void cp_parser_using_enum |
2493 | (cp_parser *); |
2494 | static tree cp_parser_alias_declaration |
2495 | (cp_parser *); |
2496 | static void cp_parser_asm_definition |
2497 | (cp_parser *); |
2498 | static void cp_parser_linkage_specification |
2499 | (cp_parser *, tree); |
2500 | static void cp_parser_static_assert |
2501 | (cp_parser *, bool); |
2502 | static tree cp_parser_decltype |
2503 | (cp_parser *); |
2504 | static tree cp_parser_decomposition_declaration |
2505 | (cp_parser *, cp_decl_specifier_seq *, tree *, location_t *); |
2506 | |
2507 | /* Declarators [gram.dcl.decl] */ |
2508 | |
2509 | static tree cp_parser_init_declarator |
2510 | (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, |
2511 | vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *, |
2512 | location_t *, tree *); |
2513 | static cp_declarator *cp_parser_declarator |
2514 | (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *, |
2515 | bool, bool, bool); |
2516 | static cp_declarator *cp_parser_direct_declarator |
2517 | (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool, |
2518 | bool); |
2519 | static enum tree_code cp_parser_ptr_operator |
2520 | (cp_parser *, tree *, cp_cv_quals *, tree *); |
2521 | static cp_cv_quals cp_parser_cv_qualifier_seq_opt |
2522 | (cp_parser *); |
2523 | static cp_virt_specifiers cp_parser_virt_specifier_seq_opt |
2524 | (cp_parser *); |
2525 | static cp_ref_qualifier cp_parser_ref_qualifier_opt |
2526 | (cp_parser *); |
2527 | static tree cp_parser_tx_qualifier_opt |
2528 | (cp_parser *); |
2529 | static tree cp_parser_late_return_type_opt |
2530 | (cp_parser *, cp_declarator *, tree &); |
2531 | static tree cp_parser_declarator_id |
2532 | (cp_parser *, bool); |
2533 | static tree cp_parser_type_id |
2534 | (cp_parser *, cp_parser_flags = CP_PARSER_FLAGS_NONE, location_t * = NULL); |
2535 | static tree cp_parser_template_type_arg |
2536 | (cp_parser *); |
2537 | static tree cp_parser_trailing_type_id (cp_parser *); |
2538 | static tree cp_parser_type_id_1 |
2539 | (cp_parser *, cp_parser_flags, bool, bool, location_t *); |
2540 | static void cp_parser_type_specifier_seq |
2541 | (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *); |
2542 | static tree cp_parser_parameter_declaration_clause |
2543 | (cp_parser *, cp_parser_flags); |
2544 | static tree cp_parser_parameter_declaration_list |
2545 | (cp_parser *, cp_parser_flags, auto_vec<tree> *); |
2546 | static cp_parameter_declarator *cp_parser_parameter_declaration |
2547 | (cp_parser *, cp_parser_flags, bool, bool *); |
2548 | static tree cp_parser_default_argument |
2549 | (cp_parser *, bool); |
2550 | static void cp_parser_function_body |
2551 | (cp_parser *, bool); |
2552 | static tree cp_parser_initializer |
2553 | (cp_parser *, bool * = nullptr, bool * = nullptr, bool = false); |
2554 | static cp_expr cp_parser_initializer_clause |
2555 | (cp_parser *, bool * = nullptr); |
2556 | static cp_expr cp_parser_braced_list |
2557 | (cp_parser*, bool * = nullptr); |
2558 | static vec<constructor_elt, va_gc> *cp_parser_initializer_list |
2559 | (cp_parser *, bool *, bool *); |
2560 | |
2561 | static void cp_parser_ctor_initializer_opt_and_function_body |
2562 | (cp_parser *, bool); |
2563 | |
2564 | static tree cp_parser_late_parsing_omp_declare_simd |
2565 | (cp_parser *, tree); |
2566 | |
2567 | static tree cp_parser_late_parsing_oacc_routine |
2568 | (cp_parser *, tree); |
2569 | |
2570 | static tree synthesize_implicit_template_parm |
2571 | (cp_parser *, tree); |
2572 | static tree finish_fully_implicit_template |
2573 | (cp_parser *, tree); |
2574 | static void abort_fully_implicit_template |
2575 | (cp_parser *); |
2576 | |
2577 | /* Classes [gram.class] */ |
2578 | |
2579 | static tree cp_parser_class_name |
2580 | (cp_parser *, bool, bool, enum tag_types, bool, bool, bool, bool = false); |
2581 | static tree cp_parser_class_specifier |
2582 | (cp_parser *); |
2583 | static tree cp_parser_class_head |
2584 | (cp_parser *, bool *); |
2585 | static enum tag_types cp_parser_class_key |
2586 | (cp_parser *); |
2587 | static void cp_parser_type_parameter_key |
2588 | (cp_parser* parser); |
2589 | static void cp_parser_member_specification_opt |
2590 | (cp_parser *); |
2591 | static void cp_parser_member_declaration |
2592 | (cp_parser *); |
2593 | static tree cp_parser_pure_specifier |
2594 | (cp_parser *); |
2595 | static tree cp_parser_constant_initializer |
2596 | (cp_parser *); |
2597 | |
2598 | /* Derived classes [gram.class.derived] */ |
2599 | |
2600 | static tree cp_parser_base_clause |
2601 | (cp_parser *); |
2602 | static tree cp_parser_base_specifier |
2603 | (cp_parser *); |
2604 | |
2605 | /* Special member functions [gram.special] */ |
2606 | |
2607 | static tree cp_parser_conversion_function_id |
2608 | (cp_parser *); |
2609 | static tree cp_parser_conversion_type_id |
2610 | (cp_parser *); |
2611 | static cp_declarator *cp_parser_conversion_declarator_opt |
2612 | (cp_parser *); |
2613 | static void cp_parser_ctor_initializer_opt |
2614 | (cp_parser *); |
2615 | static void cp_parser_mem_initializer_list |
2616 | (cp_parser *); |
2617 | static tree cp_parser_mem_initializer |
2618 | (cp_parser *); |
2619 | static tree cp_parser_mem_initializer_id |
2620 | (cp_parser *); |
2621 | |
2622 | /* Overloading [gram.over] */ |
2623 | |
2624 | static cp_expr cp_parser_operator_function_id |
2625 | (cp_parser *); |
2626 | static cp_expr cp_parser_operator |
2627 | (cp_parser *, location_t); |
2628 | |
2629 | /* Templates [gram.temp] */ |
2630 | |
2631 | static void cp_parser_template_declaration |
2632 | (cp_parser *, bool); |
2633 | static tree cp_parser_template_parameter_list |
2634 | (cp_parser *); |
2635 | static tree cp_parser_template_parameter |
2636 | (cp_parser *, bool *, bool *); |
2637 | static tree cp_parser_type_parameter |
2638 | (cp_parser *, bool *); |
2639 | static tree cp_parser_template_id |
2640 | (cp_parser *, bool, bool, enum tag_types, bool); |
2641 | static tree cp_parser_template_id_expr |
2642 | (cp_parser *, bool, bool, bool); |
2643 | static tree cp_parser_template_name |
2644 | (cp_parser *, bool, bool, bool, enum tag_types, bool *); |
2645 | static tree cp_parser_template_argument_list |
2646 | (cp_parser *); |
2647 | static tree cp_parser_template_argument |
2648 | (cp_parser *); |
2649 | static void cp_parser_explicit_instantiation |
2650 | (cp_parser *); |
2651 | static void cp_parser_explicit_specialization |
2652 | (cp_parser *); |
2653 | |
2654 | /* Exception handling [gram.except] */ |
2655 | |
2656 | static tree cp_parser_try_block |
2657 | (cp_parser *); |
2658 | static void cp_parser_function_try_block |
2659 | (cp_parser *); |
2660 | static void cp_parser_handler_seq |
2661 | (cp_parser *); |
2662 | static void cp_parser_handler |
2663 | (cp_parser *); |
2664 | static tree cp_parser_exception_declaration |
2665 | (cp_parser *); |
2666 | static tree cp_parser_throw_expression |
2667 | (cp_parser *); |
2668 | static tree cp_parser_exception_specification_opt |
2669 | (cp_parser *, cp_parser_flags); |
2670 | static tree cp_parser_type_id_list |
2671 | (cp_parser *); |
2672 | static tree cp_parser_noexcept_specification_opt |
2673 | (cp_parser *, cp_parser_flags, bool, bool *, bool); |
2674 | |
2675 | /* GNU Extensions */ |
2676 | |
2677 | static tree cp_parser_asm_specification_opt |
2678 | (cp_parser *); |
2679 | static tree cp_parser_asm_operand_list |
2680 | (cp_parser *); |
2681 | static tree cp_parser_asm_clobber_list |
2682 | (cp_parser *); |
2683 | static tree cp_parser_asm_label_list |
2684 | (cp_parser *); |
2685 | static bool cp_next_tokens_can_be_attribute_p |
2686 | (cp_parser *); |
2687 | static bool cp_next_tokens_can_be_gnu_attribute_p |
2688 | (cp_parser *); |
2689 | static bool cp_next_tokens_can_be_std_attribute_p |
2690 | (cp_parser *); |
2691 | static bool cp_nth_tokens_can_be_std_attribute_p |
2692 | (cp_parser *, size_t); |
2693 | static bool cp_nth_tokens_can_be_gnu_attribute_p |
2694 | (cp_parser *, size_t); |
2695 | static bool cp_nth_tokens_can_be_attribute_p |
2696 | (cp_parser *, size_t); |
2697 | static tree cp_parser_attributes_opt |
2698 | (cp_parser *); |
2699 | static tree cp_parser_gnu_attributes_opt |
2700 | (cp_parser *); |
2701 | static tree cp_parser_gnu_attribute_list |
2702 | (cp_parser *, bool = false); |
2703 | static tree cp_parser_std_attribute |
2704 | (cp_parser *, tree); |
2705 | static tree cp_parser_std_attribute_spec |
2706 | (cp_parser *); |
2707 | static tree cp_parser_std_attribute_spec_seq |
2708 | (cp_parser *); |
2709 | static size_t cp_parser_skip_std_attribute_spec_seq |
2710 | (cp_parser *, size_t); |
2711 | static size_t cp_parser_skip_attributes_opt |
2712 | (cp_parser *, size_t); |
2713 | static bool cp_parser_extension_opt |
2714 | (cp_parser *, int *); |
2715 | static void cp_parser_label_declaration |
2716 | (cp_parser *); |
2717 | |
2718 | /* Concept Extensions */ |
2719 | |
2720 | static tree cp_parser_concept_definition |
2721 | (cp_parser *); |
2722 | static tree cp_parser_constraint_expression |
2723 | (cp_parser *); |
2724 | static tree cp_parser_requires_clause_opt |
2725 | (cp_parser *, bool); |
2726 | static tree cp_parser_requires_expression |
2727 | (cp_parser *); |
2728 | static tree cp_parser_requirement_parameter_list |
2729 | (cp_parser *); |
2730 | static tree cp_parser_requirement_body |
2731 | (cp_parser *); |
2732 | static tree cp_parser_requirement_seq |
2733 | (cp_parser *); |
2734 | static tree cp_parser_requirement |
2735 | (cp_parser *); |
2736 | static tree cp_parser_simple_requirement |
2737 | (cp_parser *); |
2738 | static tree cp_parser_compound_requirement |
2739 | (cp_parser *); |
2740 | static tree cp_parser_type_requirement |
2741 | (cp_parser *); |
2742 | static tree cp_parser_nested_requirement |
2743 | (cp_parser *); |
2744 | |
2745 | /* Transactional Memory Extensions */ |
2746 | |
2747 | static tree cp_parser_transaction |
2748 | (cp_parser *, cp_token *); |
2749 | static tree cp_parser_transaction_expression |
2750 | (cp_parser *, enum rid); |
2751 | static void cp_parser_function_transaction |
2752 | (cp_parser *, enum rid); |
2753 | static tree cp_parser_transaction_cancel |
2754 | (cp_parser *); |
2755 | |
2756 | /* Coroutine extensions. */ |
2757 | |
2758 | static tree cp_parser_yield_expression |
2759 | (cp_parser *); |
2760 | |
2761 | /* Contracts */ |
2762 | |
2763 | static void cp_parser_late_contract_condition |
2764 | (cp_parser *, tree, tree); |
2765 | |
2766 | enum pragma_context { |
2767 | pragma_external, |
2768 | pragma_member, |
2769 | pragma_objc_icode, |
2770 | pragma_stmt, |
2771 | pragma_compound |
2772 | }; |
2773 | static bool cp_parser_pragma |
2774 | (cp_parser *, enum pragma_context, bool *); |
2775 | |
2776 | /* Objective-C++ Productions */ |
2777 | |
2778 | static tree cp_parser_objc_message_receiver |
2779 | (cp_parser *); |
2780 | static tree cp_parser_objc_message_args |
2781 | (cp_parser *); |
2782 | static tree cp_parser_objc_message_expression |
2783 | (cp_parser *); |
2784 | static cp_expr cp_parser_objc_encode_expression |
2785 | (cp_parser *); |
2786 | static tree cp_parser_objc_defs_expression |
2787 | (cp_parser *); |
2788 | static tree cp_parser_objc_protocol_expression |
2789 | (cp_parser *); |
2790 | static tree cp_parser_objc_selector_expression |
2791 | (cp_parser *); |
2792 | static cp_expr cp_parser_objc_expression |
2793 | (cp_parser *); |
2794 | static bool cp_parser_objc_selector_p |
2795 | (enum cpp_ttype); |
2796 | static tree cp_parser_objc_selector |
2797 | (cp_parser *); |
2798 | static tree cp_parser_objc_protocol_refs_opt |
2799 | (cp_parser *); |
2800 | static void cp_parser_objc_declaration |
2801 | (cp_parser *, tree); |
2802 | static tree cp_parser_objc_statement |
2803 | (cp_parser *); |
2804 | static bool cp_parser_objc_valid_prefix_attributes |
2805 | (cp_parser *, tree *); |
2806 | static void cp_parser_objc_at_property_declaration |
2807 | (cp_parser *) ; |
2808 | static void cp_parser_objc_at_synthesize_declaration |
2809 | (cp_parser *) ; |
2810 | static void cp_parser_objc_at_dynamic_declaration |
2811 | (cp_parser *) ; |
2812 | static tree cp_parser_objc_struct_declaration |
2813 | (cp_parser *) ; |
2814 | |
2815 | /* Utility Routines */ |
2816 | |
2817 | static cp_expr cp_parser_lookup_name |
2818 | (cp_parser *, tree, enum tag_types, int, bool, bool, tree *, location_t); |
2819 | static tree cp_parser_lookup_name_simple |
2820 | (cp_parser *, tree, location_t); |
2821 | static tree cp_parser_maybe_treat_template_as_class |
2822 | (tree, bool); |
2823 | static bool cp_parser_check_declarator_template_parameters |
2824 | (cp_parser *, cp_declarator *, location_t); |
2825 | static bool cp_parser_check_template_parameters |
2826 | (cp_parser *, unsigned, bool, location_t, cp_declarator *); |
2827 | static cp_expr cp_parser_simple_cast_expression |
2828 | (cp_parser *); |
2829 | static tree cp_parser_global_scope_opt |
2830 | (cp_parser *, bool); |
2831 | static bool cp_parser_constructor_declarator_p |
2832 | (cp_parser *, cp_parser_flags, bool); |
2833 | static tree cp_parser_function_definition_from_specifiers_and_declarator |
2834 | (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *); |
2835 | static tree cp_parser_function_definition_after_declarator |
2836 | (cp_parser *, bool); |
2837 | static bool cp_parser_template_declaration_after_export |
2838 | (cp_parser *, bool); |
2839 | static void cp_parser_perform_template_parameter_access_checks |
2840 | (vec<deferred_access_check, va_gc> *); |
2841 | static tree cp_parser_single_declaration |
2842 | (cp_parser *, vec<deferred_access_check, va_gc> *, bool, bool, bool *); |
2843 | static cp_expr cp_parser_functional_cast |
2844 | (cp_parser *, tree); |
2845 | static tree cp_parser_save_member_function_body |
2846 | (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree); |
2847 | static tree cp_parser_save_nsdmi |
2848 | (cp_parser *); |
2849 | static tree cp_parser_enclosed_template_argument_list |
2850 | (cp_parser *); |
2851 | static void cp_parser_save_default_args |
2852 | (cp_parser *, tree); |
2853 | static void cp_parser_late_parsing_for_member |
2854 | (cp_parser *, tree); |
2855 | static tree cp_parser_late_parse_one_default_arg |
2856 | (cp_parser *, tree, tree, tree); |
2857 | static void cp_parser_late_parsing_nsdmi |
2858 | (cp_parser *, tree); |
2859 | static void cp_parser_late_parsing_default_args |
2860 | (cp_parser *, tree); |
2861 | static tree cp_parser_sizeof_operand |
2862 | (cp_parser *, enum rid); |
2863 | static cp_expr cp_parser_trait |
2864 | (cp_parser *, enum rid); |
2865 | static bool cp_parser_declares_only_class_p |
2866 | (cp_parser *); |
2867 | static void cp_parser_set_storage_class |
2868 | (cp_parser *, cp_decl_specifier_seq *, enum rid, cp_token *); |
2869 | static void cp_parser_set_decl_spec_type |
2870 | (cp_decl_specifier_seq *, tree, cp_token *, bool); |
2871 | static void set_and_check_decl_spec_loc |
2872 | (cp_decl_specifier_seq *decl_specs, |
2873 | cp_decl_spec ds, cp_token *); |
2874 | static bool cp_parser_friend_p |
2875 | (const cp_decl_specifier_seq *); |
2876 | static void cp_parser_required_error |
2877 | (cp_parser *, required_token, bool, location_t); |
2878 | static cp_token *cp_parser_require |
2879 | (cp_parser *, enum cpp_ttype, required_token, location_t = UNKNOWN_LOCATION); |
2880 | static cp_token *cp_parser_require_keyword |
2881 | (cp_parser *, enum rid, required_token); |
2882 | static bool cp_parser_token_starts_function_definition_p |
2883 | (cp_token *); |
2884 | static bool cp_parser_next_token_starts_class_definition_p |
2885 | (cp_parser *); |
2886 | static bool cp_parser_next_token_ends_template_argument_p |
2887 | (cp_parser *); |
2888 | static bool cp_parser_nth_token_starts_template_argument_list_p |
2889 | (cp_parser *, size_t); |
2890 | static enum tag_types cp_parser_token_is_class_key |
2891 | (cp_token *); |
2892 | static enum tag_types cp_parser_token_is_type_parameter_key |
2893 | (cp_token *); |
2894 | static void cp_parser_maybe_warn_enum_key (cp_parser *, location_t, tree, rid); |
2895 | static void cp_parser_check_class_key |
2896 | (cp_parser *, location_t, enum tag_types, tree type, bool, bool); |
2897 | static void cp_parser_check_access_in_redeclaration |
2898 | (tree type, location_t location); |
2899 | static bool cp_parser_optional_template_keyword |
2900 | (cp_parser *); |
2901 | static void cp_parser_pre_parsed_nested_name_specifier |
2902 | (cp_parser *); |
2903 | static bool cp_parser_cache_group |
2904 | (cp_parser *, enum cpp_ttype, unsigned); |
2905 | static tree cp_parser_cache_defarg |
2906 | (cp_parser *parser, bool nsdmi); |
2907 | static void cp_parser_parse_tentatively |
2908 | (cp_parser *); |
2909 | static void cp_parser_commit_to_tentative_parse |
2910 | (cp_parser *); |
2911 | static void cp_parser_commit_to_topmost_tentative_parse |
2912 | (cp_parser *); |
2913 | static void cp_parser_abort_tentative_parse |
2914 | (cp_parser *); |
2915 | static bool cp_parser_parse_definitely |
2916 | (cp_parser *); |
2917 | static inline bool cp_parser_parsing_tentatively |
2918 | (cp_parser *); |
2919 | static bool cp_parser_uncommitted_to_tentative_parse_p |
2920 | (cp_parser *); |
2921 | static void cp_parser_error |
2922 | (cp_parser *, const char *); |
2923 | static void cp_parser_name_lookup_error |
2924 | (cp_parser *, tree, tree, name_lookup_error, location_t); |
2925 | static bool cp_parser_simulate_error |
2926 | (cp_parser *); |
2927 | static bool cp_parser_check_type_definition |
2928 | (cp_parser *); |
2929 | static void cp_parser_check_for_definition_in_return_type |
2930 | (cp_declarator *, tree, location_t type_location); |
2931 | static void cp_parser_check_for_invalid_template_id |
2932 | (cp_parser *, tree, enum tag_types, location_t location); |
2933 | static bool cp_parser_non_integral_constant_expression |
2934 | (cp_parser *, non_integral_constant); |
2935 | static void cp_parser_diagnose_invalid_type_name |
2936 | (cp_parser *, tree, location_t); |
2937 | static bool cp_parser_parse_and_diagnose_invalid_type_name |
2938 | (cp_parser *); |
2939 | static int cp_parser_skip_to_closing_parenthesis |
2940 | (cp_parser *, bool, bool, bool); |
2941 | static void cp_parser_skip_to_end_of_statement |
2942 | (cp_parser *); |
2943 | static void cp_parser_consume_semicolon_at_end_of_statement |
2944 | (cp_parser *); |
2945 | static void cp_parser_skip_to_end_of_block_or_statement |
2946 | (cp_parser *); |
2947 | static bool cp_parser_skip_to_closing_brace |
2948 | (cp_parser *); |
2949 | static bool cp_parser_skip_entire_template_parameter_list |
2950 | (cp_parser *); |
2951 | static void cp_parser_require_end_of_template_parameter_list |
2952 | (cp_parser *); |
2953 | static bool cp_parser_skip_to_end_of_template_parameter_list |
2954 | (cp_parser *); |
2955 | static void cp_parser_skip_to_pragma_eol |
2956 | (cp_parser*, cp_token *); |
2957 | static bool cp_parser_error_occurred |
2958 | (cp_parser *); |
2959 | static bool cp_parser_allow_gnu_extensions_p |
2960 | (cp_parser *); |
2961 | static bool cp_parser_is_pure_string_literal |
2962 | (cp_token *); |
2963 | static bool cp_parser_is_string_literal |
2964 | (cp_token *); |
2965 | static bool cp_parser_is_keyword |
2966 | (cp_token *, enum rid); |
2967 | static tree cp_parser_make_typename_type |
2968 | (cp_parser *, tree, location_t location); |
2969 | static cp_declarator * cp_parser_make_indirect_declarator |
2970 | (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree); |
2971 | static bool cp_parser_compound_literal_p |
2972 | (cp_parser *); |
2973 | static bool cp_parser_array_designator_p |
2974 | (cp_parser *); |
2975 | static bool cp_parser_init_statement_p |
2976 | (cp_parser *); |
2977 | static bool cp_parser_skip_up_to_closing_square_bracket |
2978 | (cp_parser *); |
2979 | static bool cp_parser_skip_to_closing_square_bracket |
2980 | (cp_parser *); |
2981 | static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t); |
2982 | static tree cp_parser_omp_loop_nest (cp_parser *, bool *); |
2983 | |
2984 | // -------------------------------------------------------------------------- // |
2985 | // Unevaluated Operand Guard |
2986 | // |
2987 | // Implementation of an RAII helper for unevaluated operand parsing. |
2988 | cp_unevaluated::cp_unevaluated () |
2989 | { |
2990 | ++cp_unevaluated_operand; |
2991 | ++c_inhibit_evaluation_warnings; |
2992 | } |
2993 | |
2994 | cp_unevaluated::~cp_unevaluated () |
2995 | { |
2996 | --c_inhibit_evaluation_warnings; |
2997 | --cp_unevaluated_operand; |
2998 | } |
2999 | |
3000 | // -------------------------------------------------------------------------- // |
3001 | // Tentative Parsing |
3002 | |
3003 | /* Returns nonzero if we are parsing tentatively. */ |
3004 | |
3005 | static inline bool |
3006 | cp_parser_parsing_tentatively (cp_parser* parser) |
3007 | { |
3008 | return parser->context->next != NULL; |
3009 | } |
3010 | |
3011 | /* Returns nonzero if TOKEN is a string literal. */ |
3012 | |
3013 | static bool |
3014 | cp_parser_is_pure_string_literal (cp_token* token) |
3015 | { |
3016 | return (token->type == CPP_STRING || |
3017 | token->type == CPP_STRING16 || |
3018 | token->type == CPP_STRING32 || |
3019 | token->type == CPP_WSTRING || |
3020 | token->type == CPP_UTF8STRING); |
3021 | } |
3022 | |
3023 | /* Returns nonzero if TOKEN is a string literal |
3024 | of a user-defined string literal. */ |
3025 | |
3026 | static bool |
3027 | cp_parser_is_string_literal (cp_token* token) |
3028 | { |
3029 | return (cp_parser_is_pure_string_literal (token) || |
3030 | token->type == CPP_STRING_USERDEF || |
3031 | token->type == CPP_STRING16_USERDEF || |
3032 | token->type == CPP_STRING32_USERDEF || |
3033 | token->type == CPP_WSTRING_USERDEF || |
3034 | token->type == CPP_UTF8STRING_USERDEF); |
3035 | } |
3036 | |
3037 | /* Returns nonzero if TOKEN is the indicated KEYWORD. */ |
3038 | |
3039 | static bool |
3040 | cp_parser_is_keyword (cp_token* token, enum rid keyword) |
3041 | { |
3042 | return token->keyword == keyword; |
3043 | } |
3044 | |
3045 | /* Helper function for cp_parser_error. |
3046 | Having peeked a token of kind TOK1_KIND that might signify |
3047 | a conflict marker, peek successor tokens to determine |
3048 | if we actually do have a conflict marker. |
3049 | Specifically, we consider a run of 7 '<', '=' or '>' characters |
3050 | at the start of a line as a conflict marker. |
3051 | These come through the lexer as three pairs and a single, |
3052 | e.g. three CPP_LSHIFT tokens ("<<") and a CPP_LESS token ('<'). |
3053 | If it returns true, *OUT_LOC is written to with the location/range |
3054 | of the marker. */ |
3055 | |
3056 | static bool |
3057 | cp_lexer_peek_conflict_marker (cp_lexer *lexer, enum cpp_ttype tok1_kind, |
3058 | location_t *out_loc) |
3059 | { |
3060 | cp_token *token2 = cp_lexer_peek_nth_token (lexer, n: 2); |
3061 | if (token2->type != tok1_kind) |
3062 | return false; |
3063 | cp_token *token3 = cp_lexer_peek_nth_token (lexer, n: 3); |
3064 | if (token3->type != tok1_kind) |
3065 | return false; |
3066 | cp_token *token4 = cp_lexer_peek_nth_token (lexer, n: 4); |
3067 | if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind)) |
3068 | return false; |
3069 | |
3070 | /* It must be at the start of the line. */ |
3071 | location_t start_loc = cp_lexer_peek_token (lexer)->location; |
3072 | if (LOCATION_COLUMN (start_loc) != 1) |
3073 | return false; |
3074 | |
3075 | /* We have a conflict marker. Construct a location of the form: |
3076 | <<<<<<< |
3077 | ^~~~~~~ |
3078 | with start == caret, finishing at the end of the marker. */ |
3079 | location_t finish_loc = get_finish (loc: token4->location); |
3080 | *out_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
3081 | |
3082 | return true; |
3083 | } |
3084 | |
3085 | /* Get a description of the matching symbol to TOKEN_DESC e.g. "(" for |
3086 | RT_CLOSE_PAREN. */ |
3087 | |
3088 | static const char * |
3089 | get_matching_symbol (required_token token_desc) |
3090 | { |
3091 | switch (token_desc) |
3092 | { |
3093 | default: |
3094 | gcc_unreachable (); |
3095 | return "" ; |
3096 | case RT_CLOSE_BRACE: |
3097 | return "{" ; |
3098 | case RT_CLOSE_PAREN: |
3099 | return "(" ; |
3100 | } |
3101 | } |
3102 | |
3103 | /* Attempt to convert TOKEN_DESC from a required_token to an |
3104 | enum cpp_ttype, returning CPP_EOF if there is no good conversion. */ |
3105 | |
3106 | static enum cpp_ttype |
3107 | get_required_cpp_ttype (required_token token_desc) |
3108 | { |
3109 | switch (token_desc) |
3110 | { |
3111 | case RT_SEMICOLON: |
3112 | return CPP_SEMICOLON; |
3113 | case RT_OPEN_PAREN: |
3114 | return CPP_OPEN_PAREN; |
3115 | case RT_CLOSE_BRACE: |
3116 | return CPP_CLOSE_BRACE; |
3117 | case RT_OPEN_BRACE: |
3118 | return CPP_OPEN_BRACE; |
3119 | case RT_CLOSE_SQUARE: |
3120 | return CPP_CLOSE_SQUARE; |
3121 | case RT_OPEN_SQUARE: |
3122 | return CPP_OPEN_SQUARE; |
3123 | case RT_COMMA: |
3124 | return CPP_COMMA; |
3125 | case RT_COLON: |
3126 | return CPP_COLON; |
3127 | case RT_CLOSE_PAREN: |
3128 | return CPP_CLOSE_PAREN; |
3129 | |
3130 | default: |
3131 | /* Use CPP_EOF as a "no completions possible" code. */ |
3132 | return CPP_EOF; |
3133 | } |
3134 | } |
3135 | |
3136 | |
3137 | /* Subroutine of cp_parser_error and cp_parser_required_error. |
3138 | |
3139 | Issue a diagnostic of the form |
3140 | FILE:LINE: MESSAGE before TOKEN |
3141 | where TOKEN is the next token in the input stream. MESSAGE |
3142 | (specified by the caller) is usually of the form "expected |
3143 | OTHER-TOKEN". |
3144 | |
3145 | This bypasses the check for tentative passing, and potentially |
3146 | adds material needed by cp_parser_required_error. |
3147 | |
3148 | If MISSING_TOKEN_DESC is not RT_NONE, then potentially add fix-it hints |
3149 | suggesting insertion of the missing token. |
3150 | |
3151 | Additionally, if MATCHING_LOCATION is not UNKNOWN_LOCATION, then we |
3152 | have an unmatched symbol at MATCHING_LOCATION; highlight this secondary |
3153 | location. */ |
3154 | |
3155 | static void |
3156 | cp_parser_error_1 (cp_parser* parser, const char* gmsgid, |
3157 | required_token missing_token_desc, |
3158 | location_t matching_location) |
3159 | { |
3160 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
3161 | /* This diagnostic makes more sense if it is tagged to the line |
3162 | of the token we just peeked at. */ |
3163 | cp_lexer_set_source_position_from_token (token); |
3164 | |
3165 | if (token->type == CPP_PRAGMA) |
3166 | { |
3167 | error_at (token->location, |
3168 | "%<#pragma%> is not allowed here" ); |
3169 | cp_parser_skip_to_pragma_eol (parser, token); |
3170 | return; |
3171 | } |
3172 | |
3173 | /* If this is actually a conflict marker, report it as such. */ |
3174 | if (token->type == CPP_LSHIFT |
3175 | || token->type == CPP_RSHIFT |
3176 | || token->type == CPP_EQ_EQ) |
3177 | { |
3178 | location_t loc; |
3179 | if (cp_lexer_peek_conflict_marker (lexer: parser->lexer, tok1_kind: token->type, out_loc: &loc)) |
3180 | { |
3181 | error_at (loc, "version control conflict marker in file" ); |
3182 | expanded_location token_exploc = expand_location (token->location); |
3183 | /* Consume tokens until the end of the source line. */ |
3184 | for (;;) |
3185 | { |
3186 | cp_lexer_consume_token (lexer: parser->lexer); |
3187 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
3188 | if (next->type == CPP_EOF) |
3189 | break; |
3190 | if (next->location == UNKNOWN_LOCATION |
3191 | || loc == UNKNOWN_LOCATION) |
3192 | break; |
3193 | |
3194 | expanded_location next_exploc = expand_location (next->location); |
3195 | if (next_exploc.file != token_exploc.file) |
3196 | break; |
3197 | if (next_exploc.line != token_exploc.line) |
3198 | break; |
3199 | } |
3200 | return; |
3201 | } |
3202 | } |
3203 | |
3204 | auto_diagnostic_group d; |
3205 | gcc_rich_location richloc (input_location); |
3206 | |
3207 | bool added_matching_location = false; |
3208 | |
3209 | if (missing_token_desc != RT_NONE) |
3210 | if (cp_token *prev_token = cp_lexer_safe_previous_token (lexer: parser->lexer)) |
3211 | { |
3212 | /* Potentially supply a fix-it hint, suggesting to add the |
3213 | missing token immediately after the *previous* token. |
3214 | This may move the primary location within richloc. */ |
3215 | enum cpp_ttype ttype = get_required_cpp_ttype (token_desc: missing_token_desc); |
3216 | location_t prev_token_loc = prev_token->location; |
3217 | maybe_suggest_missing_token_insertion (richloc: &richloc, token_type: ttype, |
3218 | prev_token_loc); |
3219 | |
3220 | /* If matching_location != UNKNOWN_LOCATION, highlight it. |
3221 | Attempt to consolidate diagnostics by printing it as a |
3222 | secondary range within the main diagnostic. */ |
3223 | if (matching_location != UNKNOWN_LOCATION) |
3224 | added_matching_location |
3225 | = richloc.add_location_if_nearby (loc: matching_location); |
3226 | } |
3227 | |
3228 | /* If we were parsing a string-literal and there is an unknown name |
3229 | token right after, then check to see if that could also have been |
3230 | a literal string by checking the name against a list of known |
3231 | standard string literal constants defined in header files. If |
3232 | there is one, then add that as an hint to the error message. */ |
3233 | name_hint h; |
3234 | if (token->type == CPP_NAME) |
3235 | if (cp_token *prev_token = cp_lexer_safe_previous_token (lexer: parser->lexer)) |
3236 | if (cp_parser_is_string_literal (token: prev_token)) |
3237 | { |
3238 | tree name = token->u.value; |
3239 | const char *token_name = IDENTIFIER_POINTER (name); |
3240 | const char * |
3241 | = get_cp_stdlib_header_for_string_macro_name (n: token_name); |
3242 | if (header_hint != NULL) |
3243 | h = name_hint (NULL, new suggest_missing_header (token->location, |
3244 | token_name, |
3245 | header_hint)); |
3246 | } |
3247 | |
3248 | /* Actually emit the error. */ |
3249 | c_parse_error (gmsgid, |
3250 | /* Because c_parser_error does not understand |
3251 | CPP_KEYWORD, keywords are treated like |
3252 | identifiers. */ |
3253 | (token->type == CPP_KEYWORD ? CPP_NAME : token->type), |
3254 | token->u.value, token->flags, richloc: &richloc); |
3255 | |
3256 | if (missing_token_desc != RT_NONE) |
3257 | { |
3258 | /* If we weren't able to consolidate matching_location, then |
3259 | print it as a secondary diagnostic. */ |
3260 | if (matching_location != UNKNOWN_LOCATION |
3261 | && !added_matching_location) |
3262 | inform (matching_location, "to match this %qs" , |
3263 | get_matching_symbol (token_desc: missing_token_desc)); |
3264 | } |
3265 | } |
3266 | |
3267 | /* If not parsing tentatively, issue a diagnostic of the form |
3268 | FILE:LINE: MESSAGE before TOKEN |
3269 | where TOKEN is the next token in the input stream. MESSAGE |
3270 | (specified by the caller) is usually of the form "expected |
3271 | OTHER-TOKEN". */ |
3272 | |
3273 | static void |
3274 | cp_parser_error (cp_parser* parser, const char* gmsgid) |
3275 | { |
3276 | if (!cp_parser_simulate_error (parser)) |
3277 | cp_parser_error_1 (parser, gmsgid, missing_token_desc: RT_NONE, UNKNOWN_LOCATION); |
3278 | } |
3279 | |
3280 | /* Issue an error about name-lookup failing. NAME is the |
3281 | IDENTIFIER_NODE DECL is the result of |
3282 | the lookup (as returned from cp_parser_lookup_name). DESIRED is |
3283 | the thing that we hoped to find. */ |
3284 | |
3285 | static void |
3286 | cp_parser_name_lookup_error (cp_parser* parser, |
3287 | tree name, |
3288 | tree decl, |
3289 | name_lookup_error desired, |
3290 | location_t location) |
3291 | { |
3292 | /* If name lookup completely failed, tell the user that NAME was not |
3293 | declared. */ |
3294 | if (decl == error_mark_node) |
3295 | { |
3296 | if (parser->scope && parser->scope != global_namespace) |
3297 | error_at (location, "%<%E::%E%> has not been declared" , |
3298 | parser->scope, name); |
3299 | else if (parser->scope == global_namespace) |
3300 | error_at (location, "%<::%E%> has not been declared" , name); |
3301 | else if (parser->object_scope |
3302 | && !CLASS_TYPE_P (parser->object_scope)) |
3303 | error_at (location, "request for member %qE in non-class type %qT" , |
3304 | name, parser->object_scope); |
3305 | else if (parser->object_scope) |
3306 | error_at (location, "%<%T::%E%> has not been declared" , |
3307 | parser->object_scope, name); |
3308 | else |
3309 | error_at (location, "%qE has not been declared" , name); |
3310 | } |
3311 | else if (parser->scope && parser->scope != global_namespace) |
3312 | { |
3313 | switch (desired) |
3314 | { |
3315 | case NLE_TYPE: |
3316 | error_at (location, "%<%E::%E%> is not a type" , |
3317 | parser->scope, name); |
3318 | break; |
3319 | case NLE_CXX98: |
3320 | error_at (location, "%<%E::%E%> is not a class or namespace" , |
3321 | parser->scope, name); |
3322 | break; |
3323 | case NLE_NOT_CXX98: |
3324 | error_at (location, |
3325 | "%<%E::%E%> is not a class, namespace, or enumeration" , |
3326 | parser->scope, name); |
3327 | break; |
3328 | default: |
3329 | gcc_unreachable (); |
3330 | |
3331 | } |
3332 | } |
3333 | else if (parser->scope == global_namespace) |
3334 | { |
3335 | switch (desired) |
3336 | { |
3337 | case NLE_TYPE: |
3338 | error_at (location, "%<::%E%> is not a type" , name); |
3339 | break; |
3340 | case NLE_CXX98: |
3341 | error_at (location, "%<::%E%> is not a class or namespace" , name); |
3342 | break; |
3343 | case NLE_NOT_CXX98: |
3344 | error_at (location, |
3345 | "%<::%E%> is not a class, namespace, or enumeration" , |
3346 | name); |
3347 | break; |
3348 | default: |
3349 | gcc_unreachable (); |
3350 | } |
3351 | } |
3352 | else |
3353 | { |
3354 | switch (desired) |
3355 | { |
3356 | case NLE_TYPE: |
3357 | error_at (location, "%qE is not a type" , name); |
3358 | break; |
3359 | case NLE_CXX98: |
3360 | error_at (location, "%qE is not a class or namespace" , name); |
3361 | break; |
3362 | case NLE_NOT_CXX98: |
3363 | error_at (location, |
3364 | "%qE is not a class, namespace, or enumeration" , name); |
3365 | break; |
3366 | default: |
3367 | gcc_unreachable (); |
3368 | } |
3369 | } |
3370 | } |
3371 | |
3372 | /* If we are parsing tentatively, remember that an error has occurred |
3373 | during this tentative parse. Returns true if the error was |
3374 | simulated; false if a message should be issued by the caller. */ |
3375 | |
3376 | static bool |
3377 | cp_parser_simulate_error (cp_parser* parser) |
3378 | { |
3379 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3380 | { |
3381 | parser->context->status = CP_PARSER_STATUS_KIND_ERROR; |
3382 | return true; |
3383 | } |
3384 | return false; |
3385 | } |
3386 | |
3387 | /* This function is called when a type is defined. If type |
3388 | definitions are forbidden at this point, an error message is |
3389 | issued. */ |
3390 | |
3391 | static bool |
3392 | cp_parser_check_type_definition (cp_parser* parser) |
3393 | { |
3394 | /* If types are forbidden here, issue a message. */ |
3395 | if (parser->type_definition_forbidden_message) |
3396 | { |
3397 | /* Don't use `%s' to print the string, because quotations (`%<', `%>') |
3398 | or %qs in the message need to be interpreted. */ |
3399 | error (parser->type_definition_forbidden_message, |
3400 | parser->type_definition_forbidden_message_arg); |
3401 | return false; |
3402 | } |
3403 | return true; |
3404 | } |
3405 | |
3406 | /* This function is called when the DECLARATOR is processed. The TYPE |
3407 | was a type defined in the decl-specifiers. If it is invalid to |
3408 | define a type in the decl-specifiers for DECLARATOR, an error is |
3409 | issued. TYPE_LOCATION is the location of TYPE and is used |
3410 | for error reporting. */ |
3411 | |
3412 | static void |
3413 | cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, |
3414 | tree type, location_t type_location) |
3415 | { |
3416 | /* [dcl.fct] forbids type definitions in return types. |
3417 | Unfortunately, it's not easy to know whether or not we are |
3418 | processing a return type until after the fact. */ |
3419 | while (declarator |
3420 | && (declarator->kind == cdk_pointer |
3421 | || declarator->kind == cdk_reference |
3422 | || declarator->kind == cdk_ptrmem)) |
3423 | declarator = declarator->declarator; |
3424 | if (declarator |
3425 | && declarator->kind == cdk_function) |
3426 | { |
3427 | error_at (type_location, |
3428 | "new types may not be defined in a return type" ); |
3429 | inform (type_location, |
3430 | "(perhaps a semicolon is missing after the definition of %qT)" , |
3431 | type); |
3432 | } |
3433 | } |
3434 | |
3435 | /* A type-specifier (TYPE) has been parsed which cannot be followed by |
3436 | "<" in any valid C++ program. If the next token is indeed "<", |
3437 | issue a message warning the user about what appears to be an |
3438 | invalid attempt to form a template-id. LOCATION is the location |
3439 | of the type-specifier (TYPE) */ |
3440 | |
3441 | static void |
3442 | cp_parser_check_for_invalid_template_id (cp_parser* parser, |
3443 | tree type, |
3444 | enum tag_types tag_type, |
3445 | location_t location) |
3446 | { |
3447 | cp_token_position start = 0; |
3448 | |
3449 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3450 | { |
3451 | if (TREE_CODE (type) == TYPE_DECL) |
3452 | type = TREE_TYPE (type); |
3453 | if (TYPE_P (type) && !template_placeholder_p (type)) |
3454 | error_at (location, "%qT is not a template" , type); |
3455 | else if (identifier_p (t: type)) |
3456 | { |
3457 | if (tag_type != none_type) |
3458 | error_at (location, "%qE is not a class template" , type); |
3459 | else |
3460 | error_at (location, "%qE is not a template" , type); |
3461 | } |
3462 | else |
3463 | error_at (location, "invalid template-id" ); |
3464 | /* Remember the location of the invalid "<". */ |
3465 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3466 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: true); |
3467 | /* Consume the "<". */ |
3468 | cp_lexer_consume_token (lexer: parser->lexer); |
3469 | /* Parse the template arguments. */ |
3470 | cp_parser_enclosed_template_argument_list (parser); |
3471 | /* Permanently remove the invalid template arguments so that |
3472 | this error message is not issued again. */ |
3473 | if (start) |
3474 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
3475 | } |
3476 | } |
3477 | |
3478 | /* If parsing an integral constant-expression, issue an error message |
3479 | about the fact that THING appeared and return true. Otherwise, |
3480 | return false. In either case, set |
3481 | PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P. */ |
3482 | |
3483 | static bool |
3484 | cp_parser_non_integral_constant_expression (cp_parser *parser, |
3485 | non_integral_constant thing) |
3486 | { |
3487 | parser->non_integral_constant_expression_p = true; |
3488 | if (parser->integral_constant_expression_p) |
3489 | { |
3490 | if (!parser->allow_non_integral_constant_expression_p) |
3491 | { |
3492 | const char *msg = NULL; |
3493 | switch (thing) |
3494 | { |
3495 | case NIC_FLOAT: |
3496 | pedwarn (input_location, OPT_Wpedantic, |
3497 | "ISO C++ forbids using a floating-point literal " |
3498 | "in a constant-expression" ); |
3499 | return true; |
3500 | case NIC_CAST: |
3501 | error ("a cast to a type other than an integral or " |
3502 | "enumeration type cannot appear in a " |
3503 | "constant-expression" ); |
3504 | return true; |
3505 | case NIC_TYPEID: |
3506 | error ("%<typeid%> operator " |
3507 | "cannot appear in a constant-expression" ); |
3508 | return true; |
3509 | case NIC_NCC: |
3510 | error ("non-constant compound literals " |
3511 | "cannot appear in a constant-expression" ); |
3512 | return true; |
3513 | case NIC_FUNC_CALL: |
3514 | error ("a function call " |
3515 | "cannot appear in a constant-expression" ); |
3516 | return true; |
3517 | case NIC_INC: |
3518 | error ("an increment " |
3519 | "cannot appear in a constant-expression" ); |
3520 | return true; |
3521 | case NIC_DEC: |
3522 | error ("an decrement " |
3523 | "cannot appear in a constant-expression" ); |
3524 | return true; |
3525 | case NIC_ARRAY_REF: |
3526 | error ("an array reference " |
3527 | "cannot appear in a constant-expression" ); |
3528 | return true; |
3529 | case NIC_ADDR_LABEL: |
3530 | error ("the address of a label " |
3531 | "cannot appear in a constant-expression" ); |
3532 | return true; |
3533 | case NIC_OVERLOADED: |
3534 | error ("calls to overloaded operators " |
3535 | "cannot appear in a constant-expression" ); |
3536 | return true; |
3537 | case NIC_ASSIGNMENT: |
3538 | error ("an assignment cannot appear in a constant-expression" ); |
3539 | return true; |
3540 | case NIC_COMMA: |
3541 | error ("a comma operator " |
3542 | "cannot appear in a constant-expression" ); |
3543 | return true; |
3544 | case NIC_CONSTRUCTOR: |
3545 | error ("a call to a constructor " |
3546 | "cannot appear in a constant-expression" ); |
3547 | return true; |
3548 | case NIC_TRANSACTION: |
3549 | error ("a transaction expression " |
3550 | "cannot appear in a constant-expression" ); |
3551 | return true; |
3552 | case NIC_THIS: |
3553 | msg = "this" ; |
3554 | break; |
3555 | case NIC_FUNC_NAME: |
3556 | msg = "__FUNCTION__" ; |
3557 | break; |
3558 | case NIC_PRETTY_FUNC: |
3559 | msg = "__PRETTY_FUNCTION__" ; |
3560 | break; |
3561 | case NIC_C99_FUNC: |
3562 | msg = "__func__" ; |
3563 | break; |
3564 | case NIC_VA_ARG: |
3565 | msg = "va_arg" ; |
3566 | break; |
3567 | case NIC_ARROW: |
3568 | msg = "->" ; |
3569 | break; |
3570 | case NIC_POINT: |
3571 | msg = "." ; |
3572 | break; |
3573 | case NIC_STAR: |
3574 | msg = "*" ; |
3575 | break; |
3576 | case NIC_ADDR: |
3577 | msg = "&" ; |
3578 | break; |
3579 | case NIC_PREINCREMENT: |
3580 | msg = "++" ; |
3581 | break; |
3582 | case NIC_PREDECREMENT: |
3583 | msg = "--" ; |
3584 | break; |
3585 | case NIC_NEW: |
3586 | msg = "new" ; |
3587 | break; |
3588 | case NIC_DEL: |
3589 | msg = "delete" ; |
3590 | break; |
3591 | default: |
3592 | gcc_unreachable (); |
3593 | } |
3594 | if (msg) |
3595 | error ("%qs cannot appear in a constant-expression" , msg); |
3596 | return true; |
3597 | } |
3598 | } |
3599 | return false; |
3600 | } |
3601 | |
3602 | /* Emit a diagnostic for an invalid type name. This function commits |
3603 | to the current active tentative parse, if any. (Otherwise, the |
3604 | problematic construct might be encountered again later, resulting |
3605 | in duplicate error messages.) LOCATION is the location of ID. */ |
3606 | |
3607 | static void |
3608 | cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, |
3609 | location_t location) |
3610 | { |
3611 | tree decl, ambiguous_decls; |
3612 | cp_parser_commit_to_tentative_parse (parser); |
3613 | /* Try to lookup the identifier. */ |
3614 | decl = cp_parser_lookup_name (parser, id, none_type, |
3615 | /*is_template=*/false, |
3616 | /*is_namespace=*/false, |
3617 | /*check_dependency=*/true, |
3618 | &ambiguous_decls, location); |
3619 | if (ambiguous_decls) |
3620 | /* If the lookup was ambiguous, an error will already have |
3621 | been issued. */ |
3622 | return; |
3623 | /* If the lookup found a template-name, it means that the user forgot |
3624 | to specify an argument list. Emit a useful error message. */ |
3625 | if (DECL_TYPE_TEMPLATE_P (decl)) |
3626 | { |
3627 | auto_diagnostic_group d; |
3628 | error_at (location, |
3629 | "invalid use of template-name %qE without an argument list" , |
3630 | decl); |
3631 | if (DECL_CLASS_TEMPLATE_P (decl) && cxx_dialect < cxx17) |
3632 | inform (location, "class template argument deduction is only available " |
3633 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
3634 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3635 | } |
3636 | else if (TREE_CODE (id) == BIT_NOT_EXPR) |
3637 | error_at (location, "invalid use of destructor %qD as a type" , id); |
3638 | else if (TREE_CODE (decl) == TYPE_DECL) |
3639 | /* Something like 'unsigned A a;' */ |
3640 | error_at (location, "invalid combination of multiple type-specifiers" ); |
3641 | else if (!parser->scope) |
3642 | { |
3643 | /* Issue an error message. */ |
3644 | auto_diagnostic_group d; |
3645 | name_hint hint; |
3646 | if (TREE_CODE (id) == IDENTIFIER_NODE) |
3647 | hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location); |
3648 | if (const char *suggestion = hint.suggestion ()) |
3649 | { |
3650 | gcc_rich_location richloc (location); |
3651 | richloc.add_fixit_replace (new_content: suggestion); |
3652 | error_at (&richloc, |
3653 | "%qE does not name a type; did you mean %qs?" , |
3654 | id, suggestion); |
3655 | } |
3656 | else |
3657 | error_at (location, "%qE does not name a type" , id); |
3658 | /* If we're in a template class, it's possible that the user was |
3659 | referring to a type from a base class. For example: |
3660 | |
3661 | template <typename T> struct A { typedef T X; }; |
3662 | template <typename T> struct B : public A<T> { X x; }; |
3663 | |
3664 | The user should have said "typename A<T>::X". */ |
3665 | if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_CONSTEXPR]) |
3666 | inform (location, "C++11 %<constexpr%> only available with " |
3667 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3668 | else if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_NOEXCEPT]) |
3669 | inform (location, "C++11 %<noexcept%> only available with " |
3670 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3671 | else if (TREE_CODE (id) == IDENTIFIER_NODE |
3672 | && (id_equal (id, str: "module" ) || id_equal (id, str: "import" ))) |
3673 | { |
3674 | if (modules_p ()) |
3675 | inform (location, "%qE is not recognized as a module control-line" , |
3676 | id); |
3677 | else if (cxx_dialect < cxx20) |
3678 | inform (location, "C++20 %qE only available with %<-fmodules-ts%>" , |
3679 | id); |
3680 | else |
3681 | inform (location, "C++20 %qE only available with %<-fmodules-ts%>" |
3682 | ", which is not yet enabled with %<-std=c++20%>" , id); |
3683 | } |
3684 | else if (cxx_dialect < cxx11 |
3685 | && TREE_CODE (id) == IDENTIFIER_NODE |
3686 | && id_equal (id, str: "thread_local" )) |
3687 | inform (location, "C++11 %<thread_local%> only available with " |
3688 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
3689 | else if (cxx_dialect < cxx20 && id == ridpointers[(int)RID_CONSTINIT]) |
3690 | inform (location, "C++20 %<constinit%> only available with " |
3691 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
3692 | else if (!flag_concepts && id == ridpointers[(int)RID_CONCEPT]) |
3693 | inform (location, "%<concept%> only available with %<-std=c++20%> or " |
3694 | "%<-fconcepts%>" ); |
3695 | else if (!flag_concepts && id == ridpointers[(int)RID_REQUIRES]) |
3696 | inform (location, "%<requires%> only available with %<-std=c++20%> or " |
3697 | "%<-fconcepts%>" ); |
3698 | else if (processing_template_decl && current_class_type |
3699 | && TYPE_BINFO (current_class_type)) |
3700 | { |
3701 | for (tree b = TREE_CHAIN (TYPE_BINFO (current_class_type)); |
3702 | b; b = TREE_CHAIN (b)) |
3703 | { |
3704 | tree base_type = BINFO_TYPE (b); |
3705 | if (CLASS_TYPE_P (base_type) |
3706 | && dependent_type_p (base_type)) |
3707 | { |
3708 | /* Go from a particular instantiation of the |
3709 | template (which will have an empty TYPE_FIELDs), |
3710 | to the main version. */ |
3711 | base_type = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type); |
3712 | for (tree field = TYPE_FIELDS (base_type); |
3713 | field; field = DECL_CHAIN (field)) |
3714 | if (TREE_CODE (field) == TYPE_DECL |
3715 | && DECL_NAME (field) == id) |
3716 | { |
3717 | inform (location, |
3718 | "(perhaps %<typename %T::%E%> was intended)" , |
3719 | BINFO_TYPE (b), id); |
3720 | goto found; |
3721 | } |
3722 | } |
3723 | } |
3724 | found:; |
3725 | } |
3726 | } |
3727 | /* Here we diagnose qualified-ids where the scope is actually correct, |
3728 | but the identifier does not resolve to a valid type name. */ |
3729 | else if (parser->scope != error_mark_node) |
3730 | { |
3731 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
3732 | { |
3733 | auto_diagnostic_group d; |
3734 | name_hint hint; |
3735 | if (decl == error_mark_node) |
3736 | hint = suggest_alternative_in_explicit_scope (location, id, |
3737 | parser->scope); |
3738 | const char *suggestion = hint.suggestion (); |
3739 | gcc_rich_location richloc (location_of (id)); |
3740 | if (suggestion) |
3741 | richloc.add_fixit_replace (new_content: suggestion); |
3742 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3743 | { |
3744 | if (suggestion) |
3745 | error_at (&richloc, |
3746 | "%qE in namespace %qE does not name a template" |
3747 | " type; did you mean %qs?" , |
3748 | id, parser->scope, suggestion); |
3749 | else |
3750 | error_at (&richloc, |
3751 | "%qE in namespace %qE does not name a template type" , |
3752 | id, parser->scope); |
3753 | } |
3754 | else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) |
3755 | { |
3756 | if (suggestion) |
3757 | error_at (&richloc, |
3758 | "%qE in namespace %qE does not name a template" |
3759 | " type; did you mean %qs?" , |
3760 | TREE_OPERAND (id, 0), parser->scope, suggestion); |
3761 | else |
3762 | error_at (&richloc, |
3763 | "%qE in namespace %qE does not name a template" |
3764 | " type" , |
3765 | TREE_OPERAND (id, 0), parser->scope); |
3766 | } |
3767 | else |
3768 | { |
3769 | if (suggestion) |
3770 | error_at (&richloc, |
3771 | "%qE in namespace %qE does not name a type" |
3772 | "; did you mean %qs?" , |
3773 | id, parser->scope, suggestion); |
3774 | else |
3775 | error_at (&richloc, |
3776 | "%qE in namespace %qE does not name a type" , |
3777 | id, parser->scope); |
3778 | } |
3779 | if (DECL_P (decl)) |
3780 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3781 | } |
3782 | else if (CLASS_TYPE_P (parser->scope) |
3783 | && constructor_name_p (id, parser->scope)) |
3784 | { |
3785 | /* A<T>::A<T>() */ |
3786 | auto_diagnostic_group d; |
3787 | error_at (location, "%<%T::%E%> names the constructor, not" |
3788 | " the type" , parser->scope, id); |
3789 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3790 | error_at (location, "and %qT has no template constructors" , |
3791 | parser->scope); |
3792 | } |
3793 | else if (TYPE_P (parser->scope) |
3794 | && dependent_scope_p (parser->scope)) |
3795 | { |
3796 | gcc_rich_location richloc (location); |
3797 | richloc.add_fixit_insert_before (new_content: "typename " ); |
3798 | if (TREE_CODE (parser->scope) == TYPENAME_TYPE) |
3799 | error_at (&richloc, |
3800 | "need %<typename%> before %<%T::%D::%E%> because " |
3801 | "%<%T::%D%> is a dependent scope" , |
3802 | TYPE_CONTEXT (parser->scope), |
3803 | TYPENAME_TYPE_FULLNAME (parser->scope), |
3804 | id, |
3805 | TYPE_CONTEXT (parser->scope), |
3806 | TYPENAME_TYPE_FULLNAME (parser->scope)); |
3807 | else |
3808 | error_at (&richloc, "need %<typename%> before %<%T::%E%> because " |
3809 | "%qT is a dependent scope" , |
3810 | parser->scope, id, parser->scope); |
3811 | } |
3812 | else if (TYPE_P (parser->scope)) |
3813 | { |
3814 | auto_diagnostic_group d; |
3815 | if (!COMPLETE_TYPE_P (parser->scope)) |
3816 | cxx_incomplete_type_error (location_of (id), NULL_TREE, |
3817 | parser->scope); |
3818 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
3819 | error_at (location_of (id), |
3820 | "%qE in %q#T does not name a template type" , |
3821 | id, parser->scope); |
3822 | else if (TREE_CODE (id) == TEMPLATE_ID_EXPR) |
3823 | error_at (location_of (id), |
3824 | "%qE in %q#T does not name a template type" , |
3825 | TREE_OPERAND (id, 0), parser->scope); |
3826 | else |
3827 | error_at (location_of (id), |
3828 | "%qE in %q#T does not name a type" , |
3829 | id, parser->scope); |
3830 | if (DECL_P (decl)) |
3831 | inform (DECL_SOURCE_LOCATION (decl), "%qD declared here" , decl); |
3832 | } |
3833 | else |
3834 | gcc_unreachable (); |
3835 | } |
3836 | } |
3837 | |
3838 | /* Check for a common situation where a type-name should be present, |
3839 | but is not, and issue a sensible error message. Returns true if an |
3840 | invalid type-name was detected. |
3841 | |
3842 | The situation handled by this function are variable declarations of the |
3843 | form `ID a', where `ID' is an id-expression and `a' is a plain identifier. |
3844 | Usually, `ID' should name a type, but if we got here it means that it |
3845 | does not. We try to emit the best possible error message depending on |
3846 | how exactly the id-expression looks like. */ |
3847 | |
3848 | static bool |
3849 | cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) |
3850 | { |
3851 | tree id; |
3852 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
3853 | |
3854 | /* Avoid duplicate error about ambiguous lookup. */ |
3855 | if (token->type == CPP_NESTED_NAME_SPECIFIER) |
3856 | { |
3857 | cp_token *next = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
3858 | if (next->type == CPP_NAME && next->error_reported) |
3859 | goto out; |
3860 | } |
3861 | |
3862 | cp_parser_parse_tentatively (parser); |
3863 | id = cp_parser_id_expression (parser, |
3864 | /*template_keyword_p=*/false, |
3865 | /*check_dependency_p=*/true, |
3866 | /*template_p=*/NULL, |
3867 | /*declarator_p=*/true, |
3868 | /*optional_p=*/false); |
3869 | /* If the next token is a (, this is a function with no explicit return |
3870 | type, i.e. constructor, destructor or conversion op. */ |
3871 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
3872 | || TREE_CODE (id) == TYPE_DECL) |
3873 | { |
3874 | cp_parser_abort_tentative_parse (parser); |
3875 | return false; |
3876 | } |
3877 | if (!cp_parser_parse_definitely (parser)) |
3878 | return false; |
3879 | |
3880 | /* Emit a diagnostic for the invalid type. */ |
3881 | cp_parser_diagnose_invalid_type_name (parser, id, location: token->location); |
3882 | out: |
3883 | /* If we aren't in the middle of a declarator (i.e. in a |
3884 | parameter-declaration-clause), skip to the end of the declaration; |
3885 | there's no point in trying to process it. */ |
3886 | if (!parser->in_declarator_p) |
3887 | cp_parser_skip_to_end_of_block_or_statement (parser); |
3888 | return true; |
3889 | } |
3890 | |
3891 | /* Consume tokens up to, and including, the next non-nested closing `)'. |
3892 | Returns 1 iff we found a closing `)'. RECOVERING is true, if we |
3893 | are doing error recovery. Returns -1 if OR_TTYPE is not CPP_EOF and we |
3894 | found an unnested token of that type. */ |
3895 | |
3896 | static int |
3897 | cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser, |
3898 | bool recovering, |
3899 | cpp_ttype or_ttype, |
3900 | bool consume_paren) |
3901 | { |
3902 | unsigned paren_depth = 0; |
3903 | unsigned brace_depth = 0; |
3904 | unsigned square_depth = 0; |
3905 | unsigned condop_depth = 0; |
3906 | |
3907 | if (recovering && or_ttype == CPP_EOF |
3908 | && cp_parser_uncommitted_to_tentative_parse_p (parser)) |
3909 | return 0; |
3910 | |
3911 | while (true) |
3912 | { |
3913 | cp_token * token = cp_lexer_peek_token (lexer: parser->lexer); |
3914 | |
3915 | /* Have we found what we're looking for before the closing paren? */ |
3916 | if (token->type == or_ttype && or_ttype != CPP_EOF |
3917 | && !brace_depth && !paren_depth && !square_depth && !condop_depth) |
3918 | return -1; |
3919 | |
3920 | switch (token->type) |
3921 | { |
3922 | case CPP_PRAGMA_EOL: |
3923 | if (!parser->lexer->in_pragma) |
3924 | break; |
3925 | /* FALLTHRU */ |
3926 | case CPP_EOF: |
3927 | /* If we've run out of tokens, then there is no closing `)'. */ |
3928 | return 0; |
3929 | |
3930 | /* This is good for lambda expression capture-lists. */ |
3931 | case CPP_OPEN_SQUARE: |
3932 | ++square_depth; |
3933 | break; |
3934 | case CPP_CLOSE_SQUARE: |
3935 | if (!square_depth--) |
3936 | return 0; |
3937 | break; |
3938 | |
3939 | case CPP_SEMICOLON: |
3940 | /* This matches the processing in skip_to_end_of_statement. */ |
3941 | if (!brace_depth) |
3942 | return 0; |
3943 | break; |
3944 | |
3945 | case CPP_OPEN_BRACE: |
3946 | ++brace_depth; |
3947 | break; |
3948 | case CPP_CLOSE_BRACE: |
3949 | if (!brace_depth--) |
3950 | return 0; |
3951 | break; |
3952 | |
3953 | case CPP_OPEN_PAREN: |
3954 | if (!brace_depth) |
3955 | ++paren_depth; |
3956 | break; |
3957 | |
3958 | case CPP_CLOSE_PAREN: |
3959 | if (!brace_depth && !paren_depth--) |
3960 | { |
3961 | if (consume_paren) |
3962 | cp_lexer_consume_token (lexer: parser->lexer); |
3963 | return 1; |
3964 | } |
3965 | break; |
3966 | |
3967 | case CPP_QUERY: |
3968 | if (!brace_depth && !paren_depth && !square_depth) |
3969 | ++condop_depth; |
3970 | break; |
3971 | |
3972 | case CPP_COLON: |
3973 | if (!brace_depth && !paren_depth && !square_depth && condop_depth > 0) |
3974 | condop_depth--; |
3975 | break; |
3976 | |
3977 | case CPP_KEYWORD: |
3978 | if (!cp_token_is_module_directive (token)) |
3979 | break; |
3980 | /* FALLTHROUGH */ |
3981 | |
3982 | case CPP_PRAGMA: |
3983 | /* We fell into a pragma. Skip it, and continue. */ |
3984 | cp_parser_skip_to_pragma_eol (parser, recovering ? token : nullptr); |
3985 | continue; |
3986 | |
3987 | default: |
3988 | break; |
3989 | } |
3990 | |
3991 | /* Consume the token. */ |
3992 | cp_lexer_consume_token (lexer: parser->lexer); |
3993 | } |
3994 | } |
3995 | |
3996 | /* Consume tokens up to, and including, the next non-nested closing `)'. |
3997 | Returns 1 iff we found a closing `)'. RECOVERING is true, if we |
3998 | are doing error recovery. Returns -1 if OR_COMMA is true and we |
3999 | found an unnested token of that type. */ |
4000 | |
4001 | static int |
4002 | cp_parser_skip_to_closing_parenthesis (cp_parser *parser, |
4003 | bool recovering, |
4004 | bool or_comma, |
4005 | bool consume_paren) |
4006 | { |
4007 | cpp_ttype ttype = or_comma ? CPP_COMMA : CPP_EOF; |
4008 | return cp_parser_skip_to_closing_parenthesis_1 (parser, recovering, |
4009 | or_ttype: ttype, consume_paren); |
4010 | } |
4011 | |
4012 | /* Consume tokens until we reach the end of the current statement. |
4013 | Normally, that will be just before consuming a `;'. However, if a |
4014 | non-nested `}' comes first, then we stop before consuming that. */ |
4015 | |
4016 | static void |
4017 | cp_parser_skip_to_end_of_statement (cp_parser* parser) |
4018 | { |
4019 | unsigned nesting_depth = 0; |
4020 | |
4021 | /* Unwind generic function template scope if necessary. */ |
4022 | if (parser->fully_implicit_function_template_p) |
4023 | abort_fully_implicit_template (parser); |
4024 | |
4025 | while (true) |
4026 | { |
4027 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4028 | |
4029 | switch (token->type) |
4030 | { |
4031 | case CPP_PRAGMA_EOL: |
4032 | if (!parser->lexer->in_pragma) |
4033 | break; |
4034 | /* FALLTHRU */ |
4035 | case CPP_EOF: |
4036 | /* If we've run out of tokens, stop. */ |
4037 | return; |
4038 | |
4039 | case CPP_SEMICOLON: |
4040 | /* If the next token is a `;', we have reached the end of the |
4041 | statement. */ |
4042 | if (!nesting_depth) |
4043 | return; |
4044 | break; |
4045 | |
4046 | case CPP_CLOSE_BRACE: |
4047 | /* If this is a non-nested '}', stop before consuming it. |
4048 | That way, when confronted with something like: |
4049 | |
4050 | { 3 + } |
4051 | |
4052 | we stop before consuming the closing '}', even though we |
4053 | have not yet reached a `;'. */ |
4054 | if (nesting_depth == 0) |
4055 | return; |
4056 | |
4057 | /* If it is the closing '}' for a block that we have |
4058 | scanned, stop -- but only after consuming the token. |
4059 | That way given: |
4060 | |
4061 | void f g () { ... } |
4062 | typedef int I; |
4063 | |
4064 | we will stop after the body of the erroneously declared |
4065 | function, but before consuming the following `typedef' |
4066 | declaration. */ |
4067 | if (--nesting_depth == 0) |
4068 | { |
4069 | cp_lexer_consume_token (lexer: parser->lexer); |
4070 | return; |
4071 | } |
4072 | break; |
4073 | |
4074 | case CPP_OPEN_BRACE: |
4075 | ++nesting_depth; |
4076 | break; |
4077 | |
4078 | case CPP_KEYWORD: |
4079 | if (!cp_token_is_module_directive (token)) |
4080 | break; |
4081 | /* FALLTHROUGH */ |
4082 | |
4083 | case CPP_PRAGMA: |
4084 | /* We fell into a pragma. Skip it, and continue or return. */ |
4085 | cp_parser_skip_to_pragma_eol (parser, token); |
4086 | if (!nesting_depth) |
4087 | return; |
4088 | continue; |
4089 | |
4090 | default: |
4091 | break; |
4092 | } |
4093 | |
4094 | /* Consume the token. */ |
4095 | cp_lexer_consume_token (lexer: parser->lexer); |
4096 | } |
4097 | } |
4098 | |
4099 | /* This function is called at the end of a statement or declaration. |
4100 | If the next token is a semicolon, it is consumed; otherwise, error |
4101 | recovery is attempted. */ |
4102 | |
4103 | static void |
4104 | cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser) |
4105 | { |
4106 | /* Look for the trailing `;'. */ |
4107 | if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
4108 | { |
4109 | /* If there is additional (erroneous) input, skip to the end of |
4110 | the statement. */ |
4111 | cp_parser_skip_to_end_of_statement (parser); |
4112 | /* If the next token is now a `;', consume it. */ |
4113 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
4114 | cp_lexer_consume_token (lexer: parser->lexer); |
4115 | } |
4116 | } |
4117 | |
4118 | /* Skip tokens until we have consumed an entire block, or until we |
4119 | have consumed a non-nested `;'. */ |
4120 | |
4121 | static void |
4122 | cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) |
4123 | { |
4124 | int nesting_depth = 0; |
4125 | |
4126 | /* Unwind generic function template scope if necessary. */ |
4127 | if (parser->fully_implicit_function_template_p) |
4128 | abort_fully_implicit_template (parser); |
4129 | |
4130 | while (nesting_depth >= 0) |
4131 | { |
4132 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4133 | |
4134 | switch (token->type) |
4135 | { |
4136 | case CPP_PRAGMA_EOL: |
4137 | if (!parser->lexer->in_pragma) |
4138 | break; |
4139 | /* FALLTHRU */ |
4140 | case CPP_EOF: |
4141 | /* If we've run out of tokens, stop. */ |
4142 | return; |
4143 | |
4144 | case CPP_SEMICOLON: |
4145 | /* Stop if this is an unnested ';'. */ |
4146 | if (!nesting_depth) |
4147 | nesting_depth = -1; |
4148 | break; |
4149 | |
4150 | case CPP_CLOSE_BRACE: |
4151 | /* Stop if this is an unnested '}', or closes the outermost |
4152 | nesting level. */ |
4153 | nesting_depth--; |
4154 | if (nesting_depth < 0) |
4155 | return; |
4156 | if (!nesting_depth) |
4157 | nesting_depth = -1; |
4158 | break; |
4159 | |
4160 | case CPP_OPEN_BRACE: |
4161 | /* Nest. */ |
4162 | nesting_depth++; |
4163 | break; |
4164 | |
4165 | case CPP_KEYWORD: |
4166 | if (!cp_token_is_module_directive (token)) |
4167 | break; |
4168 | /* FALLTHROUGH */ |
4169 | |
4170 | case CPP_PRAGMA: |
4171 | /* Skip it, and continue or return. */ |
4172 | cp_parser_skip_to_pragma_eol (parser, token); |
4173 | if (!nesting_depth) |
4174 | return; |
4175 | continue; |
4176 | |
4177 | default: |
4178 | break; |
4179 | } |
4180 | |
4181 | /* Consume the token. */ |
4182 | cp_lexer_consume_token (lexer: parser->lexer); |
4183 | } |
4184 | } |
4185 | |
4186 | /* Skip tokens until a non-nested closing curly brace is the next |
4187 | token, or there are no more tokens. Return true in the first case, |
4188 | false otherwise. */ |
4189 | |
4190 | static bool |
4191 | cp_parser_skip_to_closing_brace (cp_parser *parser) |
4192 | { |
4193 | unsigned nesting_depth = 0; |
4194 | |
4195 | while (true) |
4196 | { |
4197 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
4198 | |
4199 | switch (token->type) |
4200 | { |
4201 | case CPP_PRAGMA_EOL: |
4202 | if (!parser->lexer->in_pragma) |
4203 | break; |
4204 | /* FALLTHRU */ |
4205 | case CPP_EOF: |
4206 | /* If we've run out of tokens, stop. */ |
4207 | return false; |
4208 | |
4209 | case CPP_CLOSE_BRACE: |
4210 | /* If the next token is a non-nested `}', then we have reached |
4211 | the end of the current block. */ |
4212 | if (nesting_depth-- == 0) |
4213 | return true; |
4214 | break; |
4215 | |
4216 | case CPP_OPEN_BRACE: |
4217 | /* If it the next token is a `{', then we are entering a new |
4218 | block. Consume the entire block. */ |
4219 | ++nesting_depth; |
4220 | break; |
4221 | |
4222 | default: |
4223 | break; |
4224 | } |
4225 | |
4226 | /* Consume the token. */ |
4227 | cp_lexer_consume_token (lexer: parser->lexer); |
4228 | } |
4229 | } |
4230 | |
4231 | /* Consume tokens until we reach the end of the pragma. The PRAGMA_TOK |
4232 | parameter is the PRAGMA token, allowing us to purge the entire pragma |
4233 | sequence. PRAGMA_TOK can be NULL, if we're speculatively scanning |
4234 | forwards (not error recovery). */ |
4235 | |
4236 | static void |
4237 | cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) |
4238 | { |
4239 | cp_token *token; |
4240 | |
4241 | do |
4242 | { |
4243 | /* The preprocessor makes sure that a PRAGMA_EOL token appears |
4244 | before an EOF token, even when the EOF is on the pragma line. |
4245 | We should never get here without being inside a deferred |
4246 | pragma. */ |
4247 | gcc_checking_assert (cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)); |
4248 | token = cp_lexer_consume_token (lexer: parser->lexer); |
4249 | } |
4250 | while (token->type != CPP_PRAGMA_EOL); |
4251 | |
4252 | if (pragma_tok) |
4253 | { |
4254 | parser->lexer->in_pragma = false; |
4255 | if (parser->lexer->in_omp_attribute_pragma |
4256 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
4257 | { |
4258 | parser->lexer = parser->lexer->next; |
4259 | /* Put the current source position back where it was before this |
4260 | lexer was pushed. */ |
4261 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4262 | } |
4263 | } |
4264 | } |
4265 | |
4266 | /* Require pragma end of line, resyncing with it as necessary. The |
4267 | arguments are as for cp_parser_skip_to_pragma_eol. */ |
4268 | |
4269 | static void |
4270 | cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) |
4271 | { |
4272 | parser->lexer->in_pragma = false; |
4273 | if (!cp_parser_require (parser, CPP_PRAGMA_EOL, RT_PRAGMA_EOL)) |
4274 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
4275 | else if (parser->lexer->in_omp_attribute_pragma |
4276 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
4277 | { |
4278 | parser->lexer = parser->lexer->next; |
4279 | /* Put the current source position back where it was before this |
4280 | lexer was pushed. */ |
4281 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4282 | } |
4283 | } |
4284 | |
4285 | /* This is a simple wrapper around make_typename_type. When the id is |
4286 | an unresolved identifier node, we can provide a superior diagnostic |
4287 | using cp_parser_diagnose_invalid_type_name. */ |
4288 | |
4289 | static tree |
4290 | cp_parser_make_typename_type (cp_parser *parser, tree id, |
4291 | location_t id_location) |
4292 | { |
4293 | tree result; |
4294 | if (identifier_p (t: id)) |
4295 | { |
4296 | result = make_typename_type (parser->scope, id, typename_type, |
4297 | /*complain=*/tf_none); |
4298 | if (result == error_mark_node) |
4299 | cp_parser_diagnose_invalid_type_name (parser, id, location: id_location); |
4300 | return result; |
4301 | } |
4302 | return make_typename_type (parser->scope, id, typename_type, tf_error); |
4303 | } |
4304 | |
4305 | /* This is a wrapper around the |
4306 | make_{pointer,ptrmem,reference}_declarator functions that decides |
4307 | which one to call based on the CODE and CLASS_TYPE arguments. The |
4308 | CODE argument should be one of the values returned by |
4309 | cp_parser_ptr_operator. ATTRIBUTES represent the attributes that |
4310 | appertain to the pointer or reference. */ |
4311 | |
4312 | static cp_declarator * |
4313 | cp_parser_make_indirect_declarator (enum tree_code code, tree class_type, |
4314 | cp_cv_quals cv_qualifiers, |
4315 | cp_declarator *target, |
4316 | tree attributes) |
4317 | { |
4318 | if (code == ERROR_MARK || target == cp_error_declarator) |
4319 | return cp_error_declarator; |
4320 | |
4321 | if (code == INDIRECT_REF) |
4322 | if (class_type == NULL_TREE) |
4323 | return make_pointer_declarator (cv_qualifiers, target, attributes); |
4324 | else |
4325 | return make_ptrmem_declarator (cv_qualifiers, class_type, |
4326 | pointee: target, attributes); |
4327 | else if (code == ADDR_EXPR && class_type == NULL_TREE) |
4328 | return make_reference_declarator (cv_qualifiers, target, |
4329 | rvalue_ref: false, attributes); |
4330 | else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE) |
4331 | return make_reference_declarator (cv_qualifiers, target, |
4332 | rvalue_ref: true, attributes); |
4333 | gcc_unreachable (); |
4334 | } |
4335 | |
4336 | /* Create a new C++ parser. */ |
4337 | |
4338 | static cp_parser * |
4339 | cp_parser_new (cp_lexer *lexer) |
4340 | { |
4341 | /* Initialize the binops_by_token so that we can get the tree |
4342 | directly from the token. */ |
4343 | for (unsigned i = 0; i < ARRAY_SIZE (binops); i++) |
4344 | binops_by_token[binops[i].token_type] = binops[i]; |
4345 | |
4346 | cp_parser *parser = ggc_cleared_alloc<cp_parser> (); |
4347 | parser->lexer = lexer; |
4348 | parser->context = cp_parser_context_new (NULL); |
4349 | |
4350 | /* For now, we always accept GNU extensions. */ |
4351 | parser->allow_gnu_extensions_p = 1; |
4352 | |
4353 | /* The `>' token is a greater-than operator, not the end of a |
4354 | template-id. */ |
4355 | parser->greater_than_is_operator_p = true; |
4356 | |
4357 | parser->default_arg_ok_p = true; |
4358 | |
4359 | /* We are not parsing a constant-expression. */ |
4360 | parser->integral_constant_expression_p = false; |
4361 | parser->allow_non_integral_constant_expression_p = false; |
4362 | parser->non_integral_constant_expression_p = false; |
4363 | |
4364 | /* Local variable names are not forbidden. */ |
4365 | parser->local_variables_forbidden_p = 0; |
4366 | |
4367 | /* We are not processing an `extern "C"' declaration. */ |
4368 | parser->in_unbraced_linkage_specification_p = false; |
4369 | |
4370 | /* We are not processing a declarator. */ |
4371 | parser->in_declarator_p = false; |
4372 | |
4373 | /* We are not processing a template-argument-list. */ |
4374 | parser->in_template_argument_list_p = false; |
4375 | |
4376 | /* We are not in an iteration statement. */ |
4377 | parser->in_statement = 0; |
4378 | |
4379 | /* We are not in a switch statement. */ |
4380 | parser->in_switch_statement_p = false; |
4381 | |
4382 | /* We are not parsing a type-id inside an expression. */ |
4383 | parser->in_type_id_in_expr_p = false; |
4384 | |
4385 | /* String literals should be translated to the execution character set. */ |
4386 | parser->translate_strings_p = true; |
4387 | |
4388 | /* We are not parsing a function body. */ |
4389 | parser->in_function_body = false; |
4390 | |
4391 | /* We can correct until told otherwise. */ |
4392 | parser->colon_corrects_to_scope_p = true; |
4393 | |
4394 | /* The unparsed function queue is empty. */ |
4395 | push_unparsed_function_queues (parser); |
4396 | |
4397 | /* There are no classes being defined. */ |
4398 | parser->num_classes_being_defined = 0; |
4399 | |
4400 | /* No template parameters apply. */ |
4401 | parser->num_template_parameter_lists = 0; |
4402 | |
4403 | /* Special parsing data structures. */ |
4404 | parser->omp_declare_simd = NULL; |
4405 | parser->oacc_routine = NULL; |
4406 | |
4407 | /* Not declaring an implicit function template. */ |
4408 | parser->auto_is_implicit_function_template_parm_p = false; |
4409 | parser->fully_implicit_function_template_p = false; |
4410 | parser->implicit_template_parms = 0; |
4411 | parser->implicit_template_scope = 0; |
4412 | |
4413 | /* Allow constrained-type-specifiers. */ |
4414 | parser->prevent_constrained_type_specifiers = 0; |
4415 | |
4416 | /* We haven't yet seen an 'extern "C"'. */ |
4417 | parser->innermost_linkage_specification_location = UNKNOWN_LOCATION; |
4418 | |
4419 | return parser; |
4420 | } |
4421 | |
4422 | /* Create a cp_lexer structure which will emit the tokens in CACHE |
4423 | and push it onto the parser's lexer stack. This is used for delayed |
4424 | parsing of in-class method bodies and default arguments, and should |
4425 | not be confused with tentative parsing. */ |
4426 | static void |
4427 | cp_parser_push_lexer_for_tokens (cp_parser *parser, cp_token_cache *cache) |
4428 | { |
4429 | cp_lexer *lexer = cp_lexer_new_from_tokens (cache); |
4430 | lexer->next = parser->lexer; |
4431 | parser->lexer = lexer; |
4432 | |
4433 | /* Move the current source position to that of the first token in the |
4434 | new lexer. */ |
4435 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
4436 | } |
4437 | |
4438 | /* Pop the top lexer off the parser stack. This is never used for the |
4439 | "main" lexer, only for those pushed by cp_parser_push_lexer_for_tokens. */ |
4440 | static void |
4441 | cp_parser_pop_lexer (cp_parser *parser) |
4442 | { |
4443 | cp_lexer *lexer = parser->lexer; |
4444 | parser->lexer = lexer->next; |
4445 | cp_lexer_destroy (lexer); |
4446 | |
4447 | /* Put the current source position back where it was before this |
4448 | lexer was pushed. */ |
4449 | cp_lexer_set_source_position_from_token (token: parser->lexer->next_token); |
4450 | } |
4451 | |
4452 | /* Lexical conventions [gram.lex] */ |
4453 | |
4454 | /* Parse an identifier. Returns an IDENTIFIER_NODE representing the |
4455 | identifier. */ |
4456 | |
4457 | static cp_expr |
4458 | cp_parser_identifier (cp_parser* parser) |
4459 | { |
4460 | cp_token *token; |
4461 | |
4462 | /* Look for the identifier. */ |
4463 | token = cp_parser_require (parser, CPP_NAME, RT_NAME); |
4464 | /* Return the value. */ |
4465 | if (token) |
4466 | return cp_expr (token->u.value, token->location); |
4467 | else |
4468 | return error_mark_node; |
4469 | } |
4470 | |
4471 | /* Worker for cp_parser_string_literal, cp_parser_userdef_string_literal |
4472 | and cp_parser_unevaluated_string_literal. |
4473 | Do not call this directly; use either of the above. |
4474 | |
4475 | Parse a sequence of adjacent string constants. Return a |
4476 | TREE_STRING representing the combined, nul-terminated string |
4477 | constant. If TRANSLATE is true, translate the string to the |
4478 | execution character set. If WIDE_OK is true, a wide string is |
4479 | valid here. If UDL_OK is true, a string literal with user-defined |
4480 | suffix can be used in this context. If UNEVAL is true, diagnose |
4481 | numeric and conditional escape sequences in it if pedantic. |
4482 | |
4483 | C++98 [lex.string] says that if a narrow string literal token is |
4484 | adjacent to a wide string literal token, the behavior is undefined. |
4485 | However, C99 6.4.5p4 says that this results in a wide string literal. |
4486 | We follow C99 here, for consistency with the C front end. |
4487 | |
4488 | This code is largely lifted from lex_string() in c-lex.cc. |
4489 | |
4490 | FUTURE: ObjC++ will need to handle @-strings here. */ |
4491 | |
4492 | static cp_expr |
4493 | cp_parser_string_literal_common (cp_parser *parser, bool translate, |
4494 | bool wide_ok, bool udl_ok, |
4495 | bool lookup_udlit, bool uneval) |
4496 | { |
4497 | tree value; |
4498 | size_t count; |
4499 | struct obstack str_ob; |
4500 | struct obstack loc_ob; |
4501 | cpp_string str, istr, *strs; |
4502 | cp_token *tok; |
4503 | enum cpp_ttype type, curr_type; |
4504 | int have_suffix_p = 0; |
4505 | tree string_tree; |
4506 | tree suffix_id = NULL_TREE; |
4507 | bool curr_tok_is_userdef_p = false; |
4508 | |
4509 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
4510 | if (!cp_parser_is_string_literal (token: tok)) |
4511 | { |
4512 | cp_parser_error (parser, gmsgid: "expected string-literal" ); |
4513 | return error_mark_node; |
4514 | } |
4515 | |
4516 | location_t loc = tok->location; |
4517 | |
4518 | if (cpp_userdef_string_p (type: tok->type)) |
4519 | { |
4520 | if (!udl_ok) |
4521 | { |
4522 | error_at (loc, "string literal with user-defined suffix " |
4523 | "is invalid in this context" ); |
4524 | return error_mark_node; |
4525 | } |
4526 | string_tree = USERDEF_LITERAL_VALUE (tok->u.value); |
4527 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4528 | curr_tok_is_userdef_p = true; |
4529 | } |
4530 | else |
4531 | { |
4532 | string_tree = tok->u.value; |
4533 | curr_type = tok->type; |
4534 | } |
4535 | type = curr_type; |
4536 | |
4537 | /* Try to avoid the overhead of creating and destroying an obstack |
4538 | for the common case of just one string. */ |
4539 | if (!cp_parser_is_string_literal |
4540 | (token: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))) |
4541 | { |
4542 | cp_lexer_consume_token (lexer: parser->lexer); |
4543 | |
4544 | str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); |
4545 | str.len = TREE_STRING_LENGTH (string_tree); |
4546 | count = 1; |
4547 | |
4548 | if (curr_tok_is_userdef_p) |
4549 | { |
4550 | suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); |
4551 | have_suffix_p = 1; |
4552 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4553 | } |
4554 | else |
4555 | curr_type = tok->type; |
4556 | |
4557 | strs = &str; |
4558 | } |
4559 | else |
4560 | { |
4561 | location_t last_tok_loc = tok->location; |
4562 | gcc_obstack_init (&str_ob); |
4563 | gcc_obstack_init (&loc_ob); |
4564 | count = 0; |
4565 | |
4566 | do |
4567 | { |
4568 | cp_lexer_consume_token (lexer: parser->lexer); |
4569 | count++; |
4570 | str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); |
4571 | str.len = TREE_STRING_LENGTH (string_tree); |
4572 | |
4573 | if (curr_tok_is_userdef_p) |
4574 | { |
4575 | tree curr_suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); |
4576 | if (have_suffix_p == 0) |
4577 | { |
4578 | suffix_id = curr_suffix_id; |
4579 | have_suffix_p = 1; |
4580 | } |
4581 | else if (have_suffix_p == 1 |
4582 | && curr_suffix_id != suffix_id) |
4583 | { |
4584 | error ("inconsistent user-defined literal suffixes" |
4585 | " %qD and %qD in string literal" , |
4586 | suffix_id, curr_suffix_id); |
4587 | have_suffix_p = -1; |
4588 | } |
4589 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4590 | } |
4591 | else |
4592 | curr_type = tok->type; |
4593 | |
4594 | if (type != curr_type) |
4595 | { |
4596 | if (type == CPP_STRING) |
4597 | type = curr_type; |
4598 | else if (curr_type != CPP_STRING) |
4599 | { |
4600 | rich_location rich_loc (line_table, tok->location); |
4601 | rich_loc.add_range (loc: last_tok_loc); |
4602 | error_at (&rich_loc, |
4603 | "concatenation of string literals with " |
4604 | "conflicting encoding prefixes" ); |
4605 | } |
4606 | } |
4607 | |
4608 | obstack_grow (&str_ob, &str, sizeof (cpp_string)); |
4609 | obstack_grow (&loc_ob, &tok->location, sizeof (location_t)); |
4610 | |
4611 | last_tok_loc = tok->location; |
4612 | |
4613 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
4614 | if (cpp_userdef_string_p (type: tok->type)) |
4615 | { |
4616 | if (!udl_ok) |
4617 | { |
4618 | error_at (loc, "string literal with user-defined suffix " |
4619 | "is invalid in this context" ); |
4620 | return error_mark_node; |
4621 | } |
4622 | string_tree = USERDEF_LITERAL_VALUE (tok->u.value); |
4623 | curr_type = cpp_userdef_string_remove_type (type: tok->type); |
4624 | curr_tok_is_userdef_p = true; |
4625 | } |
4626 | else |
4627 | { |
4628 | string_tree = tok->u.value; |
4629 | curr_type = tok->type; |
4630 | curr_tok_is_userdef_p = false; |
4631 | } |
4632 | } |
4633 | while (cp_parser_is_string_literal (token: tok)); |
4634 | |
4635 | /* A string literal built by concatenation has its caret=start at |
4636 | the start of the initial string, and its finish at the finish of |
4637 | the final string literal. */ |
4638 | loc = make_location (caret: loc, start: loc, finish: get_finish (loc: last_tok_loc)); |
4639 | |
4640 | strs = (cpp_string *) obstack_finish (&str_ob); |
4641 | } |
4642 | |
4643 | if (type != CPP_STRING && !wide_ok) |
4644 | { |
4645 | cp_parser_error (parser, gmsgid: "a wide string is invalid in this context" ); |
4646 | type = CPP_STRING; |
4647 | } |
4648 | if (uneval) |
4649 | type = CPP_UNEVAL_STRING; |
4650 | |
4651 | if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate) |
4652 | (parse_in, strs, count, &istr, type)) |
4653 | { |
4654 | value = build_string (istr.len, (const char *)istr.text); |
4655 | free (CONST_CAST (unsigned char *, istr.text)); |
4656 | if (count > 1) |
4657 | { |
4658 | location_t *locs = (location_t *)obstack_finish (&loc_ob); |
4659 | gcc_assert (g_string_concat_db); |
4660 | g_string_concat_db->record_string_concatenation (num: count, locs); |
4661 | } |
4662 | |
4663 | switch (type) |
4664 | { |
4665 | default: |
4666 | case CPP_STRING: |
4667 | TREE_TYPE (value) = char_array_type_node; |
4668 | break; |
4669 | case CPP_UTF8STRING: |
4670 | if (flag_char8_t) |
4671 | TREE_TYPE (value) = char8_array_type_node; |
4672 | else |
4673 | TREE_TYPE (value) = char_array_type_node; |
4674 | break; |
4675 | case CPP_STRING16: |
4676 | TREE_TYPE (value) = char16_array_type_node; |
4677 | break; |
4678 | case CPP_STRING32: |
4679 | TREE_TYPE (value) = char32_array_type_node; |
4680 | break; |
4681 | case CPP_WSTRING: |
4682 | TREE_TYPE (value) = wchar_array_type_node; |
4683 | break; |
4684 | } |
4685 | |
4686 | value = fix_string_type (value); |
4687 | |
4688 | if (have_suffix_p) |
4689 | { |
4690 | tree literal = build_userdef_literal (suffix_id, value, |
4691 | overflow: OT_NONE, NULL_TREE); |
4692 | if (lookup_udlit) |
4693 | value = finish_userdef_string_literal (literal); |
4694 | else |
4695 | value = literal; |
4696 | } |
4697 | } |
4698 | else |
4699 | /* cpp_interpret_string has issued an error. */ |
4700 | value = error_mark_node; |
4701 | |
4702 | if (count > 1) |
4703 | { |
4704 | obstack_free (&str_ob, 0); |
4705 | obstack_free (&loc_ob, 0); |
4706 | } |
4707 | |
4708 | return cp_expr (value, loc); |
4709 | } |
4710 | |
4711 | /* Parse a sequence of adjacent string constants. Return a TREE_STRING |
4712 | representing the combined, nul-terminated string constant. If |
4713 | TRANSLATE is true, translate the string to the execution character set. |
4714 | If WIDE_OK is true, a wide string is valid here. |
4715 | |
4716 | This function issues an error if a user defined string literal is |
4717 | encountered; use cp_parser_userdef_string_literal if UDLs are allowed. */ |
4718 | |
4719 | static inline cp_expr |
4720 | cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) |
4721 | { |
4722 | return cp_parser_string_literal_common (parser, translate, wide_ok, |
4723 | /*udl_ok=*/false, |
4724 | /*lookup_udlit=*/false, |
4725 | /*uneval=*/false); |
4726 | } |
4727 | |
4728 | /* Parse a string literal or user defined string literal. |
4729 | |
4730 | user-defined-string-literal : |
4731 | string-literal ud-suffix |
4732 | |
4733 | If LOOKUP_UDLIT, perform a lookup for a suitable template function. */ |
4734 | |
4735 | static inline cp_expr |
4736 | cp_parser_userdef_string_literal (cp_parser *parser, bool lookup_udlit) |
4737 | { |
4738 | return cp_parser_string_literal_common (parser, /*translate=*/true, |
4739 | /*wide_ok=*/true, /*udl_ok=*/true, |
4740 | lookup_udlit, /*uneval=*/false); |
4741 | } |
4742 | |
4743 | /* Parse an unevaluated string literal. |
4744 | |
4745 | unevaluated-string: |
4746 | string-literal */ |
4747 | |
4748 | static inline cp_expr |
4749 | cp_parser_unevaluated_string_literal (cp_parser *parser) |
4750 | { |
4751 | return cp_parser_string_literal_common (parser, /*translate=*/false, |
4752 | /*wide_ok=*/false, /*udl_ok=*/false, |
4753 | /*lookup_udlit=*/false, |
4754 | /*uneval=*/true); |
4755 | } |
4756 | |
4757 | /* Look up a literal operator with the name and the exact arguments. */ |
4758 | |
4759 | static tree |
4760 | lookup_literal_operator (tree name, vec<tree, va_gc> *args) |
4761 | { |
4762 | tree decl = lookup_name (name); |
4763 | if (!decl || !is_overloaded_fn (decl)) |
4764 | return error_mark_node; |
4765 | |
4766 | for (lkp_iterator iter (decl); iter; ++iter) |
4767 | { |
4768 | tree fn = *iter; |
4769 | |
4770 | if (tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn))) |
4771 | { |
4772 | unsigned int ix; |
4773 | bool found = true; |
4774 | |
4775 | for (ix = 0; |
4776 | found && ix < vec_safe_length (v: args) && parmtypes != NULL_TREE; |
4777 | ++ix, parmtypes = TREE_CHAIN (parmtypes)) |
4778 | { |
4779 | tree tparm = TREE_VALUE (parmtypes); |
4780 | tree targ = TREE_TYPE ((*args)[ix]); |
4781 | bool ptr = TYPE_PTR_P (tparm); |
4782 | bool arr = TREE_CODE (targ) == ARRAY_TYPE; |
4783 | if ((ptr || arr || !same_type_p (tparm, targ)) |
4784 | && (!ptr || !arr |
4785 | || !same_type_p (TREE_TYPE (tparm), |
4786 | TREE_TYPE (targ)))) |
4787 | found = false; |
4788 | } |
4789 | |
4790 | if (found |
4791 | && ix == vec_safe_length (v: args) |
4792 | /* May be this should be sufficient_parms_p instead, |
4793 | depending on how exactly should user-defined literals |
4794 | work in presence of default arguments on the literal |
4795 | operator parameters. */ |
4796 | && parmtypes == void_list_node) |
4797 | return decl; |
4798 | } |
4799 | } |
4800 | |
4801 | return error_mark_node; |
4802 | } |
4803 | |
4804 | /* Parse a user-defined char constant. Returns a call to a user-defined |
4805 | literal operator taking the character as an argument. */ |
4806 | |
4807 | static cp_expr |
4808 | cp_parser_userdef_char_literal (cp_parser *parser) |
4809 | { |
4810 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
4811 | tree literal = token->u.value; |
4812 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
4813 | tree value = USERDEF_LITERAL_VALUE (literal); |
4814 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
4815 | tree decl, result; |
4816 | |
4817 | /* Build up a call to the user-defined operator */ |
4818 | /* Lookup the name we got back from the id-expression. */ |
4819 | releasing_vec args; |
4820 | vec_safe_push (r&: args, t: value); |
4821 | decl = lookup_literal_operator (name, args); |
4822 | if (!decl || decl == error_mark_node) |
4823 | { |
4824 | error ("unable to find character literal operator %qD with %qT argument" , |
4825 | name, TREE_TYPE (value)); |
4826 | return error_mark_node; |
4827 | } |
4828 | result = finish_call_expr (decl, &args, false, true, tf_warning_or_error); |
4829 | return result; |
4830 | } |
4831 | |
4832 | /* A subroutine of cp_parser_userdef_numeric_literal to |
4833 | create a char... template parameter pack from a string node. */ |
4834 | |
4835 | static tree |
4836 | make_char_string_pack (tree value) |
4837 | { |
4838 | tree charvec; |
4839 | tree argpack = make_node (NONTYPE_ARGUMENT_PACK); |
4840 | const unsigned char *str |
4841 | = (const unsigned char *) TREE_STRING_POINTER (value); |
4842 | int i, len = TREE_STRING_LENGTH (value) - 1; |
4843 | tree argvec = make_tree_vec (1); |
4844 | |
4845 | /* Fill in CHARVEC with all of the parameters. */ |
4846 | charvec = make_tree_vec (len); |
4847 | for (i = 0; i < len; ++i) |
4848 | { |
4849 | unsigned char s[3] = { '\'', str[i], '\'' }; |
4850 | cpp_string in = { .len: 3, .text: s }; |
4851 | cpp_string out = { .len: 0, .text: 0 }; |
4852 | if (!cpp_interpret_string (parse_in, &in, 1, &out, CPP_STRING)) |
4853 | return NULL_TREE; |
4854 | gcc_assert (out.len == 2); |
4855 | TREE_VEC_ELT (charvec, i) = build_int_cst (char_type_node, |
4856 | out.text[0]); |
4857 | } |
4858 | |
4859 | /* Build the argument packs. */ |
4860 | ARGUMENT_PACK_ARGS (argpack) = charvec; |
4861 | |
4862 | TREE_VEC_ELT (argvec, 0) = argpack; |
4863 | |
4864 | return argvec; |
4865 | } |
4866 | |
4867 | /* A subroutine of cp_parser_userdef_numeric_literal to |
4868 | create a char... template parameter pack from a string node. */ |
4869 | |
4870 | static tree |
4871 | make_string_pack (tree value) |
4872 | { |
4873 | tree charvec; |
4874 | tree argpack = make_node (NONTYPE_ARGUMENT_PACK); |
4875 | const unsigned char *str |
4876 | = (const unsigned char *) TREE_STRING_POINTER (value); |
4877 | int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))); |
4878 | int len = TREE_STRING_LENGTH (value) / sz - 1; |
4879 | tree argvec = make_tree_vec (2); |
4880 | |
4881 | tree str_char_type_node = TREE_TYPE (TREE_TYPE (value)); |
4882 | str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node); |
4883 | |
4884 | /* First template parm is character type. */ |
4885 | TREE_VEC_ELT (argvec, 0) = str_char_type_node; |
4886 | |
4887 | /* Fill in CHARVEC with all of the parameters. */ |
4888 | charvec = make_tree_vec (len); |
4889 | for (int i = 0; i < len; ++i) |
4890 | TREE_VEC_ELT (charvec, i) |
4891 | = double_int_to_tree (str_char_type_node, |
4892 | double_int::from_buffer (buffer: str + i * sz, len: sz)); |
4893 | |
4894 | /* Build the argument packs. */ |
4895 | ARGUMENT_PACK_ARGS (argpack) = charvec; |
4896 | |
4897 | TREE_VEC_ELT (argvec, 1) = argpack; |
4898 | |
4899 | return argvec; |
4900 | } |
4901 | |
4902 | /* Parse a user-defined numeric constant. returns a call to a user-defined |
4903 | literal operator. */ |
4904 | |
4905 | static cp_expr |
4906 | cp_parser_userdef_numeric_literal (cp_parser *parser) |
4907 | { |
4908 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
4909 | tree literal = token->u.value; |
4910 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
4911 | tree value = USERDEF_LITERAL_VALUE (literal); |
4912 | int overflow = USERDEF_LITERAL_OVERFLOW (literal); |
4913 | tree num_string = USERDEF_LITERAL_NUM_STRING (literal); |
4914 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
4915 | tree decl, result; |
4916 | |
4917 | /* Look for a literal operator taking the exact type of numeric argument |
4918 | as the literal value. */ |
4919 | releasing_vec args; |
4920 | vec_safe_push (r&: args, t: value); |
4921 | decl = lookup_literal_operator (name, args); |
4922 | if (decl && decl != error_mark_node) |
4923 | { |
4924 | result = finish_call_expr (decl, &args, false, true, |
4925 | tf_warning_or_error); |
4926 | |
4927 | if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0) |
4928 | { |
4929 | warning_at (token->location, OPT_Woverflow, |
4930 | "integer literal exceeds range of %qT type" , |
4931 | long_long_unsigned_type_node); |
4932 | } |
4933 | else |
4934 | { |
4935 | if (overflow > 0) |
4936 | warning_at (token->location, OPT_Woverflow, |
4937 | "floating literal exceeds range of %qT type" , |
4938 | long_double_type_node); |
4939 | else if (overflow < 0) |
4940 | warning_at (token->location, OPT_Woverflow, |
4941 | "floating literal truncated to zero" ); |
4942 | } |
4943 | |
4944 | return result; |
4945 | } |
4946 | |
4947 | /* If the numeric argument didn't work, look for a raw literal |
4948 | operator taking a const char* argument consisting of the number |
4949 | in string format. */ |
4950 | args->truncate (size: 0); |
4951 | vec_safe_push (r&: args, t: num_string); |
4952 | decl = lookup_literal_operator (name, args); |
4953 | if (decl && decl != error_mark_node) |
4954 | { |
4955 | result = finish_call_expr (decl, &args, false, true, |
4956 | tf_warning_or_error); |
4957 | return result; |
4958 | } |
4959 | |
4960 | /* If the raw literal didn't work, look for a non-type template |
4961 | function with parameter pack char.... Call the function with |
4962 | template parameter characters representing the number. */ |
4963 | args->truncate (size: 0); |
4964 | decl = lookup_literal_operator (name, args); |
4965 | if (decl && decl != error_mark_node) |
4966 | { |
4967 | tree tmpl_args = make_char_string_pack (value: num_string); |
4968 | if (tmpl_args == NULL_TREE) |
4969 | { |
4970 | error ("failed to translate literal to execution character set %qT" , |
4971 | num_string); |
4972 | return error_mark_node; |
4973 | } |
4974 | decl = lookup_template_function (decl, tmpl_args); |
4975 | result = finish_call_expr (decl, &args, false, true, |
4976 | tf_warning_or_error); |
4977 | return result; |
4978 | } |
4979 | |
4980 | /* In C++14 the standard library defines complex number suffixes that |
4981 | conflict with GNU extensions. Prefer them if <complex> is #included. */ |
4982 | bool ext = cpp_get_options (parse_in)->ext_numeric_literals; |
4983 | bool i14 = (cxx_dialect > cxx11 |
4984 | && (id_equal (id: suffix_id, str: "i" ) |
4985 | || id_equal (id: suffix_id, str: "if" ) |
4986 | || id_equal (id: suffix_id, str: "il" ))); |
4987 | diagnostic_t kind = DK_ERROR; |
4988 | int opt = 0; |
4989 | |
4990 | if (i14 && ext) |
4991 | { |
4992 | tree cxlit = lookup_qualified_name (std_node, name: "complex_literals" , |
4993 | LOOK_want::NORMAL, false); |
4994 | if (cxlit == error_mark_node) |
4995 | { |
4996 | /* No <complex>, so pedwarn and use GNU semantics. */ |
4997 | kind = DK_PEDWARN; |
4998 | opt = OPT_Wpedantic; |
4999 | } |
5000 | } |
5001 | |
5002 | bool complained |
5003 | = emit_diagnostic (kind, input_location, opt, |
5004 | "unable to find numeric literal operator %qD" , name); |
5005 | |
5006 | if (!complained) |
5007 | /* Don't inform either. */; |
5008 | else if (i14) |
5009 | { |
5010 | inform (token->location, "add %<using namespace std::complex_literals%> " |
5011 | "(from %<<complex>%>) to enable the C++14 user-defined literal " |
5012 | "suffixes" ); |
5013 | if (ext) |
5014 | inform (token->location, "or use %<j%> instead of %<i%> for the " |
5015 | "GNU built-in suffix" ); |
5016 | } |
5017 | else if (!ext) |
5018 | inform (token->location, "use %<-fext-numeric-literals%> " |
5019 | "to enable more built-in suffixes" ); |
5020 | |
5021 | if (kind == DK_ERROR) |
5022 | value = error_mark_node; |
5023 | else |
5024 | { |
5025 | /* Use the built-in semantics. */ |
5026 | tree type; |
5027 | if (id_equal (id: suffix_id, str: "i" )) |
5028 | { |
5029 | if (TREE_CODE (value) == INTEGER_CST) |
5030 | type = integer_type_node; |
5031 | else |
5032 | type = double_type_node; |
5033 | } |
5034 | else if (id_equal (id: suffix_id, str: "if" )) |
5035 | type = float_type_node; |
5036 | else /* if (id_equal (suffix_id, "il")) */ |
5037 | type = long_double_type_node; |
5038 | |
5039 | value = fold_build2 (COMPLEX_EXPR, build_complex_type (type), |
5040 | build_zero_cst (type), fold_convert (type, value)); |
5041 | } |
5042 | |
5043 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5044 | /* Avoid repeated diagnostics. */ |
5045 | token->u.value = value; |
5046 | return value; |
5047 | } |
5048 | |
5049 | /* Parse a user-defined string constant. Returns a call to a user-defined |
5050 | literal operator taking a character pointer and the length of the string |
5051 | as arguments. */ |
5052 | |
5053 | static tree |
5054 | finish_userdef_string_literal (tree literal) |
5055 | { |
5056 | tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); |
5057 | tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); |
5058 | tree value = USERDEF_LITERAL_VALUE (literal); |
5059 | int len = TREE_STRING_LENGTH (value) |
5060 | / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1; |
5061 | tree decl; |
5062 | |
5063 | /* Build up a call to the user-defined operator. */ |
5064 | /* Lookup the name we got back from the id-expression. */ |
5065 | releasing_vec args; |
5066 | vec_safe_push (r&: args, t: value); |
5067 | vec_safe_push (r&: args, t: build_int_cst (size_type_node, len)); |
5068 | decl = lookup_literal_operator (name, args); |
5069 | |
5070 | if (decl && decl != error_mark_node) |
5071 | return finish_call_expr (decl, &args, false, true, |
5072 | tf_warning_or_error); |
5073 | |
5074 | /* Look for a suitable template function, either (C++20) with a single |
5075 | parameter of class type, or (N3599) with typename parameter CharT and |
5076 | parameter pack CharT... */ |
5077 | args->truncate (size: 0); |
5078 | decl = lookup_literal_operator (name, args); |
5079 | if (decl && decl != error_mark_node) |
5080 | { |
5081 | /* Use resolve_nondeduced_context to try to choose one form of template |
5082 | or the other. */ |
5083 | tree tmpl_args = make_tree_vec (1); |
5084 | TREE_VEC_ELT (tmpl_args, 0) = value; |
5085 | decl = lookup_template_function (decl, tmpl_args); |
5086 | tree res = resolve_nondeduced_context (decl, tf_none); |
5087 | if (DECL_P (res)) |
5088 | decl = res; |
5089 | else |
5090 | { |
5091 | TREE_OPERAND (decl, 1) = make_string_pack (value); |
5092 | res = resolve_nondeduced_context (decl, tf_none); |
5093 | if (DECL_P (res)) |
5094 | decl = res; |
5095 | } |
5096 | if (!DECL_P (decl) && cxx_dialect > cxx17) |
5097 | TREE_OPERAND (decl, 1) = tmpl_args; |
5098 | return finish_call_expr (decl, &args, false, true, |
5099 | tf_warning_or_error); |
5100 | } |
5101 | |
5102 | error ("unable to find string literal operator %qD with %qT, %qT arguments" , |
5103 | name, TREE_TYPE (value), size_type_node); |
5104 | return error_mark_node; |
5105 | } |
5106 | |
5107 | |
5108 | /* Basic concepts [gram.basic] */ |
5109 | |
5110 | /* Parse a translation-unit. |
5111 | |
5112 | translation-unit: |
5113 | declaration-seq [opt] */ |
5114 | |
5115 | static void |
5116 | cp_parser_translation_unit (cp_parser* parser) |
5117 | { |
5118 | gcc_checking_assert (!cp_error_declarator); |
5119 | |
5120 | /* Create the declarator obstack. */ |
5121 | gcc_obstack_init (&declarator_obstack); |
5122 | /* Create the error declarator. */ |
5123 | cp_error_declarator = make_declarator (kind: cdk_error); |
5124 | /* Create the empty parameter list. */ |
5125 | no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE, |
5126 | UNKNOWN_LOCATION); |
5127 | /* Remember where the base of the declarator obstack lies. */ |
5128 | void *declarator_obstack_base = obstack_next_free (&declarator_obstack); |
5129 | |
5130 | push_deferring_access_checks (flag_access_control |
5131 | ? dk_no_deferred : dk_no_check); |
5132 | |
5133 | module_parse mp_state = MP_NOT_MODULE; |
5134 | if (modules_p () && !header_module_p ()) |
5135 | mp_state = MP_FIRST; |
5136 | |
5137 | bool implicit_extern_c = false; |
5138 | |
5139 | /* Parse until EOF. */ |
5140 | for (;;) |
5141 | { |
5142 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
5143 | |
5144 | /* If we're entering or exiting a region that's implicitly |
5145 | extern "C", modify the lang context appropriately. This is |
5146 | so horrible. Please die. */ |
5147 | if (implicit_extern_c |
5148 | != cp_lexer_peek_token (lexer: parser->lexer)->implicit_extern_c) |
5149 | { |
5150 | implicit_extern_c = !implicit_extern_c; |
5151 | if (implicit_extern_c) |
5152 | push_lang_context (lang_name_c); |
5153 | else |
5154 | pop_lang_context (); |
5155 | } |
5156 | |
5157 | if (token->type == CPP_EOF) |
5158 | break; |
5159 | |
5160 | if (modules_p ()) |
5161 | { |
5162 | /* Top-level module declarations are ok, and change the |
5163 | portion of file we're in. Top-level import declarations |
5164 | are significant for the import portions. */ |
5165 | |
5166 | cp_token *next = token; |
5167 | bool exporting = token->keyword == RID__EXPORT; |
5168 | if (exporting) |
5169 | { |
5170 | cp_lexer_consume_token (lexer: parser->lexer); |
5171 | next = cp_lexer_peek_token (lexer: parser->lexer); |
5172 | } |
5173 | if (next->keyword == RID__MODULE) |
5174 | { |
5175 | mp_state |
5176 | = cp_parser_module_declaration (parser, mp_state, exporting); |
5177 | continue; |
5178 | } |
5179 | else if (next->keyword == RID__IMPORT) |
5180 | { |
5181 | if (mp_state == MP_FIRST) |
5182 | mp_state = MP_NOT_MODULE; |
5183 | cp_parser_import_declaration (parser, mp_state, exporting); |
5184 | continue; |
5185 | } |
5186 | else |
5187 | gcc_checking_assert (!exporting); |
5188 | |
5189 | if (mp_state == MP_GLOBAL && token->main_source_p) |
5190 | { |
5191 | static bool warned = false; |
5192 | if (!warned) |
5193 | { |
5194 | warned = true; |
5195 | error_at (token->location, |
5196 | "global module fragment contents must be" |
5197 | " from preprocessor inclusion" ); |
5198 | } |
5199 | } |
5200 | } |
5201 | |
5202 | /* This relies on the ordering of module_parse values. */ |
5203 | if (mp_state == MP_PURVIEW_IMPORTS || mp_state == MP_PRIVATE_IMPORTS) |
5204 | /* We're no longer in the import portion of a named module. */ |
5205 | mp_state = module_parse (mp_state + 1); |
5206 | else if (mp_state == MP_FIRST) |
5207 | mp_state = MP_NOT_MODULE; |
5208 | |
5209 | if (token->type == CPP_CLOSE_BRACE) |
5210 | { |
5211 | cp_parser_error (parser, gmsgid: "expected declaration" ); |
5212 | cp_lexer_consume_token (lexer: parser->lexer); |
5213 | /* If the next token is now a `;', consume it. */ |
5214 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
5215 | cp_lexer_consume_token (lexer: parser->lexer); |
5216 | } |
5217 | else |
5218 | cp_parser_toplevel_declaration (parser); |
5219 | } |
5220 | |
5221 | /* Get rid of the token array; we don't need it any more. */ |
5222 | cp_lexer_destroy (lexer: parser->lexer); |
5223 | parser->lexer = NULL; |
5224 | |
5225 | /* The EOF should have reset this. */ |
5226 | gcc_checking_assert (!implicit_extern_c); |
5227 | |
5228 | /* Make sure the declarator obstack was fully cleaned up. */ |
5229 | gcc_assert (obstack_next_free (&declarator_obstack) |
5230 | == declarator_obstack_base); |
5231 | } |
5232 | |
5233 | /* Return the appropriate tsubst flags for parsing, possibly in N3276 |
5234 | decltype context. */ |
5235 | |
5236 | static inline tsubst_flags_t |
5237 | complain_flags (bool decltype_p) |
5238 | { |
5239 | tsubst_flags_t complain = tf_warning_or_error; |
5240 | if (decltype_p) |
5241 | complain |= tf_decltype; |
5242 | return complain; |
5243 | } |
5244 | |
5245 | /* We're about to parse a collection of statements. If we're currently |
5246 | parsing tentatively, set up a firewall so that any nested |
5247 | cp_parser_commit_to_tentative_parse won't affect the current context. */ |
5248 | |
5249 | static cp_token_position |
5250 | cp_parser_start_tentative_firewall (cp_parser *parser) |
5251 | { |
5252 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5253 | return 0; |
5254 | |
5255 | cp_parser_parse_tentatively (parser); |
5256 | cp_parser_commit_to_topmost_tentative_parse (parser); |
5257 | return cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
5258 | } |
5259 | |
5260 | /* We've finished parsing the collection of statements. Wrap up the |
5261 | firewall and replace the relevant tokens with the parsed form. */ |
5262 | |
5263 | static void |
5264 | cp_parser_end_tentative_firewall (cp_parser *parser, cp_token_position start, |
5265 | tree expr) |
5266 | { |
5267 | if (!start) |
5268 | return; |
5269 | |
5270 | /* Finish the firewall level. */ |
5271 | cp_parser_parse_definitely (parser); |
5272 | /* And remember the result of the parse for when we try again. */ |
5273 | cp_token *token = cp_lexer_token_at (parser->lexer, pos: start); |
5274 | token->type = CPP_PREPARSED_EXPR; |
5275 | token->u.value = expr; |
5276 | token->keyword = RID_MAX; |
5277 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
5278 | } |
5279 | |
5280 | /* Like the above functions, but let the user modify the tokens. Used by |
5281 | CPP_DECLTYPE and CPP_TEMPLATE_ID, where we are saving the side-effects for |
5282 | later parses, so it makes sense to localize the effects of |
5283 | cp_parser_commit_to_tentative_parse. */ |
5284 | |
5285 | struct tentative_firewall |
5286 | { |
5287 | cp_parser *parser; |
5288 | bool set; |
5289 | |
5290 | tentative_firewall (cp_parser *p): parser(p) |
5291 | { |
5292 | /* If we're currently parsing tentatively, start a committed level as a |
5293 | firewall and then an inner tentative parse. */ |
5294 | if ((set = cp_parser_uncommitted_to_tentative_parse_p (parser))) |
5295 | { |
5296 | cp_parser_parse_tentatively (parser); |
5297 | cp_parser_commit_to_topmost_tentative_parse (parser); |
5298 | cp_parser_parse_tentatively (parser); |
5299 | } |
5300 | } |
5301 | |
5302 | ~tentative_firewall() |
5303 | { |
5304 | if (set) |
5305 | { |
5306 | /* Finish the inner tentative parse and the firewall, propagating any |
5307 | uncommitted error state to the outer tentative parse. */ |
5308 | bool err = cp_parser_error_occurred (parser); |
5309 | cp_parser_parse_definitely (parser); |
5310 | cp_parser_parse_definitely (parser); |
5311 | if (err) |
5312 | cp_parser_simulate_error (parser); |
5313 | } |
5314 | } |
5315 | }; |
5316 | |
5317 | /* Some tokens naturally come in pairs e.g.'(' and ')'. |
5318 | This class is for tracking such a matching pair of symbols. |
5319 | In particular, it tracks the location of the first token, |
5320 | so that if the second token is missing, we can highlight the |
5321 | location of the first token when notifying the user about the |
5322 | problem. */ |
5323 | |
5324 | template <typename traits_t> |
5325 | class token_pair |
5326 | { |
5327 | public: |
5328 | /* token_pair's ctor. */ |
5329 | token_pair () : m_open_loc (UNKNOWN_LOCATION) {} |
5330 | |
5331 | /* If the next token is the opening symbol for this pair, consume it and |
5332 | return true. |
5333 | Otherwise, issue an error and return false. |
5334 | In either case, record the location of the opening token. */ |
5335 | |
5336 | bool require_open (cp_parser *parser) |
5337 | { |
5338 | m_open_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5339 | return cp_parser_require (parser, traits_t::open_token_type, |
5340 | traits_t::required_token_open); |
5341 | } |
5342 | |
5343 | /* Consume the next token from PARSER, recording its location as |
5344 | that of the opening token within the pair. */ |
5345 | |
5346 | cp_token * consume_open (cp_parser *parser) |
5347 | { |
5348 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
5349 | gcc_assert (tok->type == traits_t::open_token_type); |
5350 | m_open_loc = tok->location; |
5351 | return tok; |
5352 | } |
5353 | |
5354 | /* If the next token is the closing symbol for this pair, consume it |
5355 | and return it. |
5356 | Otherwise, issue an error, highlighting the location of the |
5357 | corresponding opening token, and return NULL. */ |
5358 | |
5359 | cp_token *require_close (cp_parser *parser) const |
5360 | { |
5361 | return cp_parser_require (parser, traits_t::close_token_type, |
5362 | traits_t::required_token_close, |
5363 | m_open_loc); |
5364 | } |
5365 | |
5366 | location_t open_location () const { return m_open_loc; } |
5367 | |
5368 | private: |
5369 | location_t m_open_loc; |
5370 | }; |
5371 | |
5372 | /* Traits for token_pair<T> for tracking matching pairs of parentheses. */ |
5373 | |
5374 | struct matching_paren_traits |
5375 | { |
5376 | static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; |
5377 | static const enum required_token required_token_open = RT_OPEN_PAREN; |
5378 | static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; |
5379 | static const enum required_token required_token_close = RT_CLOSE_PAREN; |
5380 | }; |
5381 | |
5382 | /* "matching_parens" is a token_pair<T> class for tracking matching |
5383 | pairs of parentheses. */ |
5384 | |
5385 | typedef token_pair<matching_paren_traits> matching_parens; |
5386 | |
5387 | /* Traits for token_pair<T> for tracking matching pairs of braces. */ |
5388 | |
5389 | struct matching_brace_traits |
5390 | { |
5391 | static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; |
5392 | static const enum required_token required_token_open = RT_OPEN_BRACE; |
5393 | static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; |
5394 | static const enum required_token required_token_close = RT_CLOSE_BRACE; |
5395 | }; |
5396 | |
5397 | /* "matching_braces" is a token_pair<T> class for tracking matching |
5398 | pairs of braces. */ |
5399 | |
5400 | typedef token_pair<matching_brace_traits> matching_braces; |
5401 | |
5402 | |
5403 | /* Parse a GNU statement-expression, i.e. ({ stmts }), except for the |
5404 | enclosing parentheses. */ |
5405 | |
5406 | static cp_expr |
5407 | cp_parser_statement_expr (cp_parser *parser) |
5408 | { |
5409 | cp_token_position start = cp_parser_start_tentative_firewall (parser); |
5410 | |
5411 | /* Consume the '('. */ |
5412 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5413 | matching_parens parens; |
5414 | parens.consume_open (parser); |
5415 | /* Start the statement-expression. */ |
5416 | tree expr = begin_stmt_expr (); |
5417 | /* Parse the compound-statement. */ |
5418 | cp_parser_compound_statement (parser, expr, BCS_STMT_EXPR, false); |
5419 | /* Finish up. */ |
5420 | expr = finish_stmt_expr (expr, false); |
5421 | /* Consume the ')'. */ |
5422 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5423 | if (!parens.require_close (parser)) |
5424 | cp_parser_skip_to_end_of_statement (parser); |
5425 | |
5426 | cp_parser_end_tentative_firewall (parser, start, expr); |
5427 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
5428 | return cp_expr (expr, combined_loc); |
5429 | } |
5430 | |
5431 | /* Expressions [gram.expr] */ |
5432 | |
5433 | /* Parse a fold-operator. |
5434 | |
5435 | fold-operator: |
5436 | - * / % ^ & | = < > << >> |
5437 | = -= *= /= %= ^= &= |= <<= >>= |
5438 | == != <= >= && || , .* ->* |
5439 | |
5440 | This returns the tree code corresponding to the matched operator |
5441 | as an int. When the current token matches a compound assignment |
5442 | operator, the resulting tree code is the negative value of the |
5443 | non-assignment operator. */ |
5444 | |
5445 | static int |
5446 | cp_parser_fold_operator (cp_token *token) |
5447 | { |
5448 | switch (token->type) |
5449 | { |
5450 | case CPP_PLUS: return PLUS_EXPR; |
5451 | case CPP_MINUS: return MINUS_EXPR; |
5452 | case CPP_MULT: return MULT_EXPR; |
5453 | case CPP_DIV: return TRUNC_DIV_EXPR; |
5454 | case CPP_MOD: return TRUNC_MOD_EXPR; |
5455 | case CPP_XOR: return BIT_XOR_EXPR; |
5456 | case CPP_AND: return BIT_AND_EXPR; |
5457 | case CPP_OR: return BIT_IOR_EXPR; |
5458 | case CPP_LSHIFT: return LSHIFT_EXPR; |
5459 | case CPP_RSHIFT: return RSHIFT_EXPR; |
5460 | |
5461 | case CPP_EQ: return -NOP_EXPR; |
5462 | case CPP_PLUS_EQ: return -PLUS_EXPR; |
5463 | case CPP_MINUS_EQ: return -MINUS_EXPR; |
5464 | case CPP_MULT_EQ: return -MULT_EXPR; |
5465 | case CPP_DIV_EQ: return -TRUNC_DIV_EXPR; |
5466 | case CPP_MOD_EQ: return -TRUNC_MOD_EXPR; |
5467 | case CPP_XOR_EQ: return -BIT_XOR_EXPR; |
5468 | case CPP_AND_EQ: return -BIT_AND_EXPR; |
5469 | case CPP_OR_EQ: return -BIT_IOR_EXPR; |
5470 | case CPP_LSHIFT_EQ: return -LSHIFT_EXPR; |
5471 | case CPP_RSHIFT_EQ: return -RSHIFT_EXPR; |
5472 | |
5473 | case CPP_EQ_EQ: return EQ_EXPR; |
5474 | case CPP_NOT_EQ: return NE_EXPR; |
5475 | case CPP_LESS: return LT_EXPR; |
5476 | case CPP_GREATER: return GT_EXPR; |
5477 | case CPP_LESS_EQ: return LE_EXPR; |
5478 | case CPP_GREATER_EQ: return GE_EXPR; |
5479 | |
5480 | case CPP_AND_AND: return TRUTH_ANDIF_EXPR; |
5481 | case CPP_OR_OR: return TRUTH_ORIF_EXPR; |
5482 | |
5483 | case CPP_COMMA: return COMPOUND_EXPR; |
5484 | |
5485 | case CPP_DOT_STAR: return DOTSTAR_EXPR; |
5486 | case CPP_DEREF_STAR: return MEMBER_REF; |
5487 | |
5488 | default: return ERROR_MARK; |
5489 | } |
5490 | } |
5491 | |
5492 | /* Returns true if CODE indicates a binary expression, which is not allowed in |
5493 | the LHS of a fold-expression. More codes will need to be added to use this |
5494 | function in other contexts. */ |
5495 | |
5496 | static bool |
5497 | is_binary_op (tree_code code) |
5498 | { |
5499 | switch (code) |
5500 | { |
5501 | case PLUS_EXPR: |
5502 | case POINTER_PLUS_EXPR: |
5503 | case MINUS_EXPR: |
5504 | case MULT_EXPR: |
5505 | case TRUNC_DIV_EXPR: |
5506 | case TRUNC_MOD_EXPR: |
5507 | case BIT_XOR_EXPR: |
5508 | case BIT_AND_EXPR: |
5509 | case BIT_IOR_EXPR: |
5510 | case LSHIFT_EXPR: |
5511 | case RSHIFT_EXPR: |
5512 | |
5513 | case MODOP_EXPR: |
5514 | |
5515 | case EQ_EXPR: |
5516 | case NE_EXPR: |
5517 | case LE_EXPR: |
5518 | case GE_EXPR: |
5519 | case LT_EXPR: |
5520 | case GT_EXPR: |
5521 | |
5522 | case TRUTH_ANDIF_EXPR: |
5523 | case TRUTH_ORIF_EXPR: |
5524 | |
5525 | case COMPOUND_EXPR: |
5526 | |
5527 | case DOTSTAR_EXPR: |
5528 | case MEMBER_REF: |
5529 | return true; |
5530 | |
5531 | default: |
5532 | return false; |
5533 | } |
5534 | } |
5535 | |
5536 | /* If the next token is a suitable fold operator, consume it and return as |
5537 | the function above. */ |
5538 | |
5539 | static int |
5540 | cp_parser_fold_operator (cp_parser *parser) |
5541 | { |
5542 | cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
5543 | int code = cp_parser_fold_operator (token); |
5544 | if (code != ERROR_MARK) |
5545 | cp_lexer_consume_token (lexer: parser->lexer); |
5546 | return code; |
5547 | } |
5548 | |
5549 | /* Parse a fold-expression. |
5550 | |
5551 | fold-expression: |
5552 | ( ... folding-operator cast-expression) |
5553 | ( cast-expression folding-operator ... ) |
5554 | ( cast-expression folding operator ... folding-operator cast-expression) |
5555 | |
5556 | Note that the '(' and ')' are matched in primary expression. */ |
5557 | |
5558 | static cp_expr |
5559 | cp_parser_fold_expression (cp_parser *parser, tree expr1) |
5560 | { |
5561 | cp_id_kind pidk; |
5562 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
5563 | const cp_token *token = nullptr; |
5564 | |
5565 | // Left fold. |
5566 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5567 | { |
5568 | if (expr1) |
5569 | return error_mark_node; |
5570 | cp_lexer_consume_token (lexer: parser->lexer); |
5571 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5572 | int op = cp_parser_fold_operator (parser); |
5573 | if (op == ERROR_MARK) |
5574 | { |
5575 | cp_parser_error (parser, gmsgid: "expected binary operator" ); |
5576 | return error_mark_node; |
5577 | } |
5578 | |
5579 | tree expr = cp_parser_cast_expression (parser, false, false, |
5580 | false, &pidk); |
5581 | if (expr == error_mark_node) |
5582 | return error_mark_node; |
5583 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5584 | return finish_left_unary_fold_expr (loc, expr, op); |
5585 | } |
5586 | |
5587 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5588 | int op = cp_parser_fold_operator (parser); |
5589 | if (op == ERROR_MARK) |
5590 | { |
5591 | cp_parser_error (parser, gmsgid: "expected binary operator" ); |
5592 | return error_mark_node; |
5593 | } |
5594 | |
5595 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5596 | { |
5597 | cp_parser_error (parser, gmsgid: "expected ..." ); |
5598 | return error_mark_node; |
5599 | } |
5600 | cp_lexer_consume_token (lexer: parser->lexer); |
5601 | |
5602 | /* The operands of a fold-expression are cast-expressions, so binary or |
5603 | conditional expressions are not allowed. We check this here to avoid |
5604 | tentative parsing. */ |
5605 | if (EXPR_P (expr1) && warning_suppressed_p (expr1, OPT_Wparentheses)) |
5606 | /* OK, the expression was parenthesized. */; |
5607 | else if (is_binary_op (TREE_CODE (expr1))) |
5608 | error_at (location_of (expr1), |
5609 | "binary expression in operand of fold-expression" ); |
5610 | else if (TREE_CODE (expr1) == COND_EXPR |
5611 | || (REFERENCE_REF_P (expr1) |
5612 | && TREE_CODE (TREE_OPERAND (expr1, 0)) == COND_EXPR)) |
5613 | error_at (location_of (expr1), |
5614 | "conditional expression in operand of fold-expression" ); |
5615 | |
5616 | // Right fold. |
5617 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
5618 | { |
5619 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5620 | return finish_right_unary_fold_expr (loc, expr1, op); |
5621 | } |
5622 | |
5623 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: token->type)) |
5624 | { |
5625 | cp_parser_error (parser, gmsgid: "mismatched operator in fold-expression" ); |
5626 | return error_mark_node; |
5627 | } |
5628 | cp_lexer_consume_token (lexer: parser->lexer); |
5629 | |
5630 | // Binary left or right fold. |
5631 | tree expr2 = cp_parser_cast_expression (parser, false, false, false, &pidk); |
5632 | if (expr2 == error_mark_node) |
5633 | return error_mark_node; |
5634 | loc = make_location (caret: token->location, start: loc, lexer: parser->lexer); |
5635 | return finish_binary_fold_expr (loc, expr1, expr2, op); |
5636 | } |
5637 | |
5638 | /* Parse a primary-expression. |
5639 | |
5640 | primary-expression: |
5641 | literal |
5642 | this |
5643 | ( expression ) |
5644 | id-expression |
5645 | lambda-expression (C++11) |
5646 | |
5647 | GNU Extensions: |
5648 | |
5649 | primary-expression: |
5650 | ( compound-statement ) |
5651 | __builtin_va_arg ( assignment-expression , type-id ) |
5652 | __builtin_offsetof ( type-id , offsetof-expression ) |
5653 | |
5654 | C++ Extensions: |
5655 | __has_nothrow_assign ( type-id ) |
5656 | __has_nothrow_constructor ( type-id ) |
5657 | __has_nothrow_copy ( type-id ) |
5658 | __has_trivial_assign ( type-id ) |
5659 | __has_trivial_constructor ( type-id ) |
5660 | __has_trivial_copy ( type-id ) |
5661 | __has_trivial_destructor ( type-id ) |
5662 | __has_virtual_destructor ( type-id ) |
5663 | __is_abstract ( type-id ) |
5664 | __is_base_of ( type-id , type-id ) |
5665 | __is_class ( type-id ) |
5666 | __is_empty ( type-id ) |
5667 | __is_enum ( type-id ) |
5668 | __is_final ( type-id ) |
5669 | __is_literal_type ( type-id ) |
5670 | __is_pod ( type-id ) |
5671 | __is_polymorphic ( type-id ) |
5672 | __is_std_layout ( type-id ) |
5673 | __is_trivial ( type-id ) |
5674 | __is_union ( type-id ) |
5675 | |
5676 | Objective-C++ Extension: |
5677 | |
5678 | primary-expression: |
5679 | objc-expression |
5680 | |
5681 | literal: |
5682 | __null |
5683 | |
5684 | ADDRESS_P is true iff this expression was immediately preceded by |
5685 | "&" and therefore might denote a pointer-to-member. CAST_P is true |
5686 | iff this expression is the target of a cast. TEMPLATE_ARG_P is |
5687 | true iff this expression is a template argument. |
5688 | |
5689 | Returns a representation of the expression. Upon return, *IDK |
5690 | indicates what kind of id-expression (if any) was present. */ |
5691 | |
5692 | static cp_expr |
5693 | cp_parser_primary_expression (cp_parser *parser, |
5694 | bool address_p, |
5695 | bool cast_p, |
5696 | bool template_arg_p, |
5697 | bool decltype_p, |
5698 | cp_id_kind *idk) |
5699 | { |
5700 | cp_token *token = NULL; |
5701 | |
5702 | /* Assume the primary expression is not an id-expression. */ |
5703 | *idk = CP_ID_KIND_NONE; |
5704 | |
5705 | /* Peek at the next token. */ |
5706 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5707 | switch ((int) token->type) |
5708 | { |
5709 | /* literal: |
5710 | integer-literal |
5711 | character-literal |
5712 | floating-literal |
5713 | string-literal |
5714 | boolean-literal |
5715 | pointer-literal |
5716 | user-defined-literal */ |
5717 | case CPP_CHAR: |
5718 | case CPP_CHAR16: |
5719 | case CPP_CHAR32: |
5720 | case CPP_WCHAR: |
5721 | case CPP_UTF8CHAR: |
5722 | case CPP_NUMBER: |
5723 | case CPP_PREPARSED_EXPR: |
5724 | if (TREE_CODE (token->u.value) == USERDEF_LITERAL) |
5725 | return cp_parser_userdef_numeric_literal (parser); |
5726 | token = cp_lexer_consume_token (lexer: parser->lexer); |
5727 | if (TREE_CODE (token->u.value) == FIXED_CST) |
5728 | { |
5729 | error_at (token->location, |
5730 | "fixed-point types not supported in C++" ); |
5731 | return error_mark_node; |
5732 | } |
5733 | /* Floating-point literals are only allowed in an integral |
5734 | constant expression if they are cast to an integral or |
5735 | enumeration type. */ |
5736 | if ((TREE_CODE (token->u.value) == REAL_CST |
5737 | || (TREE_CODE (token->u.value) == EXCESS_PRECISION_EXPR |
5738 | && TREE_CODE (TREE_OPERAND (token->u.value, 0)) == REAL_CST)) |
5739 | && parser->integral_constant_expression_p |
5740 | && pedantic) |
5741 | { |
5742 | /* CAST_P will be set even in invalid code like "int(2.7 + |
5743 | ...)". Therefore, we have to check that the next token |
5744 | is sure to end the cast. */ |
5745 | if (cast_p) |
5746 | { |
5747 | cp_token *next_token; |
5748 | |
5749 | next_token = cp_lexer_peek_token (lexer: parser->lexer); |
5750 | if (/* The comma at the end of an |
5751 | enumerator-definition. */ |
5752 | next_token->type != CPP_COMMA |
5753 | /* The curly brace at the end of an enum-specifier. */ |
5754 | && next_token->type != CPP_CLOSE_BRACE |
5755 | /* The end of a statement. */ |
5756 | && next_token->type != CPP_SEMICOLON |
5757 | /* The end of the cast-expression. */ |
5758 | && next_token->type != CPP_CLOSE_PAREN |
5759 | /* The end of an array bound. */ |
5760 | && next_token->type != CPP_CLOSE_SQUARE |
5761 | /* The closing ">" in a template-argument-list. */ |
5762 | && (next_token->type != CPP_GREATER |
5763 | || parser->greater_than_is_operator_p) |
5764 | /* C++0x only: A ">>" treated like two ">" tokens, |
5765 | in a template-argument-list. */ |
5766 | && (next_token->type != CPP_RSHIFT |
5767 | || (cxx_dialect == cxx98) |
5768 | || parser->greater_than_is_operator_p)) |
5769 | cast_p = false; |
5770 | } |
5771 | |
5772 | /* If we are within a cast, then the constraint that the |
5773 | cast is to an integral or enumeration type will be |
5774 | checked at that point. If we are not within a cast, then |
5775 | this code is invalid. */ |
5776 | if (!cast_p) |
5777 | cp_parser_non_integral_constant_expression (parser, thing: NIC_FLOAT); |
5778 | } |
5779 | return (cp_expr (token->u.value, token->location, token->flags & DECIMAL_INT) |
5780 | .maybe_add_location_wrapper ()); |
5781 | |
5782 | case CPP_CHAR_USERDEF: |
5783 | case CPP_CHAR16_USERDEF: |
5784 | case CPP_CHAR32_USERDEF: |
5785 | case CPP_WCHAR_USERDEF: |
5786 | case CPP_UTF8CHAR_USERDEF: |
5787 | return cp_parser_userdef_char_literal (parser); |
5788 | |
5789 | case CPP_STRING: |
5790 | case CPP_STRING16: |
5791 | case CPP_STRING32: |
5792 | case CPP_WSTRING: |
5793 | case CPP_UTF8STRING: |
5794 | case CPP_STRING_USERDEF: |
5795 | case CPP_STRING16_USERDEF: |
5796 | case CPP_STRING32_USERDEF: |
5797 | case CPP_WSTRING_USERDEF: |
5798 | case CPP_UTF8STRING_USERDEF: |
5799 | /* ??? Should wide strings be allowed when parser->translate_strings_p |
5800 | is false (i.e. in attributes)? If not, we can kill the third |
5801 | argument to cp_parser_string_literal. */ |
5802 | if (parser->translate_strings_p) |
5803 | return (cp_parser_userdef_string_literal (parser, |
5804 | /*lookup_udlit=*/true) |
5805 | .maybe_add_location_wrapper ()); |
5806 | else |
5807 | return (cp_parser_string_literal (parser, |
5808 | /*translate=*/false, |
5809 | /*wide_ok=*/true) |
5810 | .maybe_add_location_wrapper ()); |
5811 | |
5812 | case CPP_OPEN_PAREN: |
5813 | /* If we see `( { ' then we are looking at the beginning of |
5814 | a GNU statement-expression. */ |
5815 | if (cp_parser_allow_gnu_extensions_p (parser) |
5816 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_BRACE)) |
5817 | { |
5818 | /* Statement-expressions are not allowed by the standard. */ |
5819 | pedwarn (token->location, OPT_Wpedantic, |
5820 | "ISO C++ forbids braced-groups within expressions" ); |
5821 | |
5822 | /* And they're not allowed outside of a function-body; you |
5823 | cannot, for example, write: |
5824 | |
5825 | int i = ({ int j = 3; j + 1; }); |
5826 | |
5827 | at class or namespace scope. */ |
5828 | if (!parser->in_function_body |
5829 | || parser->in_template_argument_list_p) |
5830 | { |
5831 | error_at (token->location, |
5832 | "statement-expressions are not allowed outside " |
5833 | "functions nor in template-argument lists" ); |
5834 | cp_parser_skip_to_end_of_block_or_statement (parser); |
5835 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
5836 | cp_lexer_consume_token (lexer: parser->lexer); |
5837 | return error_mark_node; |
5838 | } |
5839 | else |
5840 | return cp_parser_statement_expr (parser); |
5841 | } |
5842 | /* Otherwise it's a normal parenthesized expression. */ |
5843 | { |
5844 | cp_expr expr; |
5845 | bool saved_greater_than_is_operator_p; |
5846 | |
5847 | location_t open_paren_loc = token->location; |
5848 | |
5849 | /* Consume the `('. */ |
5850 | matching_parens parens; |
5851 | parens.consume_open (parser); |
5852 | /* Within a parenthesized expression, a `>' token is always |
5853 | the greater-than operator. */ |
5854 | saved_greater_than_is_operator_p |
5855 | = parser->greater_than_is_operator_p; |
5856 | parser->greater_than_is_operator_p = true; |
5857 | |
5858 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
5859 | /* Left fold expression. */ |
5860 | expr = NULL_TREE; |
5861 | else |
5862 | /* Parse the parenthesized expression. */ |
5863 | expr = cp_parser_expression (parser, idk, cast_p, decltype_p); |
5864 | |
5865 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5866 | if (token->type == CPP_ELLIPSIS || cp_parser_fold_operator (token)) |
5867 | { |
5868 | expr = cp_parser_fold_expression (parser, expr1: expr); |
5869 | if (expr != error_mark_node |
5870 | && cxx_dialect < cxx17) |
5871 | pedwarn (input_location, OPT_Wc__17_extensions, |
5872 | "fold-expressions only available with %<-std=c++17%> " |
5873 | "or %<-std=gnu++17%>" ); |
5874 | } |
5875 | else |
5876 | /* Let the front end know that this expression was |
5877 | enclosed in parentheses. This matters in case, for |
5878 | example, the expression is of the form `A::B', since |
5879 | `&A::B' might be a pointer-to-member, but `&(A::B)' is |
5880 | not. */ |
5881 | expr = finish_parenthesized_expr (expr); |
5882 | |
5883 | /* DR 705: Wrapping an unqualified name in parentheses |
5884 | suppresses arg-dependent lookup. We want to pass back |
5885 | CP_ID_KIND_QUALIFIED for suppressing vtable lookup |
5886 | (c++/37862), but none of the others. */ |
5887 | if (*idk != CP_ID_KIND_QUALIFIED) |
5888 | *idk = CP_ID_KIND_NONE; |
5889 | |
5890 | /* The `>' token might be the end of a template-id or |
5891 | template-parameter-list now. */ |
5892 | parser->greater_than_is_operator_p |
5893 | = saved_greater_than_is_operator_p; |
5894 | |
5895 | /* Consume the `)'. */ |
5896 | token = cp_lexer_peek_token (lexer: parser->lexer); |
5897 | location_t close_paren_loc = token->location; |
5898 | bool no_wparens = warning_suppressed_p (expr, OPT_Wparentheses); |
5899 | expr.set_range (start: open_paren_loc, finish: close_paren_loc); |
5900 | if (no_wparens) |
5901 | suppress_warning (expr, OPT_Wparentheses); |
5902 | if (!parens.require_close (parser) |
5903 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
5904 | cp_parser_skip_to_end_of_statement (parser); |
5905 | |
5906 | return expr; |
5907 | } |
5908 | |
5909 | case CPP_OPEN_SQUARE: |
5910 | { |
5911 | if (c_dialect_objc ()) |
5912 | { |
5913 | /* We might have an Objective-C++ message. */ |
5914 | cp_parser_parse_tentatively (parser); |
5915 | tree msg = cp_parser_objc_message_expression (parser); |
5916 | /* If that works out, we're done ... */ |
5917 | if (cp_parser_parse_definitely (parser)) |
5918 | return msg; |
5919 | /* ... else, fall though to see if it's a lambda. */ |
5920 | } |
5921 | cp_expr lam = cp_parser_lambda_expression (parser); |
5922 | /* Don't warn about a failed tentative parse. */ |
5923 | if (cp_parser_error_occurred (parser)) |
5924 | return error_mark_node; |
5925 | maybe_warn_cpp0x (str: CPP0X_LAMBDA_EXPR); |
5926 | return lam; |
5927 | } |
5928 | |
5929 | case CPP_OBJC_STRING: |
5930 | if (c_dialect_objc ()) |
5931 | /* We have an Objective-C++ string literal. */ |
5932 | return cp_parser_objc_expression (parser); |
5933 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
5934 | return error_mark_node; |
5935 | |
5936 | case CPP_KEYWORD: |
5937 | switch (token->keyword) |
5938 | { |
5939 | /* These two are the boolean literals. */ |
5940 | case RID_TRUE: |
5941 | cp_lexer_consume_token (lexer: parser->lexer); |
5942 | return cp_expr (boolean_true_node, token->location); |
5943 | case RID_FALSE: |
5944 | cp_lexer_consume_token (lexer: parser->lexer); |
5945 | return cp_expr (boolean_false_node, token->location); |
5946 | |
5947 | /* The `__null' literal. */ |
5948 | case RID_NULL: |
5949 | cp_lexer_consume_token (lexer: parser->lexer); |
5950 | return cp_expr (null_node, token->location); |
5951 | |
5952 | /* The `nullptr' literal. */ |
5953 | case RID_NULLPTR: |
5954 | cp_lexer_consume_token (lexer: parser->lexer); |
5955 | return cp_expr (nullptr_node, token->location); |
5956 | |
5957 | /* Recognize the `this' keyword. */ |
5958 | case RID_THIS: |
5959 | cp_lexer_consume_token (lexer: parser->lexer); |
5960 | if (parser->local_variables_forbidden_p & THIS_FORBIDDEN) |
5961 | { |
5962 | error_at (token->location, |
5963 | "%<this%> may not be used in this context" ); |
5964 | return error_mark_node; |
5965 | } |
5966 | /* Pointers cannot appear in constant-expressions. */ |
5967 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_THIS)) |
5968 | return error_mark_node; |
5969 | return cp_expr (finish_this_expr (), token->location); |
5970 | |
5971 | /* The `operator' keyword can be the beginning of an |
5972 | id-expression. */ |
5973 | case RID_OPERATOR: |
5974 | goto id_expression; |
5975 | |
5976 | case RID_FUNCTION_NAME: |
5977 | case RID_PRETTY_FUNCTION_NAME: |
5978 | case RID_C99_FUNCTION_NAME: |
5979 | { |
5980 | non_integral_constant name; |
5981 | |
5982 | /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and |
5983 | __func__ are the names of variables -- but they are |
5984 | treated specially. Therefore, they are handled here, |
5985 | rather than relying on the generic id-expression logic |
5986 | below. Grammatically, these names are id-expressions. |
5987 | |
5988 | Consume the token. */ |
5989 | token = cp_lexer_consume_token (lexer: parser->lexer); |
5990 | |
5991 | switch (token->keyword) |
5992 | { |
5993 | case RID_FUNCTION_NAME: |
5994 | name = NIC_FUNC_NAME; |
5995 | break; |
5996 | case RID_PRETTY_FUNCTION_NAME: |
5997 | name = NIC_PRETTY_FUNC; |
5998 | break; |
5999 | case RID_C99_FUNCTION_NAME: |
6000 | name = NIC_C99_FUNC; |
6001 | break; |
6002 | default: |
6003 | gcc_unreachable (); |
6004 | } |
6005 | |
6006 | if (cp_parser_non_integral_constant_expression (parser, thing: name)) |
6007 | return error_mark_node; |
6008 | |
6009 | /* Look up the name. */ |
6010 | return finish_fname (token->u.value); |
6011 | } |
6012 | |
6013 | case RID_VA_ARG: |
6014 | { |
6015 | tree expression; |
6016 | tree type; |
6017 | location_t type_location; |
6018 | location_t start_loc |
6019 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6020 | /* The `__builtin_va_arg' construct is used to handle |
6021 | `va_arg'. Consume the `__builtin_va_arg' token. */ |
6022 | cp_lexer_consume_token (lexer: parser->lexer); |
6023 | /* Look for the opening `('. */ |
6024 | matching_parens parens; |
6025 | parens.require_open (parser); |
6026 | /* Now, parse the assignment-expression. */ |
6027 | expression = cp_parser_assignment_expression (parser); |
6028 | /* Look for the `,'. */ |
6029 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
6030 | type_location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6031 | /* Parse the type-id. */ |
6032 | { |
6033 | type_id_in_expr_sentinel s (parser); |
6034 | type = cp_parser_type_id (parser); |
6035 | } |
6036 | /* Look for the closing `)'. */ |
6037 | location_t finish_loc |
6038 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
6039 | parens.require_close (parser); |
6040 | /* Using `va_arg' in a constant-expression is not |
6041 | allowed. */ |
6042 | if (cp_parser_non_integral_constant_expression (parser, |
6043 | thing: NIC_VA_ARG)) |
6044 | return error_mark_node; |
6045 | /* Construct a location of the form: |
6046 | __builtin_va_arg (v, int) |
6047 | ~~~~~~~~~~~~~~~~~~~~~^~~~ |
6048 | with the caret at the type, ranging from the start of the |
6049 | "__builtin_va_arg" token to the close paren. */ |
6050 | location_t combined_loc |
6051 | = make_location (caret: type_location, start: start_loc, finish: finish_loc); |
6052 | return build_x_va_arg (combined_loc, expression, type); |
6053 | } |
6054 | |
6055 | case RID_OFFSETOF: |
6056 | return cp_parser_builtin_offsetof (parser); |
6057 | |
6058 | #define DEFTRAIT_EXPR(CODE, NAME, ARITY) \ |
6059 | case RID_##CODE: |
6060 | #include "cp-trait.def" |
6061 | #undef DEFTRAIT_EXPR |
6062 | return cp_parser_trait (parser, token->keyword); |
6063 | |
6064 | // C++ concepts |
6065 | case RID_REQUIRES: |
6066 | return cp_parser_requires_expression (parser); |
6067 | |
6068 | /* Objective-C++ expressions. */ |
6069 | case RID_AT_ENCODE: |
6070 | case RID_AT_PROTOCOL: |
6071 | case RID_AT_SELECTOR: |
6072 | return cp_parser_objc_expression (parser); |
6073 | |
6074 | case RID_OMP_ALL_MEMORY: |
6075 | gcc_assert (flag_openmp); |
6076 | cp_lexer_consume_token (lexer: parser->lexer); |
6077 | error_at (token->location, |
6078 | "%<omp_all_memory%> may only be used in OpenMP " |
6079 | "%<depend%> clause" ); |
6080 | return error_mark_node; |
6081 | |
6082 | case RID_TEMPLATE: |
6083 | if (parser->in_function_body |
6084 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
6085 | == CPP_LESS)) |
6086 | { |
6087 | error_at (token->location, |
6088 | "a template declaration cannot appear at block scope" ); |
6089 | cp_parser_skip_to_end_of_block_or_statement (parser); |
6090 | return error_mark_node; |
6091 | } |
6092 | /* FALLTHRU */ |
6093 | default: |
6094 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
6095 | return error_mark_node; |
6096 | } |
6097 | |
6098 | /* An id-expression can start with either an identifier, a |
6099 | `::' as the beginning of a qualified-id, or the "operator" |
6100 | keyword. */ |
6101 | case CPP_NAME: |
6102 | case CPP_SCOPE: |
6103 | case CPP_TEMPLATE_ID: |
6104 | case CPP_NESTED_NAME_SPECIFIER: |
6105 | { |
6106 | id_expression: |
6107 | cp_expr id_expression; |
6108 | cp_expr decl; |
6109 | const char *error_msg; |
6110 | bool template_p; |
6111 | bool done; |
6112 | cp_token *id_expr_token; |
6113 | |
6114 | /* Parse the id-expression. */ |
6115 | id_expression |
6116 | = cp_parser_id_expression (parser, |
6117 | /*template_keyword_p=*/false, |
6118 | /*check_dependency_p=*/true, |
6119 | &template_p, |
6120 | /*declarator_p=*/false, |
6121 | /*optional_p=*/false); |
6122 | if (id_expression == error_mark_node) |
6123 | return error_mark_node; |
6124 | id_expr_token = token; |
6125 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6126 | done = (token->type != CPP_OPEN_SQUARE |
6127 | && token->type != CPP_OPEN_PAREN |
6128 | && token->type != CPP_DOT |
6129 | && token->type != CPP_DEREF |
6130 | && token->type != CPP_PLUS_PLUS |
6131 | && token->type != CPP_MINUS_MINUS); |
6132 | /* If we have a template-id, then no further lookup is |
6133 | required. If the template-id was for a template-class, we |
6134 | will sometimes have a TYPE_DECL at this point. */ |
6135 | if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR |
6136 | || TREE_CODE (id_expression) == TYPE_DECL) |
6137 | decl = id_expression; |
6138 | /* Look up the name. */ |
6139 | else |
6140 | { |
6141 | tree ambiguous_decls; |
6142 | |
6143 | /* If we already know that this lookup is ambiguous, then |
6144 | we've already issued an error message; there's no reason |
6145 | to check again. */ |
6146 | if (id_expr_token->type == CPP_NAME |
6147 | && id_expr_token->error_reported) |
6148 | { |
6149 | cp_parser_simulate_error (parser); |
6150 | return error_mark_node; |
6151 | } |
6152 | |
6153 | decl = cp_parser_lookup_name (parser, id_expression, |
6154 | none_type, |
6155 | template_p, |
6156 | /*is_namespace=*/false, |
6157 | /*check_dependency=*/true, |
6158 | &ambiguous_decls, |
6159 | id_expression.get_location ()); |
6160 | /* If the lookup was ambiguous, an error will already have |
6161 | been issued. */ |
6162 | if (ambiguous_decls) |
6163 | return error_mark_node; |
6164 | |
6165 | /* In Objective-C++, we may have an Objective-C 2.0 |
6166 | dot-syntax for classes here. */ |
6167 | if (c_dialect_objc () |
6168 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT |
6169 | && TREE_CODE (decl) == TYPE_DECL |
6170 | && objc_is_class_name (decl)) |
6171 | { |
6172 | tree component; |
6173 | cp_lexer_consume_token (lexer: parser->lexer); |
6174 | component = cp_parser_identifier (parser); |
6175 | if (component == error_mark_node) |
6176 | return error_mark_node; |
6177 | |
6178 | tree result = objc_build_class_component_ref (id_expression, |
6179 | component); |
6180 | /* Build a location of the form: |
6181 | expr.component |
6182 | ~~~~~^~~~~~~~~ |
6183 | with caret at the start of the component name (at |
6184 | input_location), ranging from the start of the id_expression |
6185 | to the end of the component name. */ |
6186 | location_t combined_loc |
6187 | = make_location (caret: input_location, start: id_expression.get_start (), |
6188 | finish: get_finish (loc: input_location)); |
6189 | protected_set_expr_location (result, combined_loc); |
6190 | return result; |
6191 | } |
6192 | |
6193 | /* In Objective-C++, an instance variable (ivar) may be preferred |
6194 | to whatever cp_parser_lookup_name() found. |
6195 | Call objc_lookup_ivar. To avoid exposing cp_expr to the |
6196 | rest of c-family, we have to do a little extra work to preserve |
6197 | any location information in cp_expr "decl". Given that |
6198 | objc_lookup_ivar is implemented in "c-family" and "objc", we |
6199 | have a trip through the pure "tree" type, rather than cp_expr. |
6200 | Naively copying it back to "decl" would implicitly give the |
6201 | new cp_expr value an UNKNOWN_LOCATION for nodes that don't |
6202 | store an EXPR_LOCATION. Hence we only update "decl" (and |
6203 | hence its location_t) if we get back a different tree node. */ |
6204 | tree decl_tree = objc_lookup_ivar (decl.get_value (), |
6205 | id_expression); |
6206 | if (decl_tree != decl.get_value ()) |
6207 | decl = cp_expr (decl_tree); |
6208 | |
6209 | /* If name lookup gives us a SCOPE_REF, then the |
6210 | qualifying scope was dependent. */ |
6211 | if (TREE_CODE (decl) == SCOPE_REF) |
6212 | { |
6213 | /* At this point, we do not know if DECL is a valid |
6214 | integral constant expression. We assume that it is |
6215 | in fact such an expression, so that code like: |
6216 | |
6217 | template <int N> struct A { |
6218 | int a[B<N>::i]; |
6219 | }; |
6220 | |
6221 | is accepted. At template-instantiation time, we |
6222 | will check that B<N>::i is actually a constant. */ |
6223 | return decl; |
6224 | } |
6225 | /* Check to see if DECL is a local variable in a context |
6226 | where that is forbidden. */ |
6227 | if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) |
6228 | && local_variable_p (decl) |
6229 | /* DR 2082 permits local variables in unevaluated contexts |
6230 | within a default argument. */ |
6231 | && !cp_unevaluated_operand) |
6232 | { |
6233 | const char *msg |
6234 | = (TREE_CODE (decl) == PARM_DECL |
6235 | ? G_("parameter %qD may not appear in this context" ) |
6236 | : G_("local variable %qD may not appear in this context" )); |
6237 | error_at (id_expression.get_location (), msg, |
6238 | decl.get_value ()); |
6239 | return error_mark_node; |
6240 | } |
6241 | } |
6242 | |
6243 | decl = (finish_id_expression |
6244 | (id_expression, decl, parser->scope, |
6245 | idk, |
6246 | parser->integral_constant_expression_p, |
6247 | parser->allow_non_integral_constant_expression_p, |
6248 | &parser->non_integral_constant_expression_p, |
6249 | template_p, done, address_p, |
6250 | template_arg_p, |
6251 | &error_msg, |
6252 | id_expression.get_location ())); |
6253 | if (error_msg) |
6254 | cp_parser_error (parser, gmsgid: error_msg); |
6255 | /* Build a location for an id-expression of the form: |
6256 | ::ns::id |
6257 | ~~~~~~^~ |
6258 | or: |
6259 | id |
6260 | ^~ |
6261 | i.e. from the start of the first token to the end of the final |
6262 | token, with the caret at the start of the unqualified-id. */ |
6263 | location_t caret_loc = get_pure_location (loc: id_expression.get_location ()); |
6264 | location_t start_loc = get_start (loc: id_expr_token->location); |
6265 | location_t finish_loc = get_finish (loc: id_expression.get_location ()); |
6266 | location_t combined_loc |
6267 | = make_location (caret: caret_loc, start: start_loc, finish: finish_loc); |
6268 | |
6269 | decl.set_location (combined_loc); |
6270 | return decl; |
6271 | } |
6272 | |
6273 | /* Anything else is an error. */ |
6274 | default: |
6275 | cp_parser_error (parser, gmsgid: "expected primary-expression" ); |
6276 | return error_mark_node; |
6277 | } |
6278 | } |
6279 | |
6280 | static inline cp_expr |
6281 | cp_parser_primary_expression (cp_parser *parser, |
6282 | bool address_p, |
6283 | bool cast_p, |
6284 | bool template_arg_p, |
6285 | cp_id_kind *idk) |
6286 | { |
6287 | return cp_parser_primary_expression (parser, address_p, cast_p, template_arg_p, |
6288 | /*decltype*/decltype_p: false, idk); |
6289 | } |
6290 | |
6291 | /* Complain about missing template keyword when naming a dependent |
6292 | member template. */ |
6293 | |
6294 | static void |
6295 | missing_template_diag (location_t loc, diagnostic_t diag_kind = DK_WARNING) |
6296 | { |
6297 | if (warning_suppressed_at (loc, OPT_Wmissing_template_keyword)) |
6298 | return; |
6299 | |
6300 | gcc_rich_location richloc (loc); |
6301 | richloc.add_fixit_insert_before (new_content: "template" ); |
6302 | emit_diagnostic (diag_kind, &richloc, OPT_Wmissing_template_keyword, |
6303 | "expected %qs keyword before dependent " |
6304 | "template name" , "template" ); |
6305 | suppress_warning_at (loc, OPT_Wmissing_template_keyword); |
6306 | } |
6307 | |
6308 | /* Parse an id-expression. |
6309 | |
6310 | id-expression: |
6311 | unqualified-id |
6312 | qualified-id |
6313 | |
6314 | qualified-id: |
6315 | :: [opt] nested-name-specifier template [opt] unqualified-id |
6316 | :: identifier |
6317 | :: operator-function-id |
6318 | :: template-id |
6319 | |
6320 | Return a representation of the unqualified portion of the |
6321 | identifier. Sets PARSER->SCOPE to the qualifying scope if there is |
6322 | a `::' or nested-name-specifier. |
6323 | |
6324 | Often, if the id-expression was a qualified-id, the caller will |
6325 | want to make a SCOPE_REF to represent the qualified-id. This |
6326 | function does not do this in order to avoid wastefully creating |
6327 | SCOPE_REFs when they are not required. |
6328 | |
6329 | If TEMPLATE_KEYWORD_P is true, then we have just seen the |
6330 | `template' keyword. |
6331 | |
6332 | If CHECK_DEPENDENCY_P is false, then names are looked up inside |
6333 | uninstantiated templates. |
6334 | |
6335 | If *TEMPLATE_P is non-NULL, it is set to true iff the |
6336 | `template' keyword is used to explicitly indicate that the entity |
6337 | named is a template. |
6338 | |
6339 | If DECLARATOR_P is true, the id-expression is appearing as part of |
6340 | a declarator, rather than as part of an expression. */ |
6341 | |
6342 | static cp_expr |
6343 | cp_parser_id_expression (cp_parser *parser, |
6344 | bool template_keyword_p, |
6345 | bool check_dependency_p, |
6346 | bool *template_p, |
6347 | bool declarator_p, |
6348 | bool optional_p) |
6349 | { |
6350 | bool global_scope_p; |
6351 | bool nested_name_specifier_p; |
6352 | |
6353 | /* Assume the `template' keyword was not used. */ |
6354 | if (template_p) |
6355 | *template_p = template_keyword_p; |
6356 | |
6357 | /* Look for the optional `::' operator. */ |
6358 | global_scope_p |
6359 | = (!template_keyword_p |
6360 | && (cp_parser_global_scope_opt (parser, |
6361 | /*current_scope_valid_p=*/false) |
6362 | != NULL_TREE)); |
6363 | |
6364 | /* Look for the optional nested-name-specifier. */ |
6365 | nested_name_specifier_p |
6366 | = (cp_parser_nested_name_specifier_opt (parser, |
6367 | /*typename_keyword_p=*/false, |
6368 | check_dependency_p, |
6369 | /*type_p=*/false, |
6370 | declarator_p, |
6371 | template_keyword_p) |
6372 | != NULL_TREE); |
6373 | |
6374 | cp_expr id = NULL_TREE; |
6375 | tree scope = parser->scope; |
6376 | |
6377 | /* Peek at the next token. */ |
6378 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
6379 | |
6380 | /* If there is a nested-name-specifier, then we are looking at |
6381 | the first qualified-id production. */ |
6382 | if (nested_name_specifier_p) |
6383 | { |
6384 | tree saved_object_scope; |
6385 | tree saved_qualifying_scope; |
6386 | |
6387 | /* See if the next token is the `template' keyword. */ |
6388 | if (!template_p) |
6389 | template_p = &template_keyword_p; |
6390 | *template_p = cp_parser_optional_template_keyword (parser); |
6391 | /* Name lookup we do during the processing of the |
6392 | unqualified-id might obliterate SCOPE. */ |
6393 | saved_object_scope = parser->object_scope; |
6394 | saved_qualifying_scope = parser->qualifying_scope; |
6395 | /* Process the final unqualified-id. */ |
6396 | id = cp_parser_unqualified_id (parser, *template_p, |
6397 | check_dependency_p, |
6398 | declarator_p, |
6399 | /*optional_p=*/false); |
6400 | /* Restore the SAVED_SCOPE for our caller. */ |
6401 | parser->scope = scope; |
6402 | parser->object_scope = saved_object_scope; |
6403 | parser->qualifying_scope = saved_qualifying_scope; |
6404 | } |
6405 | /* Otherwise, if we are in global scope, then we are looking at one |
6406 | of the other qualified-id productions. */ |
6407 | else if (global_scope_p) |
6408 | { |
6409 | /* If it's an identifier, and the next token is not a "<", then |
6410 | we can avoid the template-id case. This is an optimization |
6411 | for this common case. */ |
6412 | if (token->type == CPP_NAME |
6413 | && !cp_parser_nth_token_starts_template_argument_list_p |
6414 | (parser, 2)) |
6415 | return cp_parser_identifier (parser); |
6416 | |
6417 | cp_parser_parse_tentatively (parser); |
6418 | /* Try a template-id. */ |
6419 | id = cp_parser_template_id_expr (parser, |
6420 | /*template_keyword_p=*/false, |
6421 | /*check_dependency_p=*/true, |
6422 | declarator_p); |
6423 | /* If that worked, we're done. */ |
6424 | if (cp_parser_parse_definitely (parser)) |
6425 | return id; |
6426 | |
6427 | /* Peek at the next token. (Changes in the token buffer may |
6428 | have invalidated the pointer obtained above.) */ |
6429 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6430 | |
6431 | switch (token->type) |
6432 | { |
6433 | case CPP_NAME: |
6434 | id = cp_parser_identifier (parser); |
6435 | break; |
6436 | |
6437 | case CPP_KEYWORD: |
6438 | if (token->keyword == RID_OPERATOR) |
6439 | { |
6440 | id = cp_parser_operator_function_id (parser); |
6441 | break; |
6442 | } |
6443 | /* Fall through. */ |
6444 | |
6445 | default: |
6446 | cp_parser_error (parser, gmsgid: "expected id-expression" ); |
6447 | return error_mark_node; |
6448 | } |
6449 | } |
6450 | else |
6451 | { |
6452 | if (!scope) |
6453 | scope = parser->context->object_type; |
6454 | id = cp_parser_unqualified_id (parser, template_keyword_p, |
6455 | /*check_dependency_p=*/true, |
6456 | declarator_p, |
6457 | optional_p); |
6458 | } |
6459 | |
6460 | if (id && TREE_CODE (id) == IDENTIFIER_NODE |
6461 | && warn_missing_template_keyword |
6462 | && !template_keyword_p |
6463 | /* Don't warn if we're looking inside templates. */ |
6464 | && check_dependency_p |
6465 | /* In a template argument list a > could be closing |
6466 | the enclosing targs. */ |
6467 | && !parser->in_template_argument_list_p |
6468 | && scope && dependentish_scope_p (scope) |
6469 | /* Don't confuse an ill-formed constructor declarator for a missing |
6470 | template keyword in a return type. */ |
6471 | && !(declarator_p && constructor_name_p (id, scope)) |
6472 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1) |
6473 | && warning_enabled_at (loc: token->location, |
6474 | opt: OPT_Wmissing_template_keyword)) |
6475 | { |
6476 | saved_token_sentinel toks (parser->lexer, STS_ROLLBACK); |
6477 | if (cp_parser_skip_entire_template_parameter_list (parser) |
6478 | /* An operator after the > suggests that the > ends a |
6479 | template-id; a name or literal suggests that the > is an |
6480 | operator. */ |
6481 | && (cp_lexer_peek_token (lexer: parser->lexer)->type |
6482 | <= CPP_LAST_PUNCTUATOR)) |
6483 | missing_template_diag (loc: token->location); |
6484 | } |
6485 | |
6486 | return id; |
6487 | } |
6488 | |
6489 | /* Parse an unqualified-id. |
6490 | |
6491 | unqualified-id: |
6492 | identifier |
6493 | operator-function-id |
6494 | conversion-function-id |
6495 | ~ class-name |
6496 | template-id |
6497 | |
6498 | If TEMPLATE_KEYWORD_P is TRUE, we have just seen the `template' |
6499 | keyword, in a construct like `A::template ...'. |
6500 | |
6501 | Returns a representation of unqualified-id. For the `identifier' |
6502 | production, an IDENTIFIER_NODE is returned. For the `~ class-name' |
6503 | production a BIT_NOT_EXPR is returned; the operand of the |
6504 | BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the |
6505 | other productions, see the documentation accompanying the |
6506 | corresponding parsing functions. If CHECK_DEPENDENCY_P is false, |
6507 | names are looked up in uninstantiated templates. If DECLARATOR_P |
6508 | is true, the unqualified-id is appearing as part of a declarator, |
6509 | rather than as part of an expression. */ |
6510 | |
6511 | static cp_expr |
6512 | cp_parser_unqualified_id (cp_parser* parser, |
6513 | bool template_keyword_p, |
6514 | bool check_dependency_p, |
6515 | bool declarator_p, |
6516 | bool optional_p) |
6517 | { |
6518 | cp_token *token; |
6519 | |
6520 | /* Peek at the next token. */ |
6521 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6522 | |
6523 | switch ((int) token->type) |
6524 | { |
6525 | case CPP_NAME: |
6526 | { |
6527 | tree id; |
6528 | |
6529 | /* We don't know yet whether or not this will be a |
6530 | template-id. */ |
6531 | cp_parser_parse_tentatively (parser); |
6532 | /* Try a template-id. */ |
6533 | id = cp_parser_template_id_expr (parser, template_keyword_p, |
6534 | check_dependency_p, |
6535 | declarator_p); |
6536 | /* If it worked, we're done. */ |
6537 | if (cp_parser_parse_definitely (parser)) |
6538 | return id; |
6539 | /* Otherwise, it's an ordinary identifier. */ |
6540 | return cp_parser_identifier (parser); |
6541 | } |
6542 | |
6543 | case CPP_TEMPLATE_ID: |
6544 | return cp_parser_template_id_expr (parser, template_keyword_p, |
6545 | check_dependency_p, |
6546 | declarator_p); |
6547 | |
6548 | case CPP_COMPL: |
6549 | { |
6550 | tree type_decl; |
6551 | tree qualifying_scope; |
6552 | tree object_scope; |
6553 | tree scope; |
6554 | bool done; |
6555 | location_t tilde_loc = token->location; |
6556 | |
6557 | /* Consume the `~' token. */ |
6558 | cp_lexer_consume_token (lexer: parser->lexer); |
6559 | /* Parse the class-name. The standard, as written, seems to |
6560 | say that: |
6561 | |
6562 | template <typename T> struct S { ~S (); }; |
6563 | template <typename T> S<T>::~S() {} |
6564 | |
6565 | is invalid, since `~' must be followed by a class-name, but |
6566 | `S<T>' is dependent, and so not known to be a class. |
6567 | That's not right; we need to look in uninstantiated |
6568 | templates. A further complication arises from: |
6569 | |
6570 | template <typename T> void f(T t) { |
6571 | t.T::~T(); |
6572 | } |
6573 | |
6574 | Here, it is not possible to look up `T' in the scope of `T' |
6575 | itself. We must look in both the current scope, and the |
6576 | scope of the containing complete expression. |
6577 | |
6578 | Yet another issue is: |
6579 | |
6580 | struct S { |
6581 | int S; |
6582 | ~S(); |
6583 | }; |
6584 | |
6585 | S::~S() {} |
6586 | |
6587 | The standard does not seem to say that the `S' in `~S' |
6588 | should refer to the type `S' and not the data member |
6589 | `S::S'. */ |
6590 | |
6591 | /* DR 244 says that we look up the name after the "~" in the |
6592 | same scope as we looked up the qualifying name. That idea |
6593 | isn't fully worked out; it's more complicated than that. */ |
6594 | scope = parser->scope; |
6595 | object_scope = parser->object_scope; |
6596 | qualifying_scope = parser->qualifying_scope; |
6597 | |
6598 | /* Check for invalid scopes. */ |
6599 | if (scope == error_mark_node) |
6600 | { |
6601 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
6602 | cp_lexer_consume_token (lexer: parser->lexer); |
6603 | return error_mark_node; |
6604 | } |
6605 | if (scope && TREE_CODE (scope) == NAMESPACE_DECL) |
6606 | { |
6607 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6608 | error_at (token->location, |
6609 | "scope %qT before %<~%> is not a class-name" , |
6610 | scope); |
6611 | cp_parser_simulate_error (parser); |
6612 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
6613 | cp_lexer_consume_token (lexer: parser->lexer); |
6614 | return error_mark_node; |
6615 | } |
6616 | if (template_keyword_p) |
6617 | { |
6618 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6619 | error_at (tilde_loc, "%<template%> keyword not permitted in " |
6620 | "destructor name" ); |
6621 | cp_parser_simulate_error (parser); |
6622 | return error_mark_node; |
6623 | } |
6624 | |
6625 | gcc_assert (!scope || TYPE_P (scope)); |
6626 | |
6627 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6628 | |
6629 | /* Create a location with caret == start at the tilde, |
6630 | finishing at the end of the peeked token, e.g: |
6631 | ~token |
6632 | ^~~~~~. */ |
6633 | location_t loc |
6634 | = make_location (caret: tilde_loc, start: tilde_loc, finish: token->location); |
6635 | |
6636 | /* If the name is of the form "X::~X" it's OK even if X is a |
6637 | typedef. */ |
6638 | |
6639 | if (scope |
6640 | && token->type == CPP_NAME |
6641 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
6642 | != CPP_LESS) |
6643 | && (token->u.value == TYPE_IDENTIFIER (scope) |
6644 | || (CLASS_TYPE_P (scope) |
6645 | && constructor_name_p (token->u.value, scope)))) |
6646 | { |
6647 | cp_lexer_consume_token (lexer: parser->lexer); |
6648 | return build_min_nt_loc (loc, BIT_NOT_EXPR, scope); |
6649 | } |
6650 | |
6651 | /* ~auto means the destructor of whatever the object is. */ |
6652 | if (cp_parser_is_keyword (token, keyword: RID_AUTO)) |
6653 | { |
6654 | if (cxx_dialect < cxx14) |
6655 | pedwarn (loc, OPT_Wc__14_extensions, |
6656 | "%<~auto%> only available with " |
6657 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
6658 | cp_lexer_consume_token (lexer: parser->lexer); |
6659 | return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ()); |
6660 | } |
6661 | |
6662 | /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the |
6663 | declarator-id of a constructor or destructor. */ |
6664 | if (token->type == CPP_TEMPLATE_ID && declarator_p |
6665 | && cxx_dialect >= cxx20) |
6666 | { |
6667 | if (!cp_parser_simulate_error (parser)) |
6668 | error_at (tilde_loc, "template-id not allowed for destructor" ); |
6669 | return error_mark_node; |
6670 | } |
6671 | |
6672 | /* If there was an explicit qualification (S::~T), first look |
6673 | in the scope given by the qualification (i.e., S). |
6674 | |
6675 | Note: in the calls to cp_parser_class_name below we pass |
6676 | typename_type so that lookup finds the injected-class-name |
6677 | rather than the constructor. */ |
6678 | done = false; |
6679 | type_decl = NULL_TREE; |
6680 | if (scope) |
6681 | { |
6682 | cp_parser_parse_tentatively (parser); |
6683 | type_decl = cp_parser_class_name (parser, |
6684 | /*typename_keyword_p=*/false, |
6685 | /*template_keyword_p=*/false, |
6686 | typename_type, |
6687 | /*check_dependency=*/false, |
6688 | /*class_head_p=*/false, |
6689 | declarator_p); |
6690 | if (cp_parser_parse_definitely (parser)) |
6691 | done = true; |
6692 | } |
6693 | /* In "N::S::~S", look in "N" as well. */ |
6694 | if (!done && scope && qualifying_scope) |
6695 | { |
6696 | cp_parser_parse_tentatively (parser); |
6697 | parser->scope = qualifying_scope; |
6698 | parser->object_scope = NULL_TREE; |
6699 | parser->qualifying_scope = NULL_TREE; |
6700 | type_decl |
6701 | = cp_parser_class_name (parser, |
6702 | /*typename_keyword_p=*/false, |
6703 | /*template_keyword_p=*/false, |
6704 | typename_type, |
6705 | /*check_dependency=*/false, |
6706 | /*class_head_p=*/false, |
6707 | declarator_p); |
6708 | if (cp_parser_parse_definitely (parser)) |
6709 | done = true; |
6710 | } |
6711 | /* In "p->S::~T", look in the scope given by "*p" as well. */ |
6712 | else if (!done && object_scope) |
6713 | { |
6714 | cp_parser_parse_tentatively (parser); |
6715 | parser->scope = object_scope; |
6716 | parser->object_scope = NULL_TREE; |
6717 | parser->qualifying_scope = NULL_TREE; |
6718 | type_decl |
6719 | = cp_parser_class_name (parser, |
6720 | /*typename_keyword_p=*/false, |
6721 | /*template_keyword_p=*/false, |
6722 | typename_type, |
6723 | /*check_dependency=*/false, |
6724 | /*class_head_p=*/false, |
6725 | declarator_p); |
6726 | if (cp_parser_parse_definitely (parser)) |
6727 | done = true; |
6728 | } |
6729 | /* Look in the surrounding context. */ |
6730 | if (!done) |
6731 | { |
6732 | parser->scope = NULL_TREE; |
6733 | parser->object_scope = NULL_TREE; |
6734 | parser->qualifying_scope = NULL_TREE; |
6735 | if (processing_template_decl) |
6736 | cp_parser_parse_tentatively (parser); |
6737 | type_decl |
6738 | = cp_parser_class_name (parser, |
6739 | /*typename_keyword_p=*/false, |
6740 | /*template_keyword_p=*/false, |
6741 | typename_type, |
6742 | /*check_dependency=*/false, |
6743 | /*class_head_p=*/false, |
6744 | declarator_p); |
6745 | if (processing_template_decl |
6746 | && ! cp_parser_parse_definitely (parser)) |
6747 | { |
6748 | /* We couldn't find a type with this name. If we're parsing |
6749 | tentatively, fail and try something else. */ |
6750 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6751 | { |
6752 | cp_parser_simulate_error (parser); |
6753 | return error_mark_node; |
6754 | } |
6755 | /* Otherwise, accept it and check for a match at instantiation |
6756 | time. */ |
6757 | type_decl = cp_parser_identifier (parser); |
6758 | if (type_decl != error_mark_node) |
6759 | type_decl = build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl); |
6760 | return type_decl; |
6761 | } |
6762 | } |
6763 | /* If an error occurred, assume that the name of the |
6764 | destructor is the same as the name of the qualifying |
6765 | class. That allows us to keep parsing after running |
6766 | into ill-formed destructor names. */ |
6767 | if (type_decl == error_mark_node && scope) |
6768 | return build_min_nt_loc (loc, BIT_NOT_EXPR, scope); |
6769 | else if (type_decl == error_mark_node) |
6770 | return error_mark_node; |
6771 | |
6772 | /* Check that destructor name and scope match. */ |
6773 | if (declarator_p && scope && !check_dtor_name (scope, type_decl)) |
6774 | { |
6775 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6776 | error_at (loc, |
6777 | "declaration of %<~%T%> as member of %qT" , |
6778 | type_decl, scope); |
6779 | cp_parser_simulate_error (parser); |
6780 | return error_mark_node; |
6781 | } |
6782 | |
6783 | /* [class.dtor] |
6784 | |
6785 | A typedef-name that names a class shall not be used as the |
6786 | identifier in the declarator for a destructor declaration. */ |
6787 | if (declarator_p |
6788 | && !DECL_IMPLICIT_TYPEDEF_P (type_decl) |
6789 | && !DECL_SELF_REFERENCE_P (type_decl) |
6790 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
6791 | error_at (loc, |
6792 | "typedef-name %qD used as destructor declarator" , |
6793 | type_decl); |
6794 | |
6795 | return build_min_nt_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type_decl)); |
6796 | } |
6797 | |
6798 | case CPP_KEYWORD: |
6799 | if (token->keyword == RID_OPERATOR) |
6800 | { |
6801 | cp_expr id; |
6802 | |
6803 | /* This could be a template-id, so we try that first. */ |
6804 | cp_parser_parse_tentatively (parser); |
6805 | /* Try a template-id. */ |
6806 | id = cp_parser_template_id_expr (parser, template_keyword_p, |
6807 | /*check_dependency_p=*/true, |
6808 | declarator_p); |
6809 | /* If that worked, we're done. */ |
6810 | if (cp_parser_parse_definitely (parser)) |
6811 | return id; |
6812 | /* We still don't know whether we're looking at an |
6813 | operator-function-id or a conversion-function-id. */ |
6814 | cp_parser_parse_tentatively (parser); |
6815 | /* Try an operator-function-id. */ |
6816 | id = cp_parser_operator_function_id (parser); |
6817 | /* If that didn't work, try a conversion-function-id. */ |
6818 | if (!cp_parser_parse_definitely (parser)) |
6819 | id = cp_parser_conversion_function_id (parser); |
6820 | |
6821 | return id; |
6822 | } |
6823 | /* Fall through. */ |
6824 | |
6825 | default: |
6826 | if (optional_p) |
6827 | return NULL_TREE; |
6828 | cp_parser_error (parser, gmsgid: "expected unqualified-id" ); |
6829 | return error_mark_node; |
6830 | } |
6831 | } |
6832 | |
6833 | /* Check [temp.names]/5: A name prefixed by the keyword template shall |
6834 | be a template-id or the name shall refer to a class template or an |
6835 | alias template. */ |
6836 | |
6837 | static void |
6838 | check_template_keyword_in_nested_name_spec (tree name) |
6839 | { |
6840 | if (CLASS_TYPE_P (name) |
6841 | && ((CLASSTYPE_USE_TEMPLATE (name) |
6842 | && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (name))) |
6843 | || CLASSTYPE_IS_TEMPLATE (name))) |
6844 | return; |
6845 | |
6846 | if (TREE_CODE (name) == TYPENAME_TYPE |
6847 | && TREE_CODE (TYPENAME_TYPE_FULLNAME (name)) == TEMPLATE_ID_EXPR) |
6848 | return; |
6849 | /* Alias templates are also OK. */ |
6850 | else if (alias_template_specialization_p (name, nt_opaque)) |
6851 | return; |
6852 | |
6853 | permerror (input_location, TYPE_P (name) |
6854 | ? G_("%qT is not a template" ) |
6855 | : G_("%qD is not a template" ), |
6856 | name); |
6857 | } |
6858 | |
6859 | /* Parse an (optional) nested-name-specifier. |
6860 | |
6861 | nested-name-specifier: [C++98] |
6862 | class-or-namespace-name :: nested-name-specifier [opt] |
6863 | class-or-namespace-name :: template nested-name-specifier [opt] |
6864 | |
6865 | nested-name-specifier: [C++0x] |
6866 | type-name :: |
6867 | namespace-name :: |
6868 | nested-name-specifier identifier :: |
6869 | nested-name-specifier template [opt] simple-template-id :: |
6870 | |
6871 | PARSER->SCOPE should be set appropriately before this function is |
6872 | called. TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in |
6873 | effect. TYPE_P is TRUE if we non-type bindings should be ignored |
6874 | in name lookups. |
6875 | |
6876 | Sets PARSER->SCOPE to the class (TYPE) or namespace |
6877 | (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves |
6878 | it unchanged if there is no nested-name-specifier. Returns the new |
6879 | scope iff there is a nested-name-specifier, or NULL_TREE otherwise. |
6880 | |
6881 | If CHECK_DEPENDENCY_P is FALSE, names are looked up in dependent scopes. |
6882 | |
6883 | If IS_DECLARATION is TRUE, the nested-name-specifier is known to be |
6884 | part of a declaration and/or decl-specifier. */ |
6885 | |
6886 | static tree |
6887 | cp_parser_nested_name_specifier_opt (cp_parser *parser, |
6888 | bool typename_keyword_p, |
6889 | bool check_dependency_p, |
6890 | bool type_p, |
6891 | bool is_declaration, |
6892 | bool template_keyword_p /* = false */) |
6893 | { |
6894 | bool success = false; |
6895 | cp_token_position start = 0; |
6896 | cp_token *token; |
6897 | |
6898 | /* Remember where the nested-name-specifier starts. */ |
6899 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
6900 | && cp_lexer_next_token_is_not (lexer: parser->lexer, CPP_NESTED_NAME_SPECIFIER)) |
6901 | { |
6902 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
6903 | push_deferring_access_checks (dk_deferred); |
6904 | } |
6905 | |
6906 | while (true) |
6907 | { |
6908 | tree new_scope; |
6909 | tree old_scope; |
6910 | tree saved_qualifying_scope; |
6911 | |
6912 | /* Spot cases that cannot be the beginning of a |
6913 | nested-name-specifier. */ |
6914 | token = cp_lexer_peek_token (lexer: parser->lexer); |
6915 | |
6916 | /* If the next token is CPP_NESTED_NAME_SPECIFIER, just process |
6917 | the already parsed nested-name-specifier. */ |
6918 | if (token->type == CPP_NESTED_NAME_SPECIFIER) |
6919 | { |
6920 | /* Grab the nested-name-specifier and continue the loop. */ |
6921 | cp_parser_pre_parsed_nested_name_specifier (parser); |
6922 | /* If we originally encountered this nested-name-specifier |
6923 | with CHECK_DEPENDENCY_P set to true, we will not have |
6924 | resolved TYPENAME_TYPEs, so we must do so here. */ |
6925 | if (is_declaration |
6926 | && !check_dependency_p |
6927 | && TREE_CODE (parser->scope) == TYPENAME_TYPE) |
6928 | { |
6929 | new_scope = resolve_typename_type (parser->scope, |
6930 | /*only_current_p=*/false); |
6931 | if (TREE_CODE (new_scope) != TYPENAME_TYPE) |
6932 | parser->scope = new_scope; |
6933 | } |
6934 | success = true; |
6935 | continue; |
6936 | } |
6937 | |
6938 | /* Spot cases that cannot be the beginning of a |
6939 | nested-name-specifier. On the second and subsequent times |
6940 | through the loop, we look for the `template' keyword. */ |
6941 | if (success && token->keyword == RID_TEMPLATE) |
6942 | ; |
6943 | /* A template-id can start a nested-name-specifier. */ |
6944 | else if (token->type == CPP_TEMPLATE_ID) |
6945 | ; |
6946 | /* DR 743: decltype can be used in a nested-name-specifier. */ |
6947 | else if (token_is_decltype (t: token)) |
6948 | ; |
6949 | else |
6950 | { |
6951 | /* If the next token is not an identifier, then it is |
6952 | definitely not a type-name or namespace-name. */ |
6953 | if (token->type != CPP_NAME) |
6954 | break; |
6955 | /* If the following token is neither a `<' (to begin a |
6956 | template-id), nor a `::', then we are not looking at a |
6957 | nested-name-specifier. */ |
6958 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
6959 | |
6960 | if (token->type == CPP_COLON |
6961 | && parser->colon_corrects_to_scope_p |
6962 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_NAME |
6963 | /* name:name is a valid sequence in an Objective C message. */ |
6964 | && !parser->objective_c_message_context_p) |
6965 | { |
6966 | gcc_rich_location richloc (token->location); |
6967 | richloc.add_fixit_replace (new_content: "::" ); |
6968 | error_at (&richloc, |
6969 | "found %<:%> in nested-name-specifier, " |
6970 | "expected %<::%>" ); |
6971 | token->type = CPP_SCOPE; |
6972 | } |
6973 | |
6974 | if (token->type != CPP_SCOPE |
6975 | && !cp_parser_nth_token_starts_template_argument_list_p |
6976 | (parser, 2)) |
6977 | break; |
6978 | } |
6979 | |
6980 | /* The nested-name-specifier is optional, so we parse |
6981 | tentatively. */ |
6982 | cp_parser_parse_tentatively (parser); |
6983 | |
6984 | /* Look for the optional `template' keyword, if this isn't the |
6985 | first time through the loop. */ |
6986 | if (success) |
6987 | { |
6988 | template_keyword_p = cp_parser_optional_template_keyword (parser); |
6989 | /* DR1710: "In a qualified-id used as the name in |
6990 | a typename-specifier, elaborated-type-specifier, using-declaration, |
6991 | or class-or-decltype, an optional keyword template appearing at |
6992 | the top level is ignored." */ |
6993 | if (!template_keyword_p |
6994 | && typename_keyword_p |
6995 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) |
6996 | template_keyword_p = true; |
6997 | } |
6998 | |
6999 | /* Save the old scope since the name lookup we are about to do |
7000 | might destroy it. */ |
7001 | old_scope = parser->scope; |
7002 | saved_qualifying_scope = parser->qualifying_scope; |
7003 | /* In a declarator-id like "X<T>::I::Y<T>" we must be able to |
7004 | look up names in "X<T>::I" in order to determine that "Y" is |
7005 | a template. So, if we have a typename at this point, we make |
7006 | an effort to look through it. */ |
7007 | if (is_declaration |
7008 | && !check_dependency_p |
7009 | && !typename_keyword_p |
7010 | && parser->scope |
7011 | && TREE_CODE (parser->scope) == TYPENAME_TYPE) |
7012 | parser->scope = resolve_typename_type (parser->scope, |
7013 | /*only_current_p=*/false); |
7014 | /* Parse the qualifying entity. */ |
7015 | new_scope |
7016 | = cp_parser_qualifying_entity (parser, |
7017 | typename_keyword_p, |
7018 | template_keyword_p, |
7019 | check_dependency_p, |
7020 | type_p, |
7021 | is_declaration); |
7022 | /* Look for the `::' token. */ |
7023 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
7024 | |
7025 | /* If we found what we wanted, we keep going; otherwise, we're |
7026 | done. */ |
7027 | if (!cp_parser_parse_definitely (parser)) |
7028 | { |
7029 | bool error_p = false; |
7030 | |
7031 | /* Restore the OLD_SCOPE since it was valid before the |
7032 | failed attempt at finding the last |
7033 | class-or-namespace-name. */ |
7034 | parser->scope = old_scope; |
7035 | parser->qualifying_scope = saved_qualifying_scope; |
7036 | |
7037 | /* If the next token is a decltype, and the one after that is a |
7038 | `::', then the decltype has failed to resolve to a class or |
7039 | enumeration type. Give this error even when parsing |
7040 | tentatively since it can't possibly be valid--and we're going |
7041 | to replace it with a CPP_NESTED_NAME_SPECIFIER below, so we |
7042 | won't get another chance.*/ |
7043 | if (cp_lexer_next_token_is (lexer: parser->lexer, CPP_DECLTYPE) |
7044 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
7045 | == CPP_SCOPE)) |
7046 | { |
7047 | token = cp_lexer_consume_token (lexer: parser->lexer); |
7048 | tree dtype = token->u.tree_check_value->value; |
7049 | if (dtype != error_mark_node) |
7050 | error_at (token->location, "%<decltype%> evaluates to %qT, " |
7051 | "which is not a class or enumeration type" , |
7052 | dtype); |
7053 | parser->scope = error_mark_node; |
7054 | error_p = true; |
7055 | /* As below. */ |
7056 | success = true; |
7057 | cp_lexer_consume_token (lexer: parser->lexer); |
7058 | } |
7059 | |
7060 | if (cp_lexer_next_token_is (lexer: parser->lexer, CPP_TEMPLATE_ID) |
7061 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SCOPE)) |
7062 | { |
7063 | /* If we have a non-type template-id followed by ::, it can't |
7064 | possibly be valid. */ |
7065 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7066 | tree tid = token->u.tree_check_value->value; |
7067 | if (TREE_CODE (tid) == TEMPLATE_ID_EXPR |
7068 | && TREE_CODE (TREE_OPERAND (tid, 0)) != IDENTIFIER_NODE) |
7069 | { |
7070 | tree tmpl = NULL_TREE; |
7071 | if (is_overloaded_fn (tid)) |
7072 | { |
7073 | tree fns = get_fns (tid); |
7074 | if (OVL_SINGLE_P (fns)) |
7075 | tmpl = OVL_FIRST (fns); |
7076 | if (function_concept_p (t: fns)) |
7077 | error_at (token->location, "concept-id %qD " |
7078 | "in nested-name-specifier" , tid); |
7079 | else |
7080 | error_at (token->location, "function template-id " |
7081 | "%qD in nested-name-specifier" , tid); |
7082 | } |
7083 | else |
7084 | { |
7085 | tmpl = TREE_OPERAND (tid, 0); |
7086 | if (variable_concept_p (t: tmpl) |
7087 | || standard_concept_p (t: tmpl)) |
7088 | error_at (token->location, "concept-id %qD " |
7089 | "in nested-name-specifier" , tid); |
7090 | else |
7091 | { |
7092 | /* Variable template. */ |
7093 | gcc_assert (variable_template_p (tmpl)); |
7094 | error_at (token->location, "variable template-id " |
7095 | "%qD in nested-name-specifier" , tid); |
7096 | } |
7097 | } |
7098 | if (tmpl) |
7099 | inform (DECL_SOURCE_LOCATION (tmpl), |
7100 | "%qD declared here" , tmpl); |
7101 | |
7102 | parser->scope = error_mark_node; |
7103 | error_p = true; |
7104 | /* As below. */ |
7105 | success = true; |
7106 | cp_lexer_consume_token (lexer: parser->lexer); |
7107 | cp_lexer_consume_token (lexer: parser->lexer); |
7108 | } |
7109 | } |
7110 | |
7111 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
7112 | break; |
7113 | /* If the next token is an identifier, and the one after |
7114 | that is a `::', then any valid interpretation would have |
7115 | found a class-or-namespace-name. */ |
7116 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
7117 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
7118 | == CPP_SCOPE) |
7119 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
7120 | != CPP_COMPL)) |
7121 | { |
7122 | token = cp_lexer_consume_token (lexer: parser->lexer); |
7123 | if (!error_p) |
7124 | { |
7125 | if (!token->error_reported) |
7126 | { |
7127 | tree decl; |
7128 | tree ambiguous_decls; |
7129 | |
7130 | decl = cp_parser_lookup_name (parser, token->u.value, |
7131 | none_type, |
7132 | /*is_template=*/false, |
7133 | /*is_namespace=*/false, |
7134 | /*check_dependency=*/true, |
7135 | &ambiguous_decls, |
7136 | token->location); |
7137 | if (TREE_CODE (decl) == TEMPLATE_DECL) |
7138 | error_at (token->location, |
7139 | "%qD used without template arguments" , |
7140 | decl); |
7141 | else if (ambiguous_decls) |
7142 | { |
7143 | // cp_parser_lookup_name has the same diagnostic, |
7144 | // thus make sure to emit it at most once. |
7145 | if (cp_parser_uncommitted_to_tentative_parse_p |
7146 | (parser)) |
7147 | { |
7148 | error_at (token->location, |
7149 | "reference to %qD is ambiguous" , |
7150 | token->u.value); |
7151 | print_candidates (ambiguous_decls); |
7152 | } |
7153 | decl = error_mark_node; |
7154 | } |
7155 | else |
7156 | { |
7157 | if (cxx_dialect != cxx98) |
7158 | cp_parser_name_lookup_error |
7159 | (parser, name: token->u.value, decl, desired: NLE_NOT_CXX98, |
7160 | location: token->location); |
7161 | else |
7162 | cp_parser_name_lookup_error |
7163 | (parser, name: token->u.value, decl, desired: NLE_CXX98, |
7164 | location: token->location); |
7165 | } |
7166 | } |
7167 | parser->scope = error_mark_node; |
7168 | error_p = true; |
7169 | /* Treat this as a successful nested-name-specifier |
7170 | due to: |
7171 | |
7172 | [basic.lookup.qual] |
7173 | |
7174 | If the name found is not a class-name (clause |
7175 | _class_) or namespace-name (_namespace.def_), the |
7176 | program is ill-formed. */ |
7177 | success = true; |
7178 | } |
7179 | cp_lexer_consume_token (lexer: parser->lexer); |
7180 | } |
7181 | break; |
7182 | } |
7183 | /* We've found one valid nested-name-specifier. */ |
7184 | success = true; |
7185 | /* Name lookup always gives us a DECL. */ |
7186 | if (TREE_CODE (new_scope) == TYPE_DECL) |
7187 | new_scope = TREE_TYPE (new_scope); |
7188 | /* Uses of "template" must be followed by actual templates. */ |
7189 | if (template_keyword_p) |
7190 | check_template_keyword_in_nested_name_spec (name: new_scope); |
7191 | /* If it is a class scope, try to complete it; we are about to |
7192 | be looking up names inside the class. */ |
7193 | if (TYPE_P (new_scope) |
7194 | /* Since checking types for dependency can be expensive, |
7195 | avoid doing it if the type is already complete. */ |
7196 | && !COMPLETE_TYPE_P (new_scope) |
7197 | /* Do not try to complete dependent types. */ |
7198 | && !dependent_type_p (new_scope)) |
7199 | { |
7200 | new_scope = complete_type (new_scope); |
7201 | /* If it is a typedef to current class, use the current |
7202 | class instead, as the typedef won't have any names inside |
7203 | it yet. */ |
7204 | if (!COMPLETE_TYPE_P (new_scope) |
7205 | && currently_open_class (new_scope)) |
7206 | new_scope = TYPE_MAIN_VARIANT (new_scope); |
7207 | } |
7208 | /* Make sure we look in the right scope the next time through |
7209 | the loop. */ |
7210 | parser->scope = new_scope; |
7211 | } |
7212 | |
7213 | /* If parsing tentatively, replace the sequence of tokens that makes |
7214 | up the nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER |
7215 | token. That way, should we re-parse the token stream, we will |
7216 | not have to repeat the effort required to do the parse, nor will |
7217 | we issue duplicate error messages. */ |
7218 | if (success && start) |
7219 | { |
7220 | cp_token *token; |
7221 | |
7222 | token = cp_lexer_token_at (parser->lexer, pos: start); |
7223 | /* Reset the contents of the START token. */ |
7224 | token->type = CPP_NESTED_NAME_SPECIFIER; |
7225 | /* Retrieve any deferred checks. Do not pop this access checks yet |
7226 | so the memory will not be reclaimed during token replacing below. */ |
7227 | token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
7228 | token->tree_check_p = true; |
7229 | token->u.tree_check_value->value = parser->scope; |
7230 | token->u.tree_check_value->checks = get_deferred_access_checks (); |
7231 | token->u.tree_check_value->qualifying_scope = |
7232 | parser->qualifying_scope; |
7233 | token->keyword = RID_MAX; |
7234 | |
7235 | /* Purge all subsequent tokens. */ |
7236 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
7237 | } |
7238 | |
7239 | if (start) |
7240 | pop_to_parent_deferring_access_checks (); |
7241 | |
7242 | return success ? parser->scope : NULL_TREE; |
7243 | } |
7244 | |
7245 | /* Parse a nested-name-specifier. See |
7246 | cp_parser_nested_name_specifier_opt for details. This function |
7247 | behaves identically, except that it will an issue an error if no |
7248 | nested-name-specifier is present. */ |
7249 | |
7250 | static tree |
7251 | cp_parser_nested_name_specifier (cp_parser *parser, |
7252 | bool typename_keyword_p, |
7253 | bool check_dependency_p, |
7254 | bool type_p, |
7255 | bool is_declaration) |
7256 | { |
7257 | tree scope; |
7258 | |
7259 | /* Look for the nested-name-specifier. */ |
7260 | scope = cp_parser_nested_name_specifier_opt (parser, |
7261 | typename_keyword_p, |
7262 | check_dependency_p, |
7263 | type_p, |
7264 | is_declaration); |
7265 | /* If it was not present, issue an error message. */ |
7266 | if (!scope) |
7267 | { |
7268 | cp_parser_error (parser, gmsgid: "expected nested-name-specifier" ); |
7269 | parser->scope = NULL_TREE; |
7270 | } |
7271 | |
7272 | return scope; |
7273 | } |
7274 | |
7275 | /* Parse the qualifying entity in a nested-name-specifier. For C++98, |
7276 | this is either a class-name or a namespace-name (which corresponds |
7277 | to the class-or-namespace-name production in the grammar). For |
7278 | C++0x, it can also be a type-name that refers to an enumeration |
7279 | type or a simple-template-id. |
7280 | |
7281 | TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect. |
7282 | TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect. |
7283 | CHECK_DEPENDENCY_P is FALSE iff dependent names should be looked up. |
7284 | TYPE_P is TRUE iff the next name should be taken as a class-name, |
7285 | even the same name is declared to be another entity in the same |
7286 | scope. |
7287 | |
7288 | Returns the class (TYPE_DECL) or namespace (NAMESPACE_DECL) |
7289 | specified by the class-or-namespace-name. If neither is found the |
7290 | ERROR_MARK_NODE is returned. */ |
7291 | |
7292 | static tree |
7293 | cp_parser_qualifying_entity (cp_parser *parser, |
7294 | bool typename_keyword_p, |
7295 | bool template_keyword_p, |
7296 | bool check_dependency_p, |
7297 | bool type_p, |
7298 | bool is_declaration) |
7299 | { |
7300 | tree saved_scope; |
7301 | tree saved_qualifying_scope; |
7302 | tree saved_object_scope; |
7303 | tree scope; |
7304 | bool only_class_p; |
7305 | bool successful_parse_p; |
7306 | |
7307 | /* DR 743: decltype can appear in a nested-name-specifier. */ |
7308 | if (cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
7309 | { |
7310 | scope = cp_parser_decltype (parser); |
7311 | if (TREE_CODE (scope) != ENUMERAL_TYPE |
7312 | && !MAYBE_CLASS_TYPE_P (scope)) |
7313 | { |
7314 | cp_parser_simulate_error (parser); |
7315 | return error_mark_node; |
7316 | } |
7317 | if (TYPE_NAME (scope)) |
7318 | scope = TYPE_NAME (scope); |
7319 | return scope; |
7320 | } |
7321 | |
7322 | /* Before we try to parse the class-name, we must save away the |
7323 | current PARSER->SCOPE since cp_parser_class_name will destroy |
7324 | it. */ |
7325 | saved_scope = parser->scope; |
7326 | saved_qualifying_scope = parser->qualifying_scope; |
7327 | saved_object_scope = parser->object_scope; |
7328 | /* Try for a class-name first. If the SAVED_SCOPE is a type, then |
7329 | there is no need to look for a namespace-name. */ |
7330 | only_class_p = template_keyword_p |
7331 | || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98); |
7332 | if (!only_class_p) |
7333 | cp_parser_parse_tentatively (parser); |
7334 | scope = cp_parser_class_name (parser, |
7335 | typename_keyword_p, |
7336 | template_keyword_p, |
7337 | type_p ? class_type : none_type, |
7338 | check_dependency_p, |
7339 | /*class_head_p=*/false, |
7340 | is_declaration, |
7341 | /*enum_ok=*/cxx_dialect > cxx98); |
7342 | successful_parse_p = only_class_p || cp_parser_parse_definitely (parser); |
7343 | /* If that didn't work, try for a namespace-name. */ |
7344 | if (!only_class_p && !successful_parse_p) |
7345 | { |
7346 | /* Restore the saved scope. */ |
7347 | parser->scope = saved_scope; |
7348 | parser->qualifying_scope = saved_qualifying_scope; |
7349 | parser->object_scope = saved_object_scope; |
7350 | /* If we are not looking at an identifier followed by the scope |
7351 | resolution operator, then this is not part of a |
7352 | nested-name-specifier. (Note that this function is only used |
7353 | to parse the components of a nested-name-specifier.) */ |
7354 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME) |
7355 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE) |
7356 | return error_mark_node; |
7357 | scope = cp_parser_namespace_name (parser); |
7358 | } |
7359 | |
7360 | return scope; |
7361 | } |
7362 | |
7363 | /* Return true if we are looking at a compound-literal, false otherwise. */ |
7364 | |
7365 | static bool |
7366 | cp_parser_compound_literal_p (cp_parser *parser) |
7367 | { |
7368 | cp_lexer_save_tokens (lexer: parser->lexer); |
7369 | |
7370 | /* Skip tokens until the next token is a closing parenthesis. |
7371 | If we find the closing `)', and the next token is a `{', then |
7372 | we are looking at a compound-literal. */ |
7373 | bool compound_literal_p |
7374 | = (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
7375 | /*consume_paren=*/true) |
7376 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)); |
7377 | |
7378 | /* Roll back the tokens we skipped. */ |
7379 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
7380 | |
7381 | return compound_literal_p; |
7382 | } |
7383 | |
7384 | /* Return true if EXPR is the integer constant zero or a complex constant |
7385 | of zero, without any folding, but ignoring location wrappers. */ |
7386 | |
7387 | bool |
7388 | literal_integer_zerop (const_tree expr) |
7389 | { |
7390 | return (location_wrapper_p (exp: expr) |
7391 | && integer_zerop (TREE_OPERAND (expr, 0))); |
7392 | } |
7393 | |
7394 | /* Parse a postfix-expression. |
7395 | |
7396 | postfix-expression: |
7397 | primary-expression |
7398 | postfix-expression [ expression ] |
7399 | postfix-expression ( expression-list [opt] ) |
7400 | simple-type-specifier ( expression-list [opt] ) |
7401 | typename :: [opt] nested-name-specifier identifier |
7402 | ( expression-list [opt] ) |
7403 | typename :: [opt] nested-name-specifier template [opt] template-id |
7404 | ( expression-list [opt] ) |
7405 | postfix-expression . template [opt] id-expression |
7406 | postfix-expression -> template [opt] id-expression |
7407 | postfix-expression . pseudo-destructor-name |
7408 | postfix-expression -> pseudo-destructor-name |
7409 | postfix-expression ++ |
7410 | postfix-expression -- |
7411 | dynamic_cast < type-id > ( expression ) |
7412 | static_cast < type-id > ( expression ) |
7413 | reinterpret_cast < type-id > ( expression ) |
7414 | const_cast < type-id > ( expression ) |
7415 | typeid ( expression ) |
7416 | typeid ( type-id ) |
7417 | |
7418 | GNU Extension: |
7419 | |
7420 | postfix-expression: |
7421 | ( type-id ) { initializer-list , [opt] } |
7422 | |
7423 | This extension is a GNU version of the C99 compound-literal |
7424 | construct. (The C99 grammar uses `type-name' instead of `type-id', |
7425 | but they are essentially the same concept.) |
7426 | |
7427 | If ADDRESS_P is true, the postfix expression is the operand of the |
7428 | `&' operator. CAST_P is true if this expression is the target of a |
7429 | cast. |
7430 | |
7431 | If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are |
7432 | class member access expressions [expr.ref]. |
7433 | |
7434 | Returns a representation of the expression. */ |
7435 | |
7436 | static cp_expr |
7437 | cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, |
7438 | bool member_access_only_p, bool decltype_p, |
7439 | cp_id_kind * pidk_return) |
7440 | { |
7441 | cp_token *token; |
7442 | location_t loc; |
7443 | enum rid keyword; |
7444 | cp_id_kind idk = CP_ID_KIND_NONE; |
7445 | cp_expr postfix_expression = NULL_TREE; |
7446 | bool is_member_access = false; |
7447 | |
7448 | /* Peek at the next token. */ |
7449 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7450 | loc = token->location; |
7451 | location_t start_loc = get_range_from_loc (set: line_table, loc).m_start; |
7452 | |
7453 | /* Some of the productions are determined by keywords. */ |
7454 | keyword = token->keyword; |
7455 | switch (keyword) |
7456 | { |
7457 | case RID_DYNCAST: |
7458 | case RID_STATCAST: |
7459 | case RID_REINTCAST: |
7460 | case RID_CONSTCAST: |
7461 | { |
7462 | tree type; |
7463 | cp_expr expression; |
7464 | const char *saved_message; |
7465 | bool saved_in_type_id_in_expr_p; |
7466 | |
7467 | /* All of these can be handled in the same way from the point |
7468 | of view of parsing. Begin by consuming the token |
7469 | identifying the cast. */ |
7470 | cp_lexer_consume_token (lexer: parser->lexer); |
7471 | |
7472 | /* New types cannot be defined in the cast. */ |
7473 | saved_message = parser->type_definition_forbidden_message; |
7474 | parser->type_definition_forbidden_message |
7475 | = G_("types may not be defined in casts" ); |
7476 | |
7477 | /* Look for the opening `<'. */ |
7478 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
7479 | /* Parse the type to which we are casting. */ |
7480 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7481 | parser->in_type_id_in_expr_p = true; |
7482 | type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
7483 | NULL); |
7484 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7485 | /* Look for the closing `>'. */ |
7486 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
7487 | /* Restore the old message. */ |
7488 | parser->type_definition_forbidden_message = saved_message; |
7489 | |
7490 | bool saved_greater_than_is_operator_p |
7491 | = parser->greater_than_is_operator_p; |
7492 | parser->greater_than_is_operator_p = true; |
7493 | |
7494 | /* And the expression which is being cast. */ |
7495 | matching_parens parens; |
7496 | parens.require_open (parser); |
7497 | expression = cp_parser_expression (parser, & idk, /*cast_p=*/true); |
7498 | cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, |
7499 | RT_CLOSE_PAREN); |
7500 | location_t end_loc = close_paren ? |
7501 | close_paren->location : UNKNOWN_LOCATION; |
7502 | |
7503 | parser->greater_than_is_operator_p |
7504 | = saved_greater_than_is_operator_p; |
7505 | |
7506 | /* Only type conversions to integral or enumeration types |
7507 | can be used in constant-expressions. */ |
7508 | if (!cast_valid_in_integral_constant_expression_p (type) |
7509 | && cp_parser_non_integral_constant_expression (parser, thing: NIC_CAST)) |
7510 | { |
7511 | postfix_expression = error_mark_node; |
7512 | break; |
7513 | } |
7514 | |
7515 | /* Construct a location e.g. : |
7516 | reinterpret_cast <int *> (expr) |
7517 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
7518 | ranging from the start of the "*_cast" token to the final closing |
7519 | paren, with the caret at the start. */ |
7520 | location_t cp_cast_loc = make_location (caret: start_loc, start: start_loc, finish: end_loc); |
7521 | |
7522 | switch (keyword) |
7523 | { |
7524 | case RID_DYNCAST: |
7525 | postfix_expression |
7526 | = build_dynamic_cast (cp_cast_loc, type, expression, |
7527 | tf_warning_or_error); |
7528 | break; |
7529 | case RID_STATCAST: |
7530 | postfix_expression |
7531 | = build_static_cast (cp_cast_loc, type, expression, |
7532 | tf_warning_or_error); |
7533 | break; |
7534 | case RID_REINTCAST: |
7535 | postfix_expression |
7536 | = build_reinterpret_cast (cp_cast_loc, type, expression, |
7537 | tf_warning_or_error); |
7538 | break; |
7539 | case RID_CONSTCAST: |
7540 | postfix_expression |
7541 | = build_const_cast (cp_cast_loc, type, expression, |
7542 | tf_warning_or_error); |
7543 | break; |
7544 | default: |
7545 | gcc_unreachable (); |
7546 | } |
7547 | } |
7548 | break; |
7549 | |
7550 | case RID_TYPEID: |
7551 | { |
7552 | tree type; |
7553 | const char *saved_message; |
7554 | bool saved_in_type_id_in_expr_p; |
7555 | |
7556 | /* Consume the `typeid' token. */ |
7557 | cp_lexer_consume_token (lexer: parser->lexer); |
7558 | /* Look for the `(' token. */ |
7559 | matching_parens parens; |
7560 | parens.require_open (parser); |
7561 | /* Types cannot be defined in a `typeid' expression. */ |
7562 | saved_message = parser->type_definition_forbidden_message; |
7563 | parser->type_definition_forbidden_message |
7564 | = G_("types may not be defined in a %<typeid%> expression" ); |
7565 | /* We can't be sure yet whether we're looking at a type-id or an |
7566 | expression. */ |
7567 | cp_parser_parse_tentatively (parser); |
7568 | /* Try a type-id first. */ |
7569 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7570 | parser->in_type_id_in_expr_p = true; |
7571 | type = cp_parser_type_id (parser); |
7572 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7573 | /* Look for the `)' token. Otherwise, we can't be sure that |
7574 | we're not looking at an expression: consider `typeid (int |
7575 | (3))', for example. */ |
7576 | cp_token *close_paren = parens.require_close (parser); |
7577 | /* If all went well, simply lookup the type-id. */ |
7578 | if (cp_parser_parse_definitely (parser)) |
7579 | postfix_expression = get_typeid (type, tf_warning_or_error); |
7580 | /* Otherwise, fall back to the expression variant. */ |
7581 | else |
7582 | { |
7583 | tree expression; |
7584 | |
7585 | /* Look for an expression. */ |
7586 | expression = cp_parser_expression (parser, & idk); |
7587 | /* Compute its typeid. */ |
7588 | postfix_expression = build_typeid (expression, tf_warning_or_error); |
7589 | /* Look for the `)' token. */ |
7590 | close_paren = parens.require_close (parser); |
7591 | } |
7592 | /* Restore the saved message. */ |
7593 | parser->type_definition_forbidden_message = saved_message; |
7594 | /* `typeid' may not appear in an integral constant expression. */ |
7595 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_TYPEID)) |
7596 | postfix_expression = error_mark_node; |
7597 | |
7598 | /* Construct a location e.g. : |
7599 | typeid (expr) |
7600 | ^~~~~~~~~~~~~ |
7601 | ranging from the start of the "typeid" token to the final closing |
7602 | paren, with the caret at the start. */ |
7603 | if (close_paren) |
7604 | { |
7605 | location_t typeid_loc |
7606 | = make_location (caret: start_loc, start: start_loc, finish: close_paren->location); |
7607 | postfix_expression.set_location (typeid_loc); |
7608 | postfix_expression.maybe_add_location_wrapper (); |
7609 | } |
7610 | } |
7611 | break; |
7612 | |
7613 | case RID_TYPENAME: |
7614 | { |
7615 | tree type; |
7616 | /* The syntax permitted here is the same permitted for an |
7617 | elaborated-type-specifier. */ |
7618 | ++parser->prevent_constrained_type_specifiers; |
7619 | type = cp_parser_elaborated_type_specifier (parser, |
7620 | /*is_friend=*/false, |
7621 | /*is_declaration=*/false); |
7622 | --parser->prevent_constrained_type_specifiers; |
7623 | postfix_expression = cp_parser_functional_cast (parser, type); |
7624 | } |
7625 | break; |
7626 | |
7627 | case RID_ADDRESSOF: |
7628 | case RID_BUILTIN_SHUFFLE: |
7629 | case RID_BUILTIN_SHUFFLEVECTOR: |
7630 | case RID_BUILTIN_LAUNDER: |
7631 | case RID_BUILTIN_ASSOC_BARRIER: |
7632 | { |
7633 | vec<tree, va_gc> *vec; |
7634 | |
7635 | cp_lexer_consume_token (lexer: parser->lexer); |
7636 | vec = cp_parser_parenthesized_expression_list (parser, non_attr, |
7637 | /*cast_p=*/false, /*allow_expansion_p=*/true, |
7638 | /*non_constant_p=*/NULL); |
7639 | if (vec == NULL) |
7640 | { |
7641 | postfix_expression = error_mark_node; |
7642 | break; |
7643 | } |
7644 | |
7645 | for (tree p : *vec) |
7646 | mark_exp_read (p); |
7647 | |
7648 | switch (keyword) |
7649 | { |
7650 | case RID_ADDRESSOF: |
7651 | if (vec->length () == 1) |
7652 | postfix_expression |
7653 | = cp_build_addressof (loc, (*vec)[0], tf_warning_or_error); |
7654 | else |
7655 | { |
7656 | error_at (loc, "wrong number of arguments to " |
7657 | "%<__builtin_addressof%>" ); |
7658 | postfix_expression = error_mark_node; |
7659 | } |
7660 | break; |
7661 | |
7662 | case RID_BUILTIN_LAUNDER: |
7663 | if (vec->length () == 1) |
7664 | postfix_expression = finish_builtin_launder (loc, (*vec)[0], |
7665 | tf_warning_or_error); |
7666 | else |
7667 | { |
7668 | error_at (loc, "wrong number of arguments to " |
7669 | "%<__builtin_launder%>" ); |
7670 | postfix_expression = error_mark_node; |
7671 | } |
7672 | break; |
7673 | |
7674 | case RID_BUILTIN_ASSOC_BARRIER: |
7675 | if (vec->length () == 1) |
7676 | postfix_expression = build1_loc (loc, code: PAREN_EXPR, |
7677 | TREE_TYPE ((*vec)[0]), |
7678 | arg1: (*vec)[0]); |
7679 | else |
7680 | { |
7681 | error_at (loc, "wrong number of arguments to " |
7682 | "%<__builtin_assoc_barrier%>" ); |
7683 | postfix_expression = error_mark_node; |
7684 | } |
7685 | break; |
7686 | |
7687 | case RID_BUILTIN_SHUFFLE: |
7688 | if (vec->length () == 2) |
7689 | postfix_expression |
7690 | = build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, |
7691 | (*vec)[1], tf_warning_or_error); |
7692 | else if (vec->length () == 3) |
7693 | postfix_expression |
7694 | = build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], |
7695 | (*vec)[2], tf_warning_or_error); |
7696 | else |
7697 | { |
7698 | error_at (loc, "wrong number of arguments to " |
7699 | "%<__builtin_shuffle%>" ); |
7700 | postfix_expression = error_mark_node; |
7701 | } |
7702 | break; |
7703 | |
7704 | case RID_BUILTIN_SHUFFLEVECTOR: |
7705 | if (vec->length () < 3) |
7706 | { |
7707 | error_at (loc, "wrong number of arguments to " |
7708 | "%<__builtin_shufflevector%>" ); |
7709 | postfix_expression = error_mark_node; |
7710 | } |
7711 | else |
7712 | { |
7713 | postfix_expression |
7714 | = build_x_shufflevector (loc, vec, tf_warning_or_error); |
7715 | } |
7716 | break; |
7717 | |
7718 | default: |
7719 | gcc_unreachable (); |
7720 | } |
7721 | break; |
7722 | } |
7723 | |
7724 | case RID_BUILTIN_CONVERTVECTOR: |
7725 | { |
7726 | tree expression; |
7727 | tree type; |
7728 | /* Consume the `__builtin_convertvector' token. */ |
7729 | cp_lexer_consume_token (lexer: parser->lexer); |
7730 | /* Look for the opening `('. */ |
7731 | matching_parens parens; |
7732 | parens.require_open (parser); |
7733 | /* Now, parse the assignment-expression. */ |
7734 | expression = cp_parser_assignment_expression (parser); |
7735 | /* Look for the `,'. */ |
7736 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
7737 | location_t type_location |
7738 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
7739 | /* Parse the type-id. */ |
7740 | { |
7741 | type_id_in_expr_sentinel s (parser); |
7742 | type = cp_parser_type_id (parser); |
7743 | } |
7744 | /* Look for the closing `)'. */ |
7745 | parens.require_close (parser); |
7746 | postfix_expression |
7747 | = cp_build_vec_convert (expression, type_location, type, |
7748 | tf_warning_or_error); |
7749 | break; |
7750 | } |
7751 | |
7752 | case RID_BUILTIN_BIT_CAST: |
7753 | { |
7754 | tree expression; |
7755 | tree type; |
7756 | /* Consume the `__builtin_bit_cast' token. */ |
7757 | cp_lexer_consume_token (lexer: parser->lexer); |
7758 | /* Look for the opening `('. */ |
7759 | matching_parens parens; |
7760 | parens.require_open (parser); |
7761 | location_t type_location |
7762 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
7763 | /* Parse the type-id. */ |
7764 | { |
7765 | type_id_in_expr_sentinel s (parser); |
7766 | type = cp_parser_type_id (parser); |
7767 | } |
7768 | /* Look for the `,'. */ |
7769 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
7770 | /* Now, parse the assignment-expression. */ |
7771 | expression = cp_parser_assignment_expression (parser); |
7772 | /* Look for the closing `)'. */ |
7773 | parens.require_close (parser); |
7774 | postfix_expression |
7775 | = cp_build_bit_cast (type_location, type, expression, |
7776 | tf_warning_or_error); |
7777 | break; |
7778 | } |
7779 | |
7780 | default: |
7781 | { |
7782 | tree type; |
7783 | |
7784 | /* If the next thing is a simple-type-specifier, we may be |
7785 | looking at a functional cast. We could also be looking at |
7786 | an id-expression. So, we try the functional cast, and if |
7787 | that doesn't work we fall back to the primary-expression. */ |
7788 | cp_parser_parse_tentatively (parser); |
7789 | /* Look for the simple-type-specifier. */ |
7790 | ++parser->prevent_constrained_type_specifiers; |
7791 | type = cp_parser_simple_type_specifier (parser, |
7792 | /*decl_specs=*/NULL, |
7793 | CP_PARSER_FLAGS_NONE); |
7794 | --parser->prevent_constrained_type_specifiers; |
7795 | /* Parse the cast itself. */ |
7796 | if (!cp_parser_error_occurred (parser)) |
7797 | postfix_expression |
7798 | = cp_parser_functional_cast (parser, type); |
7799 | /* If that worked, we're done. */ |
7800 | if (cp_parser_parse_definitely (parser)) |
7801 | break; |
7802 | |
7803 | /* If the functional-cast didn't work out, try a |
7804 | compound-literal. */ |
7805 | if (cp_parser_allow_gnu_extensions_p (parser) |
7806 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
7807 | { |
7808 | cp_expr initializer = NULL_TREE; |
7809 | |
7810 | cp_parser_parse_tentatively (parser); |
7811 | |
7812 | matching_parens parens; |
7813 | parens.consume_open (parser); |
7814 | |
7815 | /* Avoid calling cp_parser_type_id pointlessly, see comment |
7816 | in cp_parser_cast_expression about c++/29234. */ |
7817 | if (!cp_parser_compound_literal_p (parser)) |
7818 | cp_parser_simulate_error (parser); |
7819 | else |
7820 | { |
7821 | /* Parse the type. */ |
7822 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
7823 | parser->in_type_id_in_expr_p = true; |
7824 | type = cp_parser_type_id (parser); |
7825 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
7826 | parens.require_close (parser); |
7827 | } |
7828 | |
7829 | /* If things aren't going well, there's no need to |
7830 | keep going. */ |
7831 | if (!cp_parser_error_occurred (parser)) |
7832 | /* Parse the brace-enclosed initializer list. */ |
7833 | initializer = cp_parser_braced_list (parser); |
7834 | /* If that worked, we're definitely looking at a |
7835 | compound-literal expression. */ |
7836 | if (cp_parser_parse_definitely (parser)) |
7837 | { |
7838 | /* Warn the user that a compound literal is not |
7839 | allowed in standard C++. */ |
7840 | pedwarn (input_location, OPT_Wpedantic, |
7841 | "ISO C++ forbids compound-literals" ); |
7842 | /* For simplicity, we disallow compound literals in |
7843 | constant-expressions. We could |
7844 | allow compound literals of integer type, whose |
7845 | initializer was a constant, in constant |
7846 | expressions. Permitting that usage, as a further |
7847 | extension, would not change the meaning of any |
7848 | currently accepted programs. (Of course, as |
7849 | compound literals are not part of ISO C++, the |
7850 | standard has nothing to say.) */ |
7851 | if (cp_parser_non_integral_constant_expression (parser, |
7852 | thing: NIC_NCC)) |
7853 | { |
7854 | postfix_expression = error_mark_node; |
7855 | break; |
7856 | } |
7857 | /* Form the representation of the compound-literal. */ |
7858 | postfix_expression |
7859 | = finish_compound_literal (type, initializer, |
7860 | tf_warning_or_error, fcl_c99); |
7861 | postfix_expression.set_location (initializer.get_location ()); |
7862 | break; |
7863 | } |
7864 | } |
7865 | |
7866 | /* It must be a primary-expression. */ |
7867 | postfix_expression |
7868 | = cp_parser_primary_expression (parser, address_p, cast_p, |
7869 | /*template_arg_p=*/false, |
7870 | decltype_p, |
7871 | idk: &idk); |
7872 | } |
7873 | break; |
7874 | } |
7875 | |
7876 | /* Note that we don't need to worry about calling build_cplus_new on a |
7877 | class-valued CALL_EXPR in decltype when it isn't the end of the |
7878 | postfix-expression; unary_complex_lvalue will take care of that for |
7879 | all these cases. */ |
7880 | |
7881 | /* Keep looping until the postfix-expression is complete. */ |
7882 | while (true) |
7883 | { |
7884 | if (idk == CP_ID_KIND_UNQUALIFIED |
7885 | && identifier_p (t: postfix_expression) |
7886 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
7887 | /* It is not a Koenig lookup function call. */ |
7888 | postfix_expression |
7889 | = unqualified_name_lookup_error (postfix_expression); |
7890 | |
7891 | /* Peek at the next token. */ |
7892 | token = cp_lexer_peek_token (lexer: parser->lexer); |
7893 | |
7894 | switch (token->type) |
7895 | { |
7896 | case CPP_OPEN_SQUARE: |
7897 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
7898 | { |
7899 | cp_parser_error (parser, |
7900 | gmsgid: "two consecutive %<[%> shall " |
7901 | "only introduce an attribute" ); |
7902 | return error_mark_node; |
7903 | } |
7904 | postfix_expression |
7905 | = cp_parser_postfix_open_square_expression (parser, |
7906 | postfix_expression, |
7907 | false, |
7908 | decltype_p); |
7909 | postfix_expression.set_range (start: start_loc, |
7910 | finish: postfix_expression.get_location ()); |
7911 | |
7912 | idk = CP_ID_KIND_NONE; |
7913 | is_member_access = false; |
7914 | break; |
7915 | |
7916 | case CPP_OPEN_PAREN: |
7917 | /* postfix-expression ( expression-list [opt] ) */ |
7918 | { |
7919 | bool koenig_p; |
7920 | bool is_builtin_constant_p; |
7921 | bool saved_integral_constant_expression_p = false; |
7922 | bool saved_non_integral_constant_expression_p = false; |
7923 | tsubst_flags_t complain = complain_flags (decltype_p); |
7924 | vec<tree, va_gc> *args; |
7925 | location_t close_paren_loc = UNKNOWN_LOCATION; |
7926 | location_t combined_loc = UNKNOWN_LOCATION; |
7927 | |
7928 | is_member_access = false; |
7929 | |
7930 | tree stripped_expression |
7931 | = tree_strip_any_location_wrapper (exp: postfix_expression); |
7932 | is_builtin_constant_p |
7933 | = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression); |
7934 | if (is_builtin_constant_p) |
7935 | { |
7936 | /* The whole point of __builtin_constant_p is to allow |
7937 | non-constant expressions to appear as arguments. */ |
7938 | saved_integral_constant_expression_p |
7939 | = parser->integral_constant_expression_p; |
7940 | saved_non_integral_constant_expression_p |
7941 | = parser->non_integral_constant_expression_p; |
7942 | parser->integral_constant_expression_p = false; |
7943 | } |
7944 | else if (TREE_CODE (stripped_expression) == FUNCTION_DECL |
7945 | && fndecl_built_in_p (node: stripped_expression, |
7946 | name1: BUILT_IN_CLASSIFY_TYPE)) |
7947 | { |
7948 | /* __builtin_classify_type (type) */ |
7949 | auto cl1 = make_temp_override |
7950 | (var&: parser->type_definition_forbidden_message, |
7951 | G_("types may not be defined in " |
7952 | "%<__builtin_classify_type%> calls" )); |
7953 | auto cl2 = make_temp_override |
7954 | (var&: parser->type_definition_forbidden_message_arg, |
7955 | NULL); |
7956 | auto cl3 = make_temp_override (var&: parser->in_type_id_in_expr_p, |
7957 | overrider: true); |
7958 | cp_unevaluated uev; |
7959 | cp_parser_parse_tentatively (parser); |
7960 | matching_parens parens; |
7961 | parens.consume_open (parser); |
7962 | tree type = cp_parser_type_id (parser); |
7963 | parens.require_close (parser); |
7964 | if (cp_parser_parse_definitely (parser)) |
7965 | { |
7966 | if (dependent_type_p (type)) |
7967 | { |
7968 | postfix_expression = build_vl_exp (CALL_EXPR, 4); |
7969 | CALL_EXPR_FN (postfix_expression) |
7970 | = stripped_expression; |
7971 | CALL_EXPR_STATIC_CHAIN (postfix_expression) = type; |
7972 | CALL_EXPR_ARG (postfix_expression, 0) |
7973 | = build_min (SIZEOF_EXPR, size_type_node, type); |
7974 | TREE_TYPE (postfix_expression) = integer_type_node; |
7975 | } |
7976 | else |
7977 | { |
7978 | postfix_expression |
7979 | = build_int_cst (integer_type_node, |
7980 | type_to_class (type)); |
7981 | } |
7982 | break; |
7983 | } |
7984 | } |
7985 | args = (cp_parser_parenthesized_expression_list |
7986 | (parser, non_attr, |
7987 | /*cast_p=*/false, /*allow_expansion_p=*/true, |
7988 | /*non_constant_p=*/NULL, |
7989 | /*close_paren_loc=*/&close_paren_loc, |
7990 | /*wrap_locations_p=*/true)); |
7991 | if (is_builtin_constant_p) |
7992 | { |
7993 | parser->integral_constant_expression_p |
7994 | = saved_integral_constant_expression_p; |
7995 | parser->non_integral_constant_expression_p |
7996 | = saved_non_integral_constant_expression_p; |
7997 | } |
7998 | |
7999 | if (args == NULL) |
8000 | { |
8001 | postfix_expression = error_mark_node; |
8002 | break; |
8003 | } |
8004 | |
8005 | /* Function calls are not permitted in |
8006 | constant-expressions. */ |
8007 | if (! builtin_valid_in_constant_expr_p (postfix_expression) |
8008 | && cp_parser_non_integral_constant_expression (parser, |
8009 | thing: NIC_FUNC_CALL)) |
8010 | { |
8011 | postfix_expression = error_mark_node; |
8012 | release_tree_vector (args); |
8013 | break; |
8014 | } |
8015 | |
8016 | koenig_p = false; |
8017 | if (idk == CP_ID_KIND_UNQUALIFIED |
8018 | || idk == CP_ID_KIND_TEMPLATE_ID) |
8019 | { |
8020 | if (identifier_p (t: postfix_expression) |
8021 | /* In C++20, we may need to perform ADL for a template |
8022 | name. */ |
8023 | || (TREE_CODE (postfix_expression) == TEMPLATE_ID_EXPR |
8024 | && identifier_p (TREE_OPERAND (postfix_expression, 0)))) |
8025 | { |
8026 | if (!args->is_empty ()) |
8027 | { |
8028 | koenig_p = true; |
8029 | if (!any_type_dependent_arguments_p (args)) |
8030 | postfix_expression |
8031 | = perform_koenig_lookup (postfix_expression, args, |
8032 | complain); |
8033 | } |
8034 | else |
8035 | postfix_expression |
8036 | = unqualified_fn_lookup_error (postfix_expression); |
8037 | } |
8038 | /* We do not perform argument-dependent lookup if |
8039 | normal lookup finds a non-function, in accordance |
8040 | with the expected resolution of DR 218. */ |
8041 | else if (!args->is_empty () |
8042 | && is_overloaded_fn (postfix_expression)) |
8043 | { |
8044 | /* Do not do argument dependent lookup if regular |
8045 | lookup finds a member function or a block-scope |
8046 | function declaration. [basic.lookup.argdep]/3 */ |
8047 | bool do_adl_p = true; |
8048 | tree fns = get_fns (postfix_expression); |
8049 | for (lkp_iterator iter (fns); iter; ++iter) |
8050 | { |
8051 | tree fn = STRIP_TEMPLATE (*iter); |
8052 | if ((TREE_CODE (fn) == USING_DECL |
8053 | && DECL_DEPENDENT_P (fn)) |
8054 | || DECL_FUNCTION_MEMBER_P (fn) |
8055 | || DECL_LOCAL_DECL_P (fn)) |
8056 | { |
8057 | do_adl_p = false; |
8058 | break; |
8059 | } |
8060 | } |
8061 | |
8062 | if (do_adl_p) |
8063 | { |
8064 | koenig_p = true; |
8065 | if (!any_type_dependent_arguments_p (args)) |
8066 | postfix_expression |
8067 | = perform_koenig_lookup (postfix_expression, args, |
8068 | complain); |
8069 | } |
8070 | } |
8071 | } |
8072 | |
8073 | /* Temporarily set input_location to the combined location |
8074 | with call expression range, as e.g. build_out_target_exprs |
8075 | called from convert_default_arg relies on input_location, |
8076 | so updating it only when the call is fully built results |
8077 | in inconsistencies between location handling in templates |
8078 | and outside of templates. */ |
8079 | if (close_paren_loc != UNKNOWN_LOCATION) |
8080 | combined_loc = make_location (caret: token->location, start: start_loc, |
8081 | finish: close_paren_loc); |
8082 | iloc_sentinel ils (combined_loc); |
8083 | |
8084 | if (TREE_CODE (postfix_expression) == OFFSET_REF |
8085 | || TREE_CODE (postfix_expression) == MEMBER_REF |
8086 | || TREE_CODE (postfix_expression) == DOTSTAR_EXPR) |
8087 | postfix_expression = (build_offset_ref_call_from_tree |
8088 | (postfix_expression, &args, |
8089 | complain)); |
8090 | else |
8091 | /* All other function calls. */ |
8092 | { |
8093 | if (DECL_P (postfix_expression) |
8094 | && parser->omp_for_parse_state |
8095 | && parser->omp_for_parse_state->in_intervening_code |
8096 | && omp_runtime_api_call (fndecl: postfix_expression)) |
8097 | { |
8098 | error_at (loc, "calls to the OpenMP runtime API are " |
8099 | "not permitted in intervening code" ); |
8100 | parser->omp_for_parse_state->fail = true; |
8101 | } |
8102 | bool disallow_virtual = (idk == CP_ID_KIND_QUALIFIED); |
8103 | postfix_expression |
8104 | = finish_call_expr (postfix_expression, &args, |
8105 | disallow_virtual, |
8106 | koenig_p, |
8107 | complain); |
8108 | } |
8109 | |
8110 | if (close_paren_loc != UNKNOWN_LOCATION) |
8111 | postfix_expression.set_location (combined_loc); |
8112 | |
8113 | /* The POSTFIX_EXPRESSION is certainly no longer an id. */ |
8114 | idk = CP_ID_KIND_NONE; |
8115 | |
8116 | release_tree_vector (args); |
8117 | } |
8118 | break; |
8119 | |
8120 | case CPP_DOT: |
8121 | case CPP_DEREF: |
8122 | /* postfix-expression . template [opt] id-expression |
8123 | postfix-expression . pseudo-destructor-name |
8124 | postfix-expression -> template [opt] id-expression |
8125 | postfix-expression -> pseudo-destructor-name */ |
8126 | |
8127 | /* Consume the `.' or `->' operator. */ |
8128 | cp_lexer_consume_token (lexer: parser->lexer); |
8129 | |
8130 | postfix_expression |
8131 | = cp_parser_postfix_dot_deref_expression (parser, token->type, |
8132 | postfix_expression, |
8133 | false, &idk, loc); |
8134 | |
8135 | is_member_access = true; |
8136 | break; |
8137 | |
8138 | case CPP_PLUS_PLUS: |
8139 | /* postfix-expression ++ */ |
8140 | /* Consume the `++' token. */ |
8141 | cp_lexer_consume_token (lexer: parser->lexer); |
8142 | /* Generate a representation for the complete expression. */ |
8143 | postfix_expression |
8144 | = finish_increment_expr (postfix_expression, |
8145 | POSTINCREMENT_EXPR); |
8146 | /* Increments may not appear in constant-expressions. */ |
8147 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_INC)) |
8148 | postfix_expression = error_mark_node; |
8149 | idk = CP_ID_KIND_NONE; |
8150 | is_member_access = false; |
8151 | break; |
8152 | |
8153 | case CPP_MINUS_MINUS: |
8154 | /* postfix-expression -- */ |
8155 | /* Consume the `--' token. */ |
8156 | cp_lexer_consume_token (lexer: parser->lexer); |
8157 | /* Generate a representation for the complete expression. */ |
8158 | postfix_expression |
8159 | = finish_increment_expr (postfix_expression, |
8160 | POSTDECREMENT_EXPR); |
8161 | /* Decrements may not appear in constant-expressions. */ |
8162 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_DEC)) |
8163 | postfix_expression = error_mark_node; |
8164 | idk = CP_ID_KIND_NONE; |
8165 | is_member_access = false; |
8166 | break; |
8167 | |
8168 | default: |
8169 | if (pidk_return != NULL) |
8170 | * pidk_return = idk; |
8171 | if (member_access_only_p) |
8172 | return is_member_access |
8173 | ? postfix_expression |
8174 | : cp_expr (error_mark_node); |
8175 | else |
8176 | return postfix_expression; |
8177 | } |
8178 | } |
8179 | } |
8180 | |
8181 | /* Helper function for cp_parser_parenthesized_expression_list and |
8182 | cp_parser_postfix_open_square_expression. Parse a single element |
8183 | of parenthesized expression list. */ |
8184 | |
8185 | static cp_expr |
8186 | cp_parser_parenthesized_expression_list_elt (cp_parser *parser, bool cast_p, |
8187 | bool allow_expansion_p, |
8188 | bool *non_constant_p) |
8189 | { |
8190 | cp_expr expr (NULL_TREE); |
8191 | bool expr_non_constant_p; |
8192 | |
8193 | /* Parse the next assignment-expression. */ |
8194 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
8195 | { |
8196 | /* A braced-init-list. */ |
8197 | cp_lexer_set_source_position (lexer: parser->lexer); |
8198 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
8199 | expr = cp_parser_braced_list (parser, |
8200 | (non_constant_p != nullptr |
8201 | ? &expr_non_constant_p |
8202 | : nullptr)); |
8203 | if (non_constant_p && expr_non_constant_p) |
8204 | *non_constant_p = true; |
8205 | } |
8206 | else if (non_constant_p) |
8207 | { |
8208 | expr = cp_parser_constant_expression (parser, |
8209 | /*allow_non_constant_p=*/true, |
8210 | &expr_non_constant_p); |
8211 | if (expr_non_constant_p) |
8212 | *non_constant_p = true; |
8213 | } |
8214 | else |
8215 | expr = cp_parser_assignment_expression (parser, /*pidk=*/NULL, cast_p); |
8216 | |
8217 | /* If we have an ellipsis, then this is an expression expansion. */ |
8218 | if (allow_expansion_p |
8219 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
8220 | { |
8221 | /* Consume the `...'. */ |
8222 | cp_lexer_consume_token (lexer: parser->lexer); |
8223 | |
8224 | /* Build the argument pack. */ |
8225 | expr = make_pack_expansion (expr); |
8226 | } |
8227 | return expr; |
8228 | } |
8229 | |
8230 | /* A subroutine of cp_parser_postfix_expression that also gets hijacked |
8231 | by cp_parser_builtin_offsetof. We're looking for |
8232 | |
8233 | postfix-expression [ expression ] |
8234 | postfix-expression [ braced-init-list ] (C++11) |
8235 | postfix-expression [ expression-list[opt] ] (C++23) |
8236 | |
8237 | FOR_OFFSETOF is set if we're being called in that context, which |
8238 | changes how we deal with integer constant expressions. */ |
8239 | |
8240 | static tree |
8241 | cp_parser_postfix_open_square_expression (cp_parser *parser, |
8242 | tree postfix_expression, |
8243 | bool for_offsetof, |
8244 | bool decltype_p) |
8245 | { |
8246 | tree index = NULL_TREE; |
8247 | releasing_vec expression_list = NULL; |
8248 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
8249 | bool saved_greater_than_is_operator_p; |
8250 | |
8251 | /* Consume the `[' token. */ |
8252 | cp_lexer_consume_token (lexer: parser->lexer); |
8253 | |
8254 | saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; |
8255 | parser->greater_than_is_operator_p = true; |
8256 | |
8257 | /* Parse the index expression. */ |
8258 | /* ??? For offsetof, there is a question of what to allow here. If |
8259 | offsetof is not being used in an integral constant expression context, |
8260 | then we *could* get the right answer by computing the value at runtime. |
8261 | If we are in an integral constant expression context, then we might |
8262 | could accept any constant expression; hard to say without analysis. |
8263 | Rather than open the barn door too wide right away, allow only integer |
8264 | constant expressions here. */ |
8265 | if (for_offsetof) |
8266 | index = cp_parser_constant_expression (parser); |
8267 | else |
8268 | { |
8269 | if (cxx_dialect >= cxx23 |
8270 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
8271 | *&expression_list = make_tree_vector (); |
8272 | else if (cxx_dialect >= cxx23) |
8273 | { |
8274 | while (true) |
8275 | { |
8276 | cp_expr expr |
8277 | = cp_parser_parenthesized_expression_list_elt (parser, |
8278 | /*cast_p=*/ |
8279 | false, |
8280 | /*allow_exp_p=*/ |
8281 | allow_expansion_p: true, |
8282 | /*non_cst_p=*/ |
8283 | NULL); |
8284 | |
8285 | if (expr == error_mark_node) |
8286 | index = error_mark_node; |
8287 | else if (expression_list.get () == NULL |
8288 | && !PACK_EXPANSION_P (expr.get_value ())) |
8289 | index = expr.get_value (); |
8290 | else |
8291 | vec_safe_push (r&: expression_list, t: expr.get_value ()); |
8292 | |
8293 | /* If the next token isn't a `,', then we are done. */ |
8294 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
8295 | break; |
8296 | |
8297 | if (expression_list.get () == NULL && index != error_mark_node) |
8298 | { |
8299 | *&expression_list = make_tree_vector_single (index); |
8300 | index = NULL_TREE; |
8301 | } |
8302 | |
8303 | /* Otherwise, consume the `,' and keep going. */ |
8304 | cp_lexer_consume_token (lexer: parser->lexer); |
8305 | } |
8306 | if (expression_list.get () && index == error_mark_node) |
8307 | expression_list.release (); |
8308 | } |
8309 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
8310 | { |
8311 | cp_lexer_set_source_position (lexer: parser->lexer); |
8312 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
8313 | index = cp_parser_braced_list (parser); |
8314 | } |
8315 | else |
8316 | index = cp_parser_expression (parser, NULL, /*cast_p=*/false, |
8317 | /*decltype_p=*/false, |
8318 | /*warn_comma_p=*/warn_comma_subscript); |
8319 | } |
8320 | |
8321 | parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; |
8322 | |
8323 | /* Look for the closing `]'. */ |
8324 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
8325 | |
8326 | /* Build the ARRAY_REF. */ |
8327 | postfix_expression = grok_array_decl (loc, postfix_expression, |
8328 | index, &expression_list, |
8329 | tf_warning_or_error |
8330 | | (decltype_p ? tf_decltype : 0)); |
8331 | |
8332 | /* When not doing offsetof, array references are not permitted in |
8333 | constant-expressions. */ |
8334 | if (!for_offsetof |
8335 | && (cp_parser_non_integral_constant_expression (parser, thing: NIC_ARRAY_REF))) |
8336 | postfix_expression = error_mark_node; |
8337 | |
8338 | return postfix_expression; |
8339 | } |
8340 | |
8341 | /* A subroutine of cp_parser_postfix_dot_deref_expression. Handle dot |
8342 | dereference of incomplete type, returns true if error_mark_node should |
8343 | be returned from caller, otherwise adjusts *SCOPE, *POSTFIX_EXPRESSION |
8344 | and *DEPENDENT_P. */ |
8345 | |
8346 | bool |
8347 | cp_parser_dot_deref_incomplete (tree *scope, cp_expr *postfix_expression, |
8348 | bool *dependent_p) |
8349 | { |
8350 | /* In a template, be permissive by treating an object expression |
8351 | of incomplete type as dependent (after a pedwarn). */ |
8352 | diagnostic_t kind = (processing_template_decl |
8353 | && MAYBE_CLASS_TYPE_P (*scope) ? DK_PEDWARN : DK_ERROR); |
8354 | |
8355 | switch (TREE_CODE (*postfix_expression)) |
8356 | { |
8357 | case CAST_EXPR: |
8358 | case REINTERPRET_CAST_EXPR: |
8359 | case CONST_CAST_EXPR: |
8360 | case STATIC_CAST_EXPR: |
8361 | case DYNAMIC_CAST_EXPR: |
8362 | case IMPLICIT_CONV_EXPR: |
8363 | case VIEW_CONVERT_EXPR: |
8364 | case NON_LVALUE_EXPR: |
8365 | kind = DK_ERROR; |
8366 | break; |
8367 | case OVERLOAD: |
8368 | /* Don't emit any diagnostic for OVERLOADs. */ |
8369 | kind = DK_IGNORED; |
8370 | break; |
8371 | default: |
8372 | /* Avoid clobbering e.g. DECLs. */ |
8373 | if (!EXPR_P (*postfix_expression)) |
8374 | kind = DK_ERROR; |
8375 | break; |
8376 | } |
8377 | |
8378 | if (kind == DK_IGNORED) |
8379 | return false; |
8380 | |
8381 | location_t exploc = location_of (*postfix_expression); |
8382 | cxx_incomplete_type_diagnostic (exploc, *postfix_expression, *scope, kind); |
8383 | if (!MAYBE_CLASS_TYPE_P (*scope)) |
8384 | return true; |
8385 | if (kind == DK_ERROR) |
8386 | *scope = *postfix_expression = error_mark_node; |
8387 | else if (processing_template_decl) |
8388 | { |
8389 | *dependent_p = true; |
8390 | *scope = TREE_TYPE (*postfix_expression) = NULL_TREE; |
8391 | } |
8392 | return false; |
8393 | } |
8394 | |
8395 | /* A subroutine of cp_parser_postfix_expression that also gets hijacked |
8396 | by cp_parser_builtin_offsetof. We're looking for |
8397 | |
8398 | postfix-expression . template [opt] id-expression |
8399 | postfix-expression . pseudo-destructor-name |
8400 | postfix-expression -> template [opt] id-expression |
8401 | postfix-expression -> pseudo-destructor-name |
8402 | |
8403 | FOR_OFFSETOF is set if we're being called in that context. That sorta |
8404 | limits what of the above we'll actually accept, but nevermind. |
8405 | TOKEN_TYPE is the "." or "->" token, which will already have been |
8406 | removed from the stream. */ |
8407 | |
8408 | static tree |
8409 | cp_parser_postfix_dot_deref_expression (cp_parser *parser, |
8410 | enum cpp_ttype token_type, |
8411 | cp_expr postfix_expression, |
8412 | bool for_offsetof, cp_id_kind *idk, |
8413 | location_t location) |
8414 | { |
8415 | tree name; |
8416 | bool dependent_p; |
8417 | bool pseudo_destructor_p; |
8418 | tree scope = NULL_TREE; |
8419 | location_t start_loc = postfix_expression.get_start (); |
8420 | |
8421 | /* If this is a `->' operator, dereference the pointer. */ |
8422 | if (token_type == CPP_DEREF) |
8423 | postfix_expression = build_x_arrow (location, postfix_expression, |
8424 | tf_warning_or_error); |
8425 | /* Check to see whether or not the expression is type-dependent and |
8426 | not the current instantiation. */ |
8427 | dependent_p = type_dependent_object_expression_p (postfix_expression); |
8428 | /* The identifier following the `->' or `.' is not qualified. */ |
8429 | parser->scope = NULL_TREE; |
8430 | parser->qualifying_scope = NULL_TREE; |
8431 | parser->object_scope = NULL_TREE; |
8432 | *idk = CP_ID_KIND_NONE; |
8433 | |
8434 | /* Enter the scope corresponding to the type of the object |
8435 | given by the POSTFIX_EXPRESSION. */ |
8436 | if (!dependent_p) |
8437 | { |
8438 | scope = TREE_TYPE (postfix_expression); |
8439 | /* According to the standard, no expression should ever have |
8440 | reference type. Unfortunately, we do not currently match |
8441 | the standard in this respect in that our internal representation |
8442 | of an expression may have reference type even when the standard |
8443 | says it does not. Therefore, we have to manually obtain the |
8444 | underlying type here. */ |
8445 | scope = non_reference (scope); |
8446 | /* The type of the POSTFIX_EXPRESSION must be complete. */ |
8447 | /* Unlike the object expression in other contexts, *this is not |
8448 | required to be of complete type for purposes of class member |
8449 | access (5.2.5) outside the member function body. */ |
8450 | if (postfix_expression != current_class_ref |
8451 | && scope != error_mark_node |
8452 | && !currently_open_class (scope)) |
8453 | { |
8454 | scope = complete_type (scope); |
8455 | if (!COMPLETE_TYPE_P (scope) |
8456 | && cp_parser_dot_deref_incomplete (scope: &scope, postfix_expression: &postfix_expression, |
8457 | dependent_p: &dependent_p)) |
8458 | return error_mark_node; |
8459 | } |
8460 | |
8461 | if (!dependent_p) |
8462 | { |
8463 | /* Let the name lookup machinery know that we are processing a |
8464 | class member access expression. */ |
8465 | parser->context->object_type = scope; |
8466 | /* If something went wrong, we want to be able to discern that case, |
8467 | as opposed to the case where there was no SCOPE due to the type |
8468 | of expression being dependent. */ |
8469 | if (!scope) |
8470 | scope = error_mark_node; |
8471 | /* If the SCOPE was erroneous, make the various semantic analysis |
8472 | functions exit quickly -- and without issuing additional error |
8473 | messages. */ |
8474 | if (scope == error_mark_node) |
8475 | postfix_expression = error_mark_node; |
8476 | } |
8477 | } |
8478 | |
8479 | if (dependent_p) |
8480 | { |
8481 | tree type = TREE_TYPE (postfix_expression); |
8482 | /* If we don't have a (type-dependent) object of class type, use |
8483 | typeof to figure out the type of the object. */ |
8484 | if (type == NULL_TREE || is_auto (type)) |
8485 | type = finish_typeof (postfix_expression); |
8486 | parser->context->object_type = type; |
8487 | } |
8488 | |
8489 | /* Assume this expression is not a pseudo-destructor access. */ |
8490 | pseudo_destructor_p = false; |
8491 | |
8492 | /* If the SCOPE is a scalar type, then, if this is a valid program, |
8493 | we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION |
8494 | is type dependent, it can be pseudo-destructor-name or something else. |
8495 | Try to parse it as pseudo-destructor-name first. */ |
8496 | if ((scope && SCALAR_TYPE_P (scope)) || dependent_p) |
8497 | { |
8498 | tree s; |
8499 | tree type; |
8500 | |
8501 | cp_parser_parse_tentatively (parser); |
8502 | /* Parse the pseudo-destructor-name. */ |
8503 | s = NULL_TREE; |
8504 | cp_parser_pseudo_destructor_name (parser, postfix_expression, |
8505 | &s, &type); |
8506 | if (dependent_p |
8507 | && (cp_parser_error_occurred (parser) |
8508 | || !SCALAR_TYPE_P (type))) |
8509 | cp_parser_abort_tentative_parse (parser); |
8510 | else if (cp_parser_parse_definitely (parser)) |
8511 | { |
8512 | pseudo_destructor_p = true; |
8513 | postfix_expression |
8514 | = finish_pseudo_destructor_expr (postfix_expression, |
8515 | s, type, location); |
8516 | } |
8517 | } |
8518 | |
8519 | if (!pseudo_destructor_p) |
8520 | { |
8521 | /* If the SCOPE is not a scalar type, we are looking at an |
8522 | ordinary class member access expression, rather than a |
8523 | pseudo-destructor-name. */ |
8524 | bool template_p; |
8525 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
8526 | /* Parse the id-expression. */ |
8527 | name = (cp_parser_id_expression |
8528 | (parser, |
8529 | template_keyword_p: cp_parser_optional_template_keyword (parser), |
8530 | /*check_dependency_p=*/true, |
8531 | template_p: &template_p, |
8532 | /*declarator_p=*/false, |
8533 | /*optional_p=*/false)); |
8534 | /* In general, build a SCOPE_REF if the member name is qualified. |
8535 | However, if the name was not dependent and has already been |
8536 | resolved; there is no need to build the SCOPE_REF. For example; |
8537 | |
8538 | struct X { void f(); }; |
8539 | template <typename T> void f(T* t) { t->X::f(); } |
8540 | |
8541 | Even though "t" is dependent, "X::f" is not and has been resolved |
8542 | to a BASELINK; there is no need to include scope information. */ |
8543 | |
8544 | /* But we do need to remember that there was an explicit scope for |
8545 | virtual function calls. */ |
8546 | if (parser->scope) |
8547 | *idk = CP_ID_KIND_QUALIFIED; |
8548 | |
8549 | /* If the name is a template-id that names a type, we will get a |
8550 | TYPE_DECL here. That is invalid code. */ |
8551 | if (TREE_CODE (name) == TYPE_DECL) |
8552 | { |
8553 | error_at (token->location, "invalid use of %qD" , name); |
8554 | postfix_expression = error_mark_node; |
8555 | } |
8556 | else |
8557 | { |
8558 | if (name != error_mark_node && !BASELINK_P (name) && parser->scope) |
8559 | { |
8560 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
8561 | { |
8562 | error_at (token->location, "%<%D::%D%> is not a class member" , |
8563 | parser->scope, name); |
8564 | postfix_expression = error_mark_node; |
8565 | } |
8566 | else |
8567 | name = build_qualified_name (/*type=*/NULL_TREE, |
8568 | parser->scope, |
8569 | name, |
8570 | template_p); |
8571 | parser->scope = NULL_TREE; |
8572 | parser->qualifying_scope = NULL_TREE; |
8573 | parser->object_scope = NULL_TREE; |
8574 | } |
8575 | if (parser->scope && name && BASELINK_P (name)) |
8576 | adjust_result_of_qualified_name_lookup |
8577 | (name, parser->scope, scope); |
8578 | postfix_expression |
8579 | = finish_class_member_access_expr (postfix_expression, name, |
8580 | template_p, |
8581 | tf_warning_or_error); |
8582 | /* Build a location e.g.: |
8583 | ptr->access_expr |
8584 | ~~~^~~~~~~~~~~~~ |
8585 | where the caret is at the deref token, ranging from |
8586 | the start of postfix_expression to the end of the access expr. */ |
8587 | location_t combined_loc |
8588 | = make_location (caret: input_location, start: start_loc, lexer: parser->lexer); |
8589 | protected_set_expr_location (postfix_expression, combined_loc); |
8590 | } |
8591 | } |
8592 | |
8593 | /* We no longer need to look up names in the scope of the object on |
8594 | the left-hand side of the `.' or `->' operator. */ |
8595 | parser->context->object_type = NULL_TREE; |
8596 | |
8597 | /* Outside of offsetof, these operators may not appear in |
8598 | constant-expressions. */ |
8599 | if (!for_offsetof |
8600 | && (cp_parser_non_integral_constant_expression |
8601 | (parser, thing: token_type == CPP_DEREF ? NIC_ARROW : NIC_POINT))) |
8602 | postfix_expression = error_mark_node; |
8603 | |
8604 | return postfix_expression; |
8605 | } |
8606 | |
8607 | /* Parse a parenthesized expression-list. |
8608 | |
8609 | expression-list: |
8610 | assignment-expression |
8611 | expression-list, assignment-expression |
8612 | |
8613 | attribute-list: |
8614 | expression-list |
8615 | identifier |
8616 | identifier, expression-list |
8617 | |
8618 | CAST_P is true if this expression is the target of a cast. |
8619 | |
8620 | ALLOW_EXPANSION_P is true if this expression allows expansion of an |
8621 | argument pack. |
8622 | |
8623 | WRAP_LOCATIONS_P is true if expressions within this list for which |
8624 | CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing |
8625 | their source locations. |
8626 | |
8627 | Returns a vector of trees. Each element is a representation of an |
8628 | assignment-expression. NULL is returned if the ( and or ) are |
8629 | missing. An empty, but allocated, vector is returned on no |
8630 | expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is id_attr |
8631 | if we are parsing an attribute list for an attribute that wants a |
8632 | plain identifier argument, normal_attr for an attribute that wants |
8633 | an expression, or non_attr if we aren't parsing an attribute list. If |
8634 | NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or |
8635 | not all of the expressions in the list were constant. |
8636 | If CLOSE_PAREN_LOC is non-NULL, and no errors occur, then *CLOSE_PAREN_LOC |
8637 | will be written to with the location of the closing parenthesis. If |
8638 | an error occurs, it may or may not be written to. */ |
8639 | |
8640 | static vec<tree, va_gc> * |
8641 | cp_parser_parenthesized_expression_list (cp_parser* parser, |
8642 | int is_attribute_list, |
8643 | bool cast_p, |
8644 | bool allow_expansion_p, |
8645 | bool *non_constant_p, |
8646 | location_t *close_paren_loc, |
8647 | bool wrap_locations_p) |
8648 | { |
8649 | vec<tree, va_gc> *expression_list; |
8650 | bool saved_greater_than_is_operator_p; |
8651 | |
8652 | /* Assume all the expressions will be constant. */ |
8653 | if (non_constant_p) |
8654 | *non_constant_p = false; |
8655 | |
8656 | matching_parens parens; |
8657 | if (!parens.require_open (parser)) |
8658 | return NULL; |
8659 | |
8660 | expression_list = make_tree_vector (); |
8661 | |
8662 | /* Within a parenthesized expression, a `>' token is always |
8663 | the greater-than operator. */ |
8664 | saved_greater_than_is_operator_p |
8665 | = parser->greater_than_is_operator_p; |
8666 | parser->greater_than_is_operator_p = true; |
8667 | |
8668 | cp_expr expr (NULL_TREE); |
8669 | |
8670 | /* Consume expressions until there are no more. */ |
8671 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
8672 | while (true) |
8673 | { |
8674 | /* At the beginning of attribute lists, check to see if the |
8675 | next token is an identifier. */ |
8676 | if (is_attribute_list == id_attr |
8677 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_NAME) |
8678 | expr = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
8679 | else if (is_attribute_list == assume_attr) |
8680 | expr = cp_parser_conditional_expression (parser); |
8681 | else if (is_attribute_list == uneval_string_attr) |
8682 | expr = cp_parser_unevaluated_string_literal (parser); |
8683 | else |
8684 | expr |
8685 | = cp_parser_parenthesized_expression_list_elt (parser, cast_p, |
8686 | allow_expansion_p, |
8687 | non_constant_p); |
8688 | |
8689 | if (wrap_locations_p) |
8690 | expr.maybe_add_location_wrapper (); |
8691 | |
8692 | /* Add it to the list. We add error_mark_node |
8693 | expressions to the list, so that we can still tell if |
8694 | the correct form for a parenthesized expression-list |
8695 | is found. That gives better errors. */ |
8696 | vec_safe_push (v&: expression_list, obj: expr.get_value ()); |
8697 | |
8698 | if (expr == error_mark_node) |
8699 | goto skip_comma; |
8700 | |
8701 | /* After the first item, attribute lists look the same as |
8702 | expression lists. */ |
8703 | is_attribute_list = non_attr; |
8704 | |
8705 | get_comma:; |
8706 | /* If the next token isn't a `,', then we are done. */ |
8707 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
8708 | break; |
8709 | |
8710 | /* Otherwise, consume the `,' and keep going. */ |
8711 | cp_lexer_consume_token (lexer: parser->lexer); |
8712 | } |
8713 | |
8714 | if (close_paren_loc) |
8715 | *close_paren_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
8716 | |
8717 | if (!parens.require_close (parser)) |
8718 | { |
8719 | int ending; |
8720 | |
8721 | skip_comma:; |
8722 | /* We try and resync to an unnested comma, as that will give the |
8723 | user better diagnostics. */ |
8724 | ending = cp_parser_skip_to_closing_parenthesis (parser, |
8725 | /*recovering=*/true, |
8726 | /*or_comma=*/true, |
8727 | /*consume_paren=*/true); |
8728 | if (ending < 0) |
8729 | goto get_comma; |
8730 | if (!ending) |
8731 | { |
8732 | parser->greater_than_is_operator_p |
8733 | = saved_greater_than_is_operator_p; |
8734 | return NULL; |
8735 | } |
8736 | } |
8737 | |
8738 | parser->greater_than_is_operator_p |
8739 | = saved_greater_than_is_operator_p; |
8740 | |
8741 | return expression_list; |
8742 | } |
8743 | |
8744 | /* Parse a pseudo-destructor-name. |
8745 | |
8746 | pseudo-destructor-name: |
8747 | :: [opt] nested-name-specifier [opt] type-name :: ~ type-name |
8748 | :: [opt] nested-name-specifier template template-id :: ~ type-name |
8749 | :: [opt] nested-name-specifier [opt] ~ type-name |
8750 | |
8751 | If either of the first two productions is used, sets *SCOPE to the |
8752 | TYPE specified before the final `::'. Otherwise, *SCOPE is set to |
8753 | NULL_TREE. *TYPE is set to the TYPE_DECL for the final type-name, |
8754 | or ERROR_MARK_NODE if the parse fails. */ |
8755 | |
8756 | static void |
8757 | cp_parser_pseudo_destructor_name (cp_parser* parser, |
8758 | tree object, |
8759 | tree* scope, |
8760 | tree* type) |
8761 | { |
8762 | bool nested_name_specifier_p; |
8763 | |
8764 | /* Handle ~auto. */ |
8765 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMPL) |
8766 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_AUTO) |
8767 | && !type_dependent_expression_p (object)) |
8768 | { |
8769 | if (cxx_dialect < cxx14) |
8770 | pedwarn (input_location, OPT_Wc__14_extensions, |
8771 | "%<~auto%> only available with " |
8772 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
8773 | cp_lexer_consume_token (lexer: parser->lexer); |
8774 | cp_lexer_consume_token (lexer: parser->lexer); |
8775 | *scope = NULL_TREE; |
8776 | *type = TREE_TYPE (object); |
8777 | return; |
8778 | } |
8779 | |
8780 | /* Assume that things will not work out. */ |
8781 | *type = error_mark_node; |
8782 | |
8783 | /* Look for the optional `::' operator. */ |
8784 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true); |
8785 | /* Look for the optional nested-name-specifier. */ |
8786 | nested_name_specifier_p |
8787 | = (cp_parser_nested_name_specifier_opt (parser, |
8788 | /*typename_keyword_p=*/false, |
8789 | /*check_dependency_p=*/true, |
8790 | /*type_p=*/false, |
8791 | /*is_declaration=*/false) |
8792 | != NULL_TREE); |
8793 | /* Now, if we saw a nested-name-specifier, we might be doing the |
8794 | second production. */ |
8795 | if (nested_name_specifier_p |
8796 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
8797 | { |
8798 | /* Consume the `template' keyword. */ |
8799 | cp_lexer_consume_token (lexer: parser->lexer); |
8800 | /* Parse the template-id. */ |
8801 | cp_parser_template_id (parser, |
8802 | /*template_keyword_p=*/true, |
8803 | /*check_dependency_p=*/false, |
8804 | class_type, |
8805 | /*is_declaration=*/true); |
8806 | /* Look for the `::' token. */ |
8807 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
8808 | } |
8809 | /* If the next token is not a `~', then there might be some |
8810 | additional qualification. */ |
8811 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMPL)) |
8812 | { |
8813 | /* At this point, we're looking for "type-name :: ~". The type-name |
8814 | must not be a class-name, since this is a pseudo-destructor. So, |
8815 | it must be either an enum-name, or a typedef-name -- both of which |
8816 | are just identifiers. So, we peek ahead to check that the "::" |
8817 | and "~" tokens are present; if they are not, then we can avoid |
8818 | calling type_name. */ |
8819 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_NAME |
8820 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE |
8821 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type != CPP_COMPL) |
8822 | { |
8823 | cp_parser_error (parser, gmsgid: "non-scalar type" ); |
8824 | return; |
8825 | } |
8826 | |
8827 | /* Look for the type-name. */ |
8828 | *scope = TREE_TYPE (cp_parser_nonclass_name (parser)); |
8829 | if (*scope == error_mark_node) |
8830 | return; |
8831 | |
8832 | /* Look for the `::' token. */ |
8833 | cp_parser_require (parser, CPP_SCOPE, RT_SCOPE); |
8834 | } |
8835 | else |
8836 | *scope = NULL_TREE; |
8837 | |
8838 | /* Look for the `~'. */ |
8839 | cp_parser_require (parser, CPP_COMPL, RT_COMPL); |
8840 | |
8841 | /* Once we see the ~, this has to be a pseudo-destructor. */ |
8842 | if (!processing_template_decl && !cp_parser_error_occurred (parser)) |
8843 | cp_parser_commit_to_topmost_tentative_parse (parser); |
8844 | |
8845 | /* Look for the type-name again. We are not responsible for |
8846 | checking that it matches the first type-name. */ |
8847 | *type = TREE_TYPE (cp_parser_nonclass_name (parser)); |
8848 | } |
8849 | |
8850 | /* Parse a unary-expression. |
8851 | |
8852 | unary-expression: |
8853 | postfix-expression |
8854 | ++ cast-expression |
8855 | -- cast-expression |
8856 | await-expression |
8857 | unary-operator cast-expression |
8858 | sizeof unary-expression |
8859 | sizeof ( type-id ) |
8860 | alignof ( type-id ) [C++0x] |
8861 | new-expression |
8862 | delete-expression |
8863 | |
8864 | GNU Extensions: |
8865 | |
8866 | unary-expression: |
8867 | __extension__ cast-expression |
8868 | __alignof__ unary-expression |
8869 | __alignof__ ( type-id ) |
8870 | alignof unary-expression [C++0x] |
8871 | __real__ cast-expression |
8872 | __imag__ cast-expression |
8873 | && identifier |
8874 | sizeof ( type-id ) { initializer-list , [opt] } |
8875 | alignof ( type-id ) { initializer-list , [opt] } [C++0x] |
8876 | __alignof__ ( type-id ) { initializer-list , [opt] } |
8877 | |
8878 | ADDRESS_P is true iff the unary-expression is appearing as the |
8879 | operand of the `&' operator. CAST_P is true if this expression is |
8880 | the target of a cast. |
8881 | |
8882 | Returns a representation of the expression. */ |
8883 | |
8884 | static cp_expr |
8885 | cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, |
8886 | bool address_p, bool cast_p, bool decltype_p) |
8887 | { |
8888 | cp_token *token; |
8889 | enum tree_code unary_operator; |
8890 | |
8891 | /* Peek at the next token. */ |
8892 | token = cp_lexer_peek_token (lexer: parser->lexer); |
8893 | /* Some keywords give away the kind of expression. */ |
8894 | if (token->type == CPP_KEYWORD) |
8895 | { |
8896 | enum rid keyword = token->keyword; |
8897 | |
8898 | switch (keyword) |
8899 | { |
8900 | case RID_ALIGNOF: |
8901 | case RID_SIZEOF: |
8902 | { |
8903 | tree operand, ret; |
8904 | enum tree_code op; |
8905 | location_t start_loc = token->location; |
8906 | |
8907 | op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; |
8908 | bool std_alignof = id_equal (id: token->u.value, str: "alignof" ); |
8909 | |
8910 | /* Consume the token. */ |
8911 | cp_lexer_consume_token (lexer: parser->lexer); |
8912 | /* Parse the operand. */ |
8913 | operand = cp_parser_sizeof_operand (parser, keyword); |
8914 | |
8915 | /* Construct a location e.g. : |
8916 | alignof (expr) |
8917 | ^~~~~~~~~~~~~~ |
8918 | with start == caret at the start of the "alignof"/"sizeof" |
8919 | token, with the endpoint at the final closing paren. */ |
8920 | location_t compound_loc |
8921 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
8922 | |
8923 | if (TYPE_P (operand)) |
8924 | ret = cxx_sizeof_or_alignof_type (compound_loc, operand, op, |
8925 | std_alignof, true); |
8926 | else |
8927 | { |
8928 | /* ISO C++ defines alignof only with types, not with |
8929 | expressions. So pedwarn if alignof is used with a non- |
8930 | type expression. However, __alignof__ is ok. */ |
8931 | if (std_alignof) |
8932 | pedwarn (token->location, OPT_Wpedantic, |
8933 | "ISO C++ does not allow %<alignof%> " |
8934 | "with a non-type" ); |
8935 | |
8936 | ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op, |
8937 | std_alignof, true); |
8938 | } |
8939 | /* For SIZEOF_EXPR, just issue diagnostics, but keep |
8940 | SIZEOF_EXPR with the original operand. */ |
8941 | if (op == SIZEOF_EXPR && ret != error_mark_node) |
8942 | { |
8943 | if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand)) |
8944 | { |
8945 | if (!processing_template_decl && TYPE_P (operand)) |
8946 | { |
8947 | ret = build_min (SIZEOF_EXPR, size_type_node, |
8948 | build1 (NOP_EXPR, operand, |
8949 | error_mark_node)); |
8950 | SIZEOF_EXPR_TYPE_P (ret) = 1; |
8951 | } |
8952 | else |
8953 | ret = build_min (SIZEOF_EXPR, size_type_node, operand); |
8954 | TREE_SIDE_EFFECTS (ret) = 0; |
8955 | TREE_READONLY (ret) = 1; |
8956 | SET_EXPR_LOCATION (ret, compound_loc); |
8957 | } |
8958 | } |
8959 | |
8960 | cp_expr ret_expr (ret, compound_loc); |
8961 | ret_expr = ret_expr.maybe_add_location_wrapper (); |
8962 | return ret_expr; |
8963 | } |
8964 | |
8965 | case RID_BUILTIN_HAS_ATTRIBUTE: |
8966 | return cp_parser_has_attribute_expression (parser); |
8967 | |
8968 | case RID_NEW: |
8969 | return cp_parser_new_expression (parser); |
8970 | |
8971 | case RID_DELETE: |
8972 | return cp_parser_delete_expression (parser); |
8973 | |
8974 | case RID_EXTENSION: |
8975 | { |
8976 | /* The saved value of the PEDANTIC flag. */ |
8977 | int saved_pedantic; |
8978 | tree expr; |
8979 | |
8980 | /* Save away the PEDANTIC flag. */ |
8981 | cp_parser_extension_opt (parser, &saved_pedantic); |
8982 | /* Parse the cast-expression. */ |
8983 | expr = cp_parser_simple_cast_expression (parser); |
8984 | /* Restore the PEDANTIC flag. */ |
8985 | pedantic = saved_pedantic; |
8986 | |
8987 | return expr; |
8988 | } |
8989 | |
8990 | case RID_REALPART: |
8991 | case RID_IMAGPART: |
8992 | { |
8993 | tree expression; |
8994 | |
8995 | /* Consume the `__real__' or `__imag__' token. */ |
8996 | cp_lexer_consume_token (lexer: parser->lexer); |
8997 | /* Parse the cast-expression. */ |
8998 | expression = cp_parser_simple_cast_expression (parser); |
8999 | /* Create the complete representation. */ |
9000 | return build_x_unary_op (token->location, |
9001 | (keyword == RID_REALPART |
9002 | ? REALPART_EXPR : IMAGPART_EXPR), |
9003 | expression, NULL_TREE, |
9004 | tf_warning_or_error); |
9005 | } |
9006 | break; |
9007 | |
9008 | case RID_TRANSACTION_ATOMIC: |
9009 | case RID_TRANSACTION_RELAXED: |
9010 | return cp_parser_transaction_expression (parser, keyword); |
9011 | |
9012 | case RID_NOEXCEPT: |
9013 | { |
9014 | tree expr; |
9015 | const char *saved_message; |
9016 | bool saved_integral_constant_expression_p; |
9017 | bool saved_non_integral_constant_expression_p; |
9018 | bool saved_greater_than_is_operator_p; |
9019 | |
9020 | location_t start_loc = token->location; |
9021 | |
9022 | cp_lexer_consume_token (lexer: parser->lexer); |
9023 | matching_parens parens; |
9024 | parens.require_open (parser); |
9025 | |
9026 | saved_message = parser->type_definition_forbidden_message; |
9027 | parser->type_definition_forbidden_message |
9028 | = G_("types may not be defined in %<noexcept%> expressions" ); |
9029 | |
9030 | saved_integral_constant_expression_p |
9031 | = parser->integral_constant_expression_p; |
9032 | saved_non_integral_constant_expression_p |
9033 | = parser->non_integral_constant_expression_p; |
9034 | parser->integral_constant_expression_p = false; |
9035 | |
9036 | saved_greater_than_is_operator_p |
9037 | = parser->greater_than_is_operator_p; |
9038 | parser->greater_than_is_operator_p = true; |
9039 | |
9040 | ++cp_unevaluated_operand; |
9041 | ++c_inhibit_evaluation_warnings; |
9042 | ++cp_noexcept_operand; |
9043 | expr = cp_parser_expression (parser); |
9044 | --cp_noexcept_operand; |
9045 | --c_inhibit_evaluation_warnings; |
9046 | --cp_unevaluated_operand; |
9047 | |
9048 | parser->greater_than_is_operator_p |
9049 | = saved_greater_than_is_operator_p; |
9050 | |
9051 | parser->integral_constant_expression_p |
9052 | = saved_integral_constant_expression_p; |
9053 | parser->non_integral_constant_expression_p |
9054 | = saved_non_integral_constant_expression_p; |
9055 | |
9056 | parser->type_definition_forbidden_message = saved_message; |
9057 | |
9058 | parens.require_close (parser); |
9059 | |
9060 | /* Construct a location of the form: |
9061 | noexcept (expr) |
9062 | ^~~~~~~~~~~~~~~ |
9063 | with start == caret, finishing at the close-paren. */ |
9064 | location_t noexcept_loc |
9065 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9066 | |
9067 | return cp_expr (finish_noexcept_expr (expr, tf_warning_or_error), |
9068 | noexcept_loc); |
9069 | } |
9070 | |
9071 | case RID_CO_AWAIT: |
9072 | { |
9073 | tree expr; |
9074 | location_t kw_loc = token->location; |
9075 | |
9076 | /* Consume the `co_await' token. */ |
9077 | cp_lexer_consume_token (lexer: parser->lexer); |
9078 | /* Parse its cast-expression. */ |
9079 | expr = cp_parser_simple_cast_expression (parser); |
9080 | if (expr == error_mark_node) |
9081 | return error_mark_node; |
9082 | |
9083 | /* Handle [expr.await]. */ |
9084 | return cp_expr (finish_co_await_expr (kw_loc, expr)); |
9085 | } |
9086 | |
9087 | default: |
9088 | break; |
9089 | } |
9090 | } |
9091 | |
9092 | /* Look for the `:: new' and `:: delete', which also signal the |
9093 | beginning of a new-expression, or delete-expression, |
9094 | respectively. If the next token is `::', then it might be one of |
9095 | these. */ |
9096 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
9097 | { |
9098 | enum rid keyword; |
9099 | |
9100 | /* See if the token after the `::' is one of the keywords in |
9101 | which we're interested. */ |
9102 | keyword = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->keyword; |
9103 | /* If it's `new', we have a new-expression. */ |
9104 | if (keyword == RID_NEW) |
9105 | return cp_parser_new_expression (parser); |
9106 | /* Similarly, for `delete'. */ |
9107 | else if (keyword == RID_DELETE) |
9108 | return cp_parser_delete_expression (parser); |
9109 | } |
9110 | |
9111 | /* Look for a unary operator. */ |
9112 | unary_operator = cp_parser_unary_operator (token); |
9113 | /* The `++' and `--' operators can be handled similarly, even though |
9114 | they are not technically unary-operators in the grammar. */ |
9115 | if (unary_operator == ERROR_MARK) |
9116 | { |
9117 | if (token->type == CPP_PLUS_PLUS) |
9118 | unary_operator = PREINCREMENT_EXPR; |
9119 | else if (token->type == CPP_MINUS_MINUS) |
9120 | unary_operator = PREDECREMENT_EXPR; |
9121 | /* Handle the GNU address-of-label extension. */ |
9122 | else if (cp_parser_allow_gnu_extensions_p (parser) |
9123 | && token->type == CPP_AND_AND) |
9124 | { |
9125 | tree identifier; |
9126 | tree expression; |
9127 | location_t start_loc = token->location; |
9128 | |
9129 | /* Consume the '&&' token. */ |
9130 | cp_lexer_consume_token (lexer: parser->lexer); |
9131 | /* Look for the identifier. */ |
9132 | identifier = cp_parser_identifier (parser); |
9133 | /* Construct a location of the form: |
9134 | &&label |
9135 | ^~~~~~~ |
9136 | with caret==start at the "&&", finish at the end of the label. */ |
9137 | location_t combined_loc |
9138 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9139 | /* Create an expression representing the address. */ |
9140 | expression = finish_label_address_expr (identifier, combined_loc); |
9141 | if (cp_parser_non_integral_constant_expression (parser, |
9142 | thing: NIC_ADDR_LABEL)) |
9143 | expression = error_mark_node; |
9144 | return expression; |
9145 | } |
9146 | } |
9147 | if (unary_operator != ERROR_MARK) |
9148 | { |
9149 | cp_expr cast_expression; |
9150 | cp_expr expression = error_mark_node; |
9151 | non_integral_constant non_constant_p = NIC_NONE; |
9152 | location_t loc = token->location; |
9153 | tsubst_flags_t complain = complain_flags (decltype_p); |
9154 | |
9155 | /* Consume the operator token. */ |
9156 | token = cp_lexer_consume_token (lexer: parser->lexer); |
9157 | enum cpp_ttype op_ttype = cp_lexer_peek_token (lexer: parser->lexer)->type; |
9158 | |
9159 | /* Parse the cast-expression. */ |
9160 | cast_expression |
9161 | = cp_parser_cast_expression (parser, |
9162 | unary_operator == ADDR_EXPR, |
9163 | /*cast_p=*/false, |
9164 | /*decltype*/false, |
9165 | pidk); |
9166 | |
9167 | /* Make a location: |
9168 | OP_TOKEN CAST_EXPRESSION |
9169 | ^~~~~~~~~~~~~~~~~~~~~~~~~ |
9170 | with start==caret at the operator token, and |
9171 | extending to the end of the cast_expression. */ |
9172 | loc = make_location (caret: loc, start: loc, finish: cast_expression.get_finish ()); |
9173 | |
9174 | /* Now, build an appropriate representation. */ |
9175 | switch (unary_operator) |
9176 | { |
9177 | case INDIRECT_REF: |
9178 | non_constant_p = NIC_STAR; |
9179 | expression = build_x_indirect_ref (loc, cast_expression, |
9180 | RO_UNARY_STAR, NULL_TREE, |
9181 | complain); |
9182 | /* TODO: build_x_indirect_ref does not always honor the |
9183 | location, so ensure it is set. */ |
9184 | expression.set_location (loc); |
9185 | break; |
9186 | |
9187 | case ADDR_EXPR: |
9188 | non_constant_p = NIC_ADDR; |
9189 | /* Fall through. */ |
9190 | case BIT_NOT_EXPR: |
9191 | expression = build_x_unary_op (loc, unary_operator, |
9192 | cast_expression, |
9193 | NULL_TREE, complain); |
9194 | /* TODO: build_x_unary_op does not always honor the location, |
9195 | so ensure it is set. */ |
9196 | expression.set_location (loc); |
9197 | break; |
9198 | |
9199 | case PREINCREMENT_EXPR: |
9200 | case PREDECREMENT_EXPR: |
9201 | non_constant_p = unary_operator == PREINCREMENT_EXPR |
9202 | ? NIC_PREINCREMENT : NIC_PREDECREMENT; |
9203 | /* Fall through. */ |
9204 | case NEGATE_EXPR: |
9205 | /* Immediately fold negation of a constant, unless the constant is 0 |
9206 | (since -0 == 0) or it would overflow. */ |
9207 | if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER) |
9208 | { |
9209 | tree stripped_expr |
9210 | = tree_strip_any_location_wrapper (exp: cast_expression); |
9211 | if (CONSTANT_CLASS_P (stripped_expr) |
9212 | && !integer_zerop (stripped_expr) |
9213 | && !TREE_OVERFLOW (stripped_expr)) |
9214 | { |
9215 | tree folded = fold_build1 (unary_operator, |
9216 | TREE_TYPE (stripped_expr), |
9217 | stripped_expr); |
9218 | if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded)) |
9219 | { |
9220 | expression = maybe_wrap_with_location (folded, loc); |
9221 | break; |
9222 | } |
9223 | } |
9224 | } |
9225 | /* Fall through. */ |
9226 | case UNARY_PLUS_EXPR: |
9227 | case TRUTH_NOT_EXPR: |
9228 | expression = finish_unary_op_expr (loc, unary_operator, |
9229 | cast_expression, complain); |
9230 | break; |
9231 | |
9232 | default: |
9233 | gcc_unreachable (); |
9234 | } |
9235 | |
9236 | if (non_constant_p != NIC_NONE |
9237 | && cp_parser_non_integral_constant_expression (parser, |
9238 | thing: non_constant_p)) |
9239 | expression = error_mark_node; |
9240 | |
9241 | return expression; |
9242 | } |
9243 | |
9244 | return cp_parser_postfix_expression (parser, address_p, cast_p, |
9245 | /*member_access_only_p=*/false, |
9246 | decltype_p, |
9247 | pidk_return: pidk); |
9248 | } |
9249 | |
9250 | /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a |
9251 | unary-operator, the corresponding tree code is returned. */ |
9252 | |
9253 | static enum tree_code |
9254 | cp_parser_unary_operator (cp_token* token) |
9255 | { |
9256 | switch (token->type) |
9257 | { |
9258 | case CPP_MULT: |
9259 | return INDIRECT_REF; |
9260 | |
9261 | case CPP_AND: |
9262 | return ADDR_EXPR; |
9263 | |
9264 | case CPP_PLUS: |
9265 | return UNARY_PLUS_EXPR; |
9266 | |
9267 | case CPP_MINUS: |
9268 | return NEGATE_EXPR; |
9269 | |
9270 | case CPP_NOT: |
9271 | return TRUTH_NOT_EXPR; |
9272 | |
9273 | case CPP_COMPL: |
9274 | return BIT_NOT_EXPR; |
9275 | |
9276 | default: |
9277 | return ERROR_MARK; |
9278 | } |
9279 | } |
9280 | |
9281 | /* Parse a __builtin_has_attribute([expr|type], attribute-spec) expression. |
9282 | Returns a representation of the expression. */ |
9283 | |
9284 | static tree |
9285 | cp_parser_has_attribute_expression (cp_parser *parser) |
9286 | { |
9287 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9288 | |
9289 | /* Consume the __builtin_has_attribute token. */ |
9290 | cp_lexer_consume_token (lexer: parser->lexer); |
9291 | |
9292 | matching_parens parens; |
9293 | if (!parens.require_open (parser)) |
9294 | return error_mark_node; |
9295 | |
9296 | /* Types cannot be defined in a `sizeof' expression. Save away the |
9297 | old message. */ |
9298 | const char *saved_message = parser->type_definition_forbidden_message; |
9299 | const char *saved_message_arg |
9300 | = parser->type_definition_forbidden_message_arg; |
9301 | parser->type_definition_forbidden_message |
9302 | = G_("types may not be defined in %qs expressions" ); |
9303 | parser->type_definition_forbidden_message_arg |
9304 | = IDENTIFIER_POINTER (ridpointers[RID_BUILTIN_HAS_ATTRIBUTE]); |
9305 | |
9306 | /* The restrictions on constant-expressions do not apply inside |
9307 | sizeof expressions. */ |
9308 | bool saved_integral_constant_expression_p |
9309 | = parser->integral_constant_expression_p; |
9310 | bool saved_non_integral_constant_expression_p |
9311 | = parser->non_integral_constant_expression_p; |
9312 | parser->integral_constant_expression_p = false; |
9313 | |
9314 | /* Do not actually evaluate the expression. */ |
9315 | ++cp_unevaluated_operand; |
9316 | ++c_inhibit_evaluation_warnings; |
9317 | |
9318 | tree oper = NULL_TREE; |
9319 | |
9320 | /* We can't be sure yet whether we're looking at a type-id or an |
9321 | expression. */ |
9322 | cp_parser_parse_tentatively (parser); |
9323 | |
9324 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
9325 | parser->in_type_id_in_expr_p = true; |
9326 | /* Look for the type-id. */ |
9327 | oper = cp_parser_type_id (parser); |
9328 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
9329 | |
9330 | cp_parser_parse_definitely (parser); |
9331 | |
9332 | /* If the type-id production did not work out, then we must be |
9333 | looking at an expression. */ |
9334 | if (!oper || oper == error_mark_node) |
9335 | oper = cp_parser_assignment_expression (parser); |
9336 | |
9337 | STRIP_ANY_LOCATION_WRAPPER (oper); |
9338 | |
9339 | /* Go back to evaluating expressions. */ |
9340 | --cp_unevaluated_operand; |
9341 | --c_inhibit_evaluation_warnings; |
9342 | |
9343 | /* And restore the old one. */ |
9344 | parser->type_definition_forbidden_message = saved_message; |
9345 | parser->type_definition_forbidden_message_arg = saved_message_arg; |
9346 | parser->integral_constant_expression_p |
9347 | = saved_integral_constant_expression_p; |
9348 | parser->non_integral_constant_expression_p |
9349 | = saved_non_integral_constant_expression_p; |
9350 | |
9351 | /* Consume the comma if it's there. */ |
9352 | if (!cp_parser_require (parser, CPP_COMMA, RT_COMMA)) |
9353 | { |
9354 | cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
9355 | /*consume_paren=*/true); |
9356 | return error_mark_node; |
9357 | } |
9358 | |
9359 | /* Parse the attribute specification. */ |
9360 | bool ret = false; |
9361 | location_t atloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9362 | if (tree attr = cp_parser_gnu_attribute_list (parser, /*exactly_one=*/true)) |
9363 | { |
9364 | if (oper == error_mark_node) |
9365 | /* Nothing. */; |
9366 | else if (processing_template_decl && uses_template_parms (oper)) |
9367 | sorry_at (atloc, "%<__builtin_has_attribute%> with dependent argument " |
9368 | "not supported yet" ); |
9369 | else |
9370 | { |
9371 | /* Fold constant expressions used in attributes first. */ |
9372 | cp_check_const_attributes (attr); |
9373 | |
9374 | /* Finally, see if OPER has been declared with ATTR. */ |
9375 | ret = has_attribute (atloc, oper, attr, default_conversion); |
9376 | } |
9377 | |
9378 | parens.require_close (parser); |
9379 | } |
9380 | else |
9381 | { |
9382 | error_at (atloc, "expected identifier" ); |
9383 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
9384 | } |
9385 | |
9386 | /* Construct a location e.g. : |
9387 | __builtin_has_attribute (oper, attr) |
9388 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9389 | with start == caret at the start of the built-in token, |
9390 | and with the endpoint at the final closing paren. */ |
9391 | location_t compound_loc |
9392 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
9393 | |
9394 | cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node); |
9395 | ret_expr.set_location (compound_loc); |
9396 | ret_expr = ret_expr.maybe_add_location_wrapper (); |
9397 | return ret_expr; |
9398 | } |
9399 | |
9400 | /* Parse a new-expression. |
9401 | |
9402 | new-expression: |
9403 | :: [opt] new new-placement [opt] new-type-id new-initializer [opt] |
9404 | :: [opt] new new-placement [opt] ( type-id ) new-initializer [opt] |
9405 | |
9406 | Returns a representation of the expression. */ |
9407 | |
9408 | static tree |
9409 | cp_parser_new_expression (cp_parser* parser) |
9410 | { |
9411 | bool global_scope_p; |
9412 | vec<tree, va_gc> *placement; |
9413 | tree type; |
9414 | vec<tree, va_gc> *initializer; |
9415 | tree nelts = NULL_TREE; |
9416 | tree ret; |
9417 | |
9418 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9419 | |
9420 | /* Look for the optional `::' operator. */ |
9421 | global_scope_p |
9422 | = (cp_parser_global_scope_opt (parser, |
9423 | /*current_scope_valid_p=*/false) |
9424 | != NULL_TREE); |
9425 | /* Look for the `new' operator. */ |
9426 | cp_parser_require_keyword (parser, RID_NEW, RT_NEW); |
9427 | /* There's no easy way to tell a new-placement from the |
9428 | `( type-id )' construct. */ |
9429 | cp_parser_parse_tentatively (parser); |
9430 | /* Look for a new-placement. */ |
9431 | placement = cp_parser_new_placement (parser); |
9432 | /* If that didn't work out, there's no new-placement. */ |
9433 | if (!cp_parser_parse_definitely (parser)) |
9434 | { |
9435 | if (placement != NULL) |
9436 | release_tree_vector (placement); |
9437 | placement = NULL; |
9438 | } |
9439 | |
9440 | /* If the next token is a `(', then we have a parenthesized |
9441 | type-id. */ |
9442 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
9443 | { |
9444 | cp_token *token; |
9445 | const char *saved_message = parser->type_definition_forbidden_message; |
9446 | |
9447 | /* Consume the `('. */ |
9448 | matching_parens parens; |
9449 | parens.consume_open (parser); |
9450 | |
9451 | /* Parse the type-id. */ |
9452 | parser->type_definition_forbidden_message |
9453 | = G_("types may not be defined in a new-expression" ); |
9454 | { |
9455 | type_id_in_expr_sentinel s (parser); |
9456 | type = cp_parser_type_id (parser); |
9457 | } |
9458 | parser->type_definition_forbidden_message = saved_message; |
9459 | |
9460 | /* Look for the closing `)'. */ |
9461 | parens.require_close (parser); |
9462 | token = cp_lexer_peek_token (lexer: parser->lexer); |
9463 | /* There should not be a direct-new-declarator in this production, |
9464 | but GCC used to allowed this, so we check and emit a sensible error |
9465 | message for this case. */ |
9466 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9467 | { |
9468 | error_at (token->location, |
9469 | "array bound forbidden after parenthesized type-id" ); |
9470 | inform (token->location, |
9471 | "try removing the parentheses around the type-id" ); |
9472 | cp_parser_direct_new_declarator (parser); |
9473 | } |
9474 | } |
9475 | /* Otherwise, there must be a new-type-id. */ |
9476 | else |
9477 | type = cp_parser_new_type_id (parser, &nelts); |
9478 | |
9479 | /* If the next token is a `(' or '{', then we have a new-initializer. */ |
9480 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
9481 | if (token->type == CPP_OPEN_PAREN |
9482 | || token->type == CPP_OPEN_BRACE) |
9483 | initializer = cp_parser_new_initializer (parser); |
9484 | else |
9485 | initializer = NULL; |
9486 | |
9487 | /* A new-expression may not appear in an integral constant |
9488 | expression. */ |
9489 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_NEW)) |
9490 | ret = error_mark_node; |
9491 | /* 5.3.4/2: "If the auto type-specifier appears in the type-specifier-seq |
9492 | of a new-type-id or type-id of a new-expression, the new-expression shall |
9493 | contain a new-initializer of the form ( assignment-expression )". |
9494 | Additionally, consistently with the spirit of DR 1467, we want to accept |
9495 | 'new auto { 2 }' too. */ |
9496 | else if ((ret = type_uses_auto (type)) |
9497 | && !CLASS_PLACEHOLDER_TEMPLATE (ret) |
9498 | && (vec_safe_length (v: initializer) != 1 |
9499 | || (BRACE_ENCLOSED_INITIALIZER_P ((*initializer)[0]) |
9500 | && CONSTRUCTOR_NELTS ((*initializer)[0]) != 1))) |
9501 | { |
9502 | error_at (token->location, |
9503 | "initialization of new-expression for type %<auto%> " |
9504 | "requires exactly one element" ); |
9505 | ret = error_mark_node; |
9506 | } |
9507 | else |
9508 | { |
9509 | /* Construct a location e.g.: |
9510 | ptr = new int[100] |
9511 | ^~~~~~~~~~~~ |
9512 | with caret == start at the start of the "new" token, and the end |
9513 | at the end of the final token we consumed. */ |
9514 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
9515 | lexer: parser->lexer); |
9516 | /* Create a representation of the new-expression. */ |
9517 | ret = build_new (combined_loc, &placement, type, nelts, &initializer, |
9518 | global_scope_p, tf_warning_or_error); |
9519 | } |
9520 | |
9521 | if (placement != NULL) |
9522 | release_tree_vector (placement); |
9523 | if (initializer != NULL) |
9524 | release_tree_vector (initializer); |
9525 | |
9526 | return ret; |
9527 | } |
9528 | |
9529 | /* Parse a new-placement. |
9530 | |
9531 | new-placement: |
9532 | ( expression-list ) |
9533 | |
9534 | Returns the same representation as for an expression-list. */ |
9535 | |
9536 | static vec<tree, va_gc> * |
9537 | cp_parser_new_placement (cp_parser* parser) |
9538 | { |
9539 | vec<tree, va_gc> *expression_list; |
9540 | |
9541 | /* Parse the expression-list. */ |
9542 | expression_list = (cp_parser_parenthesized_expression_list |
9543 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
9544 | /*allow_expansion_p=*/true, |
9545 | /*non_constant_p=*/NULL)); |
9546 | |
9547 | if (expression_list && expression_list->is_empty ()) |
9548 | error ("expected expression-list or type-id" ); |
9549 | |
9550 | return expression_list; |
9551 | } |
9552 | |
9553 | /* Parse a new-type-id. |
9554 | |
9555 | new-type-id: |
9556 | type-specifier-seq new-declarator [opt] |
9557 | |
9558 | Returns the TYPE allocated. If the new-type-id indicates an array |
9559 | type, *NELTS is set to the number of elements in the last array |
9560 | bound; the TYPE will not include the last array bound. */ |
9561 | |
9562 | static tree |
9563 | cp_parser_new_type_id (cp_parser* parser, tree *nelts) |
9564 | { |
9565 | cp_decl_specifier_seq type_specifier_seq; |
9566 | cp_declarator *new_declarator; |
9567 | cp_declarator *declarator; |
9568 | cp_declarator *outer_declarator; |
9569 | const char *saved_message; |
9570 | |
9571 | /* The type-specifier sequence must not contain type definitions. |
9572 | (It cannot contain declarations of new types either, but if they |
9573 | are not definitions we will catch that because they are not |
9574 | complete.) */ |
9575 | saved_message = parser->type_definition_forbidden_message; |
9576 | parser->type_definition_forbidden_message |
9577 | = G_("types may not be defined in a new-type-id" ); |
9578 | /* Parse the type-specifier-seq. */ |
9579 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
9580 | /*is_declaration=*/false, |
9581 | /*is_trailing_return=*/false, |
9582 | &type_specifier_seq); |
9583 | /* Restore the old message. */ |
9584 | parser->type_definition_forbidden_message = saved_message; |
9585 | |
9586 | if (type_specifier_seq.type == error_mark_node) |
9587 | return error_mark_node; |
9588 | |
9589 | /* Parse the new-declarator. */ |
9590 | new_declarator = cp_parser_new_declarator_opt (parser); |
9591 | |
9592 | /* Determine the number of elements in the last array dimension, if |
9593 | any. */ |
9594 | *nelts = NULL_TREE; |
9595 | /* Skip down to the last array dimension. */ |
9596 | declarator = new_declarator; |
9597 | outer_declarator = NULL; |
9598 | while (declarator && (declarator->kind == cdk_pointer |
9599 | || declarator->kind == cdk_ptrmem)) |
9600 | { |
9601 | outer_declarator = declarator; |
9602 | declarator = declarator->declarator; |
9603 | } |
9604 | while (declarator |
9605 | && declarator->kind == cdk_array |
9606 | && declarator->declarator |
9607 | && declarator->declarator->kind == cdk_array) |
9608 | { |
9609 | outer_declarator = declarator; |
9610 | declarator = declarator->declarator; |
9611 | } |
9612 | |
9613 | if (declarator && declarator->kind == cdk_array) |
9614 | { |
9615 | *nelts = declarator->u.array.bounds; |
9616 | if (*nelts == error_mark_node) |
9617 | *nelts = integer_one_node; |
9618 | |
9619 | if (*nelts == NULL_TREE) |
9620 | /* Leave [] in the declarator. */; |
9621 | else if (outer_declarator) |
9622 | outer_declarator->declarator = declarator->declarator; |
9623 | else |
9624 | new_declarator = NULL; |
9625 | } |
9626 | |
9627 | return groktypename (&type_specifier_seq, new_declarator, false); |
9628 | } |
9629 | |
9630 | /* Parse an (optional) new-declarator. |
9631 | |
9632 | new-declarator: |
9633 | ptr-operator new-declarator [opt] |
9634 | direct-new-declarator |
9635 | |
9636 | Returns the declarator. */ |
9637 | |
9638 | static cp_declarator * |
9639 | cp_parser_new_declarator_opt (cp_parser* parser) |
9640 | { |
9641 | enum tree_code code; |
9642 | tree type, std_attributes = NULL_TREE; |
9643 | cp_cv_quals cv_quals; |
9644 | |
9645 | /* We don't know if there's a ptr-operator next, or not. */ |
9646 | cp_parser_parse_tentatively (parser); |
9647 | /* Look for a ptr-operator. */ |
9648 | code = cp_parser_ptr_operator (parser, &type, &cv_quals, &std_attributes); |
9649 | /* If that worked, look for more new-declarators. */ |
9650 | if (cp_parser_parse_definitely (parser)) |
9651 | { |
9652 | cp_declarator *declarator; |
9653 | |
9654 | /* Parse another optional declarator. */ |
9655 | declarator = cp_parser_new_declarator_opt (parser); |
9656 | |
9657 | declarator = cp_parser_make_indirect_declarator |
9658 | (code, class_type: type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
9659 | |
9660 | return declarator; |
9661 | } |
9662 | |
9663 | /* If the next token is a `[', there is a direct-new-declarator. */ |
9664 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9665 | return cp_parser_direct_new_declarator (parser); |
9666 | |
9667 | return NULL; |
9668 | } |
9669 | |
9670 | /* Parse a direct-new-declarator. |
9671 | |
9672 | direct-new-declarator: |
9673 | [ expression ] |
9674 | direct-new-declarator [constant-expression] |
9675 | |
9676 | */ |
9677 | |
9678 | static cp_declarator * |
9679 | cp_parser_direct_new_declarator (cp_parser* parser) |
9680 | { |
9681 | cp_declarator *declarator = NULL; |
9682 | bool first_p = true; |
9683 | |
9684 | while (true) |
9685 | { |
9686 | tree expression; |
9687 | cp_token *token; |
9688 | |
9689 | /* Look for the opening `['. */ |
9690 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
9691 | |
9692 | token = cp_lexer_peek_token (lexer: parser->lexer); |
9693 | if (token->type == CPP_CLOSE_SQUARE && first_p) |
9694 | expression = NULL_TREE; |
9695 | else |
9696 | expression = cp_parser_expression (parser); |
9697 | /* The standard requires that the expression have integral |
9698 | type. DR 74 adds enumeration types. We believe that the |
9699 | real intent is that these expressions be handled like the |
9700 | expression in a `switch' condition, which also allows |
9701 | classes with a single conversion to integral or |
9702 | enumeration type. */ |
9703 | if (expression && !processing_template_decl) |
9704 | { |
9705 | expression |
9706 | = build_expr_type_conversion (WANT_INT | WANT_ENUM, |
9707 | expression, |
9708 | /*complain=*/true); |
9709 | if (!expression) |
9710 | { |
9711 | error_at (token->location, |
9712 | "expression in new-declarator must have integral " |
9713 | "or enumeration type" ); |
9714 | expression = error_mark_node; |
9715 | } |
9716 | } |
9717 | |
9718 | /* Look for the closing `]'. */ |
9719 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
9720 | |
9721 | /* Add this bound to the declarator. */ |
9722 | declarator = make_array_declarator (element: declarator, bounds: expression); |
9723 | |
9724 | /* If the next token is not a `[', then there are no more |
9725 | bounds. */ |
9726 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9727 | break; |
9728 | first_p = false; |
9729 | } |
9730 | |
9731 | return declarator; |
9732 | } |
9733 | |
9734 | /* Parse a new-initializer. |
9735 | |
9736 | new-initializer: |
9737 | ( expression-list [opt] ) |
9738 | braced-init-list |
9739 | |
9740 | Returns a representation of the expression-list. */ |
9741 | |
9742 | static vec<tree, va_gc> * |
9743 | cp_parser_new_initializer (cp_parser* parser) |
9744 | { |
9745 | vec<tree, va_gc> *expression_list; |
9746 | |
9747 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
9748 | { |
9749 | cp_lexer_set_source_position (lexer: parser->lexer); |
9750 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
9751 | tree t = cp_parser_braced_list (parser); |
9752 | CONSTRUCTOR_IS_DIRECT_INIT (t) = true; |
9753 | expression_list = make_tree_vector_single (t); |
9754 | } |
9755 | else |
9756 | expression_list = (cp_parser_parenthesized_expression_list |
9757 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
9758 | /*allow_expansion_p=*/true, |
9759 | /*non_constant_p=*/NULL)); |
9760 | |
9761 | return expression_list; |
9762 | } |
9763 | |
9764 | /* Parse a delete-expression. |
9765 | |
9766 | delete-expression: |
9767 | :: [opt] delete cast-expression |
9768 | :: [opt] delete [ ] cast-expression |
9769 | |
9770 | Returns a representation of the expression. */ |
9771 | |
9772 | static tree |
9773 | cp_parser_delete_expression (cp_parser* parser) |
9774 | { |
9775 | bool global_scope_p; |
9776 | bool array_p; |
9777 | tree expression; |
9778 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
9779 | |
9780 | /* Look for the optional `::' operator. */ |
9781 | global_scope_p |
9782 | = (cp_parser_global_scope_opt (parser, |
9783 | /*current_scope_valid_p=*/false) |
9784 | != NULL_TREE); |
9785 | /* Look for the `delete' keyword. */ |
9786 | cp_parser_require_keyword (parser, RID_DELETE, RT_DELETE); |
9787 | /* See if the array syntax is in use. */ |
9788 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
9789 | { |
9790 | /* Consume the `[' token. */ |
9791 | cp_lexer_consume_token (lexer: parser->lexer); |
9792 | /* Look for the `]' token. */ |
9793 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
9794 | /* Remember that this is the `[]' construct. */ |
9795 | array_p = true; |
9796 | } |
9797 | else |
9798 | array_p = false; |
9799 | |
9800 | /* Parse the cast-expression. */ |
9801 | expression = cp_parser_simple_cast_expression (parser); |
9802 | |
9803 | /* A delete-expression may not appear in an integral constant |
9804 | expression. */ |
9805 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_DEL)) |
9806 | return error_mark_node; |
9807 | |
9808 | /* Construct a location e.g.: |
9809 | delete [ ] ptr |
9810 | ^~~~~~~~~~~~~~ |
9811 | with caret == start at the start of the "delete" token, and |
9812 | the end at the end of the final token we consumed. */ |
9813 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
9814 | lexer: parser->lexer); |
9815 | expression = delete_sanity (combined_loc, expression, NULL_TREE, array_p, |
9816 | global_scope_p, tf_warning_or_error); |
9817 | |
9818 | return expression; |
9819 | } |
9820 | |
9821 | /* Returns 1 if TOKEN may start a cast-expression and isn't '++', '--', |
9822 | neither '[' in C++11; -1 if TOKEN is '++', '--', or '[' in C++11; |
9823 | 0 otherwise. */ |
9824 | |
9825 | static int |
9826 | cp_parser_tokens_start_cast_expression (cp_parser *parser) |
9827 | { |
9828 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
9829 | switch (token->type) |
9830 | { |
9831 | case CPP_COMMA: |
9832 | case CPP_SEMICOLON: |
9833 | case CPP_QUERY: |
9834 | case CPP_COLON: |
9835 | case CPP_CLOSE_SQUARE: |
9836 | case CPP_CLOSE_PAREN: |
9837 | case CPP_CLOSE_BRACE: |
9838 | case CPP_OPEN_BRACE: |
9839 | case CPP_DOT: |
9840 | case CPP_DOT_STAR: |
9841 | case CPP_DEREF: |
9842 | case CPP_DEREF_STAR: |
9843 | case CPP_DIV: |
9844 | case CPP_MOD: |
9845 | case CPP_LSHIFT: |
9846 | case CPP_RSHIFT: |
9847 | case CPP_LESS: |
9848 | case CPP_GREATER: |
9849 | case CPP_LESS_EQ: |
9850 | case CPP_GREATER_EQ: |
9851 | case CPP_EQ_EQ: |
9852 | case CPP_NOT_EQ: |
9853 | case CPP_EQ: |
9854 | case CPP_MULT_EQ: |
9855 | case CPP_DIV_EQ: |
9856 | case CPP_MOD_EQ: |
9857 | case CPP_PLUS_EQ: |
9858 | case CPP_MINUS_EQ: |
9859 | case CPP_RSHIFT_EQ: |
9860 | case CPP_LSHIFT_EQ: |
9861 | case CPP_AND_EQ: |
9862 | case CPP_XOR_EQ: |
9863 | case CPP_OR_EQ: |
9864 | case CPP_XOR: |
9865 | case CPP_OR: |
9866 | case CPP_OR_OR: |
9867 | case CPP_EOF: |
9868 | case CPP_ELLIPSIS: |
9869 | return 0; |
9870 | |
9871 | case CPP_OPEN_PAREN: |
9872 | /* In ((type ()) () the last () isn't a valid cast-expression, |
9873 | so the whole must be parsed as postfix-expression. */ |
9874 | return cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
9875 | != CPP_CLOSE_PAREN; |
9876 | |
9877 | case CPP_OPEN_SQUARE: |
9878 | /* '[' may start a primary-expression in obj-c++ and in C++11, |
9879 | as a lambda-expression, eg, '(void)[]{}'. */ |
9880 | if (cxx_dialect >= cxx11) |
9881 | return -1; |
9882 | return c_dialect_objc (); |
9883 | |
9884 | case CPP_PLUS_PLUS: |
9885 | case CPP_MINUS_MINUS: |
9886 | /* '++' and '--' may or may not start a cast-expression: |
9887 | |
9888 | struct T { void operator++(int); }; |
9889 | void f() { (T())++; } |
9890 | |
9891 | vs |
9892 | |
9893 | int a; |
9894 | (int)++a; */ |
9895 | return -1; |
9896 | |
9897 | default: |
9898 | return 1; |
9899 | } |
9900 | } |
9901 | |
9902 | /* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them |
9903 | in the order: const_cast, static_cast, reinterpret_cast. |
9904 | |
9905 | Don't suggest dynamic_cast. |
9906 | |
9907 | Return the first legal cast kind found, or NULL otherwise. */ |
9908 | |
9909 | static const char * |
9910 | get_cast_suggestion (tree dst_type, tree orig_expr) |
9911 | { |
9912 | tree trial; |
9913 | |
9914 | /* Reuse the parser logic by attempting to build the various kinds of |
9915 | cast, with "complain" disabled. |
9916 | Identify the first such cast that is valid. */ |
9917 | |
9918 | /* Don't attempt to run such logic within template processing. */ |
9919 | if (processing_template_decl) |
9920 | return NULL; |
9921 | |
9922 | /* First try const_cast. */ |
9923 | trial = build_const_cast (input_location, dst_type, orig_expr, tf_none); |
9924 | if (trial != error_mark_node) |
9925 | return "const_cast" ; |
9926 | |
9927 | /* If that fails, try static_cast. */ |
9928 | trial = build_static_cast (input_location, dst_type, orig_expr, tf_none); |
9929 | if (trial != error_mark_node) |
9930 | return "static_cast" ; |
9931 | |
9932 | /* Finally, try reinterpret_cast. */ |
9933 | trial = build_reinterpret_cast (input_location, dst_type, orig_expr, |
9934 | tf_none); |
9935 | if (trial != error_mark_node) |
9936 | return "reinterpret_cast" ; |
9937 | |
9938 | /* No such cast possible. */ |
9939 | return NULL; |
9940 | } |
9941 | |
9942 | /* If -Wold-style-cast is enabled, add fix-its to RICHLOC, |
9943 | suggesting how to convert a C-style cast of the form: |
9944 | |
9945 | (DST_TYPE)ORIG_EXPR |
9946 | |
9947 | to a C++-style cast. |
9948 | |
9949 | The primary range of RICHLOC is asssumed to be that of the original |
9950 | expression. OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations |
9951 | of the parens in the C-style cast. */ |
9952 | |
9953 | static void |
9954 | maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc, |
9955 | location_t close_paren_loc, tree orig_expr, |
9956 | tree dst_type) |
9957 | { |
9958 | /* This function is non-trivial, so bail out now if the warning isn't |
9959 | going to be emitted. */ |
9960 | if (!warn_old_style_cast) |
9961 | return; |
9962 | |
9963 | /* Try to find a legal C++ cast, trying them in order: |
9964 | const_cast, static_cast, reinterpret_cast. */ |
9965 | const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr); |
9966 | if (!cast_suggestion) |
9967 | return; |
9968 | |
9969 | /* Replace the open paren with "CAST_SUGGESTION<". */ |
9970 | pretty_printer pp; |
9971 | pp_string (&pp, cast_suggestion); |
9972 | pp_less (&pp); |
9973 | rich_loc->add_fixit_replace (where: open_paren_loc, new_content: pp_formatted_text (&pp)); |
9974 | |
9975 | /* Replace the close paren with "> (". */ |
9976 | rich_loc->add_fixit_replace (where: close_paren_loc, new_content: "> (" ); |
9977 | |
9978 | /* Add a closing paren after the expr (the primary range of RICH_LOC). */ |
9979 | rich_loc->add_fixit_insert_after (new_content: ")" ); |
9980 | } |
9981 | |
9982 | |
9983 | /* Parse a cast-expression. |
9984 | |
9985 | cast-expression: |
9986 | unary-expression |
9987 | ( type-id ) cast-expression |
9988 | |
9989 | ADDRESS_P is true iff the unary-expression is appearing as the |
9990 | operand of the `&' operator. CAST_P is true if this expression is |
9991 | the target of a cast. |
9992 | |
9993 | Returns a representation of the expression. */ |
9994 | |
9995 | static cp_expr |
9996 | cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, |
9997 | bool decltype_p, cp_id_kind * pidk) |
9998 | { |
9999 | /* If it's a `(', then we might be looking at a cast. */ |
10000 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
10001 | { |
10002 | tree type = NULL_TREE; |
10003 | cp_expr expr (NULL_TREE); |
10004 | int cast_expression = 0; |
10005 | const char *saved_message; |
10006 | |
10007 | /* There's no way to know yet whether or not this is a cast. |
10008 | For example, `(int (3))' is a unary-expression, while `(int) |
10009 | 3' is a cast. So, we resort to parsing tentatively. */ |
10010 | cp_parser_parse_tentatively (parser); |
10011 | /* Types may not be defined in a cast. */ |
10012 | saved_message = parser->type_definition_forbidden_message; |
10013 | parser->type_definition_forbidden_message |
10014 | = G_("types may not be defined in casts" ); |
10015 | /* Consume the `('. */ |
10016 | matching_parens parens; |
10017 | cp_token *open_paren = parens.consume_open (parser); |
10018 | location_t open_paren_loc = open_paren->location; |
10019 | location_t close_paren_loc = UNKNOWN_LOCATION; |
10020 | |
10021 | /* A very tricky bit is that `(struct S) { 3 }' is a |
10022 | compound-literal (which we permit in C++ as an extension). |
10023 | But, that construct is not a cast-expression -- it is a |
10024 | postfix-expression. (The reason is that `(struct S) { 3 }.i' |
10025 | is legal; if the compound-literal were a cast-expression, |
10026 | you'd need an extra set of parentheses.) But, if we parse |
10027 | the type-id, and it happens to be a class-specifier, then we |
10028 | will commit to the parse at that point, because we cannot |
10029 | undo the action that is done when creating a new class. So, |
10030 | then we cannot back up and do a postfix-expression. |
10031 | |
10032 | Another tricky case is the following (c++/29234): |
10033 | |
10034 | struct S { void operator () (); }; |
10035 | |
10036 | void foo () |
10037 | { |
10038 | ( S()() ); |
10039 | } |
10040 | |
10041 | As a type-id we parse the parenthesized S()() as a function |
10042 | returning a function, groktypename complains and we cannot |
10043 | back up in this case either. |
10044 | |
10045 | Therefore, we scan ahead to the closing `)', and check to see |
10046 | if the tokens after the `)' can start a cast-expression. Otherwise |
10047 | we are dealing with an unary-expression, a postfix-expression |
10048 | or something else. |
10049 | |
10050 | Yet another tricky case, in C++11, is the following (c++/54891): |
10051 | |
10052 | (void)[]{}; |
10053 | |
10054 | The issue is that usually, besides the case of lambda-expressions, |
10055 | the parenthesized type-id cannot be followed by '[', and, eg, we |
10056 | want to parse '(C ())[2];' in parse/pr26997.C as unary-expression. |
10057 | Thus, if cp_parser_tokens_start_cast_expression returns -1, below |
10058 | we don't commit, we try a cast-expression, then an unary-expression. |
10059 | |
10060 | Save tokens so that we can put them back. */ |
10061 | cp_lexer_save_tokens (lexer: parser->lexer); |
10062 | |
10063 | /* We may be looking at a cast-expression. */ |
10064 | if (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
10065 | /*consume_paren=*/true)) |
10066 | cast_expression |
10067 | = cp_parser_tokens_start_cast_expression (parser); |
10068 | |
10069 | /* Roll back the tokens we skipped. */ |
10070 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
10071 | /* If we aren't looking at a cast-expression, simulate an error so |
10072 | that the call to cp_parser_error_occurred below returns true. */ |
10073 | if (!cast_expression) |
10074 | cp_parser_simulate_error (parser); |
10075 | else |
10076 | { |
10077 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
10078 | parser->in_type_id_in_expr_p = true; |
10079 | /* Look for the type-id. */ |
10080 | type = cp_parser_type_id (parser); |
10081 | /* Look for the closing `)'. */ |
10082 | cp_token *close_paren = parens.require_close (parser); |
10083 | if (close_paren) |
10084 | close_paren_loc = close_paren->location; |
10085 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
10086 | } |
10087 | |
10088 | /* Restore the saved message. */ |
10089 | parser->type_definition_forbidden_message = saved_message; |
10090 | |
10091 | /* At this point this can only be either a cast or a |
10092 | parenthesized ctor such as `(T ())' that looks like a cast to |
10093 | function returning T. */ |
10094 | if (!cp_parser_error_occurred (parser)) |
10095 | { |
10096 | /* Only commit if the cast-expression doesn't start with |
10097 | '++', '--', or '[' in C++11. */ |
10098 | if (cast_expression > 0) |
10099 | cp_parser_commit_to_topmost_tentative_parse (parser); |
10100 | |
10101 | expr = cp_parser_cast_expression (parser, |
10102 | /*address_p=*/false, |
10103 | /*cast_p=*/true, |
10104 | /*decltype_p=*/false, |
10105 | pidk); |
10106 | |
10107 | if (cp_parser_parse_definitely (parser)) |
10108 | { |
10109 | /* Warn about old-style casts, if so requested. */ |
10110 | if (warn_old_style_cast |
10111 | && !in_system_header_at (loc: input_location) |
10112 | && !VOID_TYPE_P (type) |
10113 | && current_lang_name != lang_name_c) |
10114 | { |
10115 | gcc_rich_location rich_loc (input_location); |
10116 | maybe_add_cast_fixit (rich_loc: &rich_loc, open_paren_loc, close_paren_loc, |
10117 | orig_expr: expr, dst_type: type); |
10118 | warning_at (&rich_loc, OPT_Wold_style_cast, |
10119 | "use of old-style cast to %q#T" , type); |
10120 | } |
10121 | |
10122 | /* Only type conversions to integral or enumeration types |
10123 | can be used in constant-expressions. */ |
10124 | if (!cast_valid_in_integral_constant_expression_p (type) |
10125 | && cp_parser_non_integral_constant_expression (parser, |
10126 | thing: NIC_CAST)) |
10127 | return error_mark_node; |
10128 | |
10129 | /* Perform the cast. */ |
10130 | /* Make a location: |
10131 | (TYPE) EXPR |
10132 | ^~~~~~~~~~~ |
10133 | with start==caret at the open paren, extending to the |
10134 | end of "expr". */ |
10135 | location_t cast_loc = make_location (caret: open_paren_loc, |
10136 | start: open_paren_loc, |
10137 | finish: expr.get_finish ()); |
10138 | expr = build_c_cast (loc: cast_loc, type, expr); |
10139 | return expr; |
10140 | } |
10141 | } |
10142 | else |
10143 | cp_parser_abort_tentative_parse (parser); |
10144 | } |
10145 | |
10146 | /* If we get here, then it's not a cast, so it must be a |
10147 | unary-expression. */ |
10148 | return cp_parser_unary_expression (parser, pidk, address_p, |
10149 | cast_p, decltype_p); |
10150 | } |
10151 | |
10152 | /* Parse a binary expression of the general form: |
10153 | |
10154 | pm-expression: |
10155 | cast-expression |
10156 | pm-expression .* cast-expression |
10157 | pm-expression ->* cast-expression |
10158 | |
10159 | multiplicative-expression: |
10160 | pm-expression |
10161 | multiplicative-expression * pm-expression |
10162 | multiplicative-expression / pm-expression |
10163 | multiplicative-expression % pm-expression |
10164 | |
10165 | additive-expression: |
10166 | multiplicative-expression |
10167 | additive-expression + multiplicative-expression |
10168 | additive-expression - multiplicative-expression |
10169 | |
10170 | shift-expression: |
10171 | additive-expression |
10172 | shift-expression << additive-expression |
10173 | shift-expression >> additive-expression |
10174 | |
10175 | relational-expression: |
10176 | shift-expression |
10177 | relational-expression < shift-expression |
10178 | relational-expression > shift-expression |
10179 | relational-expression <= shift-expression |
10180 | relational-expression >= shift-expression |
10181 | |
10182 | GNU Extension: |
10183 | |
10184 | relational-expression: |
10185 | relational-expression <? shift-expression |
10186 | relational-expression >? shift-expression |
10187 | |
10188 | equality-expression: |
10189 | relational-expression |
10190 | equality-expression == relational-expression |
10191 | equality-expression != relational-expression |
10192 | |
10193 | and-expression: |
10194 | equality-expression |
10195 | and-expression & equality-expression |
10196 | |
10197 | exclusive-or-expression: |
10198 | and-expression |
10199 | exclusive-or-expression ^ and-expression |
10200 | |
10201 | inclusive-or-expression: |
10202 | exclusive-or-expression |
10203 | inclusive-or-expression | exclusive-or-expression |
10204 | |
10205 | logical-and-expression: |
10206 | inclusive-or-expression |
10207 | logical-and-expression && inclusive-or-expression |
10208 | |
10209 | logical-or-expression: |
10210 | logical-and-expression |
10211 | logical-or-expression || logical-and-expression |
10212 | |
10213 | All these are implemented with a single function like: |
10214 | |
10215 | binary-expression: |
10216 | simple-cast-expression |
10217 | binary-expression <token> binary-expression |
10218 | |
10219 | CAST_P is true if this expression is the target of a cast. |
10220 | |
10221 | The binops_by_token map is used to get the tree codes for each <token> type. |
10222 | binary-expressions are associated according to a precedence table. */ |
10223 | |
10224 | #define TOKEN_PRECEDENCE(token) \ |
10225 | (((token->type == CPP_GREATER \ |
10226 | || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)) \ |
10227 | && !parser->greater_than_is_operator_p) \ |
10228 | ? PREC_NOT_OPERATOR \ |
10229 | : binops_by_token[token->type].prec) |
10230 | |
10231 | static cp_expr |
10232 | cp_parser_binary_expression (cp_parser* parser, bool cast_p, |
10233 | bool no_toplevel_fold_p, |
10234 | bool decltype_p, |
10235 | enum cp_parser_prec prec, |
10236 | cp_id_kind * pidk) |
10237 | { |
10238 | cp_parser_expression_stack stack; |
10239 | cp_parser_expression_stack_entry *sp = &stack[0]; |
10240 | cp_parser_expression_stack_entry *disable_warnings_sp = NULL; |
10241 | cp_parser_expression_stack_entry current; |
10242 | cp_expr rhs; |
10243 | cp_token *token; |
10244 | enum tree_code rhs_type; |
10245 | enum cp_parser_prec new_prec, lookahead_prec; |
10246 | tree overload; |
10247 | |
10248 | /* Parse the first expression. */ |
10249 | current.lhs_type = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
10250 | ? TRUTH_NOT_EXPR : ERROR_MARK); |
10251 | current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false, |
10252 | cast_p, decltype_p, pidk); |
10253 | current.prec = prec; |
10254 | |
10255 | if (cp_parser_error_occurred (parser)) |
10256 | return error_mark_node; |
10257 | |
10258 | for (;;) |
10259 | { |
10260 | /* Get an operator token. */ |
10261 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10262 | |
10263 | if (warn_cxx11_compat |
10264 | && token->type == CPP_RSHIFT |
10265 | && !parser->greater_than_is_operator_p) |
10266 | { |
10267 | if (warning_at (token->location, OPT_Wc__11_compat, |
10268 | "%<>>%> operator is treated" |
10269 | " as two right angle brackets in C++11" )) |
10270 | inform (token->location, |
10271 | "suggest parentheses around %<>>%> expression" ); |
10272 | } |
10273 | |
10274 | new_prec = TOKEN_PRECEDENCE (token); |
10275 | if (new_prec != PREC_NOT_OPERATOR |
10276 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10277 | /* This is a fold-expression; handle it later. */ |
10278 | new_prec = PREC_NOT_OPERATOR; |
10279 | |
10280 | /* Popping an entry off the stack means we completed a subexpression: |
10281 | - either we found a token which is not an operator (`>' where it is not |
10282 | an operator, or prec == PREC_NOT_OPERATOR), in which case popping |
10283 | will happen repeatedly; |
10284 | - or, we found an operator which has lower priority. This is the case |
10285 | where the recursive descent *ascends*, as in `3 * 4 + 5' after |
10286 | parsing `3 * 4'. */ |
10287 | if (new_prec <= current.prec) |
10288 | { |
10289 | if (sp == stack) |
10290 | break; |
10291 | else |
10292 | goto pop; |
10293 | } |
10294 | |
10295 | get_rhs: |
10296 | current.tree_type = binops_by_token[token->type].tree_type; |
10297 | current.loc = token->location; |
10298 | current.flags = token->flags; |
10299 | |
10300 | /* We used the operator token. */ |
10301 | cp_lexer_consume_token (lexer: parser->lexer); |
10302 | |
10303 | /* For "false && x" or "true || x", x will never be executed; |
10304 | disable warnings while evaluating it. */ |
10305 | if ((current.tree_type == TRUTH_ANDIF_EXPR |
10306 | && cp_fully_fold (current.lhs) == truthvalue_false_node) |
10307 | || (current.tree_type == TRUTH_ORIF_EXPR |
10308 | && cp_fully_fold (current.lhs) == truthvalue_true_node)) |
10309 | { |
10310 | disable_warnings_sp = sp; |
10311 | ++c_inhibit_evaluation_warnings; |
10312 | } |
10313 | |
10314 | /* Extract another operand. It may be the RHS of this expression |
10315 | or the LHS of a new, higher priority expression. */ |
10316 | rhs_type = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
10317 | ? TRUTH_NOT_EXPR : ERROR_MARK); |
10318 | rhs = cp_parser_simple_cast_expression (parser); |
10319 | |
10320 | /* Get another operator token. Look up its precedence to avoid |
10321 | building a useless (immediately popped) stack entry for common |
10322 | cases such as 3 + 4 + 5 or 3 * 4 + 5. */ |
10323 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10324 | lookahead_prec = TOKEN_PRECEDENCE (token); |
10325 | if (lookahead_prec != PREC_NOT_OPERATOR |
10326 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10327 | lookahead_prec = PREC_NOT_OPERATOR; |
10328 | if (lookahead_prec > new_prec) |
10329 | { |
10330 | /* ... and prepare to parse the RHS of the new, higher priority |
10331 | expression. Since precedence levels on the stack are |
10332 | monotonically increasing, we do not have to care about |
10333 | stack overflows. */ |
10334 | *sp = current; |
10335 | ++sp; |
10336 | current.lhs = rhs; |
10337 | current.lhs_type = rhs_type; |
10338 | current.prec = new_prec; |
10339 | new_prec = lookahead_prec; |
10340 | goto get_rhs; |
10341 | |
10342 | pop: |
10343 | lookahead_prec = new_prec; |
10344 | /* If the stack is not empty, we have parsed into LHS the right side |
10345 | (`4' in the example above) of an expression we had suspended. |
10346 | We can use the information on the stack to recover the LHS (`3') |
10347 | from the stack together with the tree code (`MULT_EXPR'), and |
10348 | the precedence of the higher level subexpression |
10349 | (`PREC_ADDITIVE_EXPRESSION'). TOKEN is the CPP_PLUS token, |
10350 | which will be used to actually build the additive expression. */ |
10351 | rhs = current.lhs; |
10352 | rhs_type = current.lhs_type; |
10353 | --sp; |
10354 | current = *sp; |
10355 | } |
10356 | |
10357 | /* Undo the disabling of warnings done above. */ |
10358 | if (sp == disable_warnings_sp) |
10359 | { |
10360 | disable_warnings_sp = NULL; |
10361 | --c_inhibit_evaluation_warnings; |
10362 | } |
10363 | |
10364 | if (warn_logical_not_paren |
10365 | && TREE_CODE_CLASS (current.tree_type) == tcc_comparison |
10366 | && current.lhs_type == TRUTH_NOT_EXPR |
10367 | /* Avoid warning for !!x == y. */ |
10368 | && (TREE_CODE (current.lhs) != NE_EXPR |
10369 | || !integer_zerop (TREE_OPERAND (current.lhs, 1))) |
10370 | && (TREE_CODE (current.lhs) != TRUTH_NOT_EXPR |
10371 | || (TREE_CODE (TREE_OPERAND (current.lhs, 0)) != TRUTH_NOT_EXPR |
10372 | /* Avoid warning for !b == y where b is boolean. */ |
10373 | && (TREE_TYPE (TREE_OPERAND (current.lhs, 0)) == NULL_TREE |
10374 | || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0))) |
10375 | != BOOLEAN_TYPE)))) |
10376 | /* Avoid warning for !!b == y where b is boolean. */ |
10377 | && (!(DECL_P (tree_strip_any_location_wrapper (current.lhs)) |
10378 | || (TREE_CODE (current.lhs) == NON_LVALUE_EXPR |
10379 | && DECL_P (tree_strip_any_location_wrapper |
10380 | (TREE_OPERAND (current.lhs, 0))))) |
10381 | || TREE_TYPE (current.lhs) == NULL_TREE |
10382 | || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE)) |
10383 | warn_logical_not_parentheses (current.loc, current.tree_type, |
10384 | current.lhs, maybe_constant_value (rhs)); |
10385 | |
10386 | if (warn_xor_used_as_pow |
10387 | && current.tree_type == BIT_XOR_EXPR |
10388 | /* Don't warn for named "xor" (as opposed to '^'). */ |
10389 | && !(current.flags & NAMED_OP) |
10390 | && current.lhs.decimal_p () |
10391 | && rhs.decimal_p ()) |
10392 | check_for_xor_used_as_pow |
10393 | (lhs_loc: current.lhs.get_location (), |
10394 | lhs_val: tree_strip_any_location_wrapper (exp: current.lhs), |
10395 | operator_loc: current.loc, |
10396 | rhs_loc: rhs.get_location (), |
10397 | rhs_val: tree_strip_any_location_wrapper (exp: rhs)); |
10398 | |
10399 | overload = NULL; |
10400 | |
10401 | location_t combined_loc = make_location (caret: current.loc, |
10402 | start: current.lhs.get_start (), |
10403 | finish: rhs.get_finish ()); |
10404 | |
10405 | /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type == |
10406 | ERROR_MARK for everything that is not a binary expression. |
10407 | This makes warn_about_parentheses miss some warnings that |
10408 | involve unary operators. For unary expressions we should |
10409 | pass the correct tree_code unless the unary expression was |
10410 | surrounded by parentheses. |
10411 | */ |
10412 | if (no_toplevel_fold_p |
10413 | && lookahead_prec <= current.prec |
10414 | && sp == stack) |
10415 | { |
10416 | if (current.lhs == error_mark_node || rhs == error_mark_node) |
10417 | current.lhs = error_mark_node; |
10418 | else |
10419 | { |
10420 | current.lhs.maybe_add_location_wrapper (); |
10421 | rhs.maybe_add_location_wrapper (); |
10422 | current.lhs |
10423 | = build_min (current.tree_type, |
10424 | TREE_CODE_CLASS (current.tree_type) |
10425 | == tcc_comparison |
10426 | ? boolean_type_node : TREE_TYPE (current.lhs), |
10427 | current.lhs.get_value (), rhs.get_value ()); |
10428 | SET_EXPR_LOCATION (current.lhs, combined_loc); |
10429 | } |
10430 | } |
10431 | else |
10432 | { |
10433 | op_location_t op_loc (current.loc, combined_loc); |
10434 | current.lhs = build_x_binary_op (op_loc, current.tree_type, |
10435 | current.lhs, current.lhs_type, |
10436 | rhs, rhs_type, NULL_TREE, &overload, |
10437 | complain_flags (decltype_p)); |
10438 | /* TODO: build_x_binary_op doesn't always honor the location. */ |
10439 | current.lhs.set_location (combined_loc); |
10440 | } |
10441 | current.lhs_type = current.tree_type; |
10442 | |
10443 | /* If the binary operator required the use of an overloaded operator, |
10444 | then this expression cannot be an integral constant-expression. |
10445 | An overloaded operator can be used even if both operands are |
10446 | otherwise permissible in an integral constant-expression if at |
10447 | least one of the operands is of enumeration type. */ |
10448 | |
10449 | if (overload |
10450 | && cp_parser_non_integral_constant_expression (parser, |
10451 | thing: NIC_OVERLOADED)) |
10452 | return error_mark_node; |
10453 | } |
10454 | |
10455 | return current.lhs; |
10456 | } |
10457 | |
10458 | static cp_expr |
10459 | cp_parser_binary_expression (cp_parser* parser, bool cast_p, |
10460 | bool no_toplevel_fold_p, |
10461 | enum cp_parser_prec prec, |
10462 | cp_id_kind * pidk) |
10463 | { |
10464 | return cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p, |
10465 | /*decltype*/decltype_p: false, prec, pidk); |
10466 | } |
10467 | |
10468 | /* Parse the `? expression : assignment-expression' part of a |
10469 | conditional-expression. The LOGICAL_OR_EXPR is the |
10470 | logical-or-expression that started the conditional-expression. |
10471 | Returns a representation of the entire conditional-expression. |
10472 | |
10473 | This routine is used by cp_parser_assignment_expression |
10474 | and cp_parser_conditional_expression. |
10475 | |
10476 | ? expression : assignment-expression |
10477 | |
10478 | GNU Extensions: |
10479 | |
10480 | ? : assignment-expression */ |
10481 | |
10482 | static tree |
10483 | cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr) |
10484 | { |
10485 | tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr); |
10486 | cp_expr assignment_expr; |
10487 | struct cp_token *token; |
10488 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10489 | |
10490 | /* Consume the `?' token. */ |
10491 | cp_lexer_consume_token (lexer: parser->lexer); |
10492 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10493 | if (cp_parser_allow_gnu_extensions_p (parser) |
10494 | && token->type == CPP_COLON) |
10495 | { |
10496 | pedwarn (token->location, OPT_Wpedantic, |
10497 | "ISO C++ does not allow %<?:%> with omitted middle operand" ); |
10498 | /* Implicit true clause. */ |
10499 | expr = NULL_TREE; |
10500 | c_inhibit_evaluation_warnings += |
10501 | folded_logical_or_expr == truthvalue_true_node; |
10502 | warn_for_omitted_condop (token->location, logical_or_expr); |
10503 | } |
10504 | else |
10505 | { |
10506 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
10507 | parser->colon_corrects_to_scope_p = false; |
10508 | /* Parse the expression. */ |
10509 | c_inhibit_evaluation_warnings += |
10510 | folded_logical_or_expr == truthvalue_false_node; |
10511 | expr = cp_parser_expression (parser); |
10512 | c_inhibit_evaluation_warnings += |
10513 | ((folded_logical_or_expr == truthvalue_true_node) |
10514 | - (folded_logical_or_expr == truthvalue_false_node)); |
10515 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
10516 | } |
10517 | |
10518 | /* The next token should be a `:'. */ |
10519 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
10520 | /* Parse the assignment-expression. */ |
10521 | assignment_expr = cp_parser_assignment_expression (parser); |
10522 | c_inhibit_evaluation_warnings -= |
10523 | folded_logical_or_expr == truthvalue_true_node; |
10524 | |
10525 | /* Make a location: |
10526 | LOGICAL_OR_EXPR ? EXPR : ASSIGNMENT_EXPR |
10527 | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ |
10528 | with the caret at the "?", ranging from the start of |
10529 | the logical_or_expr to the end of the assignment_expr. */ |
10530 | loc = make_location (caret: loc, |
10531 | start: logical_or_expr.get_start (), |
10532 | finish: assignment_expr.get_finish ()); |
10533 | |
10534 | /* Build the conditional-expression. */ |
10535 | return build_x_conditional_expr (loc, logical_or_expr, |
10536 | expr, |
10537 | assignment_expr, |
10538 | tf_warning_or_error); |
10539 | } |
10540 | |
10541 | /* Parse a conditional-expression. |
10542 | |
10543 | conditional-expression: |
10544 | logical-or-expression |
10545 | logical-or-expression ? expression : assignment-expression |
10546 | |
10547 | GNU Extensions: |
10548 | |
10549 | logical-or-expression ? : assignment-expression */ |
10550 | |
10551 | static cp_expr |
10552 | cp_parser_conditional_expression (cp_parser *parser) |
10553 | { |
10554 | cp_expr expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, decltype_p: false, |
10555 | prec: PREC_NOT_OPERATOR, NULL); |
10556 | /* If the next token is a `?' then we're actually looking at |
10557 | a conditional-expression; otherwise we're done. */ |
10558 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
10559 | return cp_parser_question_colon_clause (parser, logical_or_expr: expr); |
10560 | return expr; |
10561 | } |
10562 | |
10563 | /* Parse an assignment-expression. |
10564 | |
10565 | assignment-expression: |
10566 | conditional-expression |
10567 | logical-or-expression assignment-operator assignment_expression |
10568 | throw-expression |
10569 | yield-expression |
10570 | |
10571 | CAST_P is true if this expression is the target of a cast. |
10572 | DECLTYPE_P is true if this expression is the operand of decltype. |
10573 | |
10574 | Returns a representation for the expression. */ |
10575 | |
10576 | static cp_expr |
10577 | cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk, |
10578 | bool cast_p, bool decltype_p) |
10579 | { |
10580 | cp_expr expr; |
10581 | |
10582 | /* If the next token is the `throw' keyword, then we're looking at |
10583 | a throw-expression. */ |
10584 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_THROW)) |
10585 | expr = cp_parser_throw_expression (parser); |
10586 | /* If the next token is the `co_yield' keyword, then we're looking at |
10587 | a yield-expression. */ |
10588 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CO_YIELD)) |
10589 | expr = cp_parser_yield_expression (parser); |
10590 | /* Otherwise, it must be that we are looking at a |
10591 | logical-or-expression. */ |
10592 | else |
10593 | { |
10594 | /* Parse the binary expressions (logical-or-expression). */ |
10595 | expr = cp_parser_binary_expression (parser, cast_p, no_toplevel_fold_p: false, |
10596 | decltype_p, |
10597 | prec: PREC_NOT_OPERATOR, pidk); |
10598 | /* If the next token is a `?' then we're actually looking at a |
10599 | conditional-expression. */ |
10600 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
10601 | return cp_parser_question_colon_clause (parser, logical_or_expr: expr); |
10602 | else |
10603 | { |
10604 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10605 | |
10606 | /* If it's an assignment-operator, we're using the second |
10607 | production. */ |
10608 | enum tree_code assignment_operator |
10609 | = cp_parser_assignment_operator_opt (parser); |
10610 | if (assignment_operator != ERROR_MARK) |
10611 | { |
10612 | /* Parse the right-hand side of the assignment. */ |
10613 | cp_expr rhs = cp_parser_initializer_clause (parser); |
10614 | |
10615 | if (BRACE_ENCLOSED_INITIALIZER_P (rhs)) |
10616 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
10617 | |
10618 | /* An assignment may not appear in a |
10619 | constant-expression. */ |
10620 | if (cp_parser_non_integral_constant_expression (parser, |
10621 | thing: NIC_ASSIGNMENT)) |
10622 | return error_mark_node; |
10623 | /* Build the assignment expression. Its default |
10624 | location: |
10625 | LHS = RHS |
10626 | ~~~~^~~~~ |
10627 | is the location of the '=' token as the |
10628 | caret, ranging from the start of the lhs to the |
10629 | end of the rhs. */ |
10630 | loc = make_location (caret: loc, |
10631 | start: expr.get_start (), |
10632 | finish: rhs.get_finish ()); |
10633 | expr = build_x_modify_expr (loc, expr, |
10634 | assignment_operator, |
10635 | rhs, NULL_TREE, |
10636 | complain_flags (decltype_p)); |
10637 | /* TODO: build_x_modify_expr doesn't honor the location, |
10638 | so we must set it here. */ |
10639 | expr.set_location (loc); |
10640 | } |
10641 | } |
10642 | } |
10643 | |
10644 | return expr; |
10645 | } |
10646 | |
10647 | /* Parse an (optional) assignment-operator. |
10648 | |
10649 | assignment-operator: one of |
10650 | = *= /= %= += -= >>= <<= &= ^= |= |
10651 | |
10652 | GNU Extension: |
10653 | |
10654 | assignment-operator: one of |
10655 | <?= >?= |
10656 | |
10657 | If the next token is an assignment operator, the corresponding tree |
10658 | code is returned, and the token is consumed. For example, for |
10659 | `+=', PLUS_EXPR is returned. For `=' itself, the code returned is |
10660 | NOP_EXPR. For `/', TRUNC_DIV_EXPR is returned; for `%', |
10661 | TRUNC_MOD_EXPR is returned. If TOKEN is not an assignment |
10662 | operator, ERROR_MARK is returned. */ |
10663 | |
10664 | static enum tree_code |
10665 | cp_parser_assignment_operator_opt (cp_parser* parser) |
10666 | { |
10667 | enum tree_code op; |
10668 | cp_token *token; |
10669 | |
10670 | /* Peek at the next token. */ |
10671 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10672 | |
10673 | switch (token->type) |
10674 | { |
10675 | case CPP_EQ: |
10676 | op = NOP_EXPR; |
10677 | break; |
10678 | |
10679 | case CPP_MULT_EQ: |
10680 | op = MULT_EXPR; |
10681 | break; |
10682 | |
10683 | case CPP_DIV_EQ: |
10684 | op = TRUNC_DIV_EXPR; |
10685 | break; |
10686 | |
10687 | case CPP_MOD_EQ: |
10688 | op = TRUNC_MOD_EXPR; |
10689 | break; |
10690 | |
10691 | case CPP_PLUS_EQ: |
10692 | op = PLUS_EXPR; |
10693 | break; |
10694 | |
10695 | case CPP_MINUS_EQ: |
10696 | op = MINUS_EXPR; |
10697 | break; |
10698 | |
10699 | case CPP_RSHIFT_EQ: |
10700 | op = RSHIFT_EXPR; |
10701 | break; |
10702 | |
10703 | case CPP_LSHIFT_EQ: |
10704 | op = LSHIFT_EXPR; |
10705 | break; |
10706 | |
10707 | case CPP_AND_EQ: |
10708 | op = BIT_AND_EXPR; |
10709 | break; |
10710 | |
10711 | case CPP_XOR_EQ: |
10712 | op = BIT_XOR_EXPR; |
10713 | break; |
10714 | |
10715 | case CPP_OR_EQ: |
10716 | op = BIT_IOR_EXPR; |
10717 | break; |
10718 | |
10719 | default: |
10720 | /* Nothing else is an assignment operator. */ |
10721 | op = ERROR_MARK; |
10722 | } |
10723 | |
10724 | /* An operator followed by ... is a fold-expression, handled elsewhere. */ |
10725 | if (op != ERROR_MARK |
10726 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10727 | op = ERROR_MARK; |
10728 | |
10729 | /* If it was an assignment operator, consume it. */ |
10730 | if (op != ERROR_MARK) |
10731 | cp_lexer_consume_token (lexer: parser->lexer); |
10732 | |
10733 | return op; |
10734 | } |
10735 | |
10736 | /* Parse an expression. |
10737 | |
10738 | expression: |
10739 | assignment-expression |
10740 | expression , assignment-expression |
10741 | |
10742 | CAST_P is true if this expression is the target of a cast. |
10743 | DECLTYPE_P is true if this expression is the immediate operand of decltype, |
10744 | except possibly parenthesized or on the RHS of a comma (N3276). |
10745 | WARN_COMMA_P is true if a comma should be diagnosed. |
10746 | |
10747 | Returns a representation of the expression. */ |
10748 | |
10749 | static cp_expr |
10750 | cp_parser_expression (cp_parser* parser, cp_id_kind * pidk, |
10751 | bool cast_p, bool decltype_p, bool warn_comma_p) |
10752 | { |
10753 | cp_expr expression = NULL_TREE; |
10754 | location_t loc = UNKNOWN_LOCATION; |
10755 | |
10756 | while (true) |
10757 | { |
10758 | cp_expr assignment_expression; |
10759 | |
10760 | /* Parse the next assignment-expression. */ |
10761 | assignment_expression |
10762 | = cp_parser_assignment_expression (parser, pidk, cast_p, decltype_p); |
10763 | |
10764 | /* We don't create a temporary for a call that is the immediate operand |
10765 | of decltype or on the RHS of a comma. But when we see a comma, we |
10766 | need to create a temporary for a call on the LHS. */ |
10767 | if (decltype_p && !processing_template_decl |
10768 | && TREE_CODE (assignment_expression) == CALL_EXPR |
10769 | && CLASS_TYPE_P (TREE_TYPE (assignment_expression)) |
10770 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
10771 | assignment_expression |
10772 | = build_cplus_new (TREE_TYPE (assignment_expression), |
10773 | assignment_expression, tf_warning_or_error); |
10774 | |
10775 | /* If this is the first assignment-expression, we can just |
10776 | save it away. */ |
10777 | if (!expression) |
10778 | expression = assignment_expression; |
10779 | else |
10780 | { |
10781 | /* Create a location with caret at the comma, ranging |
10782 | from the start of the LHS to the end of the RHS. */ |
10783 | loc = make_location (caret: loc, |
10784 | start: expression.get_start (), |
10785 | finish: assignment_expression.get_finish ()); |
10786 | expression = build_x_compound_expr (loc, expression, |
10787 | assignment_expression, NULL_TREE, |
10788 | complain_flags (decltype_p)); |
10789 | expression.set_location (loc); |
10790 | } |
10791 | /* If the next token is not a comma, or we're in a fold-expression, then |
10792 | we are done with the expression. */ |
10793 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
10794 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS)) |
10795 | break; |
10796 | /* Consume the `,'. */ |
10797 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10798 | if (warn_comma_p) |
10799 | { |
10800 | /* [depr.comma.subscript]: A comma expression appearing as |
10801 | the expr-or-braced-init-list of a subscripting expression |
10802 | is deprecated. A parenthesized comma expression is not |
10803 | deprecated. */ |
10804 | warning_at (loc, OPT_Wcomma_subscript, |
10805 | "top-level comma expression in array subscript " |
10806 | "is deprecated" ); |
10807 | warn_comma_p = false; |
10808 | } |
10809 | cp_lexer_consume_token (lexer: parser->lexer); |
10810 | /* A comma operator cannot appear in a constant-expression. */ |
10811 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_COMMA)) |
10812 | expression = error_mark_node; |
10813 | } |
10814 | |
10815 | return expression; |
10816 | } |
10817 | |
10818 | /* Parse a constant-expression. |
10819 | |
10820 | constant-expression: |
10821 | conditional-expression |
10822 | |
10823 | If ALLOW_NON_CONSTANT_P a non-constant expression is silently |
10824 | accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not |
10825 | constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P |
10826 | is false, NON_CONSTANT_P should be NULL. If ALLOW_NON_CONSTANT_P is |
10827 | greater than 1, this isn't really a constant-expression, only a |
10828 | potentially constant-evaluated expression. If STRICT_P is true, |
10829 | only parse a conditional-expression, otherwise parse an |
10830 | assignment-expression. See below for rationale. */ |
10831 | |
10832 | static cp_expr |
10833 | cp_parser_constant_expression (cp_parser* parser, |
10834 | int allow_non_constant_p /* = 0 */, |
10835 | bool *non_constant_p /* = NULL */, |
10836 | bool strict_p /* = false */) |
10837 | { |
10838 | /* It might seem that we could simply parse the |
10839 | conditional-expression, and then check to see if it were |
10840 | TREE_CONSTANT. However, an expression that is TREE_CONSTANT is |
10841 | one that the compiler can figure out is constant, possibly after |
10842 | doing some simplifications or optimizations. The standard has a |
10843 | precise definition of constant-expression, and we must honor |
10844 | that, even though it is somewhat more restrictive. |
10845 | |
10846 | For example: |
10847 | |
10848 | int i[(2, 3)]; |
10849 | |
10850 | is not a legal declaration, because `(2, 3)' is not a |
10851 | constant-expression. The `,' operator is forbidden in a |
10852 | constant-expression. However, GCC's constant-folding machinery |
10853 | will fold this operation to an INTEGER_CST for `3'. */ |
10854 | |
10855 | /* Save the old settings. */ |
10856 | bool saved_integral_constant_expression_p |
10857 | = parser->integral_constant_expression_p; |
10858 | bool saved_allow_non_integral_constant_expression_p |
10859 | = parser->allow_non_integral_constant_expression_p; |
10860 | bool saved_non_integral_constant_expression_p |
10861 | = parser->non_integral_constant_expression_p; |
10862 | /* We are now parsing a constant-expression. */ |
10863 | parser->integral_constant_expression_p = true; |
10864 | parser->allow_non_integral_constant_expression_p |
10865 | = (allow_non_constant_p || cxx_dialect >= cxx11); |
10866 | parser->non_integral_constant_expression_p = false; |
10867 | |
10868 | /* A manifestly constant-evaluated expression is evaluated even in an |
10869 | unevaluated operand. */ |
10870 | cp_evaluated ev (/*reset if*/allow_non_constant_p <= 1); |
10871 | |
10872 | /* Although the grammar says "conditional-expression", when not STRICT_P, |
10873 | we parse an "assignment-expression", which also permits |
10874 | "throw-expression" and the use of assignment operators. In the case |
10875 | that ALLOW_NON_CONSTANT_P is false, we get better errors than we would |
10876 | otherwise. In the case that ALLOW_NON_CONSTANT_P is true, it is |
10877 | actually essential that we look for an assignment-expression. |
10878 | For example, cp_parser_initializer_clauses uses this function to |
10879 | determine whether a particular assignment-expression is in fact |
10880 | constant. */ |
10881 | cp_expr expression; |
10882 | if (strict_p) |
10883 | expression = cp_parser_conditional_expression (parser); |
10884 | else |
10885 | expression = cp_parser_assignment_expression (parser); |
10886 | /* Restore the old settings. */ |
10887 | parser->integral_constant_expression_p |
10888 | = saved_integral_constant_expression_p; |
10889 | parser->allow_non_integral_constant_expression_p |
10890 | = saved_allow_non_integral_constant_expression_p; |
10891 | if (cxx_dialect >= cxx11 |
10892 | && (!allow_non_constant_p || non_constant_p)) |
10893 | { |
10894 | /* Require an rvalue constant expression here; that's what our |
10895 | callers expect. Reference constant expressions are handled |
10896 | separately in e.g. cp_parser_template_argument. */ |
10897 | tree decay = expression; |
10898 | if (TREE_TYPE (expression) |
10899 | && TREE_CODE (TREE_TYPE (expression)) == ARRAY_TYPE) |
10900 | decay = build_address (expression); |
10901 | bool is_const = is_rvalue_constant_expression (decay); |
10902 | parser->non_integral_constant_expression_p = !is_const; |
10903 | if (!is_const && !allow_non_constant_p) |
10904 | require_rvalue_constant_expression (decay); |
10905 | } |
10906 | if (allow_non_constant_p && non_constant_p) |
10907 | *non_constant_p = parser->non_integral_constant_expression_p; |
10908 | parser->non_integral_constant_expression_p |
10909 | = saved_non_integral_constant_expression_p; |
10910 | |
10911 | return expression; |
10912 | } |
10913 | |
10914 | /* Parse __builtin_offsetof. |
10915 | |
10916 | offsetof-expression: |
10917 | "__builtin_offsetof" "(" type-id "," offsetof-member-designator ")" |
10918 | |
10919 | offsetof-member-designator: |
10920 | id-expression |
10921 | | offsetof-member-designator "." id-expression |
10922 | | offsetof-member-designator "[" expression "]" |
10923 | | offsetof-member-designator "->" id-expression */ |
10924 | |
10925 | static cp_expr |
10926 | cp_parser_builtin_offsetof (cp_parser *parser) |
10927 | { |
10928 | int save_ice_p, save_non_ice_p; |
10929 | tree type; |
10930 | cp_expr expr; |
10931 | cp_id_kind dummy; |
10932 | cp_token *token; |
10933 | location_t finish_loc; |
10934 | |
10935 | /* We're about to accept non-integral-constant things, but will |
10936 | definitely yield an integral constant expression. Save and |
10937 | restore these values around our local parsing. */ |
10938 | save_ice_p = parser->integral_constant_expression_p; |
10939 | save_non_ice_p = parser->non_integral_constant_expression_p; |
10940 | |
10941 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10942 | |
10943 | /* Consume the "__builtin_offsetof" token. */ |
10944 | cp_lexer_consume_token (lexer: parser->lexer); |
10945 | /* Consume the opening `('. */ |
10946 | matching_parens parens; |
10947 | parens.require_open (parser); |
10948 | /* Parse the type-id. */ |
10949 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10950 | { |
10951 | const char *saved_message = parser->type_definition_forbidden_message; |
10952 | parser->type_definition_forbidden_message |
10953 | = G_("types may not be defined within %<__builtin_offsetof%>" ); |
10954 | type = cp_parser_type_id (parser); |
10955 | parser->type_definition_forbidden_message = saved_message; |
10956 | } |
10957 | /* Look for the `,'. */ |
10958 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
10959 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10960 | |
10961 | /* Build the (type *)null that begins the traditional offsetof macro. */ |
10962 | tree object_ptr |
10963 | = build_static_cast (input_location, build_pointer_type (type), |
10964 | null_pointer_node, tf_warning_or_error); |
10965 | |
10966 | /* Parse the offsetof-member-designator. We begin as if we saw "expr->". */ |
10967 | expr = cp_parser_postfix_dot_deref_expression (parser, token_type: CPP_DEREF, postfix_expression: object_ptr, |
10968 | for_offsetof: true, idk: &dummy, location: token->location); |
10969 | while (true) |
10970 | { |
10971 | token = cp_lexer_peek_token (lexer: parser->lexer); |
10972 | switch (token->type) |
10973 | { |
10974 | case CPP_OPEN_SQUARE: |
10975 | /* offsetof-member-designator "[" expression "]" */ |
10976 | expr = cp_parser_postfix_open_square_expression (parser, postfix_expression: expr, |
10977 | for_offsetof: true, decltype_p: false); |
10978 | break; |
10979 | |
10980 | case CPP_DEREF: |
10981 | /* offsetof-member-designator "->" identifier */ |
10982 | expr = grok_array_decl (token->location, expr, integer_zero_node, |
10983 | NULL, tf_warning_or_error); |
10984 | /* FALLTHRU */ |
10985 | |
10986 | case CPP_DOT: |
10987 | /* offsetof-member-designator "." identifier */ |
10988 | cp_lexer_consume_token (lexer: parser->lexer); |
10989 | expr = cp_parser_postfix_dot_deref_expression (parser, token_type: CPP_DOT, |
10990 | postfix_expression: expr, for_offsetof: true, idk: &dummy, |
10991 | location: token->location); |
10992 | break; |
10993 | |
10994 | case CPP_CLOSE_PAREN: |
10995 | /* Consume the ")" token. */ |
10996 | finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
10997 | cp_lexer_consume_token (lexer: parser->lexer); |
10998 | goto success; |
10999 | |
11000 | default: |
11001 | /* Error. We know the following require will fail, but |
11002 | that gives the proper error message. */ |
11003 | parens.require_close (parser); |
11004 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
11005 | expr = error_mark_node; |
11006 | goto failure; |
11007 | } |
11008 | } |
11009 | |
11010 | success: |
11011 | /* Make a location of the form: |
11012 | __builtin_offsetof (struct s, f) |
11013 | ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~ |
11014 | with caret at the type-id, ranging from the start of the |
11015 | "_builtin_offsetof" token to the close paren. */ |
11016 | loc = make_location (caret: loc, start: start_loc, finish: finish_loc); |
11017 | /* The result will be an INTEGER_CST, so we need to explicitly |
11018 | preserve the location. */ |
11019 | expr = cp_expr (finish_offsetof (object_ptr, expr, loc), loc); |
11020 | |
11021 | failure: |
11022 | parser->integral_constant_expression_p = save_ice_p; |
11023 | parser->non_integral_constant_expression_p = save_non_ice_p; |
11024 | |
11025 | expr = expr.maybe_add_location_wrapper (); |
11026 | return expr; |
11027 | } |
11028 | |
11029 | /* Parse a builtin trait expression or type. */ |
11030 | |
11031 | static cp_expr |
11032 | cp_parser_trait (cp_parser* parser, enum rid keyword) |
11033 | { |
11034 | cp_trait_kind kind; |
11035 | tree type1, type2 = NULL_TREE; |
11036 | bool binary = false; |
11037 | bool variadic = false; |
11038 | bool type = false; |
11039 | |
11040 | switch (keyword) |
11041 | { |
11042 | #define DEFTRAIT(TCC, CODE, NAME, ARITY) \ |
11043 | case RID_##CODE: \ |
11044 | kind = CPTK_##CODE; \ |
11045 | binary = (ARITY == 2); \ |
11046 | variadic = (ARITY == -1); \ |
11047 | type = (TCC == tcc_type); \ |
11048 | break; |
11049 | #include "cp-trait.def" |
11050 | #undef DEFTRAIT |
11051 | default: |
11052 | gcc_unreachable (); |
11053 | } |
11054 | |
11055 | /* Get location of initial token. */ |
11056 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11057 | |
11058 | /* Consume the token. */ |
11059 | cp_lexer_consume_token (lexer: parser->lexer); |
11060 | |
11061 | matching_parens parens; |
11062 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11063 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
11064 | else |
11065 | parens.require_open (parser); |
11066 | |
11067 | if (kind == CPTK_IS_DEDUCIBLE) |
11068 | { |
11069 | const cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
11070 | type1 = cp_parser_id_expression (parser, |
11071 | /*template_keyword_p=*/false, |
11072 | /*check_dependency_p=*/true, |
11073 | template_p: nullptr, |
11074 | /*declarator_p=*/false, |
11075 | /*optional_p=*/false); |
11076 | type1 = cp_parser_lookup_name_simple (parser, type1, token->location); |
11077 | } |
11078 | else if (kind == CPTK_TYPE_PACK_ELEMENT) |
11079 | /* __type_pack_element takes an expression as its first argument and uses |
11080 | template-id syntax instead of function call syntax (for consistency |
11081 | with Clang). We special case these properties of __type_pack_element |
11082 | here and elsewhere. */ |
11083 | type1 = cp_parser_constant_expression (parser); |
11084 | else |
11085 | { |
11086 | type_id_in_expr_sentinel s (parser); |
11087 | type1 = cp_parser_type_id (parser); |
11088 | } |
11089 | |
11090 | if (type1 == error_mark_node) |
11091 | return error_mark_node; |
11092 | |
11093 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11094 | { |
11095 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11096 | tree trailing = cp_parser_enclosed_template_argument_list (parser); |
11097 | for (tree elt : tree_vec_range (trailing)) |
11098 | { |
11099 | if (!TYPE_P (elt)) |
11100 | { |
11101 | error_at (cp_expr_loc_or_input_loc (t: elt), |
11102 | "trailing argument to %<__type_pack_element%> " |
11103 | "is not a type" ); |
11104 | return error_mark_node; |
11105 | } |
11106 | } |
11107 | type2 = trailing; |
11108 | } |
11109 | else if (binary) |
11110 | { |
11111 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11112 | |
11113 | { |
11114 | type_id_in_expr_sentinel s (parser); |
11115 | type2 = cp_parser_type_id (parser); |
11116 | } |
11117 | |
11118 | if (type2 == error_mark_node) |
11119 | return error_mark_node; |
11120 | } |
11121 | else if (variadic) |
11122 | { |
11123 | auto_vec<tree, 4> trailing; |
11124 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
11125 | { |
11126 | cp_lexer_consume_token (lexer: parser->lexer); |
11127 | tree elt = cp_parser_type_id (parser); |
11128 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11129 | { |
11130 | cp_lexer_consume_token (lexer: parser->lexer); |
11131 | elt = make_pack_expansion (elt); |
11132 | } |
11133 | if (elt == error_mark_node) |
11134 | return error_mark_node; |
11135 | trailing.safe_push (obj: elt); |
11136 | } |
11137 | type2 = make_tree_vec (trailing.length ()); |
11138 | for (int i = 0; i < TREE_VEC_LENGTH (type2); ++i) |
11139 | TREE_VEC_ELT (type2, i) = trailing[i]; |
11140 | } |
11141 | |
11142 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11143 | if (kind == CPTK_TYPE_PACK_ELEMENT) |
11144 | /* cp_parser_enclosed_template_argument_list above already took care |
11145 | of parsing the closing '>'. */; |
11146 | else |
11147 | parens.require_close (parser); |
11148 | |
11149 | /* Construct a location of the form: |
11150 | __is_trivially_copyable(_Tp) |
11151 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
11152 | with start == caret, finishing at the close-paren. */ |
11153 | location_t trait_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
11154 | |
11155 | /* Complete the trait expression, which may mean either processing |
11156 | the trait expr now or saving it for template instantiation. */ |
11157 | switch (kind) |
11158 | { |
11159 | case CPTK_BASES: |
11160 | return cp_expr (finish_bases (type1, false), trait_loc); |
11161 | case CPTK_DIRECT_BASES: |
11162 | return cp_expr (finish_bases (type1, true), trait_loc); |
11163 | default: |
11164 | if (type) |
11165 | return finish_trait_type (kind, type1, type2, tf_warning_or_error); |
11166 | else |
11167 | return finish_trait_expr (trait_loc, kind, type1, type2); |
11168 | } |
11169 | } |
11170 | |
11171 | /* Parse a lambda expression. |
11172 | |
11173 | lambda-expression: |
11174 | lambda-introducer lambda-declarator [opt] compound-statement |
11175 | lambda-introducer < template-parameter-list > requires-clause [opt] |
11176 | lambda-declarator [opt] compound-statement |
11177 | |
11178 | Returns a representation of the expression. */ |
11179 | |
11180 | static cp_expr |
11181 | cp_parser_lambda_expression (cp_parser* parser) |
11182 | { |
11183 | tree lambda_expr = build_lambda_expr (); |
11184 | tree type; |
11185 | bool ok = true; |
11186 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
11187 | cp_token_position start = 0; |
11188 | |
11189 | LAMBDA_EXPR_LOCATION (lambda_expr) = token->location; |
11190 | |
11191 | if (cxx_dialect >= cxx20) |
11192 | { |
11193 | /* C++20 allows lambdas in unevaluated context, but one in the type of a |
11194 | non-type parameter is nonsensical. |
11195 | |
11196 | Distinguish a lambda in the parameter type from a lambda in the |
11197 | default argument by looking at local_variables_forbidden_p, which is |
11198 | only set in default arguments. */ |
11199 | if (processing_template_parmlist && !parser->local_variables_forbidden_p) |
11200 | { |
11201 | error_at (token->location, |
11202 | "lambda-expression in template parameter type" ); |
11203 | token->error_reported = true; |
11204 | ok = false; |
11205 | } |
11206 | } |
11207 | else if (cp_unevaluated_operand) |
11208 | { |
11209 | if (!token->error_reported) |
11210 | { |
11211 | error_at (LAMBDA_EXPR_LOCATION (lambda_expr), |
11212 | "lambda-expression in unevaluated context" |
11213 | " only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
11214 | token->error_reported = true; |
11215 | } |
11216 | ok = false; |
11217 | } |
11218 | else if (parser->in_template_argument_list_p || processing_template_parmlist) |
11219 | { |
11220 | if (!token->error_reported) |
11221 | { |
11222 | error_at (token->location, "lambda-expression in template-argument" |
11223 | " only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
11224 | token->error_reported = true; |
11225 | } |
11226 | ok = false; |
11227 | } |
11228 | |
11229 | /* We may be in the middle of deferred access check. Disable |
11230 | it now. */ |
11231 | push_deferring_access_checks (dk_no_deferred); |
11232 | |
11233 | cp_parser_lambda_introducer (parser, lambda_expr); |
11234 | if (cp_parser_error_occurred (parser)) |
11235 | return error_mark_node; |
11236 | |
11237 | type = begin_lambda_type (lambda_expr); |
11238 | if (type == error_mark_node) |
11239 | return error_mark_node; |
11240 | |
11241 | record_lambda_scope (lambda: lambda_expr); |
11242 | record_lambda_scope_discriminator (lambda: lambda_expr); |
11243 | |
11244 | /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ |
11245 | determine_visibility (TYPE_NAME (type)); |
11246 | |
11247 | /* Now that we've started the type, add the capture fields for any |
11248 | explicit captures. */ |
11249 | register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); |
11250 | |
11251 | { |
11252 | /* Inside the class, surrounding template-parameter-lists do not apply. */ |
11253 | unsigned int saved_num_template_parameter_lists |
11254 | = parser->num_template_parameter_lists; |
11255 | unsigned char in_statement = parser->in_statement; |
11256 | bool in_switch_statement_p = parser->in_switch_statement_p; |
11257 | bool fully_implicit_function_template_p |
11258 | = parser->fully_implicit_function_template_p; |
11259 | tree implicit_template_parms = parser->implicit_template_parms; |
11260 | cp_binding_level* implicit_template_scope = parser->implicit_template_scope; |
11261 | bool auto_is_implicit_function_template_parm_p |
11262 | = parser->auto_is_implicit_function_template_parm_p; |
11263 | |
11264 | parser->num_template_parameter_lists = 0; |
11265 | parser->in_statement = 0; |
11266 | parser->in_switch_statement_p = false; |
11267 | parser->fully_implicit_function_template_p = false; |
11268 | parser->implicit_template_parms = 0; |
11269 | parser->implicit_template_scope = 0; |
11270 | parser->auto_is_implicit_function_template_parm_p = false; |
11271 | |
11272 | /* The body of a lambda in a discarded statement is not discarded. */ |
11273 | bool discarded = in_discarded_stmt; |
11274 | in_discarded_stmt = 0; |
11275 | |
11276 | /* Similarly the body of a lambda in immediate function context is not |
11277 | in immediate function context. */ |
11278 | bool save_in_consteval_if_p = in_consteval_if_p; |
11279 | in_consteval_if_p = false; |
11280 | |
11281 | /* By virtue of defining a local class, a lambda expression has access to |
11282 | the private variables of enclosing classes. */ |
11283 | |
11284 | if (cp_parser_start_tentative_firewall (parser)) |
11285 | start = token; |
11286 | |
11287 | ok &= cp_parser_lambda_declarator_opt (parser, lambda_expr); |
11288 | |
11289 | if (ok && cp_parser_error_occurred (parser)) |
11290 | ok = false; |
11291 | |
11292 | if (ok) |
11293 | cp_parser_lambda_body (parser, lambda_expr); |
11294 | else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) |
11295 | { |
11296 | if (cp_parser_skip_to_closing_brace (parser)) |
11297 | cp_lexer_consume_token (lexer: parser->lexer); |
11298 | } |
11299 | |
11300 | /* The capture list was built up in reverse order; fix that now. */ |
11301 | LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) |
11302 | = nreverse (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); |
11303 | |
11304 | if (ok) |
11305 | maybe_add_lambda_conv_op (type); |
11306 | |
11307 | finish_struct (type, /*attributes=*/NULL_TREE); |
11308 | |
11309 | in_consteval_if_p = save_in_consteval_if_p; |
11310 | in_discarded_stmt = discarded; |
11311 | |
11312 | parser->num_template_parameter_lists = saved_num_template_parameter_lists; |
11313 | parser->in_statement = in_statement; |
11314 | parser->in_switch_statement_p = in_switch_statement_p; |
11315 | parser->fully_implicit_function_template_p |
11316 | = fully_implicit_function_template_p; |
11317 | parser->implicit_template_parms = implicit_template_parms; |
11318 | parser->implicit_template_scope = implicit_template_scope; |
11319 | parser->auto_is_implicit_function_template_parm_p |
11320 | = auto_is_implicit_function_template_parm_p; |
11321 | } |
11322 | |
11323 | /* This field is only used during parsing of the lambda. */ |
11324 | LAMBDA_EXPR_THIS_CAPTURE (lambda_expr) = NULL_TREE; |
11325 | |
11326 | /* This lambda shouldn't have any proxies left at this point. */ |
11327 | gcc_assert (LAMBDA_EXPR_PENDING_PROXIES (lambda_expr) == NULL); |
11328 | /* And now that we're done, push proxies for an enclosing lambda. */ |
11329 | insert_pending_capture_proxies (); |
11330 | |
11331 | /* Update the lambda expression to a range. */ |
11332 | LAMBDA_EXPR_LOCATION (lambda_expr) = make_location (caret: token->location, |
11333 | start: token->location, |
11334 | lexer: parser->lexer); |
11335 | |
11336 | if (ok) |
11337 | lambda_expr = build_lambda_object (lambda_expr); |
11338 | else |
11339 | lambda_expr = error_mark_node; |
11340 | |
11341 | cp_parser_end_tentative_firewall (parser, start, expr: lambda_expr); |
11342 | |
11343 | pop_deferring_access_checks (); |
11344 | |
11345 | return lambda_expr; |
11346 | } |
11347 | |
11348 | /* Parse the beginning of a lambda expression. |
11349 | |
11350 | lambda-introducer: |
11351 | [ lambda-capture [opt] ] |
11352 | |
11353 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
11354 | |
11355 | static void |
11356 | cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) |
11357 | { |
11358 | /* Need commas after the first capture. */ |
11359 | bool first = true; |
11360 | |
11361 | /* Eat the leading `['. */ |
11362 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
11363 | |
11364 | /* Record default capture mode. "[&" "[=" "[&," "[=," */ |
11365 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND) |
11366 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_ELLIPSIS) |
11367 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME) |
11368 | && !cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11369 | LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE; |
11370 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
11371 | LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY; |
11372 | |
11373 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE) |
11374 | { |
11375 | cp_lexer_consume_token (lexer: parser->lexer); |
11376 | first = false; |
11377 | |
11378 | if (!(at_function_scope_p () || parsing_nsdmi ())) |
11379 | error ("non-local lambda expression cannot have a capture-default" ); |
11380 | } |
11381 | |
11382 | hash_set<tree, true> ids; |
11383 | tree first_capture_id = NULL_TREE; |
11384 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
11385 | { |
11386 | cp_token* capture_token; |
11387 | tree capture_id; |
11388 | tree capture_init_expr; |
11389 | cp_id_kind idk = CP_ID_KIND_NONE; |
11390 | bool explicit_init_p = false; |
11391 | |
11392 | enum capture_kind_type |
11393 | { |
11394 | BY_COPY, |
11395 | BY_REFERENCE |
11396 | }; |
11397 | enum capture_kind_type capture_kind = BY_COPY; |
11398 | |
11399 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
11400 | { |
11401 | error ("expected end of capture-list" ); |
11402 | return; |
11403 | } |
11404 | |
11405 | if (first) |
11406 | first = false; |
11407 | else |
11408 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
11409 | |
11410 | /* Possibly capture `this'. */ |
11411 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_THIS)) |
11412 | { |
11413 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11414 | if (cxx_dialect < cxx20 && pedantic |
11415 | && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY) |
11416 | pedwarn (loc, OPT_Wc__20_extensions, |
11417 | "explicit by-copy capture of %<this%> " |
11418 | "with by-copy capture default only available with " |
11419 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11420 | cp_lexer_consume_token (lexer: parser->lexer); |
11421 | if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) |
11422 | pedwarn (input_location, 0, |
11423 | "already captured %qD in lambda expression" , |
11424 | this_identifier); |
11425 | else |
11426 | add_capture (lambda_expr, /*id=*/this_identifier, |
11427 | /*initializer=*/finish_this_expr (), |
11428 | /*by_reference_p=*/true, explicit_init_p); |
11429 | continue; |
11430 | } |
11431 | |
11432 | /* Possibly capture `*this'. */ |
11433 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT) |
11434 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11435 | { |
11436 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11437 | if (cxx_dialect < cxx17) |
11438 | pedwarn (loc, OPT_Wc__17_extensions, |
11439 | "%<*this%> capture only available with " |
11440 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
11441 | cp_lexer_consume_token (lexer: parser->lexer); |
11442 | cp_lexer_consume_token (lexer: parser->lexer); |
11443 | if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) |
11444 | pedwarn (input_location, 0, |
11445 | "already captured %qD in lambda expression" , |
11446 | this_identifier); |
11447 | else |
11448 | add_capture (lambda_expr, /*id=*/this_identifier, |
11449 | /*initializer=*/finish_this_expr (), |
11450 | /*by_reference_p=*/false, explicit_init_p); |
11451 | continue; |
11452 | } |
11453 | |
11454 | /* But reject `&this'. */ |
11455 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND) |
11456 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_THIS)) |
11457 | { |
11458 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
11459 | "%<this%> cannot be captured by reference" ); |
11460 | cp_lexer_consume_token (lexer: parser->lexer); |
11461 | cp_lexer_consume_token (lexer: parser->lexer); |
11462 | continue; |
11463 | } |
11464 | |
11465 | /* Remember whether we want to capture as a reference or not. */ |
11466 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND)) |
11467 | { |
11468 | capture_kind = BY_REFERENCE; |
11469 | cp_lexer_consume_token (lexer: parser->lexer); |
11470 | } |
11471 | |
11472 | bool init_pack_expansion = false; |
11473 | location_t ellipsis_loc = UNKNOWN_LOCATION; |
11474 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11475 | { |
11476 | ellipsis_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11477 | if (cxx_dialect < cxx20) |
11478 | pedwarn (ellipsis_loc, OPT_Wc__20_extensions, |
11479 | "pack init-capture only available with " |
11480 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11481 | cp_lexer_consume_token (lexer: parser->lexer); |
11482 | init_pack_expansion = true; |
11483 | } |
11484 | |
11485 | /* Early C++20 drafts had ...& instead of &...; be forgiving. */ |
11486 | if (init_pack_expansion && capture_kind != BY_REFERENCE |
11487 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND)) |
11488 | { |
11489 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
11490 | 0, "%<&%> should come before %<...%>" ); |
11491 | capture_kind = BY_REFERENCE; |
11492 | cp_lexer_consume_token (lexer: parser->lexer); |
11493 | } |
11494 | |
11495 | /* Get the identifier. */ |
11496 | capture_token = cp_lexer_peek_token (lexer: parser->lexer); |
11497 | capture_id = cp_parser_identifier (parser); |
11498 | |
11499 | if (capture_id == error_mark_node) |
11500 | /* Would be nice to have a cp_parser_skip_to_closing_x for general |
11501 | delimiters, but I modified this to stop on unnested ']' as well. It |
11502 | was already changed to stop on unnested '}', so the |
11503 | "closing_parenthesis" name is no more misleading with my change. */ |
11504 | { |
11505 | cp_parser_skip_to_closing_parenthesis (parser, |
11506 | /*recovering=*/true, |
11507 | /*or_comma=*/true, |
11508 | /*consume_paren=*/true); |
11509 | break; |
11510 | } |
11511 | |
11512 | /* Find the initializer for this capture. */ |
11513 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
11514 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
11515 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
11516 | { |
11517 | /* An explicit initializer exists. */ |
11518 | if (cxx_dialect < cxx14) |
11519 | pedwarn (input_location, OPT_Wc__14_extensions, |
11520 | "lambda capture initializers " |
11521 | "only available with %<-std=c++14%> or %<-std=gnu++14%>" ); |
11522 | capture_init_expr = cp_parser_initializer (parser, |
11523 | /*direct_init=*/nullptr, |
11524 | /*non_constant=*/nullptr, |
11525 | /*subexpression_p=*/true); |
11526 | explicit_init_p = true; |
11527 | if (capture_init_expr == NULL_TREE) |
11528 | { |
11529 | error ("empty initializer for lambda init-capture" ); |
11530 | capture_init_expr = error_mark_node; |
11531 | } |
11532 | if (init_pack_expansion) |
11533 | capture_init_expr = make_pack_expansion (capture_init_expr); |
11534 | } |
11535 | else |
11536 | { |
11537 | const char* error_msg; |
11538 | |
11539 | /* Turn the identifier into an id-expression. */ |
11540 | capture_init_expr |
11541 | = cp_parser_lookup_name_simple (parser, capture_id, |
11542 | capture_token->location); |
11543 | |
11544 | if (capture_init_expr == error_mark_node) |
11545 | { |
11546 | unqualified_name_lookup_error (capture_id); |
11547 | continue; |
11548 | } |
11549 | else if (!VAR_P (capture_init_expr) |
11550 | && TREE_CODE (capture_init_expr) != PARM_DECL) |
11551 | { |
11552 | error_at (capture_token->location, |
11553 | "capture of non-variable %qE" , |
11554 | capture_init_expr); |
11555 | if (DECL_P (capture_init_expr)) |
11556 | inform (DECL_SOURCE_LOCATION (capture_init_expr), |
11557 | "%q#D declared here" , capture_init_expr); |
11558 | continue; |
11559 | } |
11560 | if (VAR_P (capture_init_expr) |
11561 | && decl_storage_duration (capture_init_expr) != dk_auto) |
11562 | { |
11563 | if (pedwarn (capture_token->location, 0, "capture of variable " |
11564 | "%qD with non-automatic storage duration" , |
11565 | capture_init_expr)) |
11566 | inform (DECL_SOURCE_LOCATION (capture_init_expr), |
11567 | "%q#D declared here" , capture_init_expr); |
11568 | continue; |
11569 | } |
11570 | |
11571 | capture_init_expr |
11572 | = finish_id_expression |
11573 | (capture_id, |
11574 | capture_init_expr, |
11575 | parser->scope, |
11576 | &idk, |
11577 | /*integral_constant_expression_p=*/false, |
11578 | /*allow_non_integral_constant_expression_p=*/false, |
11579 | /*non_integral_constant_expression_p=*/NULL, |
11580 | /*template_p=*/false, |
11581 | /*done=*/true, |
11582 | /*address_p=*/false, |
11583 | /*template_arg_p=*/false, |
11584 | &error_msg, |
11585 | capture_token->location); |
11586 | |
11587 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
11588 | { |
11589 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11590 | cp_lexer_consume_token (lexer: parser->lexer); |
11591 | capture_init_expr = make_pack_expansion (capture_init_expr); |
11592 | if (init_pack_expansion) |
11593 | { |
11594 | /* If what follows is an initializer, the second '...' is |
11595 | invalid. But for cases like [...xs...], the first one |
11596 | is invalid. */ |
11597 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
11598 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
11599 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
11600 | ellipsis_loc = loc; |
11601 | error_at (ellipsis_loc, "too many %<...%> in lambda capture" ); |
11602 | continue; |
11603 | } |
11604 | } |
11605 | } |
11606 | |
11607 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE |
11608 | && !explicit_init_p) |
11609 | { |
11610 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY |
11611 | && capture_kind == BY_COPY) |
11612 | pedwarn (capture_token->location, 0, "explicit by-copy capture " |
11613 | "of %qD redundant with by-copy capture default" , |
11614 | capture_id); |
11615 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_REFERENCE |
11616 | && capture_kind == BY_REFERENCE) |
11617 | pedwarn (capture_token->location, 0, "explicit by-reference " |
11618 | "capture of %qD redundant with by-reference capture " |
11619 | "default" , capture_id); |
11620 | } |
11621 | |
11622 | /* Check for duplicates. |
11623 | Optimize for the zero or one explicit captures cases and only create |
11624 | the hash_set after adding second capture. */ |
11625 | bool found = false; |
11626 | if (!ids.is_empty ()) |
11627 | found = ids.add (k: capture_id); |
11628 | else if (first_capture_id == NULL_TREE) |
11629 | first_capture_id = capture_id; |
11630 | else if (capture_id == first_capture_id) |
11631 | found = true; |
11632 | else |
11633 | { |
11634 | ids.add (k: first_capture_id); |
11635 | ids.add (k: capture_id); |
11636 | } |
11637 | if (found) |
11638 | pedwarn (input_location, 0, |
11639 | "already captured %qD in lambda expression" , capture_id); |
11640 | else |
11641 | add_capture (lambda_expr, capture_id, capture_init_expr, |
11642 | /*by_reference_p=*/capture_kind == BY_REFERENCE, |
11643 | explicit_init_p); |
11644 | |
11645 | /* If there is any qualification still in effect, clear it |
11646 | now; we will be starting fresh with the next capture. */ |
11647 | parser->scope = NULL_TREE; |
11648 | parser->qualifying_scope = NULL_TREE; |
11649 | parser->object_scope = NULL_TREE; |
11650 | } |
11651 | |
11652 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
11653 | } |
11654 | |
11655 | /* Parse the (optional) middle of a lambda expression. |
11656 | |
11657 | lambda-declarator: |
11658 | ( parameter-declaration-clause ) lambda-specifiers requires-clause [opt] |
11659 | lambda-specifiers (C++23) |
11660 | |
11661 | lambda-specifiers: |
11662 | decl-specifier-seq [opt] noexcept-specifier [opt] |
11663 | attribute-specifier-seq [opt] trailing-return-type [opt] |
11664 | |
11665 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
11666 | |
11667 | static bool |
11668 | cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) |
11669 | { |
11670 | /* 5.1.1.4 of the standard says: |
11671 | If a lambda-expression does not include a lambda-declarator, it is as if |
11672 | the lambda-declarator were (). |
11673 | This means an empty parameter list, no attributes, and no exception |
11674 | specification. */ |
11675 | tree param_list = void_list_node; |
11676 | tree std_attrs = NULL_TREE; |
11677 | tree gnu_attrs = NULL_TREE; |
11678 | tree exception_spec = NULL_TREE; |
11679 | tree template_param_list = NULL_TREE; |
11680 | tree tx_qual = NULL_TREE; |
11681 | tree return_type = NULL_TREE; |
11682 | tree trailing_requires_clause = NULL_TREE; |
11683 | bool has_param_list = false; |
11684 | location_t omitted_parms_loc = UNKNOWN_LOCATION; |
11685 | cp_decl_specifier_seq lambda_specs; |
11686 | clear_decl_specs (decl_specs: &lambda_specs); |
11687 | /* A lambda op() is const unless explicitly 'mutable'. */ |
11688 | cp_cv_quals quals = TYPE_QUAL_CONST; |
11689 | |
11690 | /* The template-parameter-list is optional, but must begin with |
11691 | an opening angle if present. */ |
11692 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
11693 | { |
11694 | if (cxx_dialect < cxx20 |
11695 | && (pedantic || cxx_dialect < cxx14)) |
11696 | pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions, |
11697 | "lambda templates are only available with " |
11698 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
11699 | |
11700 | cp_lexer_consume_token (lexer: parser->lexer); |
11701 | |
11702 | template_param_list = cp_parser_template_parameter_list (parser); |
11703 | cp_parser_require_end_of_template_parameter_list (parser); |
11704 | |
11705 | /* We may have a constrained generic lambda; parse the requires-clause |
11706 | immediately after the template-parameter-list and combine with any |
11707 | shorthand constraints present. */ |
11708 | tree dreqs = cp_parser_requires_clause_opt (parser, true); |
11709 | if (flag_concepts) |
11710 | { |
11711 | tree reqs = get_shorthand_constraints (current_template_parms); |
11712 | if (dreqs) |
11713 | reqs = combine_constraint_expressions (reqs, dreqs); |
11714 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
11715 | } |
11716 | |
11717 | /* We just processed one more parameter list. */ |
11718 | ++parser->num_template_parameter_lists; |
11719 | } |
11720 | |
11721 | /* Committee discussion supports allowing attributes here. */ |
11722 | lambda_specs.attributes = cp_parser_attributes_opt (parser); |
11723 | |
11724 | /* The parameter-declaration-clause is optional (unless |
11725 | template-parameter-list was given), but must begin with an |
11726 | opening parenthesis if present. */ |
11727 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
11728 | { |
11729 | matching_parens parens; |
11730 | parens.consume_open (parser); |
11731 | |
11732 | begin_scope (sk_function_parms, /*entity=*/NULL_TREE); |
11733 | |
11734 | /* Parse parameters. */ |
11735 | param_list |
11736 | = cp_parser_parameter_declaration_clause |
11737 | (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL); |
11738 | |
11739 | /* Default arguments shall not be specified in the |
11740 | parameter-declaration-clause of a lambda-declarator. */ |
11741 | if (pedantic && cxx_dialect < cxx14) |
11742 | for (tree t = param_list; t; t = TREE_CHAIN (t)) |
11743 | if (TREE_PURPOSE (t) && DECL_P (TREE_VALUE (t))) |
11744 | pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), |
11745 | OPT_Wc__14_extensions, |
11746 | "default argument specified for lambda parameter" ); |
11747 | |
11748 | parens.require_close (parser); |
11749 | has_param_list = true; |
11750 | } |
11751 | else if (cxx_dialect < cxx23) |
11752 | omitted_parms_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
11753 | |
11754 | /* In the decl-specifier-seq of the lambda-declarator, each |
11755 | decl-specifier shall either be mutable or constexpr. */ |
11756 | int declares_class_or_enum; |
11757 | if (cp_lexer_next_token_is_decl_specifier_keyword (lexer: parser->lexer)) |
11758 | cp_parser_decl_specifier_seq (parser, |
11759 | CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR, |
11760 | &lambda_specs, &declares_class_or_enum); |
11761 | |
11762 | if (omitted_parms_loc && lambda_specs.any_specifiers_p) |
11763 | { |
11764 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11765 | "parameter declaration before lambda declaration " |
11766 | "specifiers only optional with %<-std=c++2b%> or " |
11767 | "%<-std=gnu++2b%>" ); |
11768 | omitted_parms_loc = UNKNOWN_LOCATION; |
11769 | } |
11770 | |
11771 | if (lambda_specs.storage_class == sc_mutable) |
11772 | { |
11773 | LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1; |
11774 | quals = TYPE_UNQUALIFIED; |
11775 | } |
11776 | else if (lambda_specs.storage_class == sc_static) |
11777 | { |
11778 | if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE |
11779 | || LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)) |
11780 | error_at (lambda_specs.locations[ds_storage_class], |
11781 | "%<static%> lambda specifier with lambda capture" ); |
11782 | else |
11783 | { |
11784 | LAMBDA_EXPR_STATIC_P (lambda_expr) = 1; |
11785 | quals = TYPE_UNQUALIFIED; |
11786 | } |
11787 | } |
11788 | |
11789 | tx_qual = cp_parser_tx_qualifier_opt (parser); |
11790 | if (omitted_parms_loc && tx_qual) |
11791 | { |
11792 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11793 | "parameter declaration before lambda transaction " |
11794 | "qualifier only optional with %<-std=c++2b%> or " |
11795 | "%<-std=gnu++2b%>" ); |
11796 | omitted_parms_loc = UNKNOWN_LOCATION; |
11797 | } |
11798 | |
11799 | /* Parse optional exception specification. */ |
11800 | exception_spec |
11801 | = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE); |
11802 | |
11803 | if (omitted_parms_loc && exception_spec) |
11804 | { |
11805 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11806 | "parameter declaration before lambda exception " |
11807 | "specification only optional with %<-std=c++2b%> or " |
11808 | "%<-std=gnu++2b%>" ); |
11809 | omitted_parms_loc = UNKNOWN_LOCATION; |
11810 | } |
11811 | |
11812 | /* GCC 8 accepted attributes here, and this is the place for standard C++11 |
11813 | attributes that appertain to the function type. */ |
11814 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
11815 | gnu_attrs = cp_parser_gnu_attributes_opt (parser); |
11816 | else |
11817 | std_attrs = cp_parser_std_attribute_spec_seq (parser); |
11818 | |
11819 | /* Parse optional trailing return type. */ |
11820 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
11821 | { |
11822 | if (omitted_parms_loc) |
11823 | pedwarn (omitted_parms_loc, OPT_Wc__23_extensions, |
11824 | "parameter declaration before lambda trailing " |
11825 | "return type only optional with %<-std=c++2b%> or " |
11826 | "%<-std=gnu++2b%>" ); |
11827 | cp_lexer_consume_token (lexer: parser->lexer); |
11828 | return_type = cp_parser_trailing_type_id (parser); |
11829 | } |
11830 | |
11831 | /* Also allow GNU attributes at the very end of the declaration, the usual |
11832 | place for GNU attributes. */ |
11833 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
11834 | gnu_attrs = chainon (gnu_attrs, cp_parser_gnu_attributes_opt (parser)); |
11835 | |
11836 | if (has_param_list) |
11837 | { |
11838 | /* Parse optional trailing requires clause. */ |
11839 | trailing_requires_clause = cp_parser_requires_clause_opt (parser, false); |
11840 | |
11841 | /* The function parameters must be in scope all the way until after the |
11842 | trailing-return-type in case of decltype. */ |
11843 | pop_bindings_and_leave_scope (); |
11844 | } |
11845 | |
11846 | /* Create the function call operator. |
11847 | |
11848 | Messing with declarators like this is no uglier than building up the |
11849 | FUNCTION_DECL by hand, and this is less likely to get out of sync with |
11850 | other code. */ |
11851 | { |
11852 | cp_decl_specifier_seq return_type_specs; |
11853 | cp_declarator* declarator; |
11854 | tree fco; |
11855 | void *p; |
11856 | |
11857 | clear_decl_specs (decl_specs: &return_type_specs); |
11858 | return_type_specs.type = make_auto (); |
11859 | |
11860 | if (lambda_specs.locations[ds_constexpr]) |
11861 | { |
11862 | if (cxx_dialect >= cxx17) |
11863 | return_type_specs.locations[ds_constexpr] |
11864 | = lambda_specs.locations[ds_constexpr]; |
11865 | else |
11866 | error_at (lambda_specs.locations[ds_constexpr], "%<constexpr%> " |
11867 | "lambda only available with %<-std=c++17%> or " |
11868 | "%<-std=gnu++17%>" ); |
11869 | } |
11870 | if (lambda_specs.locations[ds_consteval]) |
11871 | return_type_specs.locations[ds_consteval] |
11872 | = lambda_specs.locations[ds_consteval]; |
11873 | if (LAMBDA_EXPR_STATIC_P (lambda_expr)) |
11874 | { |
11875 | return_type_specs.storage_class = sc_static; |
11876 | return_type_specs.locations[ds_storage_class] |
11877 | = lambda_specs.locations[ds_storage_class]; |
11878 | } |
11879 | |
11880 | p = obstack_alloc (&declarator_obstack, 0); |
11881 | |
11882 | declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk: sfk_none, |
11883 | LAMBDA_EXPR_LOCATION (lambda_expr)); |
11884 | |
11885 | declarator = make_call_declarator (target: declarator, parms: param_list, cv_qualifiers: quals, |
11886 | virt_specifiers: VIRT_SPEC_UNSPECIFIED, |
11887 | ref_qualifier: REF_QUAL_NONE, |
11888 | tx_qualifier: tx_qual, |
11889 | exception_specification: exception_spec, |
11890 | late_return_type: return_type, |
11891 | requires_clause: trailing_requires_clause, |
11892 | std_attrs, |
11893 | UNKNOWN_LOCATION); |
11894 | |
11895 | fco = grokmethod (&return_type_specs, |
11896 | declarator, |
11897 | chainon (gnu_attrs, lambda_specs.attributes)); |
11898 | if (fco != error_mark_node) |
11899 | { |
11900 | DECL_INITIALIZED_IN_CLASS_P (fco) = 1; |
11901 | DECL_ARTIFICIAL (fco) = 1; |
11902 | if (!LAMBDA_EXPR_STATIC_P (lambda_expr)) |
11903 | /* Give the object parameter a different name. */ |
11904 | DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier; |
11905 | DECL_SET_LAMBDA_FUNCTION (fco, true); |
11906 | } |
11907 | if (template_param_list) |
11908 | { |
11909 | fco = finish_member_template_decl (fco); |
11910 | finish_template_decl (template_param_list); |
11911 | --parser->num_template_parameter_lists; |
11912 | } |
11913 | else if (parser->fully_implicit_function_template_p) |
11914 | fco = finish_fully_implicit_template (parser, fco); |
11915 | |
11916 | finish_member_declaration (fco); |
11917 | record_lambda_scope_sig_discriminator (lambda: lambda_expr, fn: fco); |
11918 | |
11919 | obstack_free (&declarator_obstack, p); |
11920 | |
11921 | return (fco != error_mark_node); |
11922 | } |
11923 | } |
11924 | |
11925 | /* Parse the body of a lambda expression, which is simply |
11926 | |
11927 | compound-statement |
11928 | |
11929 | but which requires special handling. |
11930 | LAMBDA_EXPR is the current representation of the lambda expression. */ |
11931 | |
11932 | static void |
11933 | cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) |
11934 | { |
11935 | bool nested = (current_function_decl != NULL_TREE); |
11936 | unsigned char local_variables_forbidden_p |
11937 | = parser->local_variables_forbidden_p; |
11938 | bool in_function_body = parser->in_function_body; |
11939 | |
11940 | /* The body of a lambda-expression is not a subexpression of the enclosing |
11941 | expression. */ |
11942 | cp_evaluated ev; |
11943 | |
11944 | if (nested) |
11945 | push_function_context (); |
11946 | else |
11947 | /* Still increment function_depth so that we don't GC in the |
11948 | middle of an expression. */ |
11949 | ++function_depth; |
11950 | |
11951 | auto odsd = make_temp_override (var&: parser->omp_declare_simd, NULL); |
11952 | auto ord = make_temp_override (var&: parser->oacc_routine, NULL); |
11953 | auto oafp = make_temp_override (var&: parser->omp_attrs_forbidden_p, overrider: false); |
11954 | vec<tree> omp_privatization_save; |
11955 | save_omp_privatization_clauses (omp_privatization_save); |
11956 | /* Clear this in case we're in the middle of a default argument. */ |
11957 | parser->local_variables_forbidden_p = 0; |
11958 | parser->in_function_body = true; |
11959 | |
11960 | { |
11961 | local_specialization_stack s (lss_copy); |
11962 | tree fco = lambda_function (lambda_expr); |
11963 | tree body = start_lambda_function (fn: fco, lambda_expr); |
11964 | |
11965 | /* Originally C++11 required us to peek for 'return expr'; and |
11966 | process it specially here to deduce the return type. N3638 |
11967 | removed the need for that. */ |
11968 | cp_parser_function_body (parser, false); |
11969 | |
11970 | finish_lambda_function (body); |
11971 | } |
11972 | |
11973 | restore_omp_privatization_clauses (omp_privatization_save); |
11974 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
11975 | parser->in_function_body = in_function_body; |
11976 | if (nested) |
11977 | pop_function_context(); |
11978 | else |
11979 | --function_depth; |
11980 | } |
11981 | |
11982 | /* Statements [gram.stmt.stmt] */ |
11983 | |
11984 | /* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ |
11985 | |
11986 | static void |
11987 | add_debug_begin_stmt (location_t loc) |
11988 | { |
11989 | if (!MAY_HAVE_DEBUG_MARKER_STMTS) |
11990 | return; |
11991 | if (DECL_DECLARED_CONCEPT_P (current_function_decl)) |
11992 | /* A concept is never expanded normally. */ |
11993 | return; |
11994 | |
11995 | tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node); |
11996 | SET_EXPR_LOCATION (stmt, loc); |
11997 | add_stmt (stmt); |
11998 | } |
11999 | |
12000 | struct cp_omp_attribute_data |
12001 | { |
12002 | cp_token_cache *tokens; |
12003 | const c_omp_directive *dir; |
12004 | c_omp_directive_kind kind; |
12005 | }; |
12006 | |
12007 | /* Handle omp::directive and omp::sequence attributes in ATTRS |
12008 | (if any) at the start of a statement or in attribute-declaration. */ |
12009 | |
12010 | static tree |
12011 | cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) |
12012 | { |
12013 | if (!flag_openmp && !flag_openmp_simd) |
12014 | return attrs; |
12015 | |
12016 | auto_vec<cp_omp_attribute_data, 16> vec; |
12017 | int cnt = 0; |
12018 | int tokens = 0; |
12019 | bool bad = false; |
12020 | for (tree *pa = &attrs; *pa; ) |
12021 | if (get_attribute_namespace (*pa) == omp_identifier |
12022 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
12023 | { |
12024 | cnt++; |
12025 | for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) |
12026 | { |
12027 | tree d = TREE_VALUE (a); |
12028 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
12029 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
12030 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
12031 | if (parser->omp_attrs_forbidden_p) |
12032 | { |
12033 | error_at (first->location, |
12034 | "mixing OpenMP directives with attribute and pragma " |
12035 | "syntax on the same statement" ); |
12036 | parser->omp_attrs_forbidden_p = false; |
12037 | bad = true; |
12038 | } |
12039 | else if (TREE_PUBLIC (d)) |
12040 | { |
12041 | error_at (first->location, |
12042 | "OpenMP %<omp::decl%> attribute on a statement" ); |
12043 | bad = true; |
12044 | } |
12045 | const char *directive[3] = {}; |
12046 | for (int i = 0; i < 3; i++) |
12047 | { |
12048 | tree id = NULL_TREE; |
12049 | if (first + i == last) |
12050 | break; |
12051 | if (first[i].type == CPP_NAME) |
12052 | id = first[i].u.value; |
12053 | else if (first[i].type == CPP_KEYWORD) |
12054 | id = ridpointers[(int) first[i].keyword]; |
12055 | else |
12056 | break; |
12057 | directive[i] = IDENTIFIER_POINTER (id); |
12058 | } |
12059 | const c_omp_directive *dir = NULL; |
12060 | if (directive[0]) |
12061 | dir = c_omp_categorize_directive (directive[0], directive[1], |
12062 | directive[2]); |
12063 | if (dir == NULL) |
12064 | { |
12065 | error_at (first->location, |
12066 | "unknown OpenMP directive name in %qs attribute " |
12067 | "argument" , |
12068 | TREE_PUBLIC (d) ? "omp::decl" : "omp::directive" ); |
12069 | continue; |
12070 | } |
12071 | c_omp_directive_kind kind = dir->kind; |
12072 | if (dir->id == PRAGMA_OMP_ORDERED) |
12073 | { |
12074 | /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain |
12075 | depend/doacross clause. */ |
12076 | if (directive[1] |
12077 | && (strcmp (s1: directive[1], s2: "depend" ) == 0 |
12078 | || strcmp (s1: directive[1], s2: "doacross" ) == 0)) |
12079 | kind = C_OMP_DIR_STANDALONE; |
12080 | else if (first + 2 < last |
12081 | && first[1].type == CPP_COMMA |
12082 | && first[2].type == CPP_NAME |
12083 | && (strcmp (IDENTIFIER_POINTER (first[2].u.value), |
12084 | s2: "depend" ) == 0 |
12085 | || strcmp (IDENTIFIER_POINTER (first[2].u.value), |
12086 | s2: "doacross" ) == 0)) |
12087 | kind = C_OMP_DIR_STANDALONE; |
12088 | } |
12089 | else if (dir->id == PRAGMA_OMP_ERROR) |
12090 | { |
12091 | /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */ |
12092 | int paren_depth = 0; |
12093 | for (int i = 1; first + i < last; i++) |
12094 | if (first[i].type == CPP_OPEN_PAREN) |
12095 | paren_depth++; |
12096 | else if (first[i].type == CPP_CLOSE_PAREN) |
12097 | paren_depth--; |
12098 | else if (paren_depth == 0 |
12099 | && first + i + 2 < last |
12100 | && first[i].type == CPP_NAME |
12101 | && first[i + 1].type == CPP_OPEN_PAREN |
12102 | && first[i + 2].type == CPP_NAME |
12103 | && !strcmp (IDENTIFIER_POINTER (first[i].u.value), |
12104 | s2: "at" ) |
12105 | && !strcmp (IDENTIFIER_POINTER (first[i |
12106 | + 2].u.value), |
12107 | s2: "execution" )) |
12108 | { |
12109 | kind = C_OMP_DIR_STANDALONE; |
12110 | break; |
12111 | } |
12112 | } |
12113 | cp_omp_attribute_data v = { DEFPARSE_TOKENS (d), .dir: dir, .kind: kind }; |
12114 | vec.safe_push (obj: v); |
12115 | if (flag_openmp || dir->simd) |
12116 | tokens += (last - first) + 1; |
12117 | } |
12118 | cp_omp_attribute_data v = {}; |
12119 | vec.safe_push (obj: v); |
12120 | *pa = TREE_CHAIN (*pa); |
12121 | } |
12122 | else |
12123 | pa = &TREE_CHAIN (*pa); |
12124 | |
12125 | if (bad) |
12126 | return attrs; |
12127 | |
12128 | unsigned int i; |
12129 | cp_omp_attribute_data *v; |
12130 | cp_omp_attribute_data *construct_seen = nullptr; |
12131 | cp_omp_attribute_data *standalone_seen = nullptr; |
12132 | cp_omp_attribute_data *prev_standalone_seen = nullptr; |
12133 | FOR_EACH_VEC_ELT (vec, i, v) |
12134 | if (v->tokens) |
12135 | { |
12136 | if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen) |
12137 | construct_seen = v; |
12138 | else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen) |
12139 | standalone_seen = v; |
12140 | } |
12141 | else |
12142 | { |
12143 | if (standalone_seen && !prev_standalone_seen) |
12144 | { |
12145 | prev_standalone_seen = standalone_seen; |
12146 | standalone_seen = nullptr; |
12147 | } |
12148 | } |
12149 | |
12150 | if (cnt > 1 && construct_seen) |
12151 | { |
12152 | error_at (construct_seen->tokens->first->location, |
12153 | "OpenMP construct among %<omp::directive%> attributes" |
12154 | " requires all %<omp::directive%> attributes on the" |
12155 | " same statement to be in the same %<omp::sequence%>" ); |
12156 | return attrs; |
12157 | } |
12158 | if (cnt > 1 && standalone_seen && prev_standalone_seen) |
12159 | { |
12160 | error_at (standalone_seen->tokens->first->location, |
12161 | "multiple OpenMP standalone directives among" |
12162 | " %<omp::directive%> attributes must be all within the" |
12163 | " same %<omp::sequence%>" ); |
12164 | return attrs; |
12165 | } |
12166 | |
12167 | if (prev_standalone_seen) |
12168 | standalone_seen = prev_standalone_seen; |
12169 | if (standalone_seen |
12170 | && !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12171 | { |
12172 | error_at (standalone_seen->tokens->first->location, |
12173 | "standalone OpenMP directives in %<omp::directive%> attribute" |
12174 | " can only appear on an empty statement" ); |
12175 | return attrs; |
12176 | } |
12177 | if (cnt && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
12178 | { |
12179 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
12180 | enum pragma_kind kind = cp_parser_pragma_kind (token); |
12181 | if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_) |
12182 | { |
12183 | error_at (token->location, |
12184 | "mixing OpenMP directives with attribute and pragma " |
12185 | "syntax on the same statement" ); |
12186 | return attrs; |
12187 | } |
12188 | } |
12189 | |
12190 | if (!tokens) |
12191 | return attrs; |
12192 | tokens++; |
12193 | cp_lexer *lexer = cp_lexer_alloc (); |
12194 | lexer->debugging_p = parser->lexer->debugging_p; |
12195 | vec_safe_reserve (v&: lexer->buffer, nelems: tokens, exact: true); |
12196 | FOR_EACH_VEC_ELT (vec, i, v) |
12197 | { |
12198 | if (!v->tokens) |
12199 | continue; |
12200 | if (!flag_openmp && !v->dir->simd) |
12201 | continue; |
12202 | cp_token *first = v->tokens->first; |
12203 | cp_token *last = v->tokens->last; |
12204 | cp_token tok = {}; |
12205 | tok.type = CPP_PRAGMA; |
12206 | tok.keyword = RID_MAX; |
12207 | tok.u.value = build_int_cst (NULL, v->dir->id); |
12208 | tok.location = first->location; |
12209 | lexer->buffer->quick_push (obj: tok); |
12210 | while (++first < last) |
12211 | lexer->buffer->quick_push (obj: *first); |
12212 | tok = {}; |
12213 | tok.type = CPP_PRAGMA_EOL; |
12214 | tok.keyword = RID_MAX; |
12215 | tok.location = last->location; |
12216 | lexer->buffer->quick_push (obj: tok); |
12217 | } |
12218 | cp_token tok = {}; |
12219 | tok.type = CPP_EOF; |
12220 | tok.keyword = RID_MAX; |
12221 | tok.location = lexer->buffer->last ().location; |
12222 | lexer->buffer->quick_push (obj: tok); |
12223 | lexer->next = parser->lexer; |
12224 | lexer->next_token = lexer->buffer->address (); |
12225 | lexer->last_token = lexer->next_token |
12226 | + lexer->buffer->length () |
12227 | - 1; |
12228 | lexer->in_omp_attribute_pragma = true; |
12229 | parser->lexer = lexer; |
12230 | /* Move the current source position to that of the first token in the |
12231 | new lexer. */ |
12232 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
12233 | return attrs; |
12234 | } |
12235 | |
12236 | /* True if and only if the name is one of the contract types. */ |
12237 | |
12238 | static bool |
12239 | contract_attribute_p (const_tree id) |
12240 | { |
12241 | return is_attribute_p (attr_name: "assert" , ident: id) |
12242 | || is_attribute_p (attr_name: "pre" , ident: id) |
12243 | || is_attribute_p (attr_name: "post" , ident: id); |
12244 | } |
12245 | |
12246 | /* Handle omp::directive and omp::sequence attributes in *PATTRS |
12247 | (if any) at the start or after declaration-id of a declaration. */ |
12248 | |
12249 | static void |
12250 | cp_parser_handle_directive_omp_attributes (cp_parser *parser, tree *pattrs, |
12251 | cp_omp_declare_simd_data *data, |
12252 | bool start) |
12253 | { |
12254 | if (!flag_openmp && !flag_openmp_simd) |
12255 | return; |
12256 | |
12257 | int cnt = 0; |
12258 | bool bad = false; |
12259 | bool variant_p = false; |
12260 | location_t loc = UNKNOWN_LOCATION; |
12261 | for (tree pa = *pattrs; pa; pa = TREE_CHAIN (pa)) |
12262 | if (get_attribute_namespace (pa) == omp_identifier |
12263 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (pa))) |
12264 | { |
12265 | for (tree a = TREE_VALUE (pa); a; a = TREE_CHAIN (a)) |
12266 | { |
12267 | tree d = TREE_VALUE (a); |
12268 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
12269 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
12270 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
12271 | const char *directive[3] = {}; |
12272 | for (int i = 0; i < 3; i++) |
12273 | { |
12274 | tree id = NULL_TREE; |
12275 | if (first + i == last) |
12276 | break; |
12277 | if (first[i].type == CPP_NAME) |
12278 | id = first[i].u.value; |
12279 | else if (first[i].type == CPP_KEYWORD) |
12280 | id = ridpointers[(int) first[i].keyword]; |
12281 | else |
12282 | break; |
12283 | directive[i] = IDENTIFIER_POINTER (id); |
12284 | } |
12285 | const c_omp_directive *dir = NULL; |
12286 | if (directive[0]) |
12287 | dir = c_omp_categorize_directive (directive[0], directive[1], |
12288 | directive[2]); |
12289 | if (dir == NULL) |
12290 | continue; |
12291 | if (dir->id == PRAGMA_OMP_DECLARE |
12292 | && (strcmp (s1: directive[1], s2: "simd" ) == 0 |
12293 | || strcmp (s1: directive[1], s2: "variant" ) == 0)) |
12294 | { |
12295 | if (cnt++ == 0) |
12296 | { |
12297 | variant_p = strcmp (s1: directive[1], s2: "variant" ) == 0; |
12298 | loc = first->location; |
12299 | } |
12300 | if (start && parser->omp_declare_simd && !bad) |
12301 | { |
12302 | error_at (first->location, |
12303 | "mixing OpenMP directives with attribute and " |
12304 | "pragma syntax on the same declaration" ); |
12305 | bad = true; |
12306 | } |
12307 | } |
12308 | } |
12309 | } |
12310 | |
12311 | if (bad) |
12312 | { |
12313 | for (tree *pa = pattrs; *pa; ) |
12314 | if (get_attribute_namespace (*pa) == omp_identifier |
12315 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
12316 | *pa = TREE_CHAIN (*pa); |
12317 | else |
12318 | pa = &TREE_CHAIN (*pa); |
12319 | return; |
12320 | } |
12321 | if (cnt == 0) |
12322 | return; |
12323 | |
12324 | if (parser->omp_declare_simd == NULL) |
12325 | { |
12326 | data->error_seen = false; |
12327 | data->fndecl_seen = false; |
12328 | data->variant_p = variant_p; |
12329 | data->loc = loc; |
12330 | data->tokens = vNULL; |
12331 | data->attribs[0] = NULL; |
12332 | data->attribs[1] = NULL; |
12333 | parser->omp_declare_simd = data; |
12334 | } |
12335 | parser->omp_declare_simd->attribs[!start] = pattrs; |
12336 | } |
12337 | |
12338 | /* Parse a statement. |
12339 | |
12340 | statement: |
12341 | labeled-statement |
12342 | expression-statement |
12343 | compound-statement |
12344 | selection-statement |
12345 | iteration-statement |
12346 | jump-statement |
12347 | declaration-statement |
12348 | try-block |
12349 | |
12350 | C++11: |
12351 | |
12352 | statement: |
12353 | labeled-statement |
12354 | attribute-specifier-seq (opt) expression-statement |
12355 | attribute-specifier-seq (opt) compound-statement |
12356 | attribute-specifier-seq (opt) selection-statement |
12357 | attribute-specifier-seq (opt) iteration-statement |
12358 | attribute-specifier-seq (opt) jump-statement |
12359 | declaration-statement |
12360 | attribute-specifier-seq (opt) try-block |
12361 | |
12362 | init-statement: |
12363 | expression-statement |
12364 | simple-declaration |
12365 | alias-declaration |
12366 | |
12367 | TM Extension: |
12368 | |
12369 | statement: |
12370 | atomic-statement |
12371 | |
12372 | IN_COMPOUND is true when the statement is nested inside a |
12373 | cp_parser_compound_statement. |
12374 | |
12375 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
12376 | is a (possibly labeled) if statement which is not enclosed in braces |
12377 | and has an else clause. This is used to implement -Wparentheses. |
12378 | |
12379 | CHAIN is a vector of if-else-if conditions. |
12380 | |
12381 | Note that this version of parsing restricts assertions to be attached to |
12382 | empty statements. */ |
12383 | |
12384 | static void |
12385 | cp_parser_statement (cp_parser* parser, tree in_statement_expr, |
12386 | const bool in_compound, bool *if_p, vec<tree> *chain, |
12387 | location_t *loc_after_labels) |
12388 | { |
12389 | tree statement, std_attrs = NULL_TREE; |
12390 | cp_token *token; |
12391 | location_t statement_location, attrs_loc; |
12392 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12393 | bool has_std_attrs; |
12394 | /* A copy of IN_COMPOUND which is set to false after seeing a label. |
12395 | This matters for certain pragmas. */ |
12396 | bool in_compound_for_pragma = in_compound; |
12397 | |
12398 | restart: |
12399 | if (if_p != NULL) |
12400 | *if_p = false; |
12401 | /* There is no statement yet. */ |
12402 | statement = NULL_TREE; |
12403 | |
12404 | saved_token_sentinel saved_tokens (parser->lexer); |
12405 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12406 | attrs_loc = token->location; |
12407 | if (c_dialect_objc ()) |
12408 | /* In obj-c++, seeing '[[' might be the either the beginning of |
12409 | c++11 attributes, or a nested objc-message-expression. So |
12410 | let's parse the c++11 attributes tentatively. */ |
12411 | cp_parser_parse_tentatively (parser); |
12412 | std_attrs = cp_parser_std_attribute_spec_seq (parser); |
12413 | if (std_attrs) |
12414 | attrs_loc = make_location (caret: attrs_loc, start: attrs_loc, lexer: parser->lexer); |
12415 | if (c_dialect_objc ()) |
12416 | { |
12417 | if (!cp_parser_parse_definitely (parser)) |
12418 | std_attrs = NULL_TREE; |
12419 | } |
12420 | has_std_attrs = cp_lexer_peek_token (lexer: parser->lexer) != token; |
12421 | |
12422 | /* Peek at the next token. */ |
12423 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12424 | |
12425 | /* If we have contracts, check that they're valid in this context. */ |
12426 | if (std_attrs != error_mark_node) |
12427 | { |
12428 | if (tree pre = lookup_attribute (attr_name: "pre" , list: std_attrs)) |
12429 | error_at (EXPR_LOCATION (TREE_VALUE (pre)), |
12430 | "preconditions cannot be statements" ); |
12431 | else if (tree post = lookup_attribute (attr_name: "post" , list: std_attrs)) |
12432 | error_at (EXPR_LOCATION (TREE_VALUE (post)), |
12433 | "postconditions cannot be statements" ); |
12434 | |
12435 | /* Check that assertions are null statements. */ |
12436 | if (cp_contract_assertion_p (std_attrs)) |
12437 | if (token->type != CPP_SEMICOLON) |
12438 | error_at (token->location, "assertions must be followed by %<;%>" ); |
12439 | } |
12440 | |
12441 | bool omp_attrs_forbidden_p; |
12442 | omp_attrs_forbidden_p = parser->omp_attrs_forbidden_p; |
12443 | |
12444 | if (std_attrs && (flag_openmp || flag_openmp_simd)) |
12445 | { |
12446 | bool handle_omp_attribs = false; |
12447 | if (token->type == CPP_KEYWORD) |
12448 | switch (token->keyword) |
12449 | { |
12450 | case RID_IF: |
12451 | case RID_SWITCH: |
12452 | case RID_WHILE: |
12453 | case RID_DO: |
12454 | case RID_FOR: |
12455 | case RID_BREAK: |
12456 | case RID_CONTINUE: |
12457 | case RID_RETURN: |
12458 | case RID_CO_RETURN: |
12459 | case RID_GOTO: |
12460 | case RID_AT_TRY: |
12461 | case RID_AT_CATCH: |
12462 | case RID_AT_FINALLY: |
12463 | case RID_AT_SYNCHRONIZED: |
12464 | case RID_AT_THROW: |
12465 | case RID_TRY: |
12466 | case RID_TRANSACTION_ATOMIC: |
12467 | case RID_TRANSACTION_RELAXED: |
12468 | case RID_SYNCHRONIZED: |
12469 | case RID_ATOMIC_NOEXCEPT: |
12470 | case RID_ATOMIC_CANCEL: |
12471 | case RID_TRANSACTION_CANCEL: |
12472 | handle_omp_attribs = true; |
12473 | break; |
12474 | default: |
12475 | break; |
12476 | } |
12477 | else if (token->type == CPP_SEMICOLON |
12478 | || token->type == CPP_OPEN_BRACE |
12479 | || token->type == CPP_PRAGMA) |
12480 | handle_omp_attribs = true; |
12481 | if (handle_omp_attribs) |
12482 | { |
12483 | std_attrs = cp_parser_handle_statement_omp_attributes (parser, |
12484 | attrs: std_attrs); |
12485 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12486 | } |
12487 | } |
12488 | parser->omp_attrs_forbidden_p = false; |
12489 | |
12490 | /* Remember the location of the first token in the statement. */ |
12491 | cp_token *statement_token = token; |
12492 | statement_location = token->location; |
12493 | add_debug_begin_stmt (loc: statement_location); |
12494 | /* If this is a keyword, then that will often determine what kind of |
12495 | statement we have. */ |
12496 | if (token->type == CPP_KEYWORD) |
12497 | { |
12498 | enum rid keyword = token->keyword; |
12499 | |
12500 | switch (keyword) |
12501 | { |
12502 | case RID_CASE: |
12503 | case RID_DEFAULT: |
12504 | /* Looks like a labeled-statement with a case label. |
12505 | Parse the label, and then use tail recursion to parse |
12506 | the statement. */ |
12507 | cp_parser_label_for_labeled_statement (parser, std_attrs); |
12508 | in_compound_for_pragma = false; |
12509 | in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12510 | goto restart; |
12511 | |
12512 | case RID_IF: |
12513 | case RID_SWITCH: |
12514 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12515 | statement = cp_parser_selection_statement (parser, if_p, chain); |
12516 | break; |
12517 | |
12518 | case RID_WHILE: |
12519 | case RID_DO: |
12520 | case RID_FOR: |
12521 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12522 | statement = cp_parser_iteration_statement (parser, if_p, false, 0, |
12523 | false); |
12524 | break; |
12525 | |
12526 | case RID_BREAK: |
12527 | case RID_CONTINUE: |
12528 | case RID_RETURN: |
12529 | case RID_CO_RETURN: |
12530 | case RID_GOTO: |
12531 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12532 | statement = cp_parser_jump_statement (parser); |
12533 | break; |
12534 | |
12535 | /* Objective-C++ exception-handling constructs. */ |
12536 | case RID_AT_TRY: |
12537 | case RID_AT_CATCH: |
12538 | case RID_AT_FINALLY: |
12539 | case RID_AT_SYNCHRONIZED: |
12540 | case RID_AT_THROW: |
12541 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12542 | statement = cp_parser_objc_statement (parser); |
12543 | break; |
12544 | |
12545 | case RID_TRY: |
12546 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12547 | statement = cp_parser_try_block (parser); |
12548 | break; |
12549 | |
12550 | case RID_NAMESPACE: |
12551 | /* This must be a namespace alias definition. */ |
12552 | if (has_std_attrs) |
12553 | { |
12554 | /* Attributes should be parsed as part of the |
12555 | declaration, so let's un-parse them. */ |
12556 | saved_tokens.rollback(); |
12557 | std_attrs = NULL_TREE; |
12558 | } |
12559 | cp_parser_declaration_statement (parser); |
12560 | return; |
12561 | |
12562 | case RID_TRANSACTION_ATOMIC: |
12563 | case RID_TRANSACTION_RELAXED: |
12564 | case RID_SYNCHRONIZED: |
12565 | case RID_ATOMIC_NOEXCEPT: |
12566 | case RID_ATOMIC_CANCEL: |
12567 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12568 | statement = cp_parser_transaction (parser, token); |
12569 | break; |
12570 | case RID_TRANSACTION_CANCEL: |
12571 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12572 | statement = cp_parser_transaction_cancel (parser); |
12573 | break; |
12574 | |
12575 | default: |
12576 | /* It might be a keyword like `int' that can start a |
12577 | declaration-statement. */ |
12578 | break; |
12579 | } |
12580 | } |
12581 | else if (token->type == CPP_NAME) |
12582 | { |
12583 | /* If the next token is a `:', then we are looking at a |
12584 | labeled-statement. */ |
12585 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
12586 | if (token->type == CPP_COLON) |
12587 | { |
12588 | /* Looks like a labeled-statement with an ordinary label. |
12589 | Parse the label, and then use tail recursion to parse |
12590 | the statement. */ |
12591 | |
12592 | cp_parser_label_for_labeled_statement (parser, std_attrs); |
12593 | |
12594 | /* If there's no statement, it's not a labeled-statement, just |
12595 | a label. That's allowed in C++23, but only if we're at the |
12596 | end of a compound-statement. */ |
12597 | if (in_compound |
12598 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
12599 | { |
12600 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
12601 | if (cxx_dialect < cxx23) |
12602 | pedwarn (loc, OPT_Wc__23_extensions, |
12603 | "label at end of compound statement only available " |
12604 | "with %<-std=c++2b%> or %<-std=gnu++2b%>" ); |
12605 | return; |
12606 | } |
12607 | in_compound_for_pragma = false; |
12608 | in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
12609 | goto restart; |
12610 | } |
12611 | } |
12612 | /* Anything that starts with a `{' must be a compound-statement. */ |
12613 | else if (token->type == CPP_OPEN_BRACE) |
12614 | { |
12615 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12616 | statement = cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); |
12617 | } |
12618 | /* CPP_PRAGMA is a #pragma inside a function body, which constitutes |
12619 | a statement all its own. */ |
12620 | else if (token->type == CPP_PRAGMA) |
12621 | { |
12622 | do_pragma:; |
12623 | cp_lexer *lexer = parser->lexer; |
12624 | bool do_restart = false; |
12625 | /* Only certain OpenMP pragmas are attached to statements, and thus |
12626 | are considered statements themselves. All others are not. In |
12627 | the context of a compound, accept the pragma as a "statement" and |
12628 | return so that we can check for a close brace. Otherwise we |
12629 | require a real statement and must go back and read one. */ |
12630 | if (in_compound_for_pragma) |
12631 | { |
12632 | if (cp_parser_pragma (parser, pragma_compound, if_p) |
12633 | && parser->omp_for_parse_state) |
12634 | check_omp_intervening_code (parser); |
12635 | } |
12636 | else if (!cp_parser_pragma (parser, pragma_stmt, if_p)) |
12637 | do_restart = true; |
12638 | else if (parser->omp_for_parse_state) |
12639 | check_omp_intervening_code (parser); |
12640 | if (parser->lexer != lexer |
12641 | && lexer->in_omp_attribute_pragma |
12642 | && (!in_omp_attribute_pragma || lexer->orphan_p)) |
12643 | { |
12644 | if (saved_tokens.lexer == lexer) |
12645 | { |
12646 | if (saved_tokens.mode == STS_COMMIT) |
12647 | cp_lexer_commit_tokens (lexer); |
12648 | gcc_assert (lexer->saved_tokens.length () == saved_tokens.len); |
12649 | saved_tokens.lexer = parser->lexer; |
12650 | saved_tokens.mode = STS_DONOTHING; |
12651 | saved_tokens.len = parser->lexer->saved_tokens.length (); |
12652 | } |
12653 | cp_lexer_destroy (lexer); |
12654 | lexer = parser->lexer; |
12655 | } |
12656 | if (do_restart) |
12657 | goto restart; |
12658 | if (parser->lexer == lexer |
12659 | && lexer->in_omp_attribute_pragma |
12660 | && !in_omp_attribute_pragma) |
12661 | parser->lexer->orphan_p = true; |
12662 | return; |
12663 | } |
12664 | else if (token->type == CPP_EOF) |
12665 | { |
12666 | cp_parser_error (parser, gmsgid: "expected statement" ); |
12667 | return; |
12668 | } |
12669 | |
12670 | /* Everything else must be a declaration-statement or an |
12671 | expression-statement. Try for the declaration-statement |
12672 | first, unless we are looking at a `;', in which case we know that |
12673 | we have an expression-statement. */ |
12674 | if (!statement) |
12675 | { |
12676 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12677 | { |
12678 | if (has_std_attrs) |
12679 | /* Attributes should be parsed as part of the declaration, |
12680 | so let's un-parse them. */ |
12681 | saved_tokens.rollback(); |
12682 | |
12683 | parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; |
12684 | cp_parser_parse_tentatively (parser); |
12685 | /* Try to parse the declaration-statement. */ |
12686 | cp_parser_declaration_statement (parser); |
12687 | parser->omp_attrs_forbidden_p = false; |
12688 | /* If that worked, we're done. */ |
12689 | if (cp_parser_parse_definitely (parser)) |
12690 | return; |
12691 | /* It didn't work, restore the post-attribute position. */ |
12692 | if (has_std_attrs) |
12693 | { |
12694 | cp_lexer_set_token_position (lexer: parser->lexer, pos: statement_token); |
12695 | if (flag_openmp || flag_openmp_simd) |
12696 | { |
12697 | size_t i = 1; |
12698 | bool handle_omp_attribs = true; |
12699 | while (cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->keyword |
12700 | == RID_EXTENSION) |
12701 | i++; |
12702 | switch (cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->keyword) |
12703 | { |
12704 | case RID_ASM: |
12705 | case RID_NAMESPACE: |
12706 | case RID_USING: |
12707 | case RID_LABEL: |
12708 | case RID_STATIC_ASSERT: |
12709 | /* Don't handle OpenMP attribs on keywords that |
12710 | always start a declaration statement but don't |
12711 | accept attribute before it and therefore |
12712 | the tentative cp_parser_declaration_statement |
12713 | fails to parse because of that. */ |
12714 | handle_omp_attribs = false; |
12715 | break; |
12716 | default: |
12717 | break; |
12718 | } |
12719 | |
12720 | if (handle_omp_attribs) |
12721 | { |
12722 | parser->omp_attrs_forbidden_p = omp_attrs_forbidden_p; |
12723 | std_attrs |
12724 | = cp_parser_handle_statement_omp_attributes |
12725 | (parser, attrs: std_attrs); |
12726 | parser->omp_attrs_forbidden_p = false; |
12727 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12728 | if (token->type == CPP_PRAGMA) |
12729 | goto do_pragma; |
12730 | } |
12731 | } |
12732 | } |
12733 | } |
12734 | /* All preceding labels have been parsed at this point. */ |
12735 | if (loc_after_labels != NULL) |
12736 | *loc_after_labels = statement_location; |
12737 | |
12738 | std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); |
12739 | |
12740 | /* Look for an expression-statement instead. */ |
12741 | statement = cp_parser_expression_statement (parser, in_statement_expr); |
12742 | |
12743 | std_attrs = process_stmt_assume_attribute (std_attrs, statement, |
12744 | attrs_loc); |
12745 | |
12746 | /* Handle [[fallthrough]];. */ |
12747 | if (attribute_fallthrough_p (std_attrs)) |
12748 | { |
12749 | /* The next token after the fallthrough attribute is ';'. */ |
12750 | if (statement == NULL_TREE) |
12751 | { |
12752 | /* Turn [[fallthrough]]; into FALLTHROUGH ();. */ |
12753 | statement = build_call_expr_internal_loc (statement_location, |
12754 | IFN_FALLTHROUGH, |
12755 | void_type_node, 0); |
12756 | finish_expr_stmt (statement); |
12757 | } |
12758 | else |
12759 | warning_at (statement_location, OPT_Wattributes, |
12760 | "%<fallthrough%> attribute not followed by %<;%>" ); |
12761 | std_attrs = NULL_TREE; |
12762 | } |
12763 | |
12764 | /* Handle [[assert: ...]]; */ |
12765 | if (cp_contract_assertion_p (std_attrs)) |
12766 | { |
12767 | /* Add the assertion as a statement in the current block. */ |
12768 | gcc_assert (!statement || statement == error_mark_node); |
12769 | emit_assertion (std_attrs); |
12770 | std_attrs = NULL_TREE; |
12771 | } |
12772 | } |
12773 | |
12774 | /* Set the line number for the statement. */ |
12775 | if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) |
12776 | SET_EXPR_LOCATION (statement, statement_location); |
12777 | |
12778 | /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise. */ |
12779 | if (std_attrs != NULL_TREE) |
12780 | warning_at (attrs_loc, |
12781 | OPT_Wattributes, |
12782 | "attributes at the beginning of statement are ignored" ); |
12783 | } |
12784 | |
12785 | /* Append ATTR to attribute list ATTRS. */ |
12786 | |
12787 | tree |
12788 | attr_chainon (tree attrs, tree attr) |
12789 | { |
12790 | if (attrs == error_mark_node) |
12791 | return error_mark_node; |
12792 | if (attr == error_mark_node) |
12793 | return error_mark_node; |
12794 | return chainon (attrs, attr); |
12795 | } |
12796 | |
12797 | /* Parse the label for a labeled-statement, i.e. |
12798 | |
12799 | label: |
12800 | attribute-specifier-seq[opt] identifier : |
12801 | attribute-specifier-seq[opt] case constant-expression : |
12802 | attribute-specifier-seq[opt] default : |
12803 | |
12804 | labeled-statement: |
12805 | label statement |
12806 | |
12807 | GNU Extension: |
12808 | case constant-expression ... constant-expression : statement |
12809 | |
12810 | When a label is parsed without errors, the label is added to the |
12811 | parse tree by the finish_* functions, so this function doesn't |
12812 | have to return the label. */ |
12813 | |
12814 | static void |
12815 | cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes) |
12816 | { |
12817 | cp_token *token; |
12818 | tree label = NULL_TREE; |
12819 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
12820 | |
12821 | /* The next token should be an identifier. */ |
12822 | token = cp_lexer_peek_token (lexer: parser->lexer); |
12823 | if (token->type != CPP_NAME |
12824 | && token->type != CPP_KEYWORD) |
12825 | { |
12826 | cp_parser_error (parser, gmsgid: "expected labeled-statement" ); |
12827 | return; |
12828 | } |
12829 | |
12830 | /* Remember whether this case or a user-defined label is allowed to fall |
12831 | through to. */ |
12832 | bool fallthrough_p = token->flags & PREV_FALLTHROUGH; |
12833 | |
12834 | parser->colon_corrects_to_scope_p = false; |
12835 | switch (token->keyword) |
12836 | { |
12837 | case RID_CASE: |
12838 | { |
12839 | tree expr, expr_hi; |
12840 | cp_token *ellipsis; |
12841 | |
12842 | /* Consume the `case' token. */ |
12843 | cp_lexer_consume_token (lexer: parser->lexer); |
12844 | /* Parse the constant-expression. */ |
12845 | expr = cp_parser_constant_expression (parser); |
12846 | if (check_for_bare_parameter_packs (expr)) |
12847 | expr = error_mark_node; |
12848 | |
12849 | ellipsis = cp_lexer_peek_token (lexer: parser->lexer); |
12850 | if (ellipsis->type == CPP_ELLIPSIS) |
12851 | { |
12852 | /* Consume the `...' token. */ |
12853 | cp_lexer_consume_token (lexer: parser->lexer); |
12854 | expr_hi = cp_parser_constant_expression (parser); |
12855 | if (check_for_bare_parameter_packs (expr_hi)) |
12856 | expr_hi = error_mark_node; |
12857 | |
12858 | /* We don't need to emit warnings here, as the common code |
12859 | will do this for us. */ |
12860 | } |
12861 | else |
12862 | expr_hi = NULL_TREE; |
12863 | |
12864 | if (parser->in_switch_statement_p) |
12865 | { |
12866 | tree l = finish_case_label (token->location, expr, expr_hi); |
12867 | if (l && TREE_CODE (l) == CASE_LABEL_EXPR) |
12868 | { |
12869 | label = CASE_LABEL (l); |
12870 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
12871 | } |
12872 | } |
12873 | else |
12874 | error_at (token->location, |
12875 | "case label %qE not within a switch statement" , |
12876 | expr); |
12877 | } |
12878 | break; |
12879 | |
12880 | case RID_DEFAULT: |
12881 | /* Consume the `default' token. */ |
12882 | cp_lexer_consume_token (lexer: parser->lexer); |
12883 | |
12884 | if (parser->in_switch_statement_p) |
12885 | { |
12886 | tree l = finish_case_label (token->location, NULL_TREE, NULL_TREE); |
12887 | if (l && TREE_CODE (l) == CASE_LABEL_EXPR) |
12888 | { |
12889 | label = CASE_LABEL (l); |
12890 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
12891 | } |
12892 | } |
12893 | else |
12894 | error_at (token->location, "case label not within a switch statement" ); |
12895 | break; |
12896 | |
12897 | default: |
12898 | /* Anything else must be an ordinary label. */ |
12899 | label = finish_label_stmt (cp_parser_identifier (parser)); |
12900 | if (label && TREE_CODE (label) == LABEL_DECL) |
12901 | FALLTHROUGH_LABEL_P (label) = fallthrough_p; |
12902 | break; |
12903 | } |
12904 | |
12905 | /* Require the `:' token. */ |
12906 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
12907 | |
12908 | /* An ordinary label may optionally be followed by attributes. |
12909 | However, this is only permitted if the attributes are then |
12910 | followed by a semicolon. This is because, for backward |
12911 | compatibility, when parsing |
12912 | lab: __attribute__ ((unused)) int i; |
12913 | we want the attribute to attach to "i", not "lab". */ |
12914 | if (label != NULL_TREE |
12915 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
12916 | { |
12917 | tree attrs; |
12918 | cp_parser_parse_tentatively (parser); |
12919 | attrs = cp_parser_gnu_attributes_opt (parser); |
12920 | if (attrs == NULL_TREE |
12921 | /* And fallthrough always binds to the expression-statement. */ |
12922 | || attribute_fallthrough_p (attrs) |
12923 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12924 | cp_parser_abort_tentative_parse (parser); |
12925 | else if (!cp_parser_parse_definitely (parser)) |
12926 | ; |
12927 | else |
12928 | attributes = attr_chainon (attrs: attributes, attr: attrs); |
12929 | } |
12930 | |
12931 | if (attributes != NULL_TREE) |
12932 | cplus_decl_attributes (&label, attributes, 0); |
12933 | |
12934 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
12935 | } |
12936 | |
12937 | /* Parse an expression-statement. |
12938 | |
12939 | expression-statement: |
12940 | expression [opt] ; |
12941 | |
12942 | Returns the new EXPR_STMT -- or NULL_TREE if the expression |
12943 | statement consists of nothing more than an `;'. IN_STATEMENT_EXPR_P |
12944 | indicates whether this expression-statement is part of an |
12945 | expression statement. */ |
12946 | |
12947 | static tree |
12948 | cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) |
12949 | { |
12950 | tree statement = NULL_TREE; |
12951 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
12952 | location_t loc = token->location; |
12953 | |
12954 | /* There might be attribute fallthrough. */ |
12955 | tree attr = cp_parser_gnu_attributes_opt (parser); |
12956 | |
12957 | /* If the next token is a ';', then there is no expression |
12958 | statement. */ |
12959 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
12960 | { |
12961 | statement = cp_parser_expression (parser); |
12962 | if (statement == error_mark_node |
12963 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
12964 | { |
12965 | cp_parser_skip_to_end_of_block_or_statement (parser); |
12966 | return error_mark_node; |
12967 | } |
12968 | } |
12969 | |
12970 | attr = process_stmt_assume_attribute (attr, statement, loc); |
12971 | |
12972 | /* Handle [[fallthrough]];. */ |
12973 | if (attribute_fallthrough_p (attr)) |
12974 | { |
12975 | /* The next token after the fallthrough attribute is ';'. */ |
12976 | if (statement == NULL_TREE) |
12977 | /* Turn [[fallthrough]]; into FALLTHROUGH ();. */ |
12978 | statement = build_call_expr_internal_loc (loc, IFN_FALLTHROUGH, |
12979 | void_type_node, 0); |
12980 | else |
12981 | warning_at (loc, OPT_Wattributes, |
12982 | "%<fallthrough%> attribute not followed by %<;%>" ); |
12983 | attr = NULL_TREE; |
12984 | } |
12985 | |
12986 | /* Allow "[[fallthrough]];", but warn otherwise. */ |
12987 | if (attr != NULL_TREE) |
12988 | warning_at (loc, OPT_Wattributes, |
12989 | "attributes at the beginning of statement are ignored" ); |
12990 | |
12991 | /* Give a helpful message for "A<T>::type t;" and the like. */ |
12992 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON) |
12993 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
12994 | { |
12995 | if (TREE_CODE (statement) == SCOPE_REF) |
12996 | error_at (token->location, "need %<typename%> before %qE because " |
12997 | "%qT is a dependent scope" , |
12998 | statement, TREE_OPERAND (statement, 0)); |
12999 | else if (is_overloaded_fn (statement) |
13000 | && DECL_CONSTRUCTOR_P (get_first_fn (statement))) |
13001 | { |
13002 | /* A::A a; */ |
13003 | tree fn = get_first_fn (statement); |
13004 | error_at (token->location, |
13005 | "%<%T::%D%> names the constructor, not the type" , |
13006 | DECL_CONTEXT (fn), DECL_NAME (fn)); |
13007 | } |
13008 | } |
13009 | |
13010 | /* Consume the final `;'. */ |
13011 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
13012 | |
13013 | if (in_statement_expr |
13014 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
13015 | /* This is the final expression statement of a statement |
13016 | expression. */ |
13017 | statement = finish_stmt_expr_expr (statement, in_statement_expr); |
13018 | else if (statement) |
13019 | statement = finish_expr_stmt (statement); |
13020 | |
13021 | return statement; |
13022 | } |
13023 | |
13024 | /* Parse a compound-statement. |
13025 | |
13026 | compound-statement: |
13027 | { statement-seq [opt] label-seq [opt] } |
13028 | |
13029 | label-seq: |
13030 | label |
13031 | label-seq label |
13032 | |
13033 | GNU extension: |
13034 | |
13035 | compound-statement: |
13036 | { label-declaration-seq [opt] statement-seq [opt] } |
13037 | |
13038 | label-declaration-seq: |
13039 | label-declaration |
13040 | label-declaration-seq label-declaration |
13041 | |
13042 | Returns a tree representing the statement. */ |
13043 | |
13044 | static tree |
13045 | cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, |
13046 | int bcs_flags, bool function_body) |
13047 | { |
13048 | tree compound_stmt; |
13049 | matching_braces braces; |
13050 | |
13051 | /* Consume the `{'. */ |
13052 | if (!braces.require_open (parser)) |
13053 | return error_mark_node; |
13054 | if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
13055 | && !function_body && cxx_dialect < cxx14) |
13056 | pedwarn (input_location, OPT_Wpedantic, |
13057 | "compound-statement in %<constexpr%> function" ); |
13058 | /* Begin the compound-statement. */ |
13059 | compound_stmt = begin_compound_stmt (bcs_flags); |
13060 | /* If the next keyword is `__label__' we have a label declaration. */ |
13061 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_LABEL)) |
13062 | cp_parser_label_declaration (parser); |
13063 | /* Parse an (optional) statement-seq. */ |
13064 | cp_parser_statement_seq_opt (parser, in_statement_expr); |
13065 | |
13066 | /* Consume the `}'. */ |
13067 | braces.require_close (parser); |
13068 | |
13069 | /* Finish the compound-statement. */ |
13070 | finish_compound_stmt (compound_stmt); |
13071 | |
13072 | return compound_stmt; |
13073 | } |
13074 | |
13075 | /* Diagnose errors related to imperfectly nested loops in an OMP |
13076 | loop construct. This function is called when such code is seen. |
13077 | Only issue one such diagnostic no matter how much invalid |
13078 | intervening code there is in the loop. |
13079 | FIXME: maybe the location associated with the diagnostic should |
13080 | be the current parser token instead of the location of the outer loop |
13081 | nest. */ |
13082 | |
13083 | static void |
13084 | check_omp_intervening_code (cp_parser *parser) |
13085 | { |
13086 | struct omp_for_parse_data *omp_for_parse_state |
13087 | = parser->omp_for_parse_state; |
13088 | gcc_assert (omp_for_parse_state); |
13089 | |
13090 | if (!omp_for_parse_state->in_intervening_code) |
13091 | return; |
13092 | omp_for_parse_state->saw_intervening_code = true; |
13093 | |
13094 | /* Only diagnose errors related to perfect nesting once. */ |
13095 | if (!omp_for_parse_state->perfect_nesting_fail) |
13096 | { |
13097 | if (omp_for_parse_state->code == OACC_LOOP) |
13098 | { |
13099 | error_at (omp_for_parse_state->for_loc, |
13100 | "inner loops must be perfectly nested in " |
13101 | "%<#pragma acc loop%>" ); |
13102 | omp_for_parse_state->perfect_nesting_fail = true; |
13103 | } |
13104 | else if (omp_for_parse_state->ordered) |
13105 | { |
13106 | error_at (omp_for_parse_state->for_loc, |
13107 | "inner loops must be perfectly nested with " |
13108 | "%<ordered%> clause" ); |
13109 | omp_for_parse_state->perfect_nesting_fail = true; |
13110 | } |
13111 | else if (omp_for_parse_state->inscan) |
13112 | { |
13113 | error_at (omp_for_parse_state->for_loc, |
13114 | "inner loops must be perfectly nested with " |
13115 | "%<reduction%> %<inscan%> clause" ); |
13116 | omp_for_parse_state->perfect_nesting_fail = true; |
13117 | } |
13118 | /* TODO: Also reject loops with TILE directive. */ |
13119 | if (omp_for_parse_state->perfect_nesting_fail) |
13120 | omp_for_parse_state->fail = true; |
13121 | } |
13122 | } |
13123 | |
13124 | /* Parse an (optional) statement-seq. |
13125 | |
13126 | statement-seq: |
13127 | statement |
13128 | statement-seq [opt] statement */ |
13129 | |
13130 | static void |
13131 | cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) |
13132 | { |
13133 | struct omp_for_parse_data *omp_for_parse_state |
13134 | = parser->omp_for_parse_state; |
13135 | bool in_omp_loop_block |
13136 | = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false; |
13137 | |
13138 | /* Scan statements until there aren't any more. */ |
13139 | while (true) |
13140 | { |
13141 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
13142 | |
13143 | /* If we are looking at a `}', then we have run out of |
13144 | statements; the same is true if we have reached the end |
13145 | of file, or have stumbled upon a stray '@end'. */ |
13146 | if (token->type == CPP_CLOSE_BRACE |
13147 | || token->type == CPP_EOF |
13148 | || token->type == CPP_PRAGMA_EOL |
13149 | || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END)) |
13150 | break; |
13151 | |
13152 | /* If we are in a compound statement and find 'else' then |
13153 | something went wrong. */ |
13154 | else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE) |
13155 | { |
13156 | if (parser->in_statement & IN_IF_STMT) |
13157 | break; |
13158 | else |
13159 | { |
13160 | token = cp_lexer_consume_token (lexer: parser->lexer); |
13161 | error_at (token->location, "%<else%> without a previous %<if%>" ); |
13162 | } |
13163 | } |
13164 | |
13165 | /* Handle special cases for OMP FOR canonical loop syntax. */ |
13166 | else if (in_omp_loop_block) |
13167 | { |
13168 | bool want_nested_loop = omp_for_parse_state->want_nested_loop; |
13169 | if (want_nested_loop |
13170 | && token->type == CPP_KEYWORD && token->keyword == RID_FOR) |
13171 | { |
13172 | /* Found the nested loop. */ |
13173 | omp_for_parse_state->depth++; |
13174 | add_stmt (cp_parser_omp_loop_nest (parser, NULL)); |
13175 | omp_for_parse_state->depth--; |
13176 | } |
13177 | else if (token->type == CPP_SEMICOLON) |
13178 | { |
13179 | /* Prior to implementing the OpenMP 5.1 syntax for canonical |
13180 | loop form, GCC used to accept an empty statements as not |
13181 | being intervening code. Continue to do that, as an |
13182 | extension. */ |
13183 | /* FIXME: Maybe issue a warning or something here? */ |
13184 | cp_lexer_consume_token (lexer: parser->lexer); |
13185 | } |
13186 | else if (want_nested_loop && token->type == CPP_OPEN_BRACE) |
13187 | /* The nested compound statement may contain the next loop, or |
13188 | it might just be intervening code. */ |
13189 | { |
13190 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13191 | if (omp_for_parse_state->want_nested_loop) |
13192 | check_omp_intervening_code (parser); |
13193 | } |
13194 | else |
13195 | { |
13196 | /* This must be intervening code. */ |
13197 | omp_for_parse_state->want_nested_loop = false; |
13198 | /* Defer calling check_omp_intervening_code on pragmas until |
13199 | cp_parser_statement, because we can't know until we parse |
13200 | it whether or not the pragma is a statement. */ |
13201 | if (token->type != CPP_PRAGMA) |
13202 | check_omp_intervening_code (parser); |
13203 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13204 | omp_for_parse_state->want_nested_loop = want_nested_loop; |
13205 | } |
13206 | continue; |
13207 | } |
13208 | |
13209 | /* Parse the statement. */ |
13210 | cp_parser_statement (parser, in_statement_expr, in_compound: true, NULL); |
13211 | } |
13212 | } |
13213 | |
13214 | /* Return true if this is the C++20 version of range-based-for with |
13215 | init-statement. */ |
13216 | |
13217 | static bool |
13218 | cp_parser_range_based_for_with_init_p (cp_parser *parser) |
13219 | { |
13220 | bool r = false; |
13221 | |
13222 | /* Save tokens so that we can put them back. */ |
13223 | cp_lexer_save_tokens (lexer: parser->lexer); |
13224 | |
13225 | /* There has to be an unnested ; followed by an unnested :. */ |
13226 | if (cp_parser_skip_to_closing_parenthesis_1 (parser, |
13227 | /*recovering=*/false, |
13228 | or_ttype: CPP_SEMICOLON, |
13229 | /*consume_paren=*/false) != -1) |
13230 | goto out; |
13231 | |
13232 | /* We found the semicolon, eat it now. */ |
13233 | cp_lexer_consume_token (lexer: parser->lexer); |
13234 | |
13235 | /* Now look for ':' that is not nested in () or {}. */ |
13236 | r = (cp_parser_skip_to_closing_parenthesis_1 (parser, |
13237 | /*recovering=*/false, |
13238 | or_ttype: CPP_COLON, |
13239 | /*consume_paren=*/false) == -1); |
13240 | |
13241 | out: |
13242 | /* Roll back the tokens we skipped. */ |
13243 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
13244 | |
13245 | return r; |
13246 | } |
13247 | |
13248 | /* Return true if we're looking at (init; cond), false otherwise. */ |
13249 | |
13250 | static bool |
13251 | cp_parser_init_statement_p (cp_parser *parser) |
13252 | { |
13253 | /* Save tokens so that we can put them back. */ |
13254 | cp_lexer_save_tokens (lexer: parser->lexer); |
13255 | |
13256 | /* Look for ';' that is not nested in () or {}. */ |
13257 | int ret = cp_parser_skip_to_closing_parenthesis_1 (parser, |
13258 | /*recovering=*/false, |
13259 | or_ttype: CPP_SEMICOLON, |
13260 | /*consume_paren=*/false); |
13261 | |
13262 | /* Roll back the tokens we skipped. */ |
13263 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
13264 | |
13265 | return ret == -1; |
13266 | } |
13267 | |
13268 | /* Parse a selection-statement. |
13269 | |
13270 | selection-statement: |
13271 | if ( init-statement [opt] condition ) statement |
13272 | if ( init-statement [opt] condition ) statement else statement |
13273 | switch ( init-statement [opt] condition ) statement |
13274 | |
13275 | Returns the new IF_STMT or SWITCH_STMT. |
13276 | |
13277 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
13278 | is a (possibly labeled) if statement which is not enclosed in |
13279 | braces and has an else clause. This is used to implement |
13280 | -Wparentheses. |
13281 | |
13282 | CHAIN is a vector of if-else-if conditions. This is used to implement |
13283 | -Wduplicated-cond. */ |
13284 | |
13285 | static tree |
13286 | cp_parser_selection_statement (cp_parser* parser, bool *if_p, |
13287 | vec<tree> *chain) |
13288 | { |
13289 | cp_token *token; |
13290 | enum rid keyword; |
13291 | token_indent_info guard_tinfo; |
13292 | |
13293 | if (if_p != NULL) |
13294 | *if_p = false; |
13295 | |
13296 | /* Peek at the next token. */ |
13297 | token = cp_parser_require (parser, CPP_KEYWORD, RT_SELECT); |
13298 | guard_tinfo = get_token_indent_info (token); |
13299 | |
13300 | /* See what kind of keyword it is. */ |
13301 | keyword = token->keyword; |
13302 | switch (keyword) |
13303 | { |
13304 | case RID_IF: |
13305 | case RID_SWITCH: |
13306 | { |
13307 | tree statement; |
13308 | tree condition; |
13309 | |
13310 | bool cx = false; |
13311 | if (keyword == RID_IF |
13312 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13313 | keyword: RID_CONSTEXPR)) |
13314 | { |
13315 | cx = true; |
13316 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
13317 | if (cxx_dialect < cxx17) |
13318 | pedwarn (tok->location, OPT_Wc__17_extensions, |
13319 | "%<if constexpr%> only available with " |
13320 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
13321 | } |
13322 | int ce = 0; |
13323 | if (keyword == RID_IF && !cx) |
13324 | { |
13325 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13326 | keyword: RID_CONSTEVAL)) |
13327 | ce = 1; |
13328 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NOT) |
13329 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, |
13330 | keyword: RID_CONSTEVAL)) |
13331 | { |
13332 | ce = -1; |
13333 | cp_lexer_consume_token (lexer: parser->lexer); |
13334 | } |
13335 | } |
13336 | if (ce) |
13337 | { |
13338 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
13339 | if (cxx_dialect < cxx23) |
13340 | pedwarn (tok->location, OPT_Wc__23_extensions, |
13341 | "%<if consteval%> only available with " |
13342 | "%<-std=c++2b%> or %<-std=gnu++2b%>" ); |
13343 | |
13344 | bool save_in_consteval_if_p = in_consteval_if_p; |
13345 | statement = begin_if_stmt (); |
13346 | IF_STMT_CONSTEVAL_P (statement) = true; |
13347 | condition = finish_if_stmt_cond (boolean_false_node, statement); |
13348 | |
13349 | gcc_rich_location richloc (tok->location); |
13350 | bool non_compound_stmt_p = false; |
13351 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13352 | { |
13353 | non_compound_stmt_p = true; |
13354 | richloc.add_fixit_insert_after (where: tok->location, new_content: "{" ); |
13355 | } |
13356 | |
13357 | in_consteval_if_p |= ce > 0; |
13358 | cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo); |
13359 | |
13360 | if (non_compound_stmt_p) |
13361 | { |
13362 | location_t before_loc |
13363 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13364 | richloc.add_fixit_insert_before (where: before_loc, new_content: "}" ); |
13365 | error_at (&richloc, |
13366 | "%<if consteval%> requires compound statement" ); |
13367 | non_compound_stmt_p = false; |
13368 | } |
13369 | |
13370 | finish_then_clause (statement); |
13371 | |
13372 | /* If the next token is `else', parse the else-clause. */ |
13373 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13374 | keyword: RID_ELSE)) |
13375 | { |
13376 | cp_token *else_tok = cp_lexer_peek_token (lexer: parser->lexer); |
13377 | gcc_rich_location else_richloc (else_tok->location); |
13378 | guard_tinfo = get_token_indent_info (token: else_tok); |
13379 | /* Consume the `else' keyword. */ |
13380 | cp_lexer_consume_token (lexer: parser->lexer); |
13381 | |
13382 | begin_else_clause (statement); |
13383 | |
13384 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13385 | { |
13386 | non_compound_stmt_p = true; |
13387 | else_richloc.add_fixit_insert_after (where: else_tok->location, |
13388 | new_content: "{" ); |
13389 | } |
13390 | |
13391 | in_consteval_if_p = save_in_consteval_if_p | (ce < 0); |
13392 | cp_parser_implicitly_scoped_statement (parser, NULL, |
13393 | guard_tinfo); |
13394 | |
13395 | if (non_compound_stmt_p) |
13396 | { |
13397 | location_t before_loc |
13398 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13399 | else_richloc.add_fixit_insert_before (where: before_loc, new_content: "}" ); |
13400 | error_at (&else_richloc, |
13401 | "%<if consteval%> requires compound statement" ); |
13402 | } |
13403 | |
13404 | finish_else_clause (statement); |
13405 | } |
13406 | |
13407 | in_consteval_if_p = save_in_consteval_if_p; |
13408 | if (ce < 0) |
13409 | { |
13410 | std::swap (THEN_CLAUSE (statement), ELSE_CLAUSE (statement)); |
13411 | if (THEN_CLAUSE (statement) == NULL_TREE) |
13412 | THEN_CLAUSE (statement) = build_empty_stmt (tok->location); |
13413 | } |
13414 | |
13415 | finish_if_stmt (statement); |
13416 | return statement; |
13417 | } |
13418 | |
13419 | /* Look for the `('. */ |
13420 | matching_parens parens; |
13421 | if (!parens.require_open (parser)) |
13422 | { |
13423 | cp_parser_skip_to_end_of_statement (parser); |
13424 | return error_mark_node; |
13425 | } |
13426 | |
13427 | /* Begin the selection-statement. */ |
13428 | if (keyword == RID_IF) |
13429 | { |
13430 | statement = begin_if_stmt (); |
13431 | IF_STMT_CONSTEXPR_P (statement) = cx; |
13432 | } |
13433 | else |
13434 | statement = begin_switch_stmt (); |
13435 | |
13436 | /* Parse the optional init-statement. */ |
13437 | if (cp_parser_init_statement_p (parser)) |
13438 | { |
13439 | tree decl; |
13440 | if (cxx_dialect < cxx17) |
13441 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
13442 | OPT_Wc__17_extensions, |
13443 | "init-statement in selection statements only available " |
13444 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
13445 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13446 | /* A non-empty init-statement can have arbitrary side |
13447 | effects. */ |
13448 | vec_free (v&: chain); |
13449 | cp_parser_init_statement (parser, decl: &decl); |
13450 | } |
13451 | |
13452 | /* Parse the condition. */ |
13453 | condition = cp_parser_condition (parser); |
13454 | /* Look for the `)'. */ |
13455 | if (!parens.require_close (parser)) |
13456 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
13457 | /*consume_paren=*/true); |
13458 | |
13459 | if (keyword == RID_IF) |
13460 | { |
13461 | bool nested_if; |
13462 | unsigned char in_statement; |
13463 | |
13464 | /* Add the condition. */ |
13465 | condition = finish_if_stmt_cond (condition, statement); |
13466 | |
13467 | if (warn_duplicated_cond) |
13468 | warn_duplicated_cond_add_or_warn (token->location, condition, |
13469 | &chain); |
13470 | |
13471 | /* Parse the then-clause. */ |
13472 | in_statement = parser->in_statement; |
13473 | parser->in_statement |= IN_IF_STMT; |
13474 | |
13475 | /* Outside a template, the non-selected branch of a constexpr |
13476 | if is a 'discarded statement', i.e. unevaluated. */ |
13477 | bool was_discarded = in_discarded_stmt; |
13478 | bool discard_then = (cx && !processing_template_decl |
13479 | && integer_zerop (condition)); |
13480 | if (discard_then) |
13481 | { |
13482 | in_discarded_stmt = true; |
13483 | ++c_inhibit_evaluation_warnings; |
13484 | } |
13485 | |
13486 | cp_parser_implicitly_scoped_statement (parser, &nested_if, |
13487 | guard_tinfo); |
13488 | |
13489 | parser->in_statement = in_statement; |
13490 | |
13491 | finish_then_clause (statement); |
13492 | |
13493 | if (discard_then) |
13494 | { |
13495 | THEN_CLAUSE (statement) = NULL_TREE; |
13496 | in_discarded_stmt = was_discarded; |
13497 | --c_inhibit_evaluation_warnings; |
13498 | } |
13499 | |
13500 | /* If the next token is `else', parse the else-clause. */ |
13501 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13502 | keyword: RID_ELSE)) |
13503 | { |
13504 | bool discard_else = (cx && !processing_template_decl |
13505 | && integer_nonzerop (condition)); |
13506 | if (discard_else) |
13507 | { |
13508 | in_discarded_stmt = true; |
13509 | ++c_inhibit_evaluation_warnings; |
13510 | } |
13511 | |
13512 | guard_tinfo |
13513 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
13514 | /* Consume the `else' keyword. */ |
13515 | cp_lexer_consume_token (lexer: parser->lexer); |
13516 | if (warn_duplicated_cond) |
13517 | { |
13518 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13519 | keyword: RID_IF) |
13520 | && chain == NULL) |
13521 | { |
13522 | /* We've got "if (COND) else if (COND2)". Start |
13523 | the condition chain and add COND as the first |
13524 | element. */ |
13525 | chain = new vec<tree> (); |
13526 | if (!CONSTANT_CLASS_P (condition) |
13527 | && !TREE_SIDE_EFFECTS (condition)) |
13528 | { |
13529 | /* Wrap it in a NOP_EXPR so that we can set the |
13530 | location of the condition. */ |
13531 | tree e = build1 (NOP_EXPR, TREE_TYPE (condition), |
13532 | condition); |
13533 | SET_EXPR_LOCATION (e, token->location); |
13534 | chain->safe_push (obj: e); |
13535 | } |
13536 | } |
13537 | else if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
13538 | keyword: RID_IF)) |
13539 | /* This is if-else without subsequent if. Zap the |
13540 | condition chain; we would have already warned at |
13541 | this point. */ |
13542 | vec_free (v&: chain); |
13543 | } |
13544 | begin_else_clause (statement); |
13545 | /* Parse the else-clause. */ |
13546 | cp_parser_implicitly_scoped_statement (parser, NULL, |
13547 | guard_tinfo, chain); |
13548 | |
13549 | finish_else_clause (statement); |
13550 | |
13551 | /* If we are currently parsing a then-clause, then |
13552 | IF_P will not be NULL. We set it to true to |
13553 | indicate that this if statement has an else clause. |
13554 | This may trigger the Wparentheses warning below |
13555 | when we get back up to the parent if statement. */ |
13556 | if (if_p != NULL) |
13557 | *if_p = true; |
13558 | |
13559 | if (discard_else) |
13560 | { |
13561 | ELSE_CLAUSE (statement) = NULL_TREE; |
13562 | in_discarded_stmt = was_discarded; |
13563 | --c_inhibit_evaluation_warnings; |
13564 | } |
13565 | } |
13566 | else |
13567 | { |
13568 | /* This if statement does not have an else clause. If |
13569 | NESTED_IF is true, then the then-clause has an if |
13570 | statement which does have an else clause. We warn |
13571 | about the potential ambiguity. */ |
13572 | if (nested_if) |
13573 | warning_at (EXPR_LOCATION (statement), OPT_Wdangling_else, |
13574 | "suggest explicit braces to avoid ambiguous" |
13575 | " %<else%>" ); |
13576 | if (warn_duplicated_cond) |
13577 | /* We don't need the condition chain anymore. */ |
13578 | vec_free (v&: chain); |
13579 | } |
13580 | |
13581 | /* Now we're all done with the if-statement. */ |
13582 | finish_if_stmt (statement); |
13583 | } |
13584 | else |
13585 | { |
13586 | bool in_switch_statement_p; |
13587 | unsigned char in_statement; |
13588 | |
13589 | /* Add the condition. */ |
13590 | finish_switch_cond (condition, statement); |
13591 | |
13592 | /* Parse the body of the switch-statement. */ |
13593 | in_switch_statement_p = parser->in_switch_statement_p; |
13594 | in_statement = parser->in_statement; |
13595 | parser->in_switch_statement_p = true; |
13596 | parser->in_statement |= IN_SWITCH_STMT; |
13597 | cp_parser_implicitly_scoped_statement (parser, if_p, |
13598 | guard_tinfo); |
13599 | parser->in_switch_statement_p = in_switch_statement_p; |
13600 | parser->in_statement = in_statement; |
13601 | |
13602 | /* Now we're all done with the switch-statement. */ |
13603 | finish_switch_stmt (statement); |
13604 | } |
13605 | |
13606 | return statement; |
13607 | } |
13608 | break; |
13609 | |
13610 | default: |
13611 | cp_parser_error (parser, gmsgid: "expected selection-statement" ); |
13612 | return error_mark_node; |
13613 | } |
13614 | } |
13615 | |
13616 | /* Helper function for cp_parser_condition and cp_parser_simple_declaration. |
13617 | If we have seen at least one decl-specifier, and the next token is not |
13618 | a parenthesis (after "int (" we might be looking at a functional cast) |
13619 | neither we are dealing with a concept-check expression then we must be |
13620 | looking at a declaration. */ |
13621 | |
13622 | static void |
13623 | cp_parser_maybe_commit_to_declaration (cp_parser* parser, |
13624 | cp_decl_specifier_seq *decl_specs) |
13625 | { |
13626 | if (decl_specs->any_specifiers_p |
13627 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
13628 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE) |
13629 | && !cp_parser_error_occurred (parser) |
13630 | && !(decl_specs->type |
13631 | && TREE_CODE (decl_specs->type) == TYPE_DECL |
13632 | && is_constrained_auto (TREE_TYPE (decl_specs->type)))) |
13633 | cp_parser_commit_to_tentative_parse (parser); |
13634 | } |
13635 | |
13636 | /* Helper function for cp_parser_condition. Enforces [stmt.stmt]/2: |
13637 | The declarator shall not specify a function or an array. Returns |
13638 | TRUE if the declarator is valid, FALSE otherwise. */ |
13639 | |
13640 | static bool |
13641 | cp_parser_check_condition_declarator (cp_parser* parser, |
13642 | cp_declarator *declarator, |
13643 | location_t loc) |
13644 | { |
13645 | if (declarator == cp_error_declarator |
13646 | || function_declarator_p (declarator) |
13647 | || declarator->kind == cdk_array) |
13648 | { |
13649 | if (declarator == cp_error_declarator) |
13650 | /* Already complained. */; |
13651 | else if (declarator->kind == cdk_array) |
13652 | error_at (loc, "condition declares an array" ); |
13653 | else |
13654 | error_at (loc, "condition declares a function" ); |
13655 | if (parser->fully_implicit_function_template_p) |
13656 | abort_fully_implicit_template (parser); |
13657 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
13658 | /*or_comma=*/false, |
13659 | /*consume_paren=*/false); |
13660 | return false; |
13661 | } |
13662 | else |
13663 | return true; |
13664 | } |
13665 | |
13666 | /* Parse a condition. |
13667 | |
13668 | condition: |
13669 | expression |
13670 | type-specifier-seq declarator = initializer-clause |
13671 | type-specifier-seq declarator braced-init-list |
13672 | |
13673 | GNU Extension: |
13674 | |
13675 | condition: |
13676 | type-specifier-seq declarator asm-specification [opt] |
13677 | attributes [opt] = assignment-expression |
13678 | |
13679 | Returns the expression that should be tested. */ |
13680 | |
13681 | static tree |
13682 | cp_parser_condition (cp_parser* parser) |
13683 | { |
13684 | cp_decl_specifier_seq type_specifiers; |
13685 | const char *saved_message; |
13686 | int declares_class_or_enum; |
13687 | |
13688 | /* Try the declaration first. */ |
13689 | cp_parser_parse_tentatively (parser); |
13690 | /* New types are not allowed in the type-specifier-seq for a |
13691 | condition. */ |
13692 | saved_message = parser->type_definition_forbidden_message; |
13693 | parser->type_definition_forbidden_message |
13694 | = G_("types may not be defined in conditions" ); |
13695 | /* Parse the type-specifier-seq. */ |
13696 | cp_parser_decl_specifier_seq (parser, |
13697 | CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR, |
13698 | &type_specifiers, |
13699 | &declares_class_or_enum); |
13700 | /* Restore the saved message. */ |
13701 | parser->type_definition_forbidden_message = saved_message; |
13702 | |
13703 | /* Gather the attributes that were provided with the |
13704 | decl-specifiers. */ |
13705 | tree prefix_attributes = type_specifiers.attributes; |
13706 | |
13707 | cp_parser_maybe_commit_to_declaration (parser, decl_specs: &type_specifiers); |
13708 | |
13709 | /* If all is well, we might be looking at a declaration. */ |
13710 | if (!cp_parser_error_occurred (parser)) |
13711 | { |
13712 | tree decl; |
13713 | tree asm_specification; |
13714 | tree attributes; |
13715 | cp_declarator *declarator; |
13716 | tree initializer = NULL_TREE; |
13717 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13718 | |
13719 | /* Parse the declarator. */ |
13720 | declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
13721 | CP_PARSER_FLAGS_NONE, |
13722 | /*ctor_dtor_or_conv_p=*/NULL, |
13723 | /*parenthesized_p=*/NULL, |
13724 | /*member_p=*/false, |
13725 | /*friend_p=*/false, |
13726 | /*static_p=*/false); |
13727 | /* Parse the attributes. */ |
13728 | attributes = cp_parser_attributes_opt (parser); |
13729 | /* Parse the asm-specification. */ |
13730 | asm_specification = cp_parser_asm_specification_opt (parser); |
13731 | /* If the next token is not an `=' or '{', then we might still be |
13732 | looking at an expression. For example: |
13733 | |
13734 | if (A(a).x) |
13735 | |
13736 | looks like a decl-specifier-seq and a declarator -- but then |
13737 | there is no `=', so this is an expression. */ |
13738 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
13739 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13740 | cp_parser_simulate_error (parser); |
13741 | |
13742 | /* If we did see an `=' or '{', then we are looking at a declaration |
13743 | for sure. */ |
13744 | if (cp_parser_parse_definitely (parser)) |
13745 | { |
13746 | tree pushed_scope; |
13747 | bool non_constant_p = false; |
13748 | int flags = LOOKUP_ONLYCONVERTING; |
13749 | |
13750 | if (!cp_parser_check_condition_declarator (parser, declarator, loc)) |
13751 | return error_mark_node; |
13752 | |
13753 | /* Create the declaration. */ |
13754 | decl = start_decl (declarator, &type_specifiers, |
13755 | /*initialized_p=*/true, |
13756 | attributes, prefix_attributes, |
13757 | &pushed_scope); |
13758 | |
13759 | declarator->init_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
13760 | /* Parse the initializer. */ |
13761 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13762 | { |
13763 | initializer = cp_parser_braced_list (parser, &non_constant_p); |
13764 | CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1; |
13765 | flags = 0; |
13766 | } |
13767 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
13768 | { |
13769 | /* Consume the `='. */ |
13770 | cp_lexer_consume_token (lexer: parser->lexer); |
13771 | initializer = cp_parser_initializer_clause (parser, |
13772 | &non_constant_p); |
13773 | } |
13774 | else |
13775 | { |
13776 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
13777 | initializer = error_mark_node; |
13778 | } |
13779 | if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) |
13780 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
13781 | |
13782 | /* Process the initializer. */ |
13783 | cp_finish_decl (decl, |
13784 | initializer, !non_constant_p, |
13785 | asm_specification, |
13786 | flags); |
13787 | |
13788 | if (pushed_scope) |
13789 | pop_scope (pushed_scope); |
13790 | |
13791 | return convert_from_reference (decl); |
13792 | } |
13793 | } |
13794 | /* If we didn't even get past the declarator successfully, we are |
13795 | definitely not looking at a declaration. */ |
13796 | else |
13797 | cp_parser_abort_tentative_parse (parser); |
13798 | |
13799 | /* Otherwise, we are looking at an expression. */ |
13800 | return cp_parser_expression (parser); |
13801 | } |
13802 | |
13803 | /* Parses a for-statement or range-for-statement until the closing ')', |
13804 | not included. */ |
13805 | |
13806 | static tree |
13807 | cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll, |
13808 | bool novector) |
13809 | { |
13810 | tree init, scope, decl; |
13811 | bool is_range_for; |
13812 | |
13813 | /* Begin the for-statement. */ |
13814 | scope = begin_for_scope (&init); |
13815 | |
13816 | /* Maybe parse the optional init-statement in a range-based for loop. */ |
13817 | if (cp_parser_range_based_for_with_init_p (parser) |
13818 | /* Checked for diagnostic purposes only. */ |
13819 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13820 | { |
13821 | tree dummy; |
13822 | cp_parser_init_statement (parser, decl: &dummy); |
13823 | if (cxx_dialect < cxx20) |
13824 | { |
13825 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
13826 | OPT_Wc__20_extensions, |
13827 | "range-based %<for%> loops with initializer only " |
13828 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
13829 | decl = error_mark_node; |
13830 | } |
13831 | } |
13832 | |
13833 | /* Parse the initialization. */ |
13834 | is_range_for = cp_parser_init_statement (parser, decl: &decl); |
13835 | |
13836 | if (is_range_for) |
13837 | return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll, |
13838 | novector, false); |
13839 | else |
13840 | return cp_parser_c_for (parser, scope, init, ivdep, unroll, novector); |
13841 | } |
13842 | |
13843 | static tree |
13844 | cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, |
13845 | unsigned short unroll, bool novector) |
13846 | { |
13847 | /* Normal for loop */ |
13848 | tree condition = NULL_TREE; |
13849 | tree expression = NULL_TREE; |
13850 | tree stmt; |
13851 | |
13852 | stmt = begin_for_stmt (scope, init); |
13853 | /* The init-statement has already been parsed in |
13854 | cp_parser_init_statement, so no work is needed here. */ |
13855 | finish_init_stmt (stmt); |
13856 | |
13857 | /* If there's a condition, process it. */ |
13858 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
13859 | condition = cp_parser_condition (parser); |
13860 | else if (ivdep) |
13861 | { |
13862 | cp_parser_error (parser, gmsgid: "missing loop condition in loop with " |
13863 | "%<GCC ivdep%> pragma" ); |
13864 | condition = error_mark_node; |
13865 | } |
13866 | else if (unroll) |
13867 | { |
13868 | cp_parser_error (parser, gmsgid: "missing loop condition in loop with " |
13869 | "%<GCC unroll%> pragma" ); |
13870 | condition = error_mark_node; |
13871 | } |
13872 | finish_for_cond (condition, stmt, ivdep, unroll, novector); |
13873 | /* Look for the `;'. */ |
13874 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
13875 | |
13876 | /* If there's an expression, process it. */ |
13877 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
13878 | expression = cp_parser_expression (parser); |
13879 | finish_for_expr (expression, stmt); |
13880 | |
13881 | return stmt; |
13882 | } |
13883 | |
13884 | /* Tries to parse a range-based for-statement: |
13885 | |
13886 | range-based-for: |
13887 | decl-specifier-seq declarator : expression |
13888 | |
13889 | The decl-specifier-seq declarator and the `:' are already parsed by |
13890 | cp_parser_init_statement. If processing_template_decl it returns a |
13891 | newly created RANGE_FOR_STMT; if not, it is converted to a |
13892 | regular FOR_STMT. */ |
13893 | |
13894 | static tree |
13895 | cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, |
13896 | bool ivdep, unsigned short unroll, bool novector, |
13897 | bool is_omp) |
13898 | { |
13899 | tree stmt, range_expr; |
13900 | auto_vec <cxx_binding *, 16> bindings; |
13901 | auto_vec <tree, 16> names; |
13902 | cp_decomp decomp_d, *decomp = NULL; |
13903 | |
13904 | /* Get the range declaration momentarily out of the way so that |
13905 | the range expression doesn't clash with it. */ |
13906 | if (range_decl != error_mark_node) |
13907 | { |
13908 | if (DECL_HAS_VALUE_EXPR_P (range_decl)) |
13909 | { |
13910 | tree v = DECL_VALUE_EXPR (range_decl); |
13911 | /* For decomposition declaration get all of the corresponding |
13912 | declarations out of the way. */ |
13913 | if (TREE_CODE (v) == ARRAY_REF |
13914 | && VAR_P (TREE_OPERAND (v, 0)) |
13915 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
13916 | { |
13917 | tree d = range_decl; |
13918 | range_decl = TREE_OPERAND (v, 0); |
13919 | decomp = &decomp_d; |
13920 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
13921 | decomp->decl = d; |
13922 | for (unsigned int i = 0; i < decomp->count; |
13923 | i++, d = DECL_CHAIN (d)) |
13924 | { |
13925 | tree name = DECL_NAME (d); |
13926 | names.safe_push (obj: name); |
13927 | bindings.safe_push (IDENTIFIER_BINDING (name)); |
13928 | IDENTIFIER_BINDING (name) |
13929 | = IDENTIFIER_BINDING (name)->previous; |
13930 | } |
13931 | } |
13932 | } |
13933 | if (names.is_empty ()) |
13934 | { |
13935 | tree name = DECL_NAME (range_decl); |
13936 | names.safe_push (obj: name); |
13937 | bindings.safe_push (IDENTIFIER_BINDING (name)); |
13938 | IDENTIFIER_BINDING (name) = IDENTIFIER_BINDING (name)->previous; |
13939 | } |
13940 | } |
13941 | |
13942 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
13943 | range_expr = cp_parser_braced_list (parser); |
13944 | else |
13945 | range_expr = cp_parser_expression (parser); |
13946 | |
13947 | /* Put the range declaration(s) back into scope. */ |
13948 | for (unsigned int i = 0; i < names.length (); i++) |
13949 | { |
13950 | cxx_binding *binding = bindings[i]; |
13951 | binding->previous = IDENTIFIER_BINDING (names[i]); |
13952 | IDENTIFIER_BINDING (names[i]) = binding; |
13953 | } |
13954 | |
13955 | /* finish_omp_for has its own code for the following, so just |
13956 | return the range_expr instead. */ |
13957 | if (is_omp) |
13958 | return range_expr; |
13959 | |
13960 | /* If in template, STMT is converted to a normal for-statement |
13961 | at instantiation. If not, it is done just ahead. */ |
13962 | if (processing_template_decl) |
13963 | { |
13964 | if (check_for_bare_parameter_packs (range_expr)) |
13965 | range_expr = error_mark_node; |
13966 | stmt = begin_range_for_stmt (scope, init); |
13967 | if (ivdep) |
13968 | RANGE_FOR_IVDEP (stmt) = 1; |
13969 | if (unroll) |
13970 | RANGE_FOR_UNROLL (stmt) = build_int_cst (integer_type_node, unroll); |
13971 | if (novector) |
13972 | RANGE_FOR_NOVECTOR (stmt) = 1; |
13973 | finish_range_for_decl (stmt, range_decl, range_expr); |
13974 | if (!type_dependent_expression_p (range_expr) |
13975 | /* do_auto_deduction doesn't mess with template init-lists. */ |
13976 | && !BRACE_ENCLOSED_INITIALIZER_P (range_expr)) |
13977 | do_range_for_auto_deduction (range_decl, range_expr, decomp); |
13978 | } |
13979 | else |
13980 | { |
13981 | stmt = begin_for_stmt (scope, init); |
13982 | stmt = cp_convert_range_for (stmt, range_decl, range_expr, decomp, |
13983 | ivdep, unroll, novector); |
13984 | } |
13985 | return stmt; |
13986 | } |
13987 | |
13988 | /* Subroutine of cp_convert_range_for: given the initializer expression, |
13989 | builds up the range temporary. */ |
13990 | |
13991 | static tree |
13992 | build_range_temp (tree range_expr) |
13993 | { |
13994 | /* Find out the type deduced by the declaration |
13995 | `auto &&__range = range_expr'. */ |
13996 | tree auto_node = make_auto (); |
13997 | tree range_type = cp_build_reference_type (auto_node, true); |
13998 | range_type = do_auto_deduction (range_type, range_expr, auto_node); |
13999 | |
14000 | /* Create the __range variable. */ |
14001 | tree range_temp = build_decl (input_location, VAR_DECL, |
14002 | for_range__identifier, range_type); |
14003 | TREE_USED (range_temp) = 1; |
14004 | DECL_ARTIFICIAL (range_temp) = 1; |
14005 | |
14006 | return range_temp; |
14007 | } |
14008 | |
14009 | /* Used by cp_parser_range_for in template context: we aren't going to |
14010 | do a full conversion yet, but we still need to resolve auto in the |
14011 | type of the for-range-declaration if present. This is basically |
14012 | a shortcut version of cp_convert_range_for. */ |
14013 | |
14014 | static void |
14015 | do_range_for_auto_deduction (tree decl, tree range_expr, cp_decomp *decomp) |
14016 | { |
14017 | tree auto_node = type_uses_auto (TREE_TYPE (decl)); |
14018 | if (auto_node) |
14019 | { |
14020 | tree begin_dummy, end_dummy, range_temp, iter_type, iter_decl; |
14021 | range_temp = convert_from_reference (build_range_temp (range_expr)); |
14022 | iter_type = (cp_parser_perform_range_for_lookup |
14023 | (range_temp, &begin_dummy, &end_dummy)); |
14024 | if (iter_type) |
14025 | { |
14026 | iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, |
14027 | iter_type); |
14028 | iter_decl = build_x_indirect_ref (input_location, iter_decl, |
14029 | RO_UNARY_STAR, NULL_TREE, |
14030 | tf_warning_or_error); |
14031 | TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), |
14032 | iter_decl, auto_node, |
14033 | tf_warning_or_error, |
14034 | adc_variable_type); |
14035 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
14036 | cp_finish_decomp (decl, decomp); |
14037 | } |
14038 | } |
14039 | } |
14040 | |
14041 | /* Warns when the loop variable should be changed to a reference type to |
14042 | avoid unnecessary copying. I.e., from |
14043 | |
14044 | for (const auto x : range) |
14045 | |
14046 | where range returns a reference, to |
14047 | |
14048 | for (const auto &x : range) |
14049 | |
14050 | if this version doesn't make a copy. |
14051 | |
14052 | This function also warns when the loop variable is initialized with |
14053 | a value of a different type resulting in a copy: |
14054 | |
14055 | int arr[10]; |
14056 | for (const double &x : arr) |
14057 | |
14058 | DECL is the RANGE_DECL; EXPR is the *__for_begin expression. |
14059 | This function is never called when processing_template_decl is on. */ |
14060 | |
14061 | static void |
14062 | warn_for_range_copy (tree decl, tree expr) |
14063 | { |
14064 | if (!warn_range_loop_construct |
14065 | || decl == error_mark_node) |
14066 | return; |
14067 | |
14068 | location_t loc = DECL_SOURCE_LOCATION (decl); |
14069 | tree type = TREE_TYPE (decl); |
14070 | |
14071 | if (from_macro_expansion_at (loc)) |
14072 | return; |
14073 | |
14074 | if (TYPE_REF_P (type)) |
14075 | { |
14076 | if (glvalue_p (expr) |
14077 | && ref_conv_binds_to_temporary (type, expr).is_true ()) |
14078 | { |
14079 | auto_diagnostic_group d; |
14080 | if (warning_at (loc, OPT_Wrange_loop_construct, |
14081 | "loop variable %qD of type %qT binds to a temporary " |
14082 | "constructed from type %qT" , decl, type, |
14083 | TREE_TYPE (expr))) |
14084 | { |
14085 | tree ref = cp_build_qualified_type (TREE_TYPE (expr), |
14086 | TYPE_QUAL_CONST); |
14087 | ref = cp_build_reference_type (ref, /*rval*/false); |
14088 | inform (loc, "use non-reference type %qT to make the copy " |
14089 | "explicit or %qT to prevent copying" , |
14090 | non_reference (type), ref); |
14091 | } |
14092 | } |
14093 | return; |
14094 | } |
14095 | else if (!CP_TYPE_CONST_P (type)) |
14096 | return; |
14097 | |
14098 | /* Since small trivially copyable types are cheap to copy, we suppress the |
14099 | warning for them. 64B is a common size of a cache line. */ |
14100 | if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST |
14101 | || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64 |
14102 | && trivially_copyable_p (type))) |
14103 | return; |
14104 | |
14105 | /* If we can initialize a reference directly, suggest that to avoid the |
14106 | copy. */ |
14107 | tree rtype = cp_build_reference_type (type, /*rval*/false); |
14108 | if (ref_conv_binds_to_temporary (rtype, expr).is_false ()) |
14109 | { |
14110 | auto_diagnostic_group d; |
14111 | if (warning_at (loc, OPT_Wrange_loop_construct, |
14112 | "loop variable %qD creates a copy from type %qT" , |
14113 | decl, type)) |
14114 | { |
14115 | gcc_rich_location richloc (loc); |
14116 | richloc.add_fixit_insert_before (new_content: "&" ); |
14117 | inform (&richloc, "use reference type to prevent copying" ); |
14118 | } |
14119 | } |
14120 | } |
14121 | |
14122 | /* Converts a range-based for-statement into a normal |
14123 | for-statement, as per the definition. |
14124 | |
14125 | for (RANGE_DECL : RANGE_EXPR) |
14126 | BLOCK |
14127 | |
14128 | should be equivalent to: |
14129 | |
14130 | { |
14131 | auto &&__range = RANGE_EXPR; |
14132 | for (auto __begin = BEGIN_EXPR, __end = END_EXPR; |
14133 | __begin != __end; |
14134 | ++__begin) |
14135 | { |
14136 | RANGE_DECL = *__begin; |
14137 | BLOCK |
14138 | } |
14139 | } |
14140 | |
14141 | If RANGE_EXPR is an array: |
14142 | BEGIN_EXPR = __range |
14143 | END_EXPR = __range + ARRAY_SIZE(__range) |
14144 | Else if RANGE_EXPR has a member 'begin' or 'end': |
14145 | BEGIN_EXPR = __range.begin() |
14146 | END_EXPR = __range.end() |
14147 | Else: |
14148 | BEGIN_EXPR = begin(__range) |
14149 | END_EXPR = end(__range); |
14150 | |
14151 | If __range has a member 'begin' but not 'end', or vice versa, we must |
14152 | still use the second alternative (it will surely fail, however). |
14153 | When calling begin()/end() in the third alternative we must use |
14154 | argument dependent lookup, but always considering 'std' as an associated |
14155 | namespace. */ |
14156 | |
14157 | tree |
14158 | cp_convert_range_for (tree statement, tree range_decl, tree range_expr, |
14159 | cp_decomp *decomp, bool ivdep, unsigned short unroll, |
14160 | bool novector) |
14161 | { |
14162 | tree begin, end; |
14163 | tree iter_type, begin_expr, end_expr; |
14164 | tree condition, expression; |
14165 | |
14166 | range_expr = mark_lvalue_use (range_expr); |
14167 | |
14168 | if (range_decl == error_mark_node || range_expr == error_mark_node) |
14169 | /* If an error happened previously do nothing or else a lot of |
14170 | unhelpful errors would be issued. */ |
14171 | begin_expr = end_expr = iter_type = error_mark_node; |
14172 | else |
14173 | { |
14174 | tree range_temp; |
14175 | |
14176 | if (VAR_P (range_expr) |
14177 | && array_of_runtime_bound_p (TREE_TYPE (range_expr))) |
14178 | /* Can't bind a reference to an array of runtime bound. */ |
14179 | range_temp = range_expr; |
14180 | else |
14181 | { |
14182 | range_temp = build_range_temp (range_expr); |
14183 | pushdecl (range_temp); |
14184 | cp_finish_decl (range_temp, range_expr, |
14185 | /*is_constant_init*/false, NULL_TREE, |
14186 | LOOKUP_ONLYCONVERTING); |
14187 | range_temp = convert_from_reference (range_temp); |
14188 | } |
14189 | iter_type = cp_parser_perform_range_for_lookup (range_temp, |
14190 | &begin_expr, &end_expr); |
14191 | } |
14192 | |
14193 | /* The new for initialization statement. */ |
14194 | begin = build_decl (input_location, VAR_DECL, for_begin__identifier, |
14195 | iter_type); |
14196 | TREE_USED (begin) = 1; |
14197 | DECL_ARTIFICIAL (begin) = 1; |
14198 | pushdecl (begin); |
14199 | cp_finish_decl (begin, begin_expr, |
14200 | /*is_constant_init*/false, NULL_TREE, |
14201 | LOOKUP_ONLYCONVERTING); |
14202 | |
14203 | if (cxx_dialect >= cxx17) |
14204 | iter_type = cv_unqualified (TREE_TYPE (end_expr)); |
14205 | end = build_decl (input_location, VAR_DECL, for_end__identifier, iter_type); |
14206 | TREE_USED (end) = 1; |
14207 | DECL_ARTIFICIAL (end) = 1; |
14208 | pushdecl (end); |
14209 | cp_finish_decl (end, end_expr, |
14210 | /*is_constant_init*/false, NULL_TREE, |
14211 | LOOKUP_ONLYCONVERTING); |
14212 | |
14213 | finish_init_stmt (statement); |
14214 | |
14215 | /* The new for condition. */ |
14216 | condition = build_x_binary_op (input_location, NE_EXPR, |
14217 | begin, ERROR_MARK, |
14218 | end, ERROR_MARK, |
14219 | NULL_TREE, NULL, tf_warning_or_error); |
14220 | finish_for_cond (condition, statement, ivdep, unroll, novector); |
14221 | |
14222 | /* The new increment expression. */ |
14223 | expression = finish_unary_op_expr (input_location, |
14224 | PREINCREMENT_EXPR, begin, |
14225 | tf_warning_or_error); |
14226 | finish_for_expr (expression, statement); |
14227 | |
14228 | /* The declaration is initialized with *__begin inside the loop body. */ |
14229 | tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
14230 | NULL_TREE, tf_warning_or_error); |
14231 | cp_finish_decl (range_decl, deref_begin, |
14232 | /*is_constant_init*/false, NULL_TREE, |
14233 | LOOKUP_ONLYCONVERTING, decomp); |
14234 | if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl)) |
14235 | cp_finish_decomp (range_decl, decomp); |
14236 | |
14237 | warn_for_range_copy (decl: range_decl, expr: deref_begin); |
14238 | |
14239 | return statement; |
14240 | } |
14241 | |
14242 | /* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for. |
14243 | We need to solve both at the same time because the method used |
14244 | depends on the existence of members begin or end. |
14245 | Returns the type deduced for the iterator expression. */ |
14246 | |
14247 | static tree |
14248 | cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) |
14249 | { |
14250 | if (error_operand_p (t: range)) |
14251 | { |
14252 | *begin = *end = error_mark_node; |
14253 | return error_mark_node; |
14254 | } |
14255 | |
14256 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (range)))) |
14257 | { |
14258 | error ("range-based %<for%> expression of type %qT " |
14259 | "has incomplete type" , TREE_TYPE (range)); |
14260 | *begin = *end = error_mark_node; |
14261 | return error_mark_node; |
14262 | } |
14263 | if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE) |
14264 | { |
14265 | /* If RANGE is an array, we will use pointer arithmetic. */ |
14266 | *begin = decay_conversion (range, tf_warning_or_error); |
14267 | *end = build_binary_op (input_location, PLUS_EXPR, |
14268 | range, |
14269 | array_type_nelts_top (TREE_TYPE (range)), |
14270 | false); |
14271 | return TREE_TYPE (*begin); |
14272 | } |
14273 | else |
14274 | { |
14275 | /* If it is not an array, we must do a bit of magic. */ |
14276 | tree id_begin, id_end; |
14277 | tree member_begin, member_end; |
14278 | |
14279 | *begin = *end = error_mark_node; |
14280 | |
14281 | id_begin = get_identifier ("begin" ); |
14282 | id_end = get_identifier ("end" ); |
14283 | member_begin = lookup_member (TREE_TYPE (range), id_begin, |
14284 | /*protect=*/2, /*want_type=*/false, |
14285 | tf_warning_or_error); |
14286 | member_end = lookup_member (TREE_TYPE (range), id_end, |
14287 | /*protect=*/2, /*want_type=*/false, |
14288 | tf_warning_or_error); |
14289 | |
14290 | if (member_begin != NULL_TREE && member_end != NULL_TREE) |
14291 | { |
14292 | /* Use the member functions. */ |
14293 | *begin = cp_parser_range_for_member_function (range, id_begin); |
14294 | *end = cp_parser_range_for_member_function (range, id_end); |
14295 | } |
14296 | else |
14297 | { |
14298 | /* Use global functions with ADL. */ |
14299 | releasing_vec vec; |
14300 | |
14301 | vec_safe_push (r&: vec, t: range); |
14302 | |
14303 | member_begin = perform_koenig_lookup (id_begin, vec, |
14304 | tf_warning_or_error); |
14305 | *begin = finish_call_expr (member_begin, &vec, false, true, |
14306 | tf_warning_or_error); |
14307 | member_end = perform_koenig_lookup (id_end, vec, |
14308 | tf_warning_or_error); |
14309 | *end = finish_call_expr (member_end, &vec, false, true, |
14310 | tf_warning_or_error); |
14311 | } |
14312 | |
14313 | /* Last common checks. */ |
14314 | if (*begin == error_mark_node || *end == error_mark_node) |
14315 | { |
14316 | /* If one of the expressions is an error do no more checks. */ |
14317 | *begin = *end = error_mark_node; |
14318 | return error_mark_node; |
14319 | } |
14320 | else if (type_dependent_expression_p (*begin) |
14321 | || type_dependent_expression_p (*end)) |
14322 | /* Can happen, when, eg, in a template context, Koenig lookup |
14323 | can't resolve begin/end (c++/58503). */ |
14324 | return NULL_TREE; |
14325 | else |
14326 | { |
14327 | tree iter_type = cv_unqualified (TREE_TYPE (*begin)); |
14328 | /* The unqualified type of the __begin and __end temporaries should |
14329 | be the same, as required by the multiple auto declaration. */ |
14330 | if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end)))) |
14331 | { |
14332 | if (cxx_dialect >= cxx17 |
14333 | && (build_x_binary_op (input_location, NE_EXPR, |
14334 | *begin, ERROR_MARK, |
14335 | *end, ERROR_MARK, |
14336 | NULL_TREE, NULL, tf_none) |
14337 | != error_mark_node)) |
14338 | /* P0184R0 allows __begin and __end to have different types, |
14339 | but make sure they are comparable so we can give a better |
14340 | diagnostic. */; |
14341 | else |
14342 | error ("inconsistent begin/end types in range-based %<for%> " |
14343 | "statement: %qT and %qT" , |
14344 | TREE_TYPE (*begin), TREE_TYPE (*end)); |
14345 | } |
14346 | return iter_type; |
14347 | } |
14348 | } |
14349 | } |
14350 | |
14351 | /* Helper function for cp_parser_perform_range_for_lookup. |
14352 | Builds a tree for RANGE.IDENTIFIER(). */ |
14353 | |
14354 | static tree |
14355 | cp_parser_range_for_member_function (tree range, tree identifier) |
14356 | { |
14357 | tree member, res; |
14358 | |
14359 | member = finish_class_member_access_expr (range, identifier, |
14360 | false, tf_warning_or_error); |
14361 | if (member == error_mark_node) |
14362 | return error_mark_node; |
14363 | |
14364 | releasing_vec vec; |
14365 | res = finish_call_expr (member, &vec, |
14366 | /*disallow_virtual=*/false, |
14367 | /*koenig_p=*/false, |
14368 | tf_warning_or_error); |
14369 | return res; |
14370 | } |
14371 | |
14372 | /* Parse an iteration-statement. |
14373 | |
14374 | iteration-statement: |
14375 | while ( condition ) statement |
14376 | do statement while ( expression ) ; |
14377 | for ( init-statement condition [opt] ; expression [opt] ) |
14378 | statement |
14379 | |
14380 | Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */ |
14381 | |
14382 | static tree |
14383 | cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, |
14384 | unsigned short unroll, bool novector) |
14385 | { |
14386 | cp_token *token; |
14387 | enum rid keyword; |
14388 | tree statement; |
14389 | unsigned char in_statement; |
14390 | token_indent_info guard_tinfo; |
14391 | |
14392 | /* Peek at the next token. */ |
14393 | token = cp_parser_require (parser, CPP_KEYWORD, RT_ITERATION); |
14394 | if (!token) |
14395 | return error_mark_node; |
14396 | |
14397 | guard_tinfo = get_token_indent_info (token); |
14398 | |
14399 | /* Remember whether or not we are already within an iteration |
14400 | statement. */ |
14401 | in_statement = parser->in_statement; |
14402 | |
14403 | /* Special case for OMP loop intervening code. Parsing of permitted |
14404 | collapsed loop nests is handled elsewhere. */ |
14405 | if (parser->omp_for_parse_state) |
14406 | { |
14407 | error_at (token->location, |
14408 | "loop not permitted in intervening code in OpenMP loop body" ); |
14409 | parser->omp_for_parse_state->fail = true; |
14410 | } |
14411 | |
14412 | /* See what kind of keyword it is. */ |
14413 | keyword = token->keyword; |
14414 | switch (keyword) |
14415 | { |
14416 | case RID_WHILE: |
14417 | { |
14418 | tree condition; |
14419 | |
14420 | /* Begin the while-statement. */ |
14421 | statement = begin_while_stmt (); |
14422 | /* Look for the `('. */ |
14423 | matching_parens parens; |
14424 | parens.require_open (parser); |
14425 | /* Parse the condition. */ |
14426 | condition = cp_parser_condition (parser); |
14427 | finish_while_stmt_cond (condition, statement, ivdep, unroll, novector); |
14428 | /* Look for the `)'. */ |
14429 | parens.require_close (parser); |
14430 | /* Parse the dependent statement. */ |
14431 | parser->in_statement = IN_ITERATION_STMT; |
14432 | bool prev = note_iteration_stmt_body_start (); |
14433 | cp_parser_already_scoped_statement (parser, if_p, guard_tinfo); |
14434 | note_iteration_stmt_body_end (prev); |
14435 | parser->in_statement = in_statement; |
14436 | /* We're done with the while-statement. */ |
14437 | finish_while_stmt (statement); |
14438 | } |
14439 | break; |
14440 | |
14441 | case RID_DO: |
14442 | { |
14443 | tree expression; |
14444 | |
14445 | /* Begin the do-statement. */ |
14446 | statement = begin_do_stmt (); |
14447 | /* Parse the body of the do-statement. */ |
14448 | parser->in_statement = IN_ITERATION_STMT; |
14449 | bool prev = note_iteration_stmt_body_start (); |
14450 | cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo); |
14451 | note_iteration_stmt_body_end (prev); |
14452 | parser->in_statement = in_statement; |
14453 | finish_do_body (statement); |
14454 | /* Look for the `while' keyword. */ |
14455 | cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE); |
14456 | /* Look for the `('. */ |
14457 | matching_parens parens; |
14458 | parens.require_open (parser); |
14459 | /* Parse the expression. */ |
14460 | expression = cp_parser_expression (parser); |
14461 | /* We're done with the do-statement. */ |
14462 | finish_do_stmt (expression, statement, ivdep, unroll, novector); |
14463 | /* Look for the `)'. */ |
14464 | parens.require_close (parser); |
14465 | /* Look for the `;'. */ |
14466 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14467 | } |
14468 | break; |
14469 | |
14470 | case RID_FOR: |
14471 | { |
14472 | /* Look for the `('. */ |
14473 | matching_parens parens; |
14474 | parens.require_open (parser); |
14475 | |
14476 | statement = cp_parser_for (parser, ivdep, unroll, novector); |
14477 | |
14478 | /* Look for the `)'. */ |
14479 | parens.require_close (parser); |
14480 | |
14481 | /* Parse the body of the for-statement. */ |
14482 | parser->in_statement = IN_ITERATION_STMT; |
14483 | bool prev = note_iteration_stmt_body_start (); |
14484 | cp_parser_already_scoped_statement (parser, if_p, guard_tinfo); |
14485 | note_iteration_stmt_body_end (prev); |
14486 | parser->in_statement = in_statement; |
14487 | |
14488 | /* We're done with the for-statement. */ |
14489 | finish_for_stmt (statement); |
14490 | } |
14491 | break; |
14492 | |
14493 | default: |
14494 | cp_parser_error (parser, gmsgid: "expected iteration-statement" ); |
14495 | statement = error_mark_node; |
14496 | break; |
14497 | } |
14498 | |
14499 | return statement; |
14500 | } |
14501 | |
14502 | /* Parse an init-statement or the declarator of a range-based-for. |
14503 | Returns true if a range-based-for declaration is seen. |
14504 | |
14505 | init-statement: |
14506 | expression-statement |
14507 | simple-declaration |
14508 | alias-declaration */ |
14509 | |
14510 | static bool |
14511 | cp_parser_init_statement (cp_parser *parser, tree *decl) |
14512 | { |
14513 | /* If the next token is a `;', then we have an empty |
14514 | expression-statement. Grammatically, this is also a |
14515 | simple-declaration, but an invalid one, because it does not |
14516 | declare anything. Therefore, if we did not handle this case |
14517 | specially, we would issue an error message about an invalid |
14518 | declaration. */ |
14519 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14520 | { |
14521 | bool is_range_for = false; |
14522 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
14523 | |
14524 | /* A colon is used in range-based for. */ |
14525 | parser->colon_corrects_to_scope_p = false; |
14526 | |
14527 | /* We're going to speculatively look for a declaration, falling back |
14528 | to an expression, if necessary. */ |
14529 | cp_parser_parse_tentatively (parser); |
14530 | bool expect_semicolon_p = true; |
14531 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
14532 | { |
14533 | cp_parser_alias_declaration (parser); |
14534 | expect_semicolon_p = false; |
14535 | if (cxx_dialect < cxx23 |
14536 | && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
14537 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
14538 | OPT_Wc__23_extensions, |
14539 | "alias-declaration in init-statement only " |
14540 | "available with %<-std=c++23%> or %<-std=gnu++23%>" ); |
14541 | } |
14542 | else |
14543 | /* Parse the declaration. */ |
14544 | cp_parser_simple_declaration (parser, |
14545 | /*function_definition_allowed_p=*/false, |
14546 | decl); |
14547 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
14548 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
14549 | { |
14550 | /* It is a range-for, consume the ':'. */ |
14551 | cp_lexer_consume_token (lexer: parser->lexer); |
14552 | is_range_for = true; |
14553 | if (cxx_dialect < cxx11) |
14554 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
14555 | OPT_Wc__11_extensions, |
14556 | "range-based %<for%> loops only available with " |
14557 | "%<-std=c++11%> or %<-std=gnu++11%>" ); |
14558 | } |
14559 | else if (expect_semicolon_p) |
14560 | /* The ';' is not consumed yet because we told |
14561 | cp_parser_simple_declaration not to. */ |
14562 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14563 | |
14564 | if (cp_parser_parse_definitely (parser)) |
14565 | return is_range_for; |
14566 | /* If the tentative parse failed, then we shall need to look for an |
14567 | expression-statement. */ |
14568 | } |
14569 | /* If we are here, it is an expression-statement. */ |
14570 | cp_parser_expression_statement (parser, NULL_TREE); |
14571 | return false; |
14572 | } |
14573 | |
14574 | /* Parse a jump-statement. |
14575 | |
14576 | jump-statement: |
14577 | break ; |
14578 | continue ; |
14579 | return expression [opt] ; |
14580 | return braced-init-list ; |
14581 | coroutine-return-statement; |
14582 | goto identifier ; |
14583 | |
14584 | GNU extension: |
14585 | |
14586 | jump-statement: |
14587 | goto * expression ; |
14588 | |
14589 | Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_EXPR, or GOTO_EXPR. */ |
14590 | |
14591 | static tree |
14592 | cp_parser_jump_statement (cp_parser* parser) |
14593 | { |
14594 | tree statement = error_mark_node; |
14595 | cp_token *token; |
14596 | enum rid keyword; |
14597 | unsigned char in_statement; |
14598 | |
14599 | /* Peek at the next token. */ |
14600 | token = cp_parser_require (parser, CPP_KEYWORD, RT_JUMP); |
14601 | if (!token) |
14602 | return error_mark_node; |
14603 | |
14604 | /* See what kind of keyword it is. */ |
14605 | keyword = token->keyword; |
14606 | switch (keyword) |
14607 | { |
14608 | case RID_BREAK: |
14609 | in_statement = parser->in_statement & ~IN_IF_STMT; |
14610 | switch (in_statement) |
14611 | { |
14612 | case 0: |
14613 | error_at (token->location, "break statement not within loop or switch" ); |
14614 | break; |
14615 | default: |
14616 | gcc_assert ((in_statement & IN_SWITCH_STMT) |
14617 | || in_statement == IN_ITERATION_STMT); |
14618 | statement = finish_break_stmt (); |
14619 | if (in_statement == IN_ITERATION_STMT) |
14620 | break_maybe_infinite_loop (); |
14621 | break; |
14622 | case IN_OMP_BLOCK: |
14623 | error_at (token->location, "invalid exit from OpenMP structured block" ); |
14624 | break; |
14625 | case IN_OMP_FOR: |
14626 | error_at (token->location, "break statement used with OpenMP for loop" ); |
14627 | break; |
14628 | } |
14629 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14630 | break; |
14631 | |
14632 | case RID_CONTINUE: |
14633 | switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT)) |
14634 | { |
14635 | case 0: |
14636 | error_at (token->location, "continue statement not within a loop" ); |
14637 | break; |
14638 | /* Fall through. */ |
14639 | case IN_ITERATION_STMT: |
14640 | case IN_OMP_FOR: |
14641 | statement = finish_continue_stmt (); |
14642 | break; |
14643 | case IN_OMP_BLOCK: |
14644 | error_at (token->location, "invalid exit from OpenMP structured block" ); |
14645 | break; |
14646 | default: |
14647 | gcc_unreachable (); |
14648 | } |
14649 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14650 | break; |
14651 | |
14652 | case RID_CO_RETURN: |
14653 | case RID_RETURN: |
14654 | { |
14655 | tree expr; |
14656 | |
14657 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14658 | { |
14659 | cp_lexer_set_source_position (lexer: parser->lexer); |
14660 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
14661 | expr = cp_parser_braced_list (parser); |
14662 | } |
14663 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14664 | expr = cp_parser_expression (parser); |
14665 | else |
14666 | /* If the next token is a `;', then there is no |
14667 | expression. */ |
14668 | expr = NULL_TREE; |
14669 | /* Build the return-statement, check co-return first, since type |
14670 | deduction is not valid there. */ |
14671 | if (keyword == RID_CO_RETURN) |
14672 | statement = finish_co_return_stmt (token->location, expr); |
14673 | else if (FNDECL_USED_AUTO (current_function_decl) && in_discarded_stmt) |
14674 | /* Don't deduce from a discarded return statement. */; |
14675 | else |
14676 | statement = finish_return_stmt (expr); |
14677 | /* Look for the final `;'. */ |
14678 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14679 | } |
14680 | break; |
14681 | |
14682 | case RID_GOTO: |
14683 | if (parser->in_function_body |
14684 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
14685 | && cxx_dialect < cxx23) |
14686 | { |
14687 | error ("%<goto%> in %<constexpr%> function only available with " |
14688 | "%<-std=c++2b%> or %<-std=gnu++2b%>" ); |
14689 | cp_function_chain->invalid_constexpr = true; |
14690 | } |
14691 | |
14692 | /* Create the goto-statement. */ |
14693 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT)) |
14694 | { |
14695 | /* Issue a warning about this use of a GNU extension. */ |
14696 | pedwarn (token->location, OPT_Wpedantic, "ISO C++ forbids computed gotos" ); |
14697 | /* Consume the '*' token. */ |
14698 | cp_lexer_consume_token (lexer: parser->lexer); |
14699 | /* Parse the dependent expression. */ |
14700 | finish_goto_stmt (cp_parser_expression (parser)); |
14701 | } |
14702 | else |
14703 | finish_goto_stmt (cp_parser_identifier (parser)); |
14704 | /* Look for the final `;'. */ |
14705 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
14706 | break; |
14707 | |
14708 | default: |
14709 | cp_parser_error (parser, gmsgid: "expected jump-statement" ); |
14710 | break; |
14711 | } |
14712 | |
14713 | return statement; |
14714 | } |
14715 | |
14716 | /* Parse a declaration-statement. |
14717 | |
14718 | declaration-statement: |
14719 | block-declaration */ |
14720 | |
14721 | static void |
14722 | cp_parser_declaration_statement (cp_parser* parser) |
14723 | { |
14724 | void *p; |
14725 | |
14726 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
14727 | p = obstack_alloc (&declarator_obstack, 0); |
14728 | |
14729 | /* Parse the block-declaration. */ |
14730 | cp_parser_block_declaration (parser, /*statement_p=*/true); |
14731 | |
14732 | /* Free any declarators allocated. */ |
14733 | obstack_free (&declarator_obstack, p); |
14734 | } |
14735 | |
14736 | /* Some dependent statements (like `if (cond) statement'), are |
14737 | implicitly in their own scope. In other words, if the statement is |
14738 | a single statement (as opposed to a compound-statement), it is |
14739 | none-the-less treated as if it were enclosed in braces. Any |
14740 | declarations appearing in the dependent statement are out of scope |
14741 | after control passes that point. This function parses a statement, |
14742 | but ensures that is in its own scope, even if it is not a |
14743 | compound-statement. |
14744 | |
14745 | If IF_P is not NULL, *IF_P is set to indicate whether the statement |
14746 | is a (possibly labeled) if statement which is not enclosed in |
14747 | braces and has an else clause. This is used to implement |
14748 | -Wparentheses. |
14749 | |
14750 | CHAIN is a vector of if-else-if conditions. This is used to implement |
14751 | -Wduplicated-cond. |
14752 | |
14753 | Returns the new statement. */ |
14754 | |
14755 | static tree |
14756 | cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p, |
14757 | const token_indent_info &guard_tinfo, |
14758 | vec<tree> *chain) |
14759 | { |
14760 | tree statement; |
14761 | location_t body_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
14762 | location_t body_loc_after_labels = UNKNOWN_LOCATION; |
14763 | token_indent_info body_tinfo |
14764 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
14765 | |
14766 | if (if_p != NULL) |
14767 | *if_p = false; |
14768 | |
14769 | /* Mark if () ; with a special NOP_EXPR. */ |
14770 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14771 | { |
14772 | cp_lexer_consume_token (lexer: parser->lexer); |
14773 | statement = add_stmt (build_empty_stmt (body_loc)); |
14774 | |
14775 | if (guard_tinfo.keyword == RID_IF |
14776 | && !cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ELSE)) |
14777 | warning_at (body_loc, OPT_Wempty_body, |
14778 | "suggest braces around empty body in an %<if%> statement" ); |
14779 | else if (guard_tinfo.keyword == RID_ELSE) |
14780 | warning_at (body_loc, OPT_Wempty_body, |
14781 | "suggest braces around empty body in an %<else%> statement" ); |
14782 | } |
14783 | /* if a compound is opened, we simply parse the statement directly. */ |
14784 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14785 | statement = cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
14786 | /* If the token is not a `{', then we must take special action. */ |
14787 | else |
14788 | { |
14789 | /* Create a compound-statement. */ |
14790 | statement = begin_compound_stmt (0); |
14791 | /* Parse the dependent-statement. */ |
14792 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p, chain, |
14793 | loc_after_labels: &body_loc_after_labels); |
14794 | /* Finish the dummy compound-statement. */ |
14795 | finish_compound_stmt (statement); |
14796 | } |
14797 | |
14798 | token_indent_info next_tinfo |
14799 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
14800 | warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo); |
14801 | |
14802 | if (body_loc_after_labels != UNKNOWN_LOCATION |
14803 | && next_tinfo.type != CPP_SEMICOLON) |
14804 | warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location, |
14805 | guard_tinfo.location, guard_tinfo.keyword); |
14806 | |
14807 | /* Return the statement. */ |
14808 | return statement; |
14809 | } |
14810 | |
14811 | /* For some dependent statements (like `while (cond) statement'), we |
14812 | have already created a scope. Therefore, even if the dependent |
14813 | statement is a compound-statement, we do not want to create another |
14814 | scope. */ |
14815 | |
14816 | static void |
14817 | cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p, |
14818 | const token_indent_info &guard_tinfo) |
14819 | { |
14820 | /* If the token is a `{', then we must take special action. */ |
14821 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
14822 | { |
14823 | token_indent_info body_tinfo |
14824 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
14825 | location_t loc_after_labels = UNKNOWN_LOCATION; |
14826 | |
14827 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p, NULL, |
14828 | loc_after_labels: &loc_after_labels); |
14829 | token_indent_info next_tinfo |
14830 | = get_token_indent_info (token: cp_lexer_peek_token (lexer: parser->lexer)); |
14831 | warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo); |
14832 | |
14833 | if (loc_after_labels != UNKNOWN_LOCATION |
14834 | && next_tinfo.type != CPP_SEMICOLON) |
14835 | warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, |
14836 | guard_tinfo.location, |
14837 | guard_tinfo.keyword); |
14838 | } |
14839 | else |
14840 | { |
14841 | /* Avoid calling cp_parser_compound_statement, so that we |
14842 | don't create a new scope. Do everything else by hand. */ |
14843 | matching_braces braces; |
14844 | braces.require_open (parser); |
14845 | /* If the next keyword is `__label__' we have a label declaration. */ |
14846 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_LABEL)) |
14847 | cp_parser_label_declaration (parser); |
14848 | /* Parse an (optional) statement-seq. */ |
14849 | cp_parser_statement_seq_opt (parser, NULL_TREE); |
14850 | braces.require_close (parser); |
14851 | } |
14852 | } |
14853 | |
14854 | /* Modules */ |
14855 | |
14856 | /* Parse a module-name, |
14857 | identifier |
14858 | module-name . identifier |
14859 | header-name |
14860 | |
14861 | Returns a pointer to module object, NULL. */ |
14862 | |
14863 | static module_state * |
14864 | cp_parser_module_name (cp_parser *parser) |
14865 | { |
14866 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
14867 | if (token->type == CPP_HEADER_NAME) |
14868 | { |
14869 | cp_lexer_consume_token (lexer: parser->lexer); |
14870 | |
14871 | return get_module (name: token->u.value); |
14872 | } |
14873 | |
14874 | module_state *parent = NULL; |
14875 | bool partitioned = false; |
14876 | if (token->type == CPP_COLON && named_module_p ()) |
14877 | { |
14878 | partitioned = true; |
14879 | cp_lexer_consume_token (lexer: parser->lexer); |
14880 | } |
14881 | |
14882 | for (;;) |
14883 | { |
14884 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_NAME) |
14885 | { |
14886 | cp_parser_error (parser, gmsgid: "expected module-name" ); |
14887 | break; |
14888 | } |
14889 | |
14890 | tree name = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
14891 | parent = get_module (name, parent, partition: partitioned); |
14892 | token = cp_lexer_peek_token (lexer: parser->lexer); |
14893 | if (!partitioned && token->type == CPP_COLON) |
14894 | partitioned = true; |
14895 | else if (token->type != CPP_DOT) |
14896 | break; |
14897 | |
14898 | cp_lexer_consume_token (lexer: parser->lexer); |
14899 | } |
14900 | |
14901 | return parent; |
14902 | } |
14903 | |
14904 | /* Named module-declaration |
14905 | __module ; PRAGMA_EOL |
14906 | __module private ; PRAGMA_EOL (unimplemented) |
14907 | [__export] __module module-name attr-spec-seq-opt ; PRAGMA_EOL |
14908 | */ |
14909 | |
14910 | static module_parse |
14911 | cp_parser_module_declaration (cp_parser *parser, module_parse mp_state, |
14912 | bool exporting) |
14913 | { |
14914 | /* We're a pseudo pragma. */ |
14915 | parser->lexer->in_pragma = true; |
14916 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
14917 | |
14918 | if (flag_header_unit) |
14919 | { |
14920 | error_at (token->location, |
14921 | "module-declaration not permitted in header-unit" ); |
14922 | goto skip_eol; |
14923 | } |
14924 | else if (mp_state == MP_FIRST && !exporting |
14925 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
14926 | { |
14927 | /* Start global module fragment. */ |
14928 | cp_lexer_consume_token (lexer: parser->lexer); |
14929 | module_kind = MK_NAMED; |
14930 | mp_state = MP_GLOBAL; |
14931 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
14932 | } |
14933 | else if (!exporting |
14934 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
14935 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_PRIVATE) |
14936 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_SEMICOLON)) |
14937 | { |
14938 | cp_lexer_consume_token (lexer: parser->lexer); |
14939 | cp_lexer_consume_token (lexer: parser->lexer); |
14940 | cp_lexer_consume_token (lexer: parser->lexer); |
14941 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
14942 | |
14943 | if ((mp_state == MP_PURVIEW || mp_state == MP_PURVIEW_IMPORTS) |
14944 | && module_has_cmi_p ()) |
14945 | { |
14946 | mp_state = MP_PRIVATE_IMPORTS; |
14947 | sorry_at (token->location, "private module fragment" ); |
14948 | } |
14949 | else |
14950 | error_at (token->location, |
14951 | "private module fragment only permitted in purview" |
14952 | " of module interface or partition" ); |
14953 | } |
14954 | else if (!(mp_state == MP_FIRST || mp_state == MP_GLOBAL)) |
14955 | { |
14956 | /* Neither the first declaration, nor in a GMF. */ |
14957 | error_at (token->location, "module-declaration only permitted as first" |
14958 | " declaration, or ending a global module fragment" ); |
14959 | skip_eol: |
14960 | cp_parser_skip_to_pragma_eol (parser, pragma_tok: token); |
14961 | } |
14962 | else |
14963 | { |
14964 | module_state *mod = cp_parser_module_name (parser); |
14965 | tree attrs = cp_parser_attributes_opt (parser); |
14966 | |
14967 | mp_state = MP_PURVIEW_IMPORTS; |
14968 | if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
14969 | goto skip_eol; |
14970 | |
14971 | declare_module (mod, token->location, export_p: exporting, attr: attrs, parse_in); |
14972 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
14973 | } |
14974 | |
14975 | return mp_state; |
14976 | } |
14977 | |
14978 | /* Import-declaration |
14979 | [__export] __import module-name attr-spec-seq-opt ; PRAGMA_EOL */ |
14980 | |
14981 | static void |
14982 | cp_parser_import_declaration (cp_parser *parser, module_parse mp_state, |
14983 | bool exporting) |
14984 | { |
14985 | /* We're a pseudo pragma. */ |
14986 | parser->lexer->in_pragma = true; |
14987 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
14988 | |
14989 | if (mp_state == MP_PURVIEW || mp_state == MP_PRIVATE) |
14990 | { |
14991 | error_at (token->location, "post-module-declaration" |
14992 | " imports must be contiguous" ); |
14993 | note_lexer: |
14994 | inform (token->location, "perhaps insert a line break, or other" |
14995 | " disambiguation, to prevent this being considered a" |
14996 | " module control-line" ); |
14997 | skip_eol: |
14998 | cp_parser_skip_to_pragma_eol (parser, pragma_tok: token); |
14999 | } |
15000 | else if (current_scope () != global_namespace) |
15001 | { |
15002 | error_at (token->location, "import-declaration must be at global scope" ); |
15003 | goto note_lexer; |
15004 | } |
15005 | else |
15006 | { |
15007 | module_state *mod = cp_parser_module_name (parser); |
15008 | tree attrs = cp_parser_attributes_opt (parser); |
15009 | |
15010 | if (!mod || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
15011 | goto skip_eol; |
15012 | cp_parser_require_pragma_eol (parser, pragma_tok: token); |
15013 | |
15014 | if (parser->in_unbraced_linkage_specification_p) |
15015 | error_at (token->location, "import cannot appear directly in" |
15016 | " a linkage-specification" ); |
15017 | |
15018 | if (mp_state == MP_PURVIEW_IMPORTS || mp_state == MP_PRIVATE_IMPORTS) |
15019 | { |
15020 | /* Module-purview imports must not be from source inclusion |
15021 | [cpp.import]/7 */ |
15022 | if (attrs |
15023 | && private_lookup_attribute (attr_name: "__translated" , |
15024 | attr_len: strlen (s: "__translated" ), list: attrs)) |
15025 | error_at (token->location, "post-module-declaration imports" |
15026 | " must not be include-translated" ); |
15027 | else if (!token->main_source_p) |
15028 | error_at (token->location, "post-module-declaration imports" |
15029 | " must not be from header inclusion" ); |
15030 | } |
15031 | |
15032 | import_module (mod, token->location, export_p: exporting, attr: attrs, parse_in); |
15033 | } |
15034 | } |
15035 | |
15036 | /* export-declaration. |
15037 | |
15038 | export declaration |
15039 | export { declaration-seq-opt } */ |
15040 | |
15041 | static void |
15042 | cp_parser_module_export (cp_parser *parser) |
15043 | { |
15044 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT)); |
15045 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
15046 | |
15047 | if (!module_interface_p ()) |
15048 | error_at (token->location, |
15049 | "%qE may only occur after a module interface declaration" , |
15050 | token->u.value); |
15051 | |
15052 | bool braced = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE); |
15053 | |
15054 | unsigned mk = module_kind; |
15055 | if (module_exporting_p ()) |
15056 | error_at (token->location, |
15057 | "%qE may only occur once in an export declaration" , |
15058 | token->u.value); |
15059 | module_kind |= MK_EXPORTING; |
15060 | |
15061 | if (braced) |
15062 | { |
15063 | cp_ensure_no_omp_declare_simd (parser); |
15064 | cp_ensure_no_oacc_routine (parser); |
15065 | |
15066 | cp_lexer_consume_token (lexer: parser->lexer); |
15067 | cp_parser_declaration_seq_opt (parser); |
15068 | cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); |
15069 | } |
15070 | else |
15071 | { |
15072 | /* Explicitly check if the next tokens might be a |
15073 | module-directive line, so we can give a clearer error message |
15074 | about why the directive will be rejected. */ |
15075 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__MODULE) |
15076 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__IMPORT) |
15077 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID__EXPORT)) |
15078 | error_at (token->location, "%<export%> not part of following" |
15079 | " module-directive" ); |
15080 | cp_parser_declaration (parser, NULL_TREE); |
15081 | } |
15082 | |
15083 | module_kind = mk; |
15084 | } |
15085 | |
15086 | /* Declarations [gram.dcl.dcl] */ |
15087 | |
15088 | /* Parse an optional declaration-sequence. TOP_LEVEL is true, if this |
15089 | is the top-level declaration sequence. That affects whether we |
15090 | deal with module-preamble. |
15091 | |
15092 | declaration-seq: |
15093 | declaration |
15094 | declaration-seq declaration */ |
15095 | |
15096 | static void |
15097 | cp_parser_declaration_seq_opt (cp_parser* parser) |
15098 | { |
15099 | while (true) |
15100 | { |
15101 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15102 | |
15103 | if (token->type == CPP_CLOSE_BRACE |
15104 | || token->type == CPP_EOF) |
15105 | break; |
15106 | else |
15107 | cp_parser_toplevel_declaration (parser); |
15108 | } |
15109 | } |
15110 | |
15111 | /* Parse a declaration. |
15112 | |
15113 | declaration: |
15114 | block-declaration |
15115 | function-definition |
15116 | template-declaration |
15117 | explicit-instantiation |
15118 | explicit-specialization |
15119 | linkage-specification |
15120 | namespace-definition |
15121 | |
15122 | C++17: |
15123 | deduction-guide |
15124 | |
15125 | modules: |
15126 | (all these are only allowed at the outermost level, check |
15127 | that semantically, for better diagnostics) |
15128 | module-declaration |
15129 | module-export-declaration |
15130 | module-import-declaration |
15131 | export-declaration |
15132 | |
15133 | GNU extension: |
15134 | |
15135 | declaration: |
15136 | __extension__ declaration */ |
15137 | |
15138 | static void |
15139 | cp_parser_declaration (cp_parser* parser, tree prefix_attrs) |
15140 | { |
15141 | int saved_pedantic; |
15142 | |
15143 | /* Check for the `__extension__' keyword. */ |
15144 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
15145 | { |
15146 | /* Parse the qualified declaration. */ |
15147 | cp_parser_declaration (parser, prefix_attrs); |
15148 | /* Restore the PEDANTIC flag. */ |
15149 | pedantic = saved_pedantic; |
15150 | |
15151 | return; |
15152 | } |
15153 | |
15154 | /* Try to figure out what kind of declaration is present. */ |
15155 | cp_token *token1 = cp_lexer_peek_token (lexer: parser->lexer); |
15156 | cp_token *token2 = (token1->type == CPP_EOF |
15157 | ? token1 : cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
15158 | |
15159 | if (token1->type == CPP_SEMICOLON) |
15160 | { |
15161 | cp_lexer_consume_token (lexer: parser->lexer); |
15162 | /* A declaration consisting of a single semicolon is invalid |
15163 | * before C++11. Allow it unless we're being pedantic. */ |
15164 | if (cxx_dialect < cxx11) |
15165 | pedwarn (input_location, OPT_Wpedantic, "extra %<;%>" ); |
15166 | return; |
15167 | } |
15168 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, |
15169 | n: cp_parser_skip_std_attribute_spec_seq (parser, |
15170 | 1), |
15171 | type: CPP_SEMICOLON)) |
15172 | { |
15173 | location_t attrs_loc = token1->location; |
15174 | tree std_attrs = cp_parser_std_attribute_spec_seq (parser); |
15175 | |
15176 | if (std_attrs && (flag_openmp || flag_openmp_simd)) |
15177 | { |
15178 | gcc_assert (!parser->lexer->in_omp_attribute_pragma); |
15179 | std_attrs = cp_parser_handle_statement_omp_attributes (parser, |
15180 | attrs: std_attrs); |
15181 | if (parser->lexer->in_omp_attribute_pragma) |
15182 | { |
15183 | cp_lexer *lexer = parser->lexer; |
15184 | while (parser->lexer->in_omp_attribute_pragma) |
15185 | { |
15186 | gcc_assert (cp_lexer_next_token_is (parser->lexer, |
15187 | CPP_PRAGMA)); |
15188 | cp_parser_pragma (parser, pragma_external, NULL); |
15189 | } |
15190 | cp_lexer_destroy (lexer); |
15191 | } |
15192 | } |
15193 | |
15194 | if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs)) |
15195 | warning_at (make_location (caret: attrs_loc, start: attrs_loc, lexer: parser->lexer), |
15196 | OPT_Wattributes, "attribute ignored" ); |
15197 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15198 | cp_lexer_consume_token (lexer: parser->lexer); |
15199 | return; |
15200 | } |
15201 | |
15202 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
15203 | void *p = obstack_alloc (&declarator_obstack, 0); |
15204 | |
15205 | tree attributes = NULL_TREE; |
15206 | |
15207 | /* Conditionally, allow attributes to precede a linkage specification. */ |
15208 | if (token1->keyword == RID_ATTRIBUTE) |
15209 | { |
15210 | cp_lexer_save_tokens (lexer: parser->lexer); |
15211 | attributes = cp_parser_attributes_opt (parser); |
15212 | cp_token *t1 = cp_lexer_peek_token (lexer: parser->lexer); |
15213 | cp_token *t2 = (t1->type == CPP_EOF |
15214 | ? t1 : cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
15215 | if (t1->keyword == RID_EXTERN |
15216 | && cp_parser_is_pure_string_literal (token: t2)) |
15217 | { |
15218 | cp_lexer_commit_tokens (lexer: parser->lexer); |
15219 | /* We might have already been here. */ |
15220 | if (!c_dialect_objc ()) |
15221 | { |
15222 | location_t where = get_finish (loc: t2->location); |
15223 | warning_at (token1->location, OPT_Wattributes, "attributes are" |
15224 | " not permitted in this position" ); |
15225 | where = linemap_position_for_loc_and_offset (set: line_table, |
15226 | loc: where, offset: 1); |
15227 | inform (where, "attributes may be inserted here" ); |
15228 | attributes = NULL_TREE; |
15229 | } |
15230 | token1 = t1; |
15231 | token2 = t2; |
15232 | } |
15233 | else |
15234 | { |
15235 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
15236 | attributes = NULL_TREE; |
15237 | } |
15238 | } |
15239 | /* If we already had some attributes, and we've added more, then prepend. |
15240 | Otherwise attributes just contains any that we just read. */ |
15241 | if (prefix_attrs) |
15242 | { |
15243 | if (attributes) |
15244 | TREE_CHAIN (prefix_attrs) = attributes; |
15245 | attributes = prefix_attrs; |
15246 | } |
15247 | |
15248 | /* If the next token is `extern' and the following token is a string |
15249 | literal, then we have a linkage specification. */ |
15250 | if (token1->keyword == RID_EXTERN |
15251 | && cp_parser_is_pure_string_literal (token: token2)) |
15252 | cp_parser_linkage_specification (parser, attributes); |
15253 | /* If the next token is `template', then we have either a template |
15254 | declaration, an explicit instantiation, or an explicit |
15255 | specialization. */ |
15256 | else if (token1->keyword == RID_TEMPLATE) |
15257 | { |
15258 | /* `template <>' indicates a template specialization. */ |
15259 | if (token2->type == CPP_LESS |
15260 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_GREATER) |
15261 | cp_parser_explicit_specialization (parser); |
15262 | /* `template <' indicates a template declaration. */ |
15263 | else if (token2->type == CPP_LESS) |
15264 | cp_parser_template_declaration (parser, /*member_p=*/false); |
15265 | /* Anything else must be an explicit instantiation. */ |
15266 | else |
15267 | cp_parser_explicit_instantiation (parser); |
15268 | } |
15269 | /* If the next token is `export', it's new-style modules or |
15270 | old-style template. */ |
15271 | else if (token1->keyword == RID_EXPORT) |
15272 | { |
15273 | if (!modules_p ()) |
15274 | cp_parser_template_declaration (parser, /*member_p=*/false); |
15275 | else |
15276 | cp_parser_module_export (parser); |
15277 | } |
15278 | else if (cp_token_is_module_directive (token: token1)) |
15279 | { |
15280 | bool exporting = token1->keyword == RID__EXPORT; |
15281 | cp_token *next = exporting ? token2 : token1; |
15282 | if (exporting) |
15283 | cp_lexer_consume_token (lexer: parser->lexer); |
15284 | // In module purview this will be ill-formed. |
15285 | auto state = (!named_module_p () ? MP_NOT_MODULE |
15286 | : module_purview_p () ? MP_PURVIEW |
15287 | : MP_GLOBAL); |
15288 | if (next->keyword == RID__MODULE) |
15289 | cp_parser_module_declaration (parser, mp_state: state, exporting); |
15290 | else |
15291 | cp_parser_import_declaration (parser, mp_state: state, exporting); |
15292 | } |
15293 | /* If the next token is `extern', 'static' or 'inline' and the one |
15294 | after that is `template', we have a GNU extended explicit |
15295 | instantiation directive. */ |
15296 | else if (cp_parser_allow_gnu_extensions_p (parser) |
15297 | && token2->keyword == RID_TEMPLATE |
15298 | && (token1->keyword == RID_EXTERN |
15299 | || token1->keyword == RID_STATIC |
15300 | || token1->keyword == RID_INLINE)) |
15301 | cp_parser_explicit_instantiation (parser); |
15302 | /* If the next token is `namespace', check for a named or unnamed |
15303 | namespace definition. */ |
15304 | else if (token1->keyword == RID_NAMESPACE |
15305 | && (/* A named namespace definition. */ |
15306 | (token2->type == CPP_NAME |
15307 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
15308 | != CPP_EQ)) |
15309 | || (token2->type == CPP_OPEN_SQUARE |
15310 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
15311 | == CPP_OPEN_SQUARE) |
15312 | /* An unnamed namespace definition. */ |
15313 | || token2->type == CPP_OPEN_BRACE |
15314 | || token2->keyword == RID_ATTRIBUTE)) |
15315 | cp_parser_namespace_definition (parser); |
15316 | /* An inline (associated) namespace definition. */ |
15317 | else if (token2->keyword == RID_NAMESPACE |
15318 | && token1->keyword == RID_INLINE) |
15319 | cp_parser_namespace_definition (parser); |
15320 | /* Objective-C++ declaration/definition. */ |
15321 | else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1->keyword)) |
15322 | cp_parser_objc_declaration (parser, attributes); |
15323 | else if (c_dialect_objc () |
15324 | && token1->keyword == RID_ATTRIBUTE |
15325 | && cp_parser_objc_valid_prefix_attributes (parser, &attributes)) |
15326 | cp_parser_objc_declaration (parser, attributes); |
15327 | /* At this point we may have a template declared by a concept |
15328 | introduction. */ |
15329 | else if (flag_concepts |
15330 | && cp_parser_template_declaration_after_export (parser, |
15331 | /*member_p=*/false)) |
15332 | /* We did. */; |
15333 | else |
15334 | /* Try to parse a block-declaration, or a function-definition. */ |
15335 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
15336 | |
15337 | /* Free any declarators allocated. */ |
15338 | obstack_free (&declarator_obstack, p); |
15339 | } |
15340 | |
15341 | /* Parse a namespace-scope declaration. */ |
15342 | |
15343 | static void |
15344 | cp_parser_toplevel_declaration (cp_parser* parser) |
15345 | { |
15346 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15347 | |
15348 | if (token->type == CPP_PRAGMA) |
15349 | /* A top-level declaration can consist solely of a #pragma. A |
15350 | nested declaration cannot, so this is done here and not in |
15351 | cp_parser_declaration. (A #pragma at block scope is |
15352 | handled in cp_parser_statement.) */ |
15353 | cp_parser_pragma (parser, pragma_external, NULL); |
15354 | else |
15355 | /* Parse the declaration itself. */ |
15356 | cp_parser_declaration (parser, NULL_TREE); |
15357 | } |
15358 | |
15359 | /* Parse a block-declaration. |
15360 | |
15361 | block-declaration: |
15362 | simple-declaration |
15363 | asm-definition |
15364 | namespace-alias-definition |
15365 | using-declaration |
15366 | using-directive |
15367 | |
15368 | GNU Extension: |
15369 | |
15370 | block-declaration: |
15371 | __extension__ block-declaration |
15372 | |
15373 | C++0x Extension: |
15374 | |
15375 | block-declaration: |
15376 | static_assert-declaration |
15377 | |
15378 | If STATEMENT_P is TRUE, then this block-declaration is occurring as |
15379 | part of a declaration-statement. */ |
15380 | |
15381 | static void |
15382 | cp_parser_block_declaration (cp_parser *parser, |
15383 | bool statement_p) |
15384 | { |
15385 | int saved_pedantic; |
15386 | |
15387 | /* Check for the `__extension__' keyword. */ |
15388 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
15389 | { |
15390 | /* Parse the qualified declaration. */ |
15391 | cp_parser_block_declaration (parser, statement_p); |
15392 | /* Restore the PEDANTIC flag. */ |
15393 | pedantic = saved_pedantic; |
15394 | |
15395 | return; |
15396 | } |
15397 | |
15398 | /* Peek at the next token to figure out which kind of declaration is |
15399 | present. */ |
15400 | cp_token *token1 = cp_lexer_peek_token (lexer: parser->lexer); |
15401 | size_t attr_idx; |
15402 | |
15403 | /* If the next keyword is `asm', we have an asm-definition. */ |
15404 | if (token1->keyword == RID_ASM) |
15405 | { |
15406 | if (statement_p) |
15407 | cp_parser_commit_to_tentative_parse (parser); |
15408 | cp_parser_asm_definition (parser); |
15409 | } |
15410 | /* If the next keyword is `namespace', we have a |
15411 | namespace-alias-definition. */ |
15412 | else if (token1->keyword == RID_NAMESPACE) |
15413 | cp_parser_namespace_alias_definition (parser); |
15414 | /* If the next keyword is `using', we have a |
15415 | using-declaration, a using-directive, or an alias-declaration. */ |
15416 | else if (token1->keyword == RID_USING) |
15417 | { |
15418 | cp_token *token2; |
15419 | |
15420 | if (statement_p) |
15421 | cp_parser_commit_to_tentative_parse (parser); |
15422 | /* If the token after `using' is `namespace', then we have a |
15423 | using-directive. */ |
15424 | token2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
15425 | if (token2->keyword == RID_NAMESPACE) |
15426 | cp_parser_using_directive (parser); |
15427 | else if (token2->keyword == RID_ENUM) |
15428 | cp_parser_using_enum (parser); |
15429 | /* If the second token after 'using' is '=', then we have an |
15430 | alias-declaration. */ |
15431 | else if (cxx_dialect >= cxx11 |
15432 | && token2->type == CPP_NAME |
15433 | && ((cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_EQ) |
15434 | || (cp_nth_tokens_can_be_attribute_p (parser, 3)))) |
15435 | cp_parser_alias_declaration (parser); |
15436 | /* Otherwise, it's a using-declaration. */ |
15437 | else |
15438 | cp_parser_using_declaration (parser, |
15439 | /*access_declaration_p=*/false); |
15440 | } |
15441 | /* If the next keyword is `__label__' we have a misplaced label |
15442 | declaration. */ |
15443 | else if (token1->keyword == RID_LABEL) |
15444 | { |
15445 | cp_lexer_consume_token (lexer: parser->lexer); |
15446 | error_at (token1->location, "%<__label__%> not at the beginning of a block" ); |
15447 | cp_parser_skip_to_end_of_statement (parser); |
15448 | /* If the next token is now a `;', consume it. */ |
15449 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15450 | cp_lexer_consume_token (lexer: parser->lexer); |
15451 | } |
15452 | /* If the next token is `static_assert' we have a static assertion. */ |
15453 | else if (token1->keyword == RID_STATIC_ASSERT) |
15454 | cp_parser_static_assert (parser, /*member_p=*/false); |
15455 | /* If the next tokens after attributes is `using namespace', then we have |
15456 | a using-directive. */ |
15457 | else if ((attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1)) != 1 |
15458 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: attr_idx, |
15459 | keyword: RID_USING) |
15460 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: attr_idx + 1, |
15461 | keyword: RID_NAMESPACE)) |
15462 | { |
15463 | if (statement_p) |
15464 | cp_parser_commit_to_tentative_parse (parser); |
15465 | cp_parser_using_directive (parser); |
15466 | } |
15467 | /* Anything else must be a simple-declaration. */ |
15468 | else |
15469 | cp_parser_simple_declaration (parser, !statement_p, |
15470 | /*maybe_range_for_decl*/NULL); |
15471 | } |
15472 | |
15473 | /* Parse a simple-declaration. |
15474 | |
15475 | simple-declaration: |
15476 | decl-specifier-seq [opt] init-declarator-list [opt] ; |
15477 | decl-specifier-seq ref-qualifier [opt] [ identifier-list ] |
15478 | brace-or-equal-initializer ; |
15479 | |
15480 | init-declarator-list: |
15481 | init-declarator |
15482 | init-declarator-list , init-declarator |
15483 | |
15484 | If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a |
15485 | function-definition as a simple-declaration. |
15486 | |
15487 | If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the |
15488 | parsed declaration if it is an uninitialized single declarator not followed |
15489 | by a `;', or to error_mark_node otherwise. Either way, the trailing `;', |
15490 | if present, will not be consumed. */ |
15491 | |
15492 | static void |
15493 | cp_parser_simple_declaration (cp_parser* parser, |
15494 | bool function_definition_allowed_p, |
15495 | tree *maybe_range_for_decl) |
15496 | { |
15497 | cp_decl_specifier_seq decl_specifiers; |
15498 | int declares_class_or_enum; |
15499 | bool saw_declarator; |
15500 | location_t comma_loc = UNKNOWN_LOCATION; |
15501 | location_t init_loc = UNKNOWN_LOCATION; |
15502 | |
15503 | if (maybe_range_for_decl) |
15504 | *maybe_range_for_decl = NULL_TREE; |
15505 | |
15506 | /* Defer access checks until we know what is being declared; the |
15507 | checks for names appearing in the decl-specifier-seq should be |
15508 | done as if we were in the scope of the thing being declared. */ |
15509 | push_deferring_access_checks (dk_deferred); |
15510 | |
15511 | /* Parse the decl-specifier-seq. We have to keep track of whether |
15512 | or not the decl-specifier-seq declares a named class or |
15513 | enumeration type, since that is the only case in which the |
15514 | init-declarator-list is allowed to be empty. |
15515 | |
15516 | [dcl.dcl] |
15517 | |
15518 | In a simple-declaration, the optional init-declarator-list can be |
15519 | omitted only when declaring a class or enumeration, that is when |
15520 | the decl-specifier-seq contains either a class-specifier, an |
15521 | elaborated-type-specifier, or an enum-specifier. */ |
15522 | cp_parser_decl_specifier_seq (parser, |
15523 | CP_PARSER_FLAGS_OPTIONAL, |
15524 | &decl_specifiers, |
15525 | &declares_class_or_enum); |
15526 | /* We no longer need to defer access checks. */ |
15527 | stop_deferring_access_checks (); |
15528 | |
15529 | cp_omp_declare_simd_data odsd; |
15530 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
15531 | cp_parser_handle_directive_omp_attributes (parser, |
15532 | pattrs: &decl_specifiers.attributes, |
15533 | data: &odsd, start: true); |
15534 | |
15535 | /* In a block scope, a valid declaration must always have a |
15536 | decl-specifier-seq. By not trying to parse declarators, we can |
15537 | resolve the declaration/expression ambiguity more quickly. */ |
15538 | if (!function_definition_allowed_p |
15539 | && !decl_specifiers.any_specifiers_p) |
15540 | { |
15541 | cp_parser_error (parser, gmsgid: "expected declaration" ); |
15542 | goto done; |
15543 | } |
15544 | |
15545 | /* If the next two tokens are both identifiers, the code is |
15546 | erroneous. The usual cause of this situation is code like: |
15547 | |
15548 | T t; |
15549 | |
15550 | where "T" should name a type -- but does not. */ |
15551 | if (!decl_specifiers.any_type_specifiers_p |
15552 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
15553 | { |
15554 | /* If parsing tentatively, we should commit; we really are |
15555 | looking at a declaration. */ |
15556 | cp_parser_commit_to_tentative_parse (parser); |
15557 | /* Give up. */ |
15558 | goto done; |
15559 | } |
15560 | |
15561 | cp_parser_maybe_commit_to_declaration (parser, decl_specs: &decl_specifiers); |
15562 | |
15563 | /* Look for C++17 decomposition declaration. */ |
15564 | for (size_t n = 1; ; n++) |
15565 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_AND) |
15566 | || cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_AND_AND)) |
15567 | continue; |
15568 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_OPEN_SQUARE) |
15569 | && !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_SQUARE) |
15570 | && decl_specifiers.any_specifiers_p) |
15571 | { |
15572 | tree decl |
15573 | = cp_parser_decomposition_declaration (parser, &decl_specifiers, |
15574 | maybe_range_for_decl, |
15575 | &init_loc); |
15576 | |
15577 | /* The next token should be either a `,' or a `;'. */ |
15578 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15579 | /* If it's a `;', we are done. */ |
15580 | if (token->type == CPP_SEMICOLON) |
15581 | goto finish; |
15582 | else if (maybe_range_for_decl) |
15583 | { |
15584 | if (*maybe_range_for_decl == NULL_TREE) |
15585 | *maybe_range_for_decl = error_mark_node; |
15586 | goto finish; |
15587 | } |
15588 | /* Anything else is an error. */ |
15589 | else |
15590 | { |
15591 | /* If we have already issued an error message we don't need |
15592 | to issue another one. */ |
15593 | if ((decl != error_mark_node |
15594 | && DECL_INITIAL (decl) != error_mark_node) |
15595 | || cp_parser_uncommitted_to_tentative_parse_p (parser)) |
15596 | cp_parser_error (parser, gmsgid: "expected %<;%>" ); |
15597 | /* Skip tokens until we reach the end of the statement. */ |
15598 | cp_parser_skip_to_end_of_statement (parser); |
15599 | /* If the next token is now a `;', consume it. */ |
15600 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15601 | cp_lexer_consume_token (lexer: parser->lexer); |
15602 | goto done; |
15603 | } |
15604 | } |
15605 | else |
15606 | break; |
15607 | |
15608 | tree last_type; |
15609 | bool auto_specifier_p; |
15610 | /* NULL_TREE if both variable and function declaration are allowed, |
15611 | error_mark_node if function declaration are not allowed and |
15612 | a FUNCTION_DECL that should be diagnosed if it is followed by |
15613 | variable declarations. */ |
15614 | tree auto_function_declaration; |
15615 | |
15616 | last_type = NULL_TREE; |
15617 | auto_specifier_p |
15618 | = decl_specifiers.type && type_uses_auto (decl_specifiers.type); |
15619 | auto_function_declaration = NULL_TREE; |
15620 | |
15621 | /* Keep going until we hit the `;' at the end of the simple |
15622 | declaration. */ |
15623 | saw_declarator = false; |
15624 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, |
15625 | type: CPP_SEMICOLON)) |
15626 | { |
15627 | cp_token *token; |
15628 | bool function_definition_p; |
15629 | tree decl; |
15630 | tree auto_result = NULL_TREE; |
15631 | |
15632 | if (saw_declarator) |
15633 | { |
15634 | /* If we are processing next declarator, comma is expected */ |
15635 | token = cp_lexer_peek_token (lexer: parser->lexer); |
15636 | gcc_assert (token->type == CPP_COMMA); |
15637 | cp_lexer_consume_token (lexer: parser->lexer); |
15638 | if (maybe_range_for_decl) |
15639 | { |
15640 | *maybe_range_for_decl = error_mark_node; |
15641 | if (comma_loc == UNKNOWN_LOCATION) |
15642 | comma_loc = token->location; |
15643 | } |
15644 | } |
15645 | else |
15646 | saw_declarator = true; |
15647 | |
15648 | /* Parse the init-declarator. */ |
15649 | decl = cp_parser_init_declarator (parser, |
15650 | CP_PARSER_FLAGS_NONE, |
15651 | &decl_specifiers, |
15652 | /*checks=*/NULL, |
15653 | function_definition_allowed_p, |
15654 | /*member_p=*/false, |
15655 | declares_class_or_enum, |
15656 | &function_definition_p, |
15657 | maybe_range_for_decl, |
15658 | &init_loc, |
15659 | &auto_result); |
15660 | const bool fndecl_p = TREE_CODE (decl) == FUNCTION_DECL; |
15661 | /* If an error occurred while parsing tentatively, exit quickly. |
15662 | (That usually happens when in the body of a function; each |
15663 | statement is treated as a declaration-statement until proven |
15664 | otherwise.) */ |
15665 | if (cp_parser_error_occurred (parser)) |
15666 | goto done; |
15667 | |
15668 | if (auto_specifier_p && cxx_dialect >= cxx14) |
15669 | { |
15670 | /* If the init-declarator-list contains more than one |
15671 | init-declarator, they shall all form declarations of |
15672 | variables. */ |
15673 | if (auto_function_declaration == NULL_TREE) |
15674 | auto_function_declaration = fndecl_p ? decl : error_mark_node; |
15675 | else if (fndecl_p || auto_function_declaration != error_mark_node) |
15676 | { |
15677 | error_at (decl_specifiers.locations[ds_type_spec], |
15678 | "non-variable %qD in declaration with more than one " |
15679 | "declarator with placeholder type" , |
15680 | fndecl_p ? decl : auto_function_declaration); |
15681 | auto_function_declaration = error_mark_node; |
15682 | } |
15683 | } |
15684 | |
15685 | if (auto_result |
15686 | && (!processing_template_decl || !type_uses_auto (auto_result))) |
15687 | { |
15688 | if (last_type |
15689 | && last_type != error_mark_node |
15690 | && !same_type_p (auto_result, last_type)) |
15691 | { |
15692 | /* If the list of declarators contains more than one declarator, |
15693 | the type of each declared variable is determined as described |
15694 | above. If the type deduced for the template parameter U is not |
15695 | the same in each deduction, the program is ill-formed. */ |
15696 | error_at (decl_specifiers.locations[ds_type_spec], |
15697 | "inconsistent deduction for %qT: %qT and then %qT" , |
15698 | decl_specifiers.type, last_type, auto_result); |
15699 | last_type = error_mark_node; |
15700 | } |
15701 | else |
15702 | last_type = auto_result; |
15703 | } |
15704 | |
15705 | /* Handle function definitions specially. */ |
15706 | if (function_definition_p) |
15707 | { |
15708 | /* If the next token is a `,', then we are probably |
15709 | processing something like: |
15710 | |
15711 | void f() {}, *p; |
15712 | |
15713 | which is erroneous. */ |
15714 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
15715 | { |
15716 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
15717 | error_at (token->location, |
15718 | "mixing" |
15719 | " declarations and function-definitions is forbidden" ); |
15720 | } |
15721 | /* Otherwise, we're done with the list of declarators. */ |
15722 | else |
15723 | { |
15724 | pop_deferring_access_checks (); |
15725 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
15726 | return; |
15727 | } |
15728 | } |
15729 | if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE) |
15730 | *maybe_range_for_decl = decl; |
15731 | /* The next token should be either a `,' or a `;'. */ |
15732 | token = cp_lexer_peek_token (lexer: parser->lexer); |
15733 | /* If it's a `,', there are more declarators to come. */ |
15734 | if (token->type == CPP_COMMA) |
15735 | /* will be consumed next time around */; |
15736 | /* If it's a `;', we are done. */ |
15737 | else if (token->type == CPP_SEMICOLON) |
15738 | break; |
15739 | else if (maybe_range_for_decl) |
15740 | { |
15741 | if ((declares_class_or_enum & 2) && token->type == CPP_COLON) |
15742 | permerror (decl_specifiers.locations[ds_type_spec], |
15743 | "types may not be defined in a for-range-declaration" ); |
15744 | break; |
15745 | } |
15746 | /* Anything else is an error. */ |
15747 | else |
15748 | { |
15749 | /* If we have already issued an error message we don't need |
15750 | to issue another one. */ |
15751 | if ((decl != error_mark_node |
15752 | /* grokfndecl sets DECL_INITIAL to error_mark_node for |
15753 | functions. */ |
15754 | && (fndecl_p || DECL_INITIAL (decl) != error_mark_node)) |
15755 | || cp_parser_uncommitted_to_tentative_parse_p (parser)) |
15756 | cp_parser_error (parser, gmsgid: "expected %<,%> or %<;%>" ); |
15757 | /* Skip tokens until we reach the end of the statement. */ |
15758 | cp_parser_skip_to_end_of_statement (parser); |
15759 | /* If the next token is now a `;', consume it. */ |
15760 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
15761 | cp_lexer_consume_token (lexer: parser->lexer); |
15762 | goto done; |
15763 | } |
15764 | /* After the first time around, a function-definition is not |
15765 | allowed -- even if it was OK at first. For example: |
15766 | |
15767 | int i, f() {} |
15768 | |
15769 | is not valid. */ |
15770 | function_definition_allowed_p = false; |
15771 | } |
15772 | |
15773 | /* Issue an error message if no declarators are present, and the |
15774 | decl-specifier-seq does not itself declare a class or |
15775 | enumeration: [dcl.dcl]/3. */ |
15776 | if (!saw_declarator) |
15777 | { |
15778 | if (cp_parser_declares_only_class_p (parser)) |
15779 | { |
15780 | if (!declares_class_or_enum |
15781 | && decl_specifiers.type |
15782 | && OVERLOAD_TYPE_P (decl_specifiers.type)) |
15783 | /* Ensure an error is issued anyway when finish_decltype_type, |
15784 | called via cp_parser_decl_specifier_seq, returns a class or |
15785 | an enumeration (c++/51786). */ |
15786 | decl_specifiers.type = NULL_TREE; |
15787 | shadow_tag (&decl_specifiers); |
15788 | } |
15789 | /* Perform any deferred access checks. */ |
15790 | perform_deferred_access_checks (tf_warning_or_error); |
15791 | } |
15792 | |
15793 | /* Consume the `;'. */ |
15794 | finish: |
15795 | if (!maybe_range_for_decl) |
15796 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
15797 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
15798 | { |
15799 | if (init_loc != UNKNOWN_LOCATION) |
15800 | error_at (init_loc, "initializer in range-based %<for%> loop" ); |
15801 | if (comma_loc != UNKNOWN_LOCATION) |
15802 | error_at (comma_loc, |
15803 | "multiple declarations in range-based %<for%> loop" ); |
15804 | } |
15805 | |
15806 | done: |
15807 | pop_deferring_access_checks (); |
15808 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
15809 | } |
15810 | |
15811 | /* Helper of cp_parser_simple_declaration, parse a decomposition declaration. |
15812 | decl-specifier-seq ref-qualifier [opt] [ identifier-list ] |
15813 | initializer ; */ |
15814 | |
15815 | static tree |
15816 | cp_parser_decomposition_declaration (cp_parser *parser, |
15817 | cp_decl_specifier_seq *decl_specifiers, |
15818 | tree *maybe_range_for_decl, |
15819 | location_t *init_loc) |
15820 | { |
15821 | cp_ref_qualifier ref_qual = cp_parser_ref_qualifier_opt (parser); |
15822 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
15823 | cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); |
15824 | |
15825 | /* Parse the identifier-list. */ |
15826 | auto_vec<cp_expr, 10> v; |
15827 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
15828 | while (true) |
15829 | { |
15830 | cp_expr e = cp_parser_identifier (parser); |
15831 | if (e.get_value () == error_mark_node) |
15832 | break; |
15833 | v.safe_push (obj: e); |
15834 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
15835 | break; |
15836 | cp_lexer_consume_token (lexer: parser->lexer); |
15837 | } |
15838 | |
15839 | location_t end_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
15840 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
15841 | { |
15842 | end_loc = UNKNOWN_LOCATION; |
15843 | cp_parser_skip_to_closing_parenthesis_1 (parser, recovering: true, or_ttype: CPP_CLOSE_SQUARE, |
15844 | consume_paren: false); |
15845 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
15846 | cp_lexer_consume_token (lexer: parser->lexer); |
15847 | else |
15848 | { |
15849 | cp_parser_skip_to_end_of_statement (parser); |
15850 | return error_mark_node; |
15851 | } |
15852 | } |
15853 | |
15854 | if (cxx_dialect < cxx17) |
15855 | pedwarn (loc, OPT_Wc__17_extensions, |
15856 | "structured bindings only available with " |
15857 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
15858 | |
15859 | tree pushed_scope; |
15860 | cp_declarator *declarator = make_declarator (kind: cdk_decomp); |
15861 | loc = end_loc == UNKNOWN_LOCATION ? loc : make_location (caret: loc, start: loc, finish: end_loc); |
15862 | declarator->id_loc = loc; |
15863 | if (ref_qual != REF_QUAL_NONE) |
15864 | declarator = make_reference_declarator (cv_qualifiers: TYPE_UNQUALIFIED, target: declarator, |
15865 | rvalue_ref: ref_qual == REF_QUAL_RVALUE, |
15866 | NULL_TREE); |
15867 | tree decl = start_decl (declarator, decl_specifiers, SD_INITIALIZED, |
15868 | NULL_TREE, decl_specifiers->attributes, |
15869 | &pushed_scope); |
15870 | tree orig_decl = decl; |
15871 | |
15872 | unsigned int i; |
15873 | cp_expr e; |
15874 | cp_decl_specifier_seq decl_specs; |
15875 | clear_decl_specs (decl_specs: &decl_specs); |
15876 | decl_specs.type = make_auto (); |
15877 | tree prev = decl; |
15878 | FOR_EACH_VEC_ELT (v, i, e) |
15879 | { |
15880 | if (i == 0) |
15881 | declarator = make_id_declarator (NULL_TREE, unqualified_name: e.get_value (), |
15882 | sfk: sfk_none, id_location: e.get_location ()); |
15883 | else |
15884 | { |
15885 | declarator->u.id.unqualified_name = e.get_value (); |
15886 | declarator->id_loc = e.get_location (); |
15887 | } |
15888 | tree elt_pushed_scope; |
15889 | tree decl2 = start_decl (declarator, &decl_specs, SD_DECOMPOSITION, |
15890 | NULL_TREE, NULL_TREE, &elt_pushed_scope); |
15891 | if (decl2 == error_mark_node) |
15892 | decl = error_mark_node; |
15893 | else if (decl != error_mark_node && DECL_CHAIN (decl2) != prev) |
15894 | { |
15895 | /* Ensure we've diagnosed redeclaration if we aren't creating |
15896 | a new VAR_DECL. */ |
15897 | gcc_assert (errorcount); |
15898 | decl = error_mark_node; |
15899 | } |
15900 | else |
15901 | prev = decl2; |
15902 | if (elt_pushed_scope) |
15903 | pop_scope (elt_pushed_scope); |
15904 | } |
15905 | |
15906 | if (v.is_empty ()) |
15907 | { |
15908 | error_at (loc, "empty structured binding declaration" ); |
15909 | decl = error_mark_node; |
15910 | } |
15911 | |
15912 | if (maybe_range_for_decl == NULL |
15913 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
15914 | { |
15915 | bool non_constant_p = false, is_direct_init = false; |
15916 | *init_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
15917 | tree initializer = cp_parser_initializer (parser, &is_direct_init, |
15918 | &non_constant_p); |
15919 | if (initializer == NULL_TREE |
15920 | || (TREE_CODE (initializer) == TREE_LIST |
15921 | && TREE_CHAIN (initializer)) |
15922 | || (is_direct_init |
15923 | && BRACE_ENCLOSED_INITIALIZER_P (initializer) |
15924 | && CONSTRUCTOR_NELTS (initializer) != 1)) |
15925 | { |
15926 | error_at (loc, "invalid initializer for structured binding " |
15927 | "declaration" ); |
15928 | initializer = error_mark_node; |
15929 | } |
15930 | |
15931 | if (decl != error_mark_node) |
15932 | { |
15933 | cp_decomp decomp = { .decl: prev, .count: v.length () }; |
15934 | cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE, |
15935 | (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT), |
15936 | &decomp); |
15937 | cp_finish_decomp (decl, &decomp); |
15938 | } |
15939 | } |
15940 | else if (decl != error_mark_node) |
15941 | { |
15942 | *maybe_range_for_decl = prev; |
15943 | cp_decomp decomp = { .decl: prev, .count: v.length () }; |
15944 | /* Ensure DECL_VALUE_EXPR is created for all the decls but |
15945 | the underlying DECL. */ |
15946 | cp_finish_decomp (decl, &decomp); |
15947 | } |
15948 | |
15949 | if (pushed_scope) |
15950 | pop_scope (pushed_scope); |
15951 | |
15952 | if (decl == error_mark_node && DECL_P (orig_decl)) |
15953 | { |
15954 | if (DECL_NAMESPACE_SCOPE_P (orig_decl)) |
15955 | SET_DECL_ASSEMBLER_NAME (orig_decl, get_identifier ("<decomp>" )); |
15956 | } |
15957 | |
15958 | return decl; |
15959 | } |
15960 | |
15961 | /* Names of storage classes. */ |
15962 | |
15963 | static const char *const |
15964 | cp_storage_class_name[] = { |
15965 | "" , "auto" , "register" , "static" , "extern" , "mutable" |
15966 | }; |
15967 | |
15968 | /* Parse a decl-specifier-seq. |
15969 | |
15970 | decl-specifier-seq: |
15971 | decl-specifier-seq [opt] decl-specifier |
15972 | decl-specifier attribute-specifier-seq [opt] (C++11) |
15973 | |
15974 | decl-specifier: |
15975 | storage-class-specifier |
15976 | type-specifier |
15977 | function-specifier |
15978 | friend |
15979 | typedef |
15980 | |
15981 | GNU Extension: |
15982 | |
15983 | decl-specifier: |
15984 | attributes |
15985 | |
15986 | Concepts Extension: |
15987 | |
15988 | decl-specifier: |
15989 | concept |
15990 | |
15991 | Set *DECL_SPECS to a representation of the decl-specifier-seq. |
15992 | |
15993 | The parser flags FLAGS is used to control type-specifier parsing. |
15994 | |
15995 | *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following |
15996 | flags: |
15997 | |
15998 | 1: one of the decl-specifiers is an elaborated-type-specifier |
15999 | (i.e., a type declaration) |
16000 | 2: one of the decl-specifiers is an enum-specifier or a |
16001 | class-specifier (i.e., a type definition) |
16002 | |
16003 | */ |
16004 | |
16005 | static void |
16006 | cp_parser_decl_specifier_seq (cp_parser* parser, |
16007 | cp_parser_flags flags, |
16008 | cp_decl_specifier_seq *decl_specs, |
16009 | int* declares_class_or_enum) |
16010 | { |
16011 | bool constructor_possible_p = !parser->in_declarator_p; |
16012 | bool found_decl_spec = false; |
16013 | cp_token *start_token = NULL; |
16014 | cp_decl_spec ds; |
16015 | |
16016 | /* Clear DECL_SPECS. */ |
16017 | clear_decl_specs (decl_specs); |
16018 | |
16019 | /* Assume no class or enumeration type is declared. */ |
16020 | *declares_class_or_enum = 0; |
16021 | |
16022 | /* Keep reading specifiers until there are no more to read. */ |
16023 | while (true) |
16024 | { |
16025 | bool constructor_p; |
16026 | cp_token *token; |
16027 | ds = ds_last; |
16028 | |
16029 | /* Peek at the next token. */ |
16030 | token = cp_lexer_peek_token (lexer: parser->lexer); |
16031 | |
16032 | /* Save the first token of the decl spec list for error |
16033 | reporting. */ |
16034 | if (!start_token) |
16035 | start_token = token; |
16036 | /* Handle attributes. */ |
16037 | if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) == 0 |
16038 | && cp_next_tokens_can_be_attribute_p (parser)) |
16039 | { |
16040 | /* Parse the attributes. */ |
16041 | tree attrs = cp_parser_attributes_opt (parser); |
16042 | |
16043 | /* In a sequence of declaration specifiers, c++11 attributes |
16044 | appertain to the type that precede them. In that case |
16045 | [dcl.spec]/1 says: |
16046 | |
16047 | The attribute-specifier-seq affects the type only for |
16048 | the declaration it appears in, not other declarations |
16049 | involving the same type. |
16050 | |
16051 | But for now let's force the user to position the |
16052 | attribute either at the beginning of the declaration or |
16053 | after the declarator-id, which would clearly mean that it |
16054 | applies to the declarator. */ |
16055 | if (cxx11_attribute_p (attrs)) |
16056 | { |
16057 | if (!found_decl_spec) |
16058 | /* The c++11 attribute is at the beginning of the |
16059 | declaration. It appertains to the entity being |
16060 | declared. */; |
16061 | else |
16062 | { |
16063 | if (find_contract (attrs)) |
16064 | { |
16065 | diagnose_misapplied_contracts (attrs); |
16066 | attrs = NULL_TREE; |
16067 | } |
16068 | else if (decl_specs->type && CLASS_TYPE_P (decl_specs->type)) |
16069 | { |
16070 | /* This is an attribute following a |
16071 | class-specifier. */ |
16072 | if (decl_specs->type_definition_p) |
16073 | warn_misplaced_attr_for_class_type (location: token->location, |
16074 | class_type: decl_specs->type); |
16075 | attrs = NULL_TREE; |
16076 | } |
16077 | else |
16078 | { |
16079 | decl_specs->std_attributes |
16080 | = attr_chainon (attrs: decl_specs->std_attributes, attr: attrs); |
16081 | if (decl_specs->locations[ds_std_attribute] == 0) |
16082 | decl_specs->locations[ds_std_attribute] = token->location; |
16083 | } |
16084 | continue; |
16085 | } |
16086 | } |
16087 | |
16088 | decl_specs->attributes |
16089 | = attr_chainon (attrs: decl_specs->attributes, attr: attrs); |
16090 | if (decl_specs->locations[ds_attribute] == 0) |
16091 | decl_specs->locations[ds_attribute] = token->location; |
16092 | continue; |
16093 | } |
16094 | /* Assume we will find a decl-specifier keyword. */ |
16095 | found_decl_spec = true; |
16096 | /* If the next token is an appropriate keyword, we can simply |
16097 | add it to the list. */ |
16098 | switch (token->keyword) |
16099 | { |
16100 | /* decl-specifier: |
16101 | friend |
16102 | constexpr |
16103 | constinit */ |
16104 | case RID_FRIEND: |
16105 | if (!at_class_scope_p ()) |
16106 | { |
16107 | gcc_rich_location richloc (token->location); |
16108 | richloc.add_fixit_remove (); |
16109 | error_at (&richloc, "%<friend%> used outside of class" ); |
16110 | cp_lexer_purge_token (lexer: parser->lexer); |
16111 | } |
16112 | else |
16113 | { |
16114 | ds = ds_friend; |
16115 | /* Consume the token. */ |
16116 | cp_lexer_consume_token (lexer: parser->lexer); |
16117 | } |
16118 | break; |
16119 | |
16120 | case RID_CONSTEXPR: |
16121 | ds = ds_constexpr; |
16122 | cp_lexer_consume_token (lexer: parser->lexer); |
16123 | break; |
16124 | |
16125 | case RID_CONSTINIT: |
16126 | ds = ds_constinit; |
16127 | cp_lexer_consume_token (lexer: parser->lexer); |
16128 | break; |
16129 | |
16130 | case RID_CONSTEVAL: |
16131 | ds = ds_consteval; |
16132 | cp_lexer_consume_token (lexer: parser->lexer); |
16133 | break; |
16134 | |
16135 | case RID_CONCEPT: |
16136 | ds = ds_concept; |
16137 | cp_lexer_consume_token (lexer: parser->lexer); |
16138 | |
16139 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16140 | break; |
16141 | |
16142 | /* Warn for concept as a decl-specifier. We'll rewrite these as |
16143 | concept declarations later. */ |
16144 | if (!flag_concepts_ts) |
16145 | { |
16146 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
16147 | if (next->keyword == RID_BOOL) |
16148 | permerror (next->location, "the %<bool%> keyword is not " |
16149 | "allowed in a C++20 concept definition" ); |
16150 | else |
16151 | error_at (token->location, "C++20 concept definition syntax " |
16152 | "is %<concept <name> = <expr>%>" ); |
16153 | } |
16154 | |
16155 | /* In C++20 a concept definition is just 'concept name = expr;' |
16156 | Support that syntax as a TS extension by pretending we've seen |
16157 | the 'bool' specifier. */ |
16158 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
16159 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_EQ) |
16160 | && !decl_specs->any_type_specifiers_p) |
16161 | { |
16162 | cp_parser_set_decl_spec_type (decl_specs, boolean_type_node, |
16163 | token, /*type_definition*/false); |
16164 | decl_specs->any_type_specifiers_p = true; |
16165 | } |
16166 | break; |
16167 | |
16168 | /* function-specifier: |
16169 | inline |
16170 | virtual |
16171 | explicit */ |
16172 | case RID_INLINE: |
16173 | case RID_VIRTUAL: |
16174 | case RID_EXPLICIT: |
16175 | cp_parser_function_specifier_opt (parser, decl_specs); |
16176 | break; |
16177 | |
16178 | /* decl-specifier: |
16179 | typedef */ |
16180 | case RID_TYPEDEF: |
16181 | ds = ds_typedef; |
16182 | /* Consume the token. */ |
16183 | cp_lexer_consume_token (lexer: parser->lexer); |
16184 | |
16185 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16186 | break; |
16187 | |
16188 | /* A constructor declarator cannot appear in a typedef. */ |
16189 | constructor_possible_p = false; |
16190 | /* The "typedef" keyword can only occur in a declaration; we |
16191 | may as well commit at this point. */ |
16192 | cp_parser_commit_to_tentative_parse (parser); |
16193 | |
16194 | if (decl_specs->storage_class != sc_none) |
16195 | { |
16196 | if (decl_specs->conflicting_specifiers_p) |
16197 | break; |
16198 | gcc_rich_location richloc (token->location); |
16199 | location_t oloc = decl_specs->locations[ds_storage_class]; |
16200 | richloc.add_location_if_nearby (loc: oloc); |
16201 | error_at (&richloc, |
16202 | "%<typedef%> specifier conflicts with %qs" , |
16203 | cp_storage_class_name[decl_specs->storage_class]); |
16204 | decl_specs->conflicting_specifiers_p = true; |
16205 | } |
16206 | break; |
16207 | |
16208 | /* storage-class-specifier: |
16209 | auto |
16210 | register |
16211 | static |
16212 | extern |
16213 | mutable |
16214 | |
16215 | GNU Extension: |
16216 | thread */ |
16217 | case RID_AUTO: |
16218 | if (cxx_dialect == cxx98) |
16219 | { |
16220 | /* Consume the token. */ |
16221 | cp_lexer_consume_token (lexer: parser->lexer); |
16222 | |
16223 | /* Complain about `auto' as a storage specifier, if |
16224 | we're complaining about C++0x compatibility. */ |
16225 | gcc_rich_location richloc (token->location); |
16226 | richloc.add_fixit_remove (); |
16227 | warning_at (&richloc, OPT_Wc__11_compat, |
16228 | "%<auto%> changes meaning in C++11; " |
16229 | "please remove it" ); |
16230 | |
16231 | /* Set the storage class anyway. */ |
16232 | cp_parser_set_storage_class (parser, decl_specs, RID_AUTO, |
16233 | token); |
16234 | } |
16235 | else |
16236 | /* C++0x auto type-specifier. */ |
16237 | found_decl_spec = false; |
16238 | break; |
16239 | |
16240 | case RID_REGISTER: |
16241 | case RID_STATIC: |
16242 | case RID_EXTERN: |
16243 | case RID_MUTABLE: |
16244 | /* Consume the token. */ |
16245 | cp_lexer_consume_token (lexer: parser->lexer); |
16246 | cp_parser_set_storage_class (parser, decl_specs, token->keyword, |
16247 | token); |
16248 | break; |
16249 | case RID_THREAD: |
16250 | /* Consume the token. */ |
16251 | ds = ds_thread; |
16252 | cp_lexer_consume_token (lexer: parser->lexer); |
16253 | break; |
16254 | |
16255 | default: |
16256 | /* We did not yet find a decl-specifier yet. */ |
16257 | found_decl_spec = false; |
16258 | break; |
16259 | } |
16260 | |
16261 | if (found_decl_spec |
16262 | && (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR) |
16263 | && token->keyword != RID_CONSTEXPR) |
16264 | error ("%qD invalid in condition" , ridpointers[token->keyword]); |
16265 | |
16266 | if (found_decl_spec |
16267 | && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16268 | && token->keyword != RID_MUTABLE |
16269 | && token->keyword != RID_CONSTEXPR |
16270 | && token->keyword != RID_CONSTEVAL) |
16271 | { |
16272 | if (token->keyword != RID_STATIC) |
16273 | error_at (token->location, "%qD invalid in lambda" , |
16274 | ridpointers[token->keyword]); |
16275 | else if (cxx_dialect < cxx23) |
16276 | pedwarn (token->location, OPT_Wc__23_extensions, |
16277 | "%qD only valid in lambda with %<-std=c++23%> or " |
16278 | "%<-std=gnu++23%>" , ridpointers[token->keyword]); |
16279 | } |
16280 | |
16281 | if (ds != ds_last) |
16282 | set_and_check_decl_spec_loc (decl_specs, ds, token); |
16283 | |
16284 | /* Constructors are a special case. The `S' in `S()' is not a |
16285 | decl-specifier; it is the beginning of the declarator. */ |
16286 | constructor_p |
16287 | = (!found_decl_spec |
16288 | && constructor_possible_p |
16289 | && (cp_parser_constructor_declarator_p |
16290 | (parser, flags, decl_spec_seq_has_spec_p (decl_specs, |
16291 | ds_friend)))); |
16292 | |
16293 | /* If we don't have a DECL_SPEC yet, then we must be looking at |
16294 | a type-specifier. */ |
16295 | if (!found_decl_spec && !constructor_p) |
16296 | { |
16297 | int decl_spec_declares_class_or_enum; |
16298 | bool is_cv_qualifier; |
16299 | tree type_spec; |
16300 | |
16301 | if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) |
16302 | flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS; |
16303 | |
16304 | type_spec |
16305 | = cp_parser_type_specifier (parser, flags, |
16306 | decl_specs, |
16307 | /*is_declaration=*/true, |
16308 | &decl_spec_declares_class_or_enum, |
16309 | &is_cv_qualifier); |
16310 | *declares_class_or_enum |= decl_spec_declares_class_or_enum; |
16311 | |
16312 | /* If this type-specifier referenced a user-defined type |
16313 | (a typedef, class-name, etc.), then we can't allow any |
16314 | more such type-specifiers henceforth. |
16315 | |
16316 | [dcl.spec] |
16317 | |
16318 | The longest sequence of decl-specifiers that could |
16319 | possibly be a type name is taken as the |
16320 | decl-specifier-seq of a declaration. The sequence shall |
16321 | be self-consistent as described below. |
16322 | |
16323 | [dcl.type] |
16324 | |
16325 | As a general rule, at most one type-specifier is allowed |
16326 | in the complete decl-specifier-seq of a declaration. The |
16327 | only exceptions are the following: |
16328 | |
16329 | -- const or volatile can be combined with any other |
16330 | type-specifier. |
16331 | |
16332 | -- signed or unsigned can be combined with char, long, |
16333 | short, or int. |
16334 | |
16335 | -- .. |
16336 | |
16337 | Example: |
16338 | |
16339 | typedef char* Pc; |
16340 | void g (const int Pc); |
16341 | |
16342 | Here, Pc is *not* part of the decl-specifier seq; it's |
16343 | the declarator. Therefore, once we see a type-specifier |
16344 | (other than a cv-qualifier), we forbid any additional |
16345 | user-defined types. We *do* still allow things like `int |
16346 | int' to be considered a decl-specifier-seq, and issue the |
16347 | error message later. */ |
16348 | if (type_spec && !is_cv_qualifier) |
16349 | flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; |
16350 | /* A constructor declarator cannot follow a type-specifier. */ |
16351 | if (type_spec) |
16352 | { |
16353 | constructor_possible_p = false; |
16354 | found_decl_spec = true; |
16355 | if (!is_cv_qualifier) |
16356 | decl_specs->any_type_specifiers_p = true; |
16357 | |
16358 | if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) != 0) |
16359 | error_at (token->location, "type-specifier invalid in lambda" ); |
16360 | } |
16361 | } |
16362 | |
16363 | /* If we still do not have a DECL_SPEC, then there are no more |
16364 | decl-specifiers. */ |
16365 | if (!found_decl_spec) |
16366 | break; |
16367 | |
16368 | if (decl_specs->std_attributes) |
16369 | { |
16370 | error_at (decl_specs->locations[ds_std_attribute], |
16371 | "standard attributes in middle of decl-specifiers" ); |
16372 | inform (decl_specs->locations[ds_std_attribute], |
16373 | "standard attributes must precede the decl-specifiers to " |
16374 | "apply to the declaration, or follow them to apply to " |
16375 | "the type" ); |
16376 | } |
16377 | |
16378 | decl_specs->any_specifiers_p = true; |
16379 | /* After we see one decl-specifier, further decl-specifiers are |
16380 | always optional. */ |
16381 | flags |= CP_PARSER_FLAGS_OPTIONAL; |
16382 | } |
16383 | |
16384 | /* Don't allow a friend specifier with a class definition. */ |
16385 | if (decl_spec_seq_has_spec_p (decl_specs, ds_friend) |
16386 | && (*declares_class_or_enum & 2)) |
16387 | error_at (decl_specs->locations[ds_friend], |
16388 | "class definition may not be declared a friend" ); |
16389 | } |
16390 | |
16391 | /* Parse an (optional) storage-class-specifier. |
16392 | |
16393 | storage-class-specifier: |
16394 | auto |
16395 | register |
16396 | static |
16397 | extern |
16398 | mutable |
16399 | |
16400 | GNU Extension: |
16401 | |
16402 | storage-class-specifier: |
16403 | thread |
16404 | |
16405 | Returns an IDENTIFIER_NODE corresponding to the keyword used. */ |
16406 | |
16407 | static tree |
16408 | cp_parser_storage_class_specifier_opt (cp_parser* parser) |
16409 | { |
16410 | switch (cp_lexer_peek_token (lexer: parser->lexer)->keyword) |
16411 | { |
16412 | case RID_AUTO: |
16413 | if (cxx_dialect != cxx98) |
16414 | return NULL_TREE; |
16415 | /* Fall through for C++98. */ |
16416 | gcc_fallthrough (); |
16417 | |
16418 | case RID_REGISTER: |
16419 | case RID_STATIC: |
16420 | case RID_EXTERN: |
16421 | case RID_MUTABLE: |
16422 | case RID_THREAD: |
16423 | /* Consume the token. */ |
16424 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16425 | |
16426 | default: |
16427 | return NULL_TREE; |
16428 | } |
16429 | } |
16430 | |
16431 | /* Parse an (optional) function-specifier. |
16432 | |
16433 | function-specifier: |
16434 | inline |
16435 | virtual |
16436 | explicit |
16437 | |
16438 | C++20 Extension: |
16439 | explicit(constant-expression) |
16440 | |
16441 | Returns an IDENTIFIER_NODE corresponding to the keyword used. |
16442 | Updates DECL_SPECS, if it is non-NULL. */ |
16443 | |
16444 | static tree |
16445 | cp_parser_function_specifier_opt (cp_parser* parser, |
16446 | cp_decl_specifier_seq *decl_specs) |
16447 | { |
16448 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
16449 | switch (token->keyword) |
16450 | { |
16451 | case RID_INLINE: |
16452 | set_and_check_decl_spec_loc (decl_specs, ds: ds_inline, token); |
16453 | break; |
16454 | |
16455 | case RID_VIRTUAL: |
16456 | /* 14.5.2.3 [temp.mem] |
16457 | |
16458 | A member function template shall not be virtual. */ |
16459 | if (PROCESSING_REAL_TEMPLATE_DECL_P () |
16460 | && current_class_type) |
16461 | error_at (token->location, "templates may not be %<virtual%>" ); |
16462 | else |
16463 | set_and_check_decl_spec_loc (decl_specs, ds: ds_virtual, token); |
16464 | break; |
16465 | |
16466 | case RID_EXPLICIT: |
16467 | { |
16468 | tree id = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16469 | /* If we see '(', it's C++20 explicit(bool). */ |
16470 | tree expr; |
16471 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
16472 | { |
16473 | matching_parens parens; |
16474 | parens.consume_open (parser); |
16475 | |
16476 | /* New types are not allowed in an explicit-specifier. */ |
16477 | const char *saved_message |
16478 | = parser->type_definition_forbidden_message; |
16479 | parser->type_definition_forbidden_message |
16480 | = G_("types may not be defined in explicit-specifier" ); |
16481 | |
16482 | if (cxx_dialect < cxx20) |
16483 | pedwarn (token->location, OPT_Wc__20_extensions, |
16484 | "%<explicit(bool)%> only available with %<-std=c++20%> " |
16485 | "or %<-std=gnu++20%>" ); |
16486 | |
16487 | /* Parse the constant-expression. */ |
16488 | expr = cp_parser_constant_expression (parser); |
16489 | |
16490 | /* Restore the saved message. */ |
16491 | parser->type_definition_forbidden_message = saved_message; |
16492 | parens.require_close (parser); |
16493 | } |
16494 | else |
16495 | /* The explicit-specifier explicit without a constant-expression is |
16496 | equivalent to the explicit-specifier explicit(true). */ |
16497 | expr = boolean_true_node; |
16498 | |
16499 | /* [dcl.fct.spec] |
16500 | "the constant-expression, if supplied, shall be a contextually |
16501 | converted constant expression of type bool." */ |
16502 | expr = build_explicit_specifier (expr, tf_warning_or_error); |
16503 | /* We could evaluate it -- mark the decl as appropriate. */ |
16504 | if (expr == boolean_true_node) |
16505 | set_and_check_decl_spec_loc (decl_specs, ds: ds_explicit, token); |
16506 | else if (expr == boolean_false_node) |
16507 | /* Don't mark the decl as explicit. */; |
16508 | else if (decl_specs) |
16509 | /* The expression was value-dependent. Remember it so that we can |
16510 | substitute it later. */ |
16511 | decl_specs->explicit_specifier = expr; |
16512 | return id; |
16513 | } |
16514 | |
16515 | default: |
16516 | return NULL_TREE; |
16517 | } |
16518 | |
16519 | /* Consume the token. */ |
16520 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
16521 | } |
16522 | |
16523 | /* Parse a linkage-specification. |
16524 | |
16525 | linkage-specification: |
16526 | extern string-literal { declaration-seq [opt] } |
16527 | extern string-literal declaration */ |
16528 | |
16529 | static void |
16530 | cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr) |
16531 | { |
16532 | /* Look for the `extern' keyword. */ |
16533 | cp_token *extern_token |
16534 | = cp_parser_require_keyword (parser, RID_EXTERN, RT_EXTERN); |
16535 | |
16536 | /* Look for the string-literal. */ |
16537 | cp_token *string_token = cp_lexer_peek_token (lexer: parser->lexer); |
16538 | tree linkage; |
16539 | if (cxx_dialect >= cxx26) |
16540 | linkage = cp_parser_unevaluated_string_literal (parser); |
16541 | else |
16542 | linkage = cp_parser_string_literal (parser, /*translate=*/false, |
16543 | /*wide_ok=*/false); |
16544 | |
16545 | /* Transform the literal into an identifier. If the literal is a |
16546 | wide-character string, or contains embedded NULs, then we can't |
16547 | handle it as the user wants. */ |
16548 | if (linkage == error_mark_node |
16549 | || strlen (TREE_STRING_POINTER (linkage)) |
16550 | != (size_t) (TREE_STRING_LENGTH (linkage) - 1)) |
16551 | { |
16552 | cp_parser_error (parser, gmsgid: "invalid linkage-specification" ); |
16553 | /* Assume C++ linkage. */ |
16554 | linkage = lang_name_cplusplus; |
16555 | } |
16556 | else |
16557 | linkage = get_identifier (TREE_STRING_POINTER (linkage)); |
16558 | |
16559 | /* We're now using the new linkage. */ |
16560 | unsigned saved_module = module_kind; |
16561 | module_kind &= ~MK_ATTACH; |
16562 | push_lang_context (linkage); |
16563 | |
16564 | /* Preserve the location of the innermost linkage specification, |
16565 | tracking the locations of nested specifications via a local. */ |
16566 | location_t saved_location |
16567 | = parser->innermost_linkage_specification_location; |
16568 | /* Construct a location ranging from the start of the "extern" to |
16569 | the end of the string-literal, with the caret at the start, e.g.: |
16570 | extern "C" { |
16571 | ^~~~~~~~~~ |
16572 | */ |
16573 | parser->innermost_linkage_specification_location |
16574 | = make_location (caret: extern_token->location, |
16575 | start: extern_token->location, |
16576 | finish: get_finish (loc: string_token->location)); |
16577 | |
16578 | /* If the next token is a `{', then we're using the first |
16579 | production. */ |
16580 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
16581 | { |
16582 | cp_ensure_no_omp_declare_simd (parser); |
16583 | cp_ensure_no_oacc_routine (parser); |
16584 | |
16585 | /* Consume the `{' token. */ |
16586 | matching_braces braces; |
16587 | braces.consume_open (parser); |
16588 | /* Parse the declarations. */ |
16589 | cp_parser_declaration_seq_opt (parser); |
16590 | /* Look for the closing `}'. */ |
16591 | braces.require_close (parser); |
16592 | } |
16593 | /* Otherwise, there's just one declaration. */ |
16594 | else |
16595 | { |
16596 | bool saved_in_unbraced_linkage_specification_p; |
16597 | |
16598 | saved_in_unbraced_linkage_specification_p |
16599 | = parser->in_unbraced_linkage_specification_p; |
16600 | parser->in_unbraced_linkage_specification_p = true; |
16601 | cp_parser_declaration (parser, prefix_attrs: prefix_attr); |
16602 | parser->in_unbraced_linkage_specification_p |
16603 | = saved_in_unbraced_linkage_specification_p; |
16604 | } |
16605 | |
16606 | /* We're done with the linkage-specification. */ |
16607 | pop_lang_context (); |
16608 | module_kind = saved_module; |
16609 | |
16610 | /* Restore location of parent linkage specification, if any. */ |
16611 | parser->innermost_linkage_specification_location = saved_location; |
16612 | } |
16613 | |
16614 | /* Parse a static_assert-declaration. |
16615 | |
16616 | static_assert-declaration: |
16617 | static_assert ( constant-expression , string-literal ) ; |
16618 | static_assert ( constant-expression ) ; (C++17) |
16619 | |
16620 | If MEMBER_P, this static_assert is a class member. */ |
16621 | |
16622 | static void |
16623 | cp_parser_static_assert (cp_parser *parser, bool member_p) |
16624 | { |
16625 | cp_expr condition; |
16626 | location_t token_loc; |
16627 | tree message; |
16628 | |
16629 | /* Peek at the `static_assert' token so we can keep track of exactly |
16630 | where the static assertion started. */ |
16631 | token_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
16632 | |
16633 | /* Look for the `static_assert' keyword. */ |
16634 | if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, |
16635 | RT_STATIC_ASSERT)) |
16636 | return; |
16637 | |
16638 | /* We know we are in a static assertion; commit to any tentative |
16639 | parse. */ |
16640 | if (cp_parser_parsing_tentatively (parser)) |
16641 | cp_parser_commit_to_tentative_parse (parser); |
16642 | |
16643 | /* Parse the `(' starting the static assertion condition. */ |
16644 | matching_parens parens; |
16645 | parens.require_open (parser); |
16646 | |
16647 | /* Parse the constant-expression. Allow a non-constant expression |
16648 | here in order to give better diagnostics in finish_static_assert. */ |
16649 | condition = |
16650 | cp_parser_constant_expression (parser, |
16651 | /*allow_non_constant_p=*/true, |
16652 | /*non_constant_p=*/nullptr); |
16653 | |
16654 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
16655 | { |
16656 | if (pedantic && cxx_dialect < cxx17) |
16657 | pedwarn (input_location, OPT_Wc__17_extensions, |
16658 | "%<static_assert%> without a message " |
16659 | "only available with %<-std=c++17%> or %<-std=gnu++17%>" ); |
16660 | /* Eat the ')' */ |
16661 | cp_lexer_consume_token (lexer: parser->lexer); |
16662 | message = build_string (1, "" ); |
16663 | TREE_TYPE (message) = char_array_type_node; |
16664 | fix_string_type (message); |
16665 | } |
16666 | else |
16667 | { |
16668 | /* Parse the separating `,'. */ |
16669 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
16670 | |
16671 | /* Parse the string-literal message. */ |
16672 | if (cxx_dialect >= cxx26) |
16673 | message = cp_parser_unevaluated_string_literal (parser); |
16674 | else |
16675 | message = cp_parser_string_literal (parser, /*translate=*/false, |
16676 | /*wide_ok=*/true); |
16677 | |
16678 | /* A `)' completes the static assertion. */ |
16679 | if (!parens.require_close (parser)) |
16680 | cp_parser_skip_to_closing_parenthesis (parser, |
16681 | /*recovering=*/true, |
16682 | /*or_comma=*/false, |
16683 | /*consume_paren=*/true); |
16684 | } |
16685 | |
16686 | /* A semicolon terminates the declaration. */ |
16687 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
16688 | |
16689 | /* Get the location for the static assertion. Use that of the |
16690 | condition if available, otherwise, use that of the "static_assert" |
16691 | token. */ |
16692 | location_t assert_loc = condition.get_location (); |
16693 | if (assert_loc == UNKNOWN_LOCATION) |
16694 | assert_loc = token_loc; |
16695 | |
16696 | /* Complete the static assertion, which may mean either processing |
16697 | the static assert now or saving it for template instantiation. */ |
16698 | finish_static_assert (condition, message, assert_loc, member_p, |
16699 | /*show_expr_p=*/false); |
16700 | } |
16701 | |
16702 | /* Parse the expression in decltype ( expression ). */ |
16703 | |
16704 | static tree |
16705 | cp_parser_decltype_expr (cp_parser *parser, |
16706 | bool &id_expression_or_member_access_p) |
16707 | { |
16708 | cp_token *id_expr_start_token; |
16709 | tree expr; |
16710 | |
16711 | /* First, try parsing an id-expression. */ |
16712 | id_expr_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
16713 | cp_parser_parse_tentatively (parser); |
16714 | expr = cp_parser_id_expression (parser, |
16715 | /*template_keyword_p=*/false, |
16716 | /*check_dependency_p=*/true, |
16717 | /*template_p=*/NULL, |
16718 | /*declarator_p=*/false, |
16719 | /*optional_p=*/false); |
16720 | |
16721 | if (!cp_parser_error_occurred (parser) && expr != error_mark_node) |
16722 | { |
16723 | bool non_integral_constant_expression_p = false; |
16724 | tree id_expression = expr; |
16725 | cp_id_kind idk; |
16726 | const char *error_msg; |
16727 | |
16728 | if (identifier_p (t: expr)) |
16729 | /* Lookup the name we got back from the id-expression. */ |
16730 | expr = cp_parser_lookup_name_simple (parser, expr, |
16731 | id_expr_start_token->location); |
16732 | |
16733 | if (expr |
16734 | && expr != error_mark_node |
16735 | && TREE_CODE (expr) != TYPE_DECL |
16736 | && (TREE_CODE (expr) != BIT_NOT_EXPR |
16737 | || !TYPE_P (TREE_OPERAND (expr, 0))) |
16738 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
16739 | { |
16740 | /* Complete lookup of the id-expression. */ |
16741 | expr = (finish_id_expression |
16742 | (id_expression, expr, parser->scope, &idk, |
16743 | /*integral_constant_expression_p=*/false, |
16744 | /*allow_non_integral_constant_expression_p=*/true, |
16745 | &non_integral_constant_expression_p, |
16746 | /*template_p=*/false, |
16747 | /*done=*/true, |
16748 | /*address_p=*/false, |
16749 | /*template_arg_p=*/false, |
16750 | &error_msg, |
16751 | id_expr_start_token->location)); |
16752 | |
16753 | if (error_msg) |
16754 | { |
16755 | /* We found an id-expression, but it was something that we |
16756 | should not have found. This is an error, not something |
16757 | we can recover from, so report the error we found and |
16758 | we'll recover as gracefully as possible. */ |
16759 | cp_parser_parse_definitely (parser); |
16760 | cp_parser_error (parser, gmsgid: error_msg); |
16761 | id_expression_or_member_access_p = true; |
16762 | return error_mark_node; |
16763 | } |
16764 | } |
16765 | |
16766 | if (expr |
16767 | && expr != error_mark_node |
16768 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
16769 | /* We have an id-expression. */ |
16770 | id_expression_or_member_access_p = true; |
16771 | } |
16772 | |
16773 | if (!id_expression_or_member_access_p) |
16774 | { |
16775 | /* Abort the id-expression parse. */ |
16776 | cp_parser_abort_tentative_parse (parser); |
16777 | |
16778 | /* Parsing tentatively, again. */ |
16779 | cp_parser_parse_tentatively (parser); |
16780 | |
16781 | /* Parse a class member access. */ |
16782 | expr = cp_parser_postfix_expression (parser, /*address_p=*/false, |
16783 | /*cast_p=*/false, /*decltype*/member_access_only_p: true, |
16784 | /*member_access_only_p=*/decltype_p: true, NULL); |
16785 | |
16786 | if (expr |
16787 | && expr != error_mark_node |
16788 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_CLOSE_PAREN) |
16789 | /* We have an id-expression. */ |
16790 | id_expression_or_member_access_p = true; |
16791 | } |
16792 | |
16793 | if (id_expression_or_member_access_p) |
16794 | /* We have parsed the complete id-expression or member access. */ |
16795 | cp_parser_parse_definitely (parser); |
16796 | else |
16797 | { |
16798 | /* Abort our attempt to parse an id-expression or member access |
16799 | expression. */ |
16800 | cp_parser_abort_tentative_parse (parser); |
16801 | |
16802 | /* Parse a full expression. */ |
16803 | expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false, |
16804 | /*decltype_p=*/true); |
16805 | } |
16806 | |
16807 | return expr; |
16808 | } |
16809 | |
16810 | /* Parse a `decltype' type. Returns the type. |
16811 | |
16812 | decltype-specifier: |
16813 | decltype ( expression ) |
16814 | C++14: |
16815 | decltype ( auto ) */ |
16816 | |
16817 | static tree |
16818 | cp_parser_decltype (cp_parser *parser) |
16819 | { |
16820 | bool id_expression_or_member_access_p = false; |
16821 | cp_token *start_token = cp_lexer_peek_token (lexer: parser->lexer); |
16822 | |
16823 | if (start_token->type == CPP_DECLTYPE) |
16824 | { |
16825 | /* Already parsed. */ |
16826 | cp_lexer_consume_token (lexer: parser->lexer); |
16827 | return saved_checks_value (check_value: start_token->u.tree_check_value); |
16828 | } |
16829 | |
16830 | /* Look for the `decltype' token. */ |
16831 | if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) |
16832 | return error_mark_node; |
16833 | |
16834 | /* Parse the opening `('. */ |
16835 | matching_parens parens; |
16836 | if (!parens.require_open (parser)) |
16837 | return error_mark_node; |
16838 | |
16839 | /* Since we're going to preserve any side-effects from this parse, set up a |
16840 | firewall to protect our callers from cp_parser_commit_to_tentative_parse |
16841 | in the expression. */ |
16842 | tentative_firewall firewall (parser); |
16843 | |
16844 | /* If in_declarator_p, a reparse as an expression might succeed (60361). |
16845 | Otherwise, commit now for better diagnostics. */ |
16846 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
16847 | && !parser->in_declarator_p) |
16848 | cp_parser_commit_to_topmost_tentative_parse (parser); |
16849 | |
16850 | push_deferring_access_checks (dk_deferred); |
16851 | |
16852 | tree expr = NULL_TREE; |
16853 | |
16854 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO) |
16855 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN)) |
16856 | { |
16857 | /* decltype (auto) */ |
16858 | cp_lexer_consume_token (lexer: parser->lexer); |
16859 | if (cxx_dialect < cxx14) |
16860 | { |
16861 | error_at (start_token->location, |
16862 | "%<decltype(auto)%> type specifier only available with " |
16863 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
16864 | expr = error_mark_node; |
16865 | } |
16866 | } |
16867 | else |
16868 | { |
16869 | /* decltype (expression) */ |
16870 | |
16871 | /* Types cannot be defined in a `decltype' expression. Save away the |
16872 | old message and set the new one. */ |
16873 | const char *saved_message = parser->type_definition_forbidden_message; |
16874 | parser->type_definition_forbidden_message |
16875 | = G_("types may not be defined in %<decltype%> expressions" ); |
16876 | |
16877 | /* The restrictions on constant-expressions do not apply inside |
16878 | decltype expressions. */ |
16879 | bool saved_integral_constant_expression_p |
16880 | = parser->integral_constant_expression_p; |
16881 | bool saved_non_integral_constant_expression_p |
16882 | = parser->non_integral_constant_expression_p; |
16883 | parser->integral_constant_expression_p = false; |
16884 | |
16885 | /* Within a parenthesized expression, a `>' token is always |
16886 | the greater-than operator. */ |
16887 | bool saved_greater_than_is_operator_p |
16888 | = parser->greater_than_is_operator_p; |
16889 | parser->greater_than_is_operator_p = true; |
16890 | |
16891 | /* Don't synthesize an implicit template type parameter here. This |
16892 | could happen with C++23 code like |
16893 | |
16894 | void f(decltype(new auto{0})); |
16895 | |
16896 | where we want to deduce the auto right away so that the parameter |
16897 | is of type 'int *'. */ |
16898 | auto cleanup = make_temp_override |
16899 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
16900 | |
16901 | /* Do not actually evaluate the expression. */ |
16902 | ++cp_unevaluated_operand; |
16903 | |
16904 | /* Do not warn about problems with the expression. */ |
16905 | ++c_inhibit_evaluation_warnings; |
16906 | |
16907 | expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); |
16908 | STRIP_ANY_LOCATION_WRAPPER (expr); |
16909 | |
16910 | /* Go back to evaluating expressions. */ |
16911 | --cp_unevaluated_operand; |
16912 | --c_inhibit_evaluation_warnings; |
16913 | |
16914 | /* The `>' token might be the end of a template-id or |
16915 | template-parameter-list now. */ |
16916 | parser->greater_than_is_operator_p |
16917 | = saved_greater_than_is_operator_p; |
16918 | |
16919 | /* Restore the old message and the integral constant expression |
16920 | flags. */ |
16921 | parser->type_definition_forbidden_message = saved_message; |
16922 | parser->integral_constant_expression_p |
16923 | = saved_integral_constant_expression_p; |
16924 | parser->non_integral_constant_expression_p |
16925 | = saved_non_integral_constant_expression_p; |
16926 | } |
16927 | |
16928 | /* Parse to the closing `)'. */ |
16929 | if (expr == error_mark_node || !parens.require_close (parser)) |
16930 | { |
16931 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
16932 | /*consume_paren=*/true); |
16933 | expr = error_mark_node; |
16934 | } |
16935 | |
16936 | /* If we got a parse error while tentative, bail out now. */ |
16937 | if (cp_parser_error_occurred (parser)) |
16938 | { |
16939 | pop_deferring_access_checks (); |
16940 | return error_mark_node; |
16941 | } |
16942 | |
16943 | if (!expr) |
16944 | /* Build auto. */ |
16945 | expr = make_decltype_auto (); |
16946 | else |
16947 | expr = finish_decltype_type (expr, id_expression_or_member_access_p, |
16948 | tf_warning_or_error); |
16949 | |
16950 | /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse |
16951 | it again. */ |
16952 | start_token->type = CPP_DECLTYPE; |
16953 | start_token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
16954 | start_token->tree_check_p = true; |
16955 | start_token->u.tree_check_value->value = expr; |
16956 | start_token->u.tree_check_value->checks = get_deferred_access_checks (); |
16957 | start_token->keyword = RID_MAX; |
16958 | |
16959 | location_t loc = start_token->location; |
16960 | loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
16961 | start_token->location = loc; |
16962 | |
16963 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_token); |
16964 | |
16965 | pop_to_parent_deferring_access_checks (); |
16966 | |
16967 | return expr; |
16968 | } |
16969 | |
16970 | /* Special member functions [gram.special] */ |
16971 | |
16972 | /* Parse a conversion-function-id. |
16973 | |
16974 | conversion-function-id: |
16975 | operator conversion-type-id |
16976 | |
16977 | Returns an IDENTIFIER_NODE representing the operator. */ |
16978 | |
16979 | static tree |
16980 | cp_parser_conversion_function_id (cp_parser* parser) |
16981 | { |
16982 | tree type; |
16983 | tree saved_scope; |
16984 | tree saved_qualifying_scope; |
16985 | tree saved_object_scope; |
16986 | tree pushed_scope = NULL_TREE; |
16987 | |
16988 | /* Look for the `operator' token. */ |
16989 | if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR)) |
16990 | return error_mark_node; |
16991 | /* When we parse the conversion-type-id, the current scope will be |
16992 | reset. However, we need that information in able to look up the |
16993 | conversion function later, so we save it here. */ |
16994 | saved_scope = parser->scope; |
16995 | saved_qualifying_scope = parser->qualifying_scope; |
16996 | saved_object_scope = parser->object_scope; |
16997 | /* We must enter the scope of the class so that the names of |
16998 | entities declared within the class are available in the |
16999 | conversion-type-id. For example, consider: |
17000 | |
17001 | struct S { |
17002 | typedef int I; |
17003 | operator I(); |
17004 | }; |
17005 | |
17006 | S::operator I() { ... } |
17007 | |
17008 | In order to see that `I' is a type-name in the definition, we |
17009 | must be in the scope of `S'. */ |
17010 | if (saved_scope) |
17011 | pushed_scope = push_scope (saved_scope); |
17012 | /* Parse the conversion-type-id. */ |
17013 | type = cp_parser_conversion_type_id (parser); |
17014 | /* Leave the scope of the class, if any. */ |
17015 | if (pushed_scope) |
17016 | pop_scope (pushed_scope); |
17017 | /* Restore the saved scope. */ |
17018 | parser->scope = saved_scope; |
17019 | parser->qualifying_scope = saved_qualifying_scope; |
17020 | parser->object_scope = saved_object_scope; |
17021 | /* If the TYPE is invalid, indicate failure. */ |
17022 | if (type == error_mark_node) |
17023 | return error_mark_node; |
17024 | return make_conv_op_name (type); |
17025 | } |
17026 | |
17027 | /* Parse a conversion-type-id: |
17028 | |
17029 | conversion-type-id: |
17030 | type-specifier-seq conversion-declarator [opt] |
17031 | |
17032 | Returns the TYPE specified. */ |
17033 | |
17034 | static tree |
17035 | cp_parser_conversion_type_id (cp_parser* parser) |
17036 | { |
17037 | tree attributes; |
17038 | cp_decl_specifier_seq type_specifiers; |
17039 | cp_declarator *declarator; |
17040 | tree type_specified; |
17041 | const char *saved_message; |
17042 | |
17043 | /* Parse the attributes. */ |
17044 | attributes = cp_parser_attributes_opt (parser); |
17045 | |
17046 | saved_message = parser->type_definition_forbidden_message; |
17047 | parser->type_definition_forbidden_message |
17048 | = G_("types may not be defined in a conversion-type-id" ); |
17049 | |
17050 | /* Parse the type-specifiers. DR 2413 clarifies that `typename' is |
17051 | optional in conversion-type-id. */ |
17052 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
17053 | /*is_declaration=*/false, |
17054 | /*is_trailing_return=*/false, |
17055 | &type_specifiers); |
17056 | |
17057 | parser->type_definition_forbidden_message = saved_message; |
17058 | |
17059 | /* If that didn't work, stop. */ |
17060 | if (type_specifiers.type == error_mark_node) |
17061 | return error_mark_node; |
17062 | /* Parse the conversion-declarator. */ |
17063 | declarator = cp_parser_conversion_declarator_opt (parser); |
17064 | |
17065 | type_specified = grokdeclarator (declarator, &type_specifiers, TYPENAME, |
17066 | /*initialized=*/0, &attributes); |
17067 | if (attributes) |
17068 | cplus_decl_attributes (&type_specified, attributes, /*flags=*/0); |
17069 | |
17070 | /* Don't give this error when parsing tentatively. This happens to |
17071 | work because we always parse this definitively once. */ |
17072 | if (! cp_parser_uncommitted_to_tentative_parse_p (parser) |
17073 | && type_uses_auto (type_specified)) |
17074 | { |
17075 | if (cxx_dialect < cxx14) |
17076 | { |
17077 | error ("invalid use of %<auto%> in conversion operator" ); |
17078 | return error_mark_node; |
17079 | } |
17080 | else if (template_parm_scope_p ()) |
17081 | warning (0, "use of %<auto%> in member template " |
17082 | "conversion operator can never be deduced" ); |
17083 | } |
17084 | |
17085 | return type_specified; |
17086 | } |
17087 | |
17088 | /* Parse an (optional) conversion-declarator. |
17089 | |
17090 | conversion-declarator: |
17091 | ptr-operator conversion-declarator [opt] |
17092 | |
17093 | */ |
17094 | |
17095 | static cp_declarator * |
17096 | cp_parser_conversion_declarator_opt (cp_parser* parser) |
17097 | { |
17098 | enum tree_code code; |
17099 | tree class_type, std_attributes = NULL_TREE; |
17100 | cp_cv_quals cv_quals; |
17101 | |
17102 | /* We don't know if there's a ptr-operator next, or not. */ |
17103 | cp_parser_parse_tentatively (parser); |
17104 | /* Try the ptr-operator. */ |
17105 | code = cp_parser_ptr_operator (parser, &class_type, &cv_quals, |
17106 | &std_attributes); |
17107 | /* If it worked, look for more conversion-declarators. */ |
17108 | if (cp_parser_parse_definitely (parser)) |
17109 | { |
17110 | cp_declarator *declarator; |
17111 | |
17112 | /* Parse another optional declarator. */ |
17113 | declarator = cp_parser_conversion_declarator_opt (parser); |
17114 | |
17115 | declarator = cp_parser_make_indirect_declarator |
17116 | (code, class_type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
17117 | |
17118 | return declarator; |
17119 | } |
17120 | |
17121 | return NULL; |
17122 | } |
17123 | |
17124 | /* Parse an (optional) ctor-initializer. |
17125 | |
17126 | ctor-initializer: |
17127 | : mem-initializer-list */ |
17128 | |
17129 | static void |
17130 | cp_parser_ctor_initializer_opt (cp_parser* parser) |
17131 | { |
17132 | /* If the next token is not a `:', then there is no |
17133 | ctor-initializer. */ |
17134 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
17135 | { |
17136 | /* Do default initialization of any bases and members. */ |
17137 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
17138 | finish_mem_initializers (NULL_TREE); |
17139 | return; |
17140 | } |
17141 | |
17142 | /* Consume the `:' token. */ |
17143 | cp_lexer_consume_token (lexer: parser->lexer); |
17144 | /* And the mem-initializer-list. */ |
17145 | cp_parser_mem_initializer_list (parser); |
17146 | } |
17147 | |
17148 | /* Parse a mem-initializer-list. |
17149 | |
17150 | mem-initializer-list: |
17151 | mem-initializer ... [opt] |
17152 | mem-initializer ... [opt] , mem-initializer-list */ |
17153 | |
17154 | static void |
17155 | cp_parser_mem_initializer_list (cp_parser* parser) |
17156 | { |
17157 | tree mem_initializer_list = NULL_TREE; |
17158 | tree target_ctor = error_mark_node; |
17159 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17160 | |
17161 | /* Let the semantic analysis code know that we are starting the |
17162 | mem-initializer-list. */ |
17163 | if (!DECL_CONSTRUCTOR_P (current_function_decl)) |
17164 | error_at (token->location, |
17165 | "only constructors take member initializers" ); |
17166 | |
17167 | /* Loop through the list. */ |
17168 | while (true) |
17169 | { |
17170 | tree mem_initializer; |
17171 | |
17172 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17173 | /* Parse the mem-initializer. */ |
17174 | mem_initializer = cp_parser_mem_initializer (parser); |
17175 | /* If the next token is a `...', we're expanding member initializers. */ |
17176 | bool ellipsis = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS); |
17177 | if (ellipsis |
17178 | || (mem_initializer != error_mark_node |
17179 | && check_for_bare_parameter_packs (TREE_PURPOSE |
17180 | (mem_initializer)))) |
17181 | { |
17182 | /* Consume the `...'. */ |
17183 | if (ellipsis) |
17184 | cp_lexer_consume_token (lexer: parser->lexer); |
17185 | |
17186 | /* The TREE_PURPOSE must be a _TYPE, because base-specifiers |
17187 | can be expanded but members cannot. */ |
17188 | if (mem_initializer != error_mark_node |
17189 | && !TYPE_P (TREE_PURPOSE (mem_initializer))) |
17190 | { |
17191 | error_at (token->location, |
17192 | "cannot expand initializer for member %qD" , |
17193 | TREE_PURPOSE (mem_initializer)); |
17194 | mem_initializer = error_mark_node; |
17195 | } |
17196 | |
17197 | /* Construct the pack expansion type. */ |
17198 | if (mem_initializer != error_mark_node) |
17199 | mem_initializer = make_pack_expansion (mem_initializer); |
17200 | } |
17201 | if (target_ctor != error_mark_node |
17202 | && mem_initializer != error_mark_node) |
17203 | { |
17204 | error ("mem-initializer for %qD follows constructor delegation" , |
17205 | TREE_PURPOSE (mem_initializer)); |
17206 | mem_initializer = error_mark_node; |
17207 | } |
17208 | /* Look for a target constructor. */ |
17209 | if (mem_initializer != error_mark_node |
17210 | && CLASS_TYPE_P (TREE_PURPOSE (mem_initializer)) |
17211 | && same_type_p (TREE_PURPOSE (mem_initializer), current_class_type)) |
17212 | { |
17213 | maybe_warn_cpp0x (str: CPP0X_DELEGATING_CTORS); |
17214 | if (mem_initializer_list) |
17215 | { |
17216 | error ("constructor delegation follows mem-initializer for %qD" , |
17217 | TREE_PURPOSE (mem_initializer_list)); |
17218 | mem_initializer = error_mark_node; |
17219 | } |
17220 | target_ctor = mem_initializer; |
17221 | } |
17222 | /* Add it to the list, unless it was erroneous. */ |
17223 | if (mem_initializer != error_mark_node) |
17224 | { |
17225 | TREE_CHAIN (mem_initializer) = mem_initializer_list; |
17226 | mem_initializer_list = mem_initializer; |
17227 | } |
17228 | /* If the next token is not a `,', we're done. */ |
17229 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
17230 | break; |
17231 | /* Consume the `,' token. */ |
17232 | cp_lexer_consume_token (lexer: parser->lexer); |
17233 | } |
17234 | |
17235 | /* Perform semantic analysis. */ |
17236 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
17237 | finish_mem_initializers (mem_initializer_list); |
17238 | } |
17239 | |
17240 | /* Parse a mem-initializer. |
17241 | |
17242 | mem-initializer: |
17243 | mem-initializer-id ( expression-list [opt] ) |
17244 | mem-initializer-id braced-init-list |
17245 | |
17246 | GNU extension: |
17247 | |
17248 | mem-initializer: |
17249 | ( expression-list [opt] ) |
17250 | |
17251 | Returns a TREE_LIST. The TREE_PURPOSE is the TYPE (for a base |
17252 | class) or FIELD_DECL (for a non-static data member) to initialize; |
17253 | the TREE_VALUE is the expression-list. An empty initialization |
17254 | list is represented by void_list_node. */ |
17255 | |
17256 | static tree |
17257 | cp_parser_mem_initializer (cp_parser* parser) |
17258 | { |
17259 | tree mem_initializer_id; |
17260 | tree expression_list; |
17261 | tree member; |
17262 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17263 | |
17264 | /* Find out what is being initialized. */ |
17265 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
17266 | { |
17267 | permerror (token->location, |
17268 | "anachronistic old-style base class initializer" ); |
17269 | mem_initializer_id = NULL_TREE; |
17270 | } |
17271 | else |
17272 | { |
17273 | mem_initializer_id = cp_parser_mem_initializer_id (parser); |
17274 | if (mem_initializer_id == error_mark_node) |
17275 | return mem_initializer_id; |
17276 | } |
17277 | member = expand_member_init (mem_initializer_id); |
17278 | if (member && !DECL_P (member)) |
17279 | in_base_initializer = 1; |
17280 | |
17281 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
17282 | { |
17283 | cp_lexer_set_source_position (lexer: parser->lexer); |
17284 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
17285 | expression_list = cp_parser_braced_list (parser); |
17286 | CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; |
17287 | expression_list = build_tree_list (NULL_TREE, expression_list); |
17288 | } |
17289 | else |
17290 | { |
17291 | vec<tree, va_gc> *vec; |
17292 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
17293 | /*cast_p=*/false, |
17294 | /*allow_expansion_p=*/true, |
17295 | /*non_constant_p=*/NULL, |
17296 | /*close_paren_loc=*/NULL, |
17297 | /*wrap_locations_p=*/true); |
17298 | if (vec == NULL) |
17299 | return error_mark_node; |
17300 | expression_list = build_tree_list_vec (vec); |
17301 | release_tree_vector (vec); |
17302 | } |
17303 | |
17304 | if (expression_list == error_mark_node) |
17305 | return error_mark_node; |
17306 | if (!expression_list) |
17307 | expression_list = void_type_node; |
17308 | |
17309 | in_base_initializer = 0; |
17310 | |
17311 | if (!member) |
17312 | return error_mark_node; |
17313 | tree node = build_tree_list (member, expression_list); |
17314 | |
17315 | /* We can't attach the source location of this initializer directly to |
17316 | the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR |
17317 | within the TREE_TYPE of the list node. */ |
17318 | location_t loc |
17319 | = make_location (caret: token->location, start: token->location, lexer: parser->lexer); |
17320 | tree dummy = build0 (EMPTY_CLASS_EXPR, NULL_TREE); |
17321 | SET_EXPR_LOCATION (dummy, loc); |
17322 | TREE_TYPE (node) = dummy; |
17323 | |
17324 | return node; |
17325 | } |
17326 | |
17327 | /* Parse a mem-initializer-id. |
17328 | |
17329 | mem-initializer-id: |
17330 | :: [opt] nested-name-specifier [opt] class-name |
17331 | decltype-specifier (C++11) |
17332 | identifier |
17333 | |
17334 | Returns a TYPE indicating the class to be initialized for the first |
17335 | production (and the second in C++11). Returns an IDENTIFIER_NODE |
17336 | indicating the data member to be initialized for the last production. */ |
17337 | |
17338 | static tree |
17339 | cp_parser_mem_initializer_id (cp_parser* parser) |
17340 | { |
17341 | bool global_scope_p; |
17342 | bool nested_name_specifier_p; |
17343 | bool template_p = false; |
17344 | tree id; |
17345 | |
17346 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
17347 | |
17348 | /* `typename' is not allowed in this context ([temp.res]). */ |
17349 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
17350 | { |
17351 | error_at (token->location, |
17352 | "keyword %<typename%> not allowed in this context (a qualified " |
17353 | "member initializer is implicitly a type)" ); |
17354 | cp_lexer_consume_token (lexer: parser->lexer); |
17355 | } |
17356 | /* Look for the optional `::' operator. */ |
17357 | global_scope_p |
17358 | = (cp_parser_global_scope_opt (parser, |
17359 | /*current_scope_valid_p=*/false) |
17360 | != NULL_TREE); |
17361 | /* Look for the optional nested-name-specifier. The simplest way to |
17362 | implement: |
17363 | |
17364 | [temp.res] |
17365 | |
17366 | The keyword `typename' is not permitted in a base-specifier or |
17367 | mem-initializer; in these contexts a qualified name that |
17368 | depends on a template-parameter is implicitly assumed to be a |
17369 | type name. |
17370 | |
17371 | is to assume that we have seen the `typename' keyword at this |
17372 | point. */ |
17373 | nested_name_specifier_p |
17374 | = (cp_parser_nested_name_specifier_opt (parser, |
17375 | /*typename_keyword_p=*/true, |
17376 | /*check_dependency_p=*/true, |
17377 | /*type_p=*/true, |
17378 | /*is_declaration=*/true) |
17379 | != NULL_TREE); |
17380 | if (nested_name_specifier_p) |
17381 | template_p = cp_parser_optional_template_keyword (parser); |
17382 | /* If there is a `::' operator or a nested-name-specifier, then we |
17383 | are definitely looking for a class-name. */ |
17384 | if (global_scope_p || nested_name_specifier_p) |
17385 | return cp_parser_class_name (parser, |
17386 | /*typename_keyword_p=*/true, |
17387 | /*template_keyword_p=*/template_p, |
17388 | typename_type, |
17389 | /*check_dependency_p=*/true, |
17390 | /*class_head_p=*/false, |
17391 | /*is_declaration=*/true); |
17392 | /* Otherwise, we could also be looking for an ordinary identifier. */ |
17393 | cp_parser_parse_tentatively (parser); |
17394 | if (cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
17395 | /* Try a decltype-specifier. */ |
17396 | id = cp_parser_decltype (parser); |
17397 | else |
17398 | /* Otherwise, try a class-name. */ |
17399 | id = cp_parser_class_name (parser, |
17400 | /*typename_keyword_p=*/true, |
17401 | /*template_keyword_p=*/false, |
17402 | none_type, |
17403 | /*check_dependency_p=*/true, |
17404 | /*class_head_p=*/false, |
17405 | /*is_declaration=*/true); |
17406 | /* If we found one, we're done. */ |
17407 | if (cp_parser_parse_definitely (parser)) |
17408 | return id; |
17409 | /* Otherwise, look for an ordinary identifier. */ |
17410 | return cp_parser_identifier (parser); |
17411 | } |
17412 | |
17413 | /* Overloading [gram.over] */ |
17414 | |
17415 | /* Parse an operator-function-id. |
17416 | |
17417 | operator-function-id: |
17418 | operator operator |
17419 | |
17420 | Returns an IDENTIFIER_NODE for the operator which is a |
17421 | human-readable spelling of the identifier, e.g., `operator +'. */ |
17422 | |
17423 | static cp_expr |
17424 | cp_parser_operator_function_id (cp_parser* parser) |
17425 | { |
17426 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
17427 | /* Look for the `operator' keyword. */ |
17428 | if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR)) |
17429 | return error_mark_node; |
17430 | /* And then the name of the operator itself. */ |
17431 | return cp_parser_operator (parser, start_loc); |
17432 | } |
17433 | |
17434 | /* Return an identifier node for a user-defined literal operator. |
17435 | The suffix identifier is chained to the operator name identifier. */ |
17436 | |
17437 | tree |
17438 | cp_literal_operator_id (const char* name) |
17439 | { |
17440 | tree identifier; |
17441 | char *buffer = XNEWVEC (char, strlen (UDLIT_OP_ANSI_PREFIX) |
17442 | + strlen (name) + 10); |
17443 | sprintf (s: buffer, UDLIT_OP_ANSI_FORMAT, name); |
17444 | identifier = get_identifier (buffer); |
17445 | XDELETEVEC (buffer); |
17446 | |
17447 | return identifier; |
17448 | } |
17449 | |
17450 | /* Parse an operator. |
17451 | |
17452 | operator: |
17453 | new delete new[] delete[] + - * / % ^ & | ~ ! = < > |
17454 | += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && |
17455 | || ++ -- , ->* -> () [] |
17456 | |
17457 | GNU Extensions: |
17458 | |
17459 | operator: |
17460 | <? >? <?= >?= |
17461 | |
17462 | Returns an IDENTIFIER_NODE for the operator which is a |
17463 | human-readable spelling of the identifier, e.g., `operator +'. */ |
17464 | |
17465 | static cp_expr |
17466 | cp_parser_operator (cp_parser* parser, location_t start_loc) |
17467 | { |
17468 | tree id = NULL_TREE; |
17469 | cp_token *token; |
17470 | bool utf8 = false; |
17471 | |
17472 | /* Peek at the next token. */ |
17473 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17474 | |
17475 | location_t end_loc = token->location; |
17476 | |
17477 | /* Figure out which operator we have. */ |
17478 | enum tree_code op = ERROR_MARK; |
17479 | bool assop = false; |
17480 | bool consumed = false; |
17481 | switch (token->type) |
17482 | { |
17483 | case CPP_KEYWORD: |
17484 | { |
17485 | /* The keyword should be either `new', `delete' or `co_await'. */ |
17486 | if (token->keyword == RID_NEW) |
17487 | op = NEW_EXPR; |
17488 | else if (token->keyword == RID_DELETE) |
17489 | op = DELETE_EXPR; |
17490 | else if (token->keyword == RID_CO_AWAIT) |
17491 | op = CO_AWAIT_EXPR; |
17492 | else |
17493 | break; |
17494 | |
17495 | /* Consume the `new', `delete' or co_await token. */ |
17496 | end_loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
17497 | |
17498 | /* Peek at the next token. */ |
17499 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17500 | /* If it's a `[' token then this is the array variant of the |
17501 | operator. */ |
17502 | if (token->type == CPP_OPEN_SQUARE |
17503 | && op != CO_AWAIT_EXPR) |
17504 | { |
17505 | /* Consume the `[' token. */ |
17506 | cp_lexer_consume_token (lexer: parser->lexer); |
17507 | /* Look for the `]' token. */ |
17508 | if (cp_token *close_token |
17509 | = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
17510 | end_loc = close_token->location; |
17511 | op = op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR; |
17512 | } |
17513 | consumed = true; |
17514 | break; |
17515 | } |
17516 | |
17517 | case CPP_PLUS: |
17518 | op = PLUS_EXPR; |
17519 | break; |
17520 | |
17521 | case CPP_MINUS: |
17522 | op = MINUS_EXPR; |
17523 | break; |
17524 | |
17525 | case CPP_MULT: |
17526 | op = MULT_EXPR; |
17527 | break; |
17528 | |
17529 | case CPP_DIV: |
17530 | op = TRUNC_DIV_EXPR; |
17531 | break; |
17532 | |
17533 | case CPP_MOD: |
17534 | op = TRUNC_MOD_EXPR; |
17535 | break; |
17536 | |
17537 | case CPP_XOR: |
17538 | op = BIT_XOR_EXPR; |
17539 | break; |
17540 | |
17541 | case CPP_AND: |
17542 | op = BIT_AND_EXPR; |
17543 | break; |
17544 | |
17545 | case CPP_OR: |
17546 | op = BIT_IOR_EXPR; |
17547 | break; |
17548 | |
17549 | case CPP_COMPL: |
17550 | op = BIT_NOT_EXPR; |
17551 | break; |
17552 | |
17553 | case CPP_NOT: |
17554 | op = TRUTH_NOT_EXPR; |
17555 | break; |
17556 | |
17557 | case CPP_EQ: |
17558 | assop = true; |
17559 | op = NOP_EXPR; |
17560 | break; |
17561 | |
17562 | case CPP_LESS: |
17563 | op = LT_EXPR; |
17564 | break; |
17565 | |
17566 | case CPP_GREATER: |
17567 | op = GT_EXPR; |
17568 | break; |
17569 | |
17570 | case CPP_PLUS_EQ: |
17571 | assop = true; |
17572 | op = PLUS_EXPR; |
17573 | break; |
17574 | |
17575 | case CPP_MINUS_EQ: |
17576 | assop = true; |
17577 | op = MINUS_EXPR; |
17578 | break; |
17579 | |
17580 | case CPP_MULT_EQ: |
17581 | assop = true; |
17582 | op = MULT_EXPR; |
17583 | break; |
17584 | |
17585 | case CPP_DIV_EQ: |
17586 | assop = true; |
17587 | op = TRUNC_DIV_EXPR; |
17588 | break; |
17589 | |
17590 | case CPP_MOD_EQ: |
17591 | assop = true; |
17592 | op = TRUNC_MOD_EXPR; |
17593 | break; |
17594 | |
17595 | case CPP_XOR_EQ: |
17596 | assop = true; |
17597 | op = BIT_XOR_EXPR; |
17598 | break; |
17599 | |
17600 | case CPP_AND_EQ: |
17601 | assop = true; |
17602 | op = BIT_AND_EXPR; |
17603 | break; |
17604 | |
17605 | case CPP_OR_EQ: |
17606 | assop = true; |
17607 | op = BIT_IOR_EXPR; |
17608 | break; |
17609 | |
17610 | case CPP_LSHIFT: |
17611 | op = LSHIFT_EXPR; |
17612 | break; |
17613 | |
17614 | case CPP_RSHIFT: |
17615 | op = RSHIFT_EXPR; |
17616 | break; |
17617 | |
17618 | case CPP_LSHIFT_EQ: |
17619 | assop = true; |
17620 | op = LSHIFT_EXPR; |
17621 | break; |
17622 | |
17623 | case CPP_RSHIFT_EQ: |
17624 | assop = true; |
17625 | op = RSHIFT_EXPR; |
17626 | break; |
17627 | |
17628 | case CPP_EQ_EQ: |
17629 | op = EQ_EXPR; |
17630 | break; |
17631 | |
17632 | case CPP_NOT_EQ: |
17633 | op = NE_EXPR; |
17634 | break; |
17635 | |
17636 | case CPP_LESS_EQ: |
17637 | op = LE_EXPR; |
17638 | break; |
17639 | |
17640 | case CPP_GREATER_EQ: |
17641 | op = GE_EXPR; |
17642 | break; |
17643 | |
17644 | case CPP_SPACESHIP: |
17645 | op = SPACESHIP_EXPR; |
17646 | break; |
17647 | |
17648 | case CPP_AND_AND: |
17649 | op = TRUTH_ANDIF_EXPR; |
17650 | break; |
17651 | |
17652 | case CPP_OR_OR: |
17653 | op = TRUTH_ORIF_EXPR; |
17654 | break; |
17655 | |
17656 | case CPP_PLUS_PLUS: |
17657 | op = POSTINCREMENT_EXPR; |
17658 | break; |
17659 | |
17660 | case CPP_MINUS_MINUS: |
17661 | op = PREDECREMENT_EXPR; |
17662 | break; |
17663 | |
17664 | case CPP_COMMA: |
17665 | op = COMPOUND_EXPR; |
17666 | break; |
17667 | |
17668 | case CPP_DEREF_STAR: |
17669 | op = MEMBER_REF; |
17670 | break; |
17671 | |
17672 | case CPP_DEREF: |
17673 | op = COMPONENT_REF; |
17674 | break; |
17675 | |
17676 | case CPP_QUERY: |
17677 | op = COND_EXPR; |
17678 | /* Consume the `?'. */ |
17679 | cp_lexer_consume_token (lexer: parser->lexer); |
17680 | /* Look for the matching `:'. */ |
17681 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
17682 | consumed = true; |
17683 | break; |
17684 | |
17685 | case CPP_OPEN_PAREN: |
17686 | { |
17687 | /* Consume the `('. */ |
17688 | matching_parens parens; |
17689 | parens.consume_open (parser); |
17690 | /* Look for the matching `)'. */ |
17691 | token = parens.require_close (parser); |
17692 | if (token) |
17693 | end_loc = token->location; |
17694 | op = CALL_EXPR; |
17695 | consumed = true; |
17696 | break; |
17697 | } |
17698 | |
17699 | case CPP_OPEN_SQUARE: |
17700 | /* Consume the `['. */ |
17701 | cp_lexer_consume_token (lexer: parser->lexer); |
17702 | /* Look for the matching `]'. */ |
17703 | token = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
17704 | if (token) |
17705 | end_loc = token->location; |
17706 | op = ARRAY_REF; |
17707 | consumed = true; |
17708 | break; |
17709 | |
17710 | case CPP_UTF8STRING: |
17711 | case CPP_UTF8STRING_USERDEF: |
17712 | utf8 = true; |
17713 | /* FALLTHRU */ |
17714 | case CPP_STRING: |
17715 | case CPP_WSTRING: |
17716 | case CPP_STRING16: |
17717 | case CPP_STRING32: |
17718 | case CPP_STRING_USERDEF: |
17719 | case CPP_WSTRING_USERDEF: |
17720 | case CPP_STRING16_USERDEF: |
17721 | case CPP_STRING32_USERDEF: |
17722 | { |
17723 | tree string_tree; |
17724 | int sz, len; |
17725 | |
17726 | if (cxx_dialect == cxx98) |
17727 | maybe_warn_cpp0x (str: CPP0X_USER_DEFINED_LITERALS); |
17728 | |
17729 | /* Consume the string. */ |
17730 | cp_expr str = cp_parser_userdef_string_literal (parser, |
17731 | /*lookup_udlit=*/false); |
17732 | if (str == error_mark_node) |
17733 | return error_mark_node; |
17734 | else if (TREE_CODE (str) == USERDEF_LITERAL) |
17735 | { |
17736 | string_tree = USERDEF_LITERAL_VALUE (str.get_value ()); |
17737 | id = USERDEF_LITERAL_SUFFIX_ID (str.get_value ()); |
17738 | end_loc = str.get_location (); |
17739 | } |
17740 | else |
17741 | { |
17742 | string_tree = str; |
17743 | /* Look for the suffix identifier. */ |
17744 | token = cp_lexer_peek_token (lexer: parser->lexer); |
17745 | if (token->type == CPP_NAME) |
17746 | { |
17747 | id = cp_parser_identifier (parser); |
17748 | end_loc = token->location; |
17749 | } |
17750 | else if (token->type == CPP_KEYWORD) |
17751 | { |
17752 | error ("unexpected keyword;" |
17753 | " remove space between quotes and suffix identifier" ); |
17754 | return error_mark_node; |
17755 | } |
17756 | else |
17757 | { |
17758 | error ("expected suffix identifier" ); |
17759 | return error_mark_node; |
17760 | } |
17761 | } |
17762 | sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT |
17763 | (TREE_TYPE (TREE_TYPE (string_tree)))); |
17764 | len = TREE_STRING_LENGTH (string_tree) / sz - 1; |
17765 | if (len != 0) |
17766 | { |
17767 | error ("expected empty string after %<operator%> keyword" ); |
17768 | return error_mark_node; |
17769 | } |
17770 | if (utf8 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string_tree))) |
17771 | != char_type_node) |
17772 | { |
17773 | error ("invalid encoding prefix in literal operator" ); |
17774 | return error_mark_node; |
17775 | } |
17776 | if (id != error_mark_node) |
17777 | { |
17778 | const char *name = IDENTIFIER_POINTER (id); |
17779 | id = cp_literal_operator_id (name); |
17780 | } |
17781 | /* Generate a location of the form: |
17782 | "" _suffix_identifier |
17783 | ^~~~~~~~~~~~~~~~~~~~~ |
17784 | with caret == start at the start token, finish at the end of the |
17785 | suffix identifier. */ |
17786 | location_t combined_loc |
17787 | = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
17788 | return cp_expr (id, combined_loc); |
17789 | } |
17790 | |
17791 | default: |
17792 | /* Anything else is an error. */ |
17793 | break; |
17794 | } |
17795 | |
17796 | /* If we have selected an identifier, we need to consume the |
17797 | operator token. */ |
17798 | if (op != ERROR_MARK) |
17799 | { |
17800 | id = ovl_op_identifier (isass: assop, code: op); |
17801 | if (!consumed) |
17802 | cp_lexer_consume_token (lexer: parser->lexer); |
17803 | } |
17804 | /* Otherwise, no valid operator name was present. */ |
17805 | else |
17806 | { |
17807 | cp_parser_error (parser, gmsgid: "expected operator" ); |
17808 | id = error_mark_node; |
17809 | } |
17810 | |
17811 | start_loc = make_location (caret: start_loc, start: start_loc, finish: get_finish (loc: end_loc)); |
17812 | return cp_expr (id, start_loc); |
17813 | } |
17814 | |
17815 | /* Parse a template-declaration. |
17816 | |
17817 | template-declaration: |
17818 | export [opt] template < template-parameter-list > declaration |
17819 | |
17820 | If MEMBER_P is TRUE, this template-declaration occurs within a |
17821 | class-specifier. |
17822 | |
17823 | The grammar rule given by the standard isn't correct. What |
17824 | is really meant is: |
17825 | |
17826 | template-declaration: |
17827 | export [opt] template-parameter-list-seq |
17828 | decl-specifier-seq [opt] init-declarator [opt] ; |
17829 | export [opt] template-parameter-list-seq |
17830 | function-definition |
17831 | |
17832 | template-parameter-list-seq: |
17833 | template-parameter-list-seq [opt] |
17834 | template < template-parameter-list > |
17835 | |
17836 | Concept Extensions: |
17837 | |
17838 | template-parameter-list-seq: |
17839 | template < template-parameter-list > requires-clause [opt] |
17840 | |
17841 | requires-clause: |
17842 | requires logical-or-expression */ |
17843 | |
17844 | static void |
17845 | cp_parser_template_declaration (cp_parser* parser, bool member_p) |
17846 | { |
17847 | /* Check for `export'. */ |
17848 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_EXPORT)) |
17849 | { |
17850 | /* Consume the `export' token. */ |
17851 | cp_lexer_consume_token (lexer: parser->lexer); |
17852 | /* Warn that this use of export is deprecated. */ |
17853 | if (cxx_dialect < cxx11) |
17854 | warning (0, "keyword %<export%> not implemented, and will be ignored" ); |
17855 | else if (cxx_dialect < cxx20) |
17856 | warning (0, "keyword %<export%> is deprecated, and is ignored" ); |
17857 | else |
17858 | warning (0, "keyword %<export%> is enabled with %<-fmodules-ts%>" ); |
17859 | } |
17860 | |
17861 | cp_parser_template_declaration_after_export (parser, member_p); |
17862 | } |
17863 | |
17864 | /* Parse a template-parameter-list. |
17865 | |
17866 | template-parameter-list: |
17867 | template-parameter |
17868 | template-parameter-list , template-parameter |
17869 | |
17870 | Returns a TREE_LIST. Each node represents a template parameter. |
17871 | The nodes are connected via their TREE_CHAINs. */ |
17872 | |
17873 | static tree |
17874 | cp_parser_template_parameter_list (cp_parser* parser) |
17875 | { |
17876 | tree parameter_list = NULL_TREE; |
17877 | |
17878 | /* Don't create wrapper nodes within a template-parameter-list, |
17879 | since we don't want to have different types based on the |
17880 | spelling location of constants and decls within them. */ |
17881 | auto_suppress_location_wrappers sentinel; |
17882 | |
17883 | begin_template_parm_list (); |
17884 | |
17885 | /* The loop below parses the template parms. We first need to know |
17886 | the total number of template parms to be able to compute proper |
17887 | canonical types of each dependent type. So after the loop, when |
17888 | we know the total number of template parms, |
17889 | end_template_parm_list computes the proper canonical types and |
17890 | fixes up the dependent types accordingly. */ |
17891 | while (true) |
17892 | { |
17893 | tree parameter; |
17894 | bool is_non_type; |
17895 | bool is_parameter_pack; |
17896 | location_t parm_loc; |
17897 | |
17898 | /* Parse the template-parameter. */ |
17899 | parm_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
17900 | parameter = cp_parser_template_parameter (parser, |
17901 | &is_non_type, |
17902 | &is_parameter_pack); |
17903 | /* Add it to the list. */ |
17904 | if (parameter != error_mark_node) |
17905 | parameter_list = process_template_parm (parameter_list, |
17906 | parm_loc, |
17907 | parameter, |
17908 | is_non_type, |
17909 | is_parameter_pack); |
17910 | else |
17911 | { |
17912 | tree err_parm = build_tree_list (parameter, parameter); |
17913 | parameter_list = chainon (parameter_list, err_parm); |
17914 | } |
17915 | |
17916 | /* If the next token is not a `,', we're done. */ |
17917 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
17918 | break; |
17919 | /* Otherwise, consume the `,' token. */ |
17920 | cp_lexer_consume_token (lexer: parser->lexer); |
17921 | } |
17922 | |
17923 | return end_template_parm_list (parameter_list); |
17924 | } |
17925 | |
17926 | /* Parse a introduction-list. |
17927 | |
17928 | introduction-list: |
17929 | introduced-parameter |
17930 | introduction-list , introduced-parameter |
17931 | |
17932 | introduced-parameter: |
17933 | ...[opt] identifier |
17934 | |
17935 | Returns a TREE_VEC of WILDCARD_DECLs. If the parameter is a pack |
17936 | then the introduced parm will have WILDCARD_PACK_P set. In addition, the |
17937 | WILDCARD_DECL will also have DECL_NAME set and token location in |
17938 | DECL_SOURCE_LOCATION. */ |
17939 | |
17940 | static tree |
17941 | cp_parser_introduction_list (cp_parser *parser) |
17942 | { |
17943 | vec<tree, va_gc> *introduction_vec = make_tree_vector (); |
17944 | |
17945 | while (true) |
17946 | { |
17947 | bool is_pack = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS); |
17948 | if (is_pack) |
17949 | cp_lexer_consume_token (lexer: parser->lexer); |
17950 | |
17951 | tree identifier = cp_parser_identifier (parser); |
17952 | if (identifier == error_mark_node) |
17953 | break; |
17954 | |
17955 | /* Build placeholder. */ |
17956 | tree parm = build_nt (WILDCARD_DECL); |
17957 | DECL_SOURCE_LOCATION (parm) |
17958 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
17959 | DECL_NAME (parm) = identifier; |
17960 | WILDCARD_PACK_P (parm) = is_pack; |
17961 | vec_safe_push (v&: introduction_vec, obj: parm); |
17962 | |
17963 | /* If the next token is not a `,', we're done. */ |
17964 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
17965 | break; |
17966 | /* Otherwise, consume the `,' token. */ |
17967 | cp_lexer_consume_token (lexer: parser->lexer); |
17968 | } |
17969 | |
17970 | /* Convert the vec into a TREE_VEC. */ |
17971 | tree introduction_list = make_tree_vec (introduction_vec->length ()); |
17972 | unsigned int n; |
17973 | tree parm; |
17974 | FOR_EACH_VEC_ELT (*introduction_vec, n, parm) |
17975 | TREE_VEC_ELT (introduction_list, n) = parm; |
17976 | |
17977 | release_tree_vector (introduction_vec); |
17978 | return introduction_list; |
17979 | } |
17980 | |
17981 | /* Given a declarator, get the declarator-id part, or NULL_TREE if this |
17982 | is an abstract declarator. */ |
17983 | |
17984 | static inline cp_declarator* |
17985 | get_id_declarator (cp_declarator *declarator) |
17986 | { |
17987 | cp_declarator *d = declarator; |
17988 | while (d && d->kind != cdk_id) |
17989 | d = d->declarator; |
17990 | return d; |
17991 | } |
17992 | |
17993 | /* Get the unqualified-id from the DECLARATOR or NULL_TREE if this |
17994 | is an abstract declarator. */ |
17995 | |
17996 | static inline tree |
17997 | get_unqualified_id (cp_declarator *declarator) |
17998 | { |
17999 | declarator = get_id_declarator (declarator); |
18000 | if (declarator) |
18001 | return declarator->u.id.unqualified_name; |
18002 | else |
18003 | return NULL_TREE; |
18004 | } |
18005 | |
18006 | /* Returns true if TYPE would declare a constrained constrained-parameter. */ |
18007 | |
18008 | static inline bool |
18009 | is_constrained_parameter (tree type) |
18010 | { |
18011 | return (type |
18012 | && TREE_CODE (type) == TYPE_DECL |
18013 | && CONSTRAINED_PARM_CONCEPT (type) |
18014 | && DECL_P (CONSTRAINED_PARM_CONCEPT (type))); |
18015 | } |
18016 | |
18017 | /* Returns true if PARM declares a constrained-parameter. */ |
18018 | |
18019 | static inline bool |
18020 | is_constrained_parameter (cp_parameter_declarator *parm) |
18021 | { |
18022 | return is_constrained_parameter (type: parm->decl_specifiers.type); |
18023 | } |
18024 | |
18025 | /* Check that the type parameter is only a declarator-id, and that its |
18026 | type is not cv-qualified. */ |
18027 | |
18028 | bool |
18029 | cp_parser_check_constrained_type_parm (cp_parser *parser, |
18030 | cp_parameter_declarator *parm) |
18031 | { |
18032 | if (!parm->declarator) |
18033 | return true; |
18034 | |
18035 | if (parm->declarator->kind != cdk_id) |
18036 | { |
18037 | cp_parser_error (parser, gmsgid: "invalid constrained type parameter" ); |
18038 | return false; |
18039 | } |
18040 | |
18041 | /* Don't allow cv-qualified type parameters. */ |
18042 | if (decl_spec_seq_has_spec_p (&parm->decl_specifiers, ds_const) |
18043 | || decl_spec_seq_has_spec_p (&parm->decl_specifiers, ds_volatile)) |
18044 | { |
18045 | cp_parser_error (parser, gmsgid: "cv-qualified type parameter" ); |
18046 | return false; |
18047 | } |
18048 | |
18049 | return true; |
18050 | } |
18051 | |
18052 | /* Finish parsing/processing a template type parameter and checking |
18053 | various restrictions. */ |
18054 | |
18055 | static inline tree |
18056 | cp_parser_constrained_type_template_parm (cp_parser *parser, |
18057 | tree id, |
18058 | cp_parameter_declarator* parmdecl) |
18059 | { |
18060 | if (cp_parser_check_constrained_type_parm (parser, parm: parmdecl)) |
18061 | return finish_template_type_parm (class_type_node, id); |
18062 | else |
18063 | return error_mark_node; |
18064 | } |
18065 | |
18066 | static tree |
18067 | finish_constrained_template_template_parm (tree proto, tree id) |
18068 | { |
18069 | /* FIXME: This should probably be copied, and we may need to adjust |
18070 | the template parameter depths. */ |
18071 | tree saved_parms = current_template_parms; |
18072 | begin_template_parm_list (); |
18073 | current_template_parms = DECL_TEMPLATE_PARMS (proto); |
18074 | end_template_parm_list (); |
18075 | |
18076 | tree parm = finish_template_template_parm (class_type_node, id); |
18077 | current_template_parms = saved_parms; |
18078 | |
18079 | return parm; |
18080 | } |
18081 | |
18082 | /* Finish parsing/processing a template template parameter by borrowing |
18083 | the template parameter list from the prototype parameter. */ |
18084 | |
18085 | static tree |
18086 | cp_parser_constrained_template_template_parm (cp_parser *parser, |
18087 | tree proto, |
18088 | tree id, |
18089 | cp_parameter_declarator *parmdecl) |
18090 | { |
18091 | if (!cp_parser_check_constrained_type_parm (parser, parm: parmdecl)) |
18092 | return error_mark_node; |
18093 | return finish_constrained_template_template_parm (proto, id); |
18094 | } |
18095 | |
18096 | /* Create a new non-type template parameter from the given PARM |
18097 | declarator. */ |
18098 | |
18099 | static tree |
18100 | cp_parser_constrained_non_type_template_parm (bool *is_non_type, |
18101 | cp_parameter_declarator *parm) |
18102 | { |
18103 | *is_non_type = true; |
18104 | cp_declarator *decl = parm->declarator; |
18105 | cp_decl_specifier_seq *specs = &parm->decl_specifiers; |
18106 | specs->type = TREE_TYPE (DECL_INITIAL (specs->type)); |
18107 | return grokdeclarator (decl, specs, TPARM, 0, NULL); |
18108 | } |
18109 | |
18110 | /* Build a constrained template parameter based on the PARMDECL |
18111 | declarator. The type of PARMDECL is the constrained type, which |
18112 | refers to the prototype template parameter that ultimately |
18113 | specifies the type of the declared parameter. */ |
18114 | |
18115 | static tree |
18116 | finish_constrained_parameter (cp_parser *parser, |
18117 | cp_parameter_declarator *parmdecl, |
18118 | bool *is_non_type) |
18119 | { |
18120 | tree decl = parmdecl->decl_specifiers.type; |
18121 | tree id = get_unqualified_id (declarator: parmdecl->declarator); |
18122 | tree def = parmdecl->default_argument; |
18123 | tree proto = DECL_INITIAL (decl); |
18124 | |
18125 | /* Build the parameter. Return an error if the declarator was invalid. */ |
18126 | tree parm; |
18127 | if (TREE_CODE (proto) == TYPE_DECL) |
18128 | parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl); |
18129 | else if (TREE_CODE (proto) == TEMPLATE_DECL) |
18130 | parm = cp_parser_constrained_template_template_parm (parser, proto, id, |
18131 | parmdecl); |
18132 | else |
18133 | parm = cp_parser_constrained_non_type_template_parm (is_non_type, parm: parmdecl); |
18134 | if (parm == error_mark_node) |
18135 | return error_mark_node; |
18136 | |
18137 | /* Finish the parameter decl and create a node attaching the |
18138 | default argument and constraint. */ |
18139 | parm = build_tree_list (def, parm); |
18140 | TEMPLATE_PARM_CONSTRAINTS (parm) = decl; |
18141 | |
18142 | return parm; |
18143 | } |
18144 | |
18145 | /* Returns true if the parsed type actually represents the declaration |
18146 | of a type template-parameter. */ |
18147 | |
18148 | static bool |
18149 | declares_constrained_type_template_parameter (tree type) |
18150 | { |
18151 | return (is_constrained_parameter (type) |
18152 | && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TYPE_PARM); |
18153 | } |
18154 | |
18155 | /* Returns true if the parsed type actually represents the declaration of |
18156 | a template template-parameter. */ |
18157 | |
18158 | static bool |
18159 | declares_constrained_template_template_parameter (tree type) |
18160 | { |
18161 | return (is_constrained_parameter (type) |
18162 | && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TEMPLATE_PARM); |
18163 | } |
18164 | |
18165 | /* Parse a default argument for a type template-parameter. |
18166 | Note that diagnostics are handled in cp_parser_template_parameter. */ |
18167 | |
18168 | static tree |
18169 | cp_parser_default_type_template_argument (cp_parser *parser) |
18170 | { |
18171 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ)); |
18172 | |
18173 | /* Consume the `=' token. */ |
18174 | cp_lexer_consume_token (lexer: parser->lexer); |
18175 | |
18176 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
18177 | |
18178 | /* Tell cp_parser_lambda_expression this is a default argument. */ |
18179 | auto lvf = make_temp_override (var&: parser->local_variables_forbidden_p); |
18180 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
18181 | |
18182 | /* Parse the default-argument. */ |
18183 | push_deferring_access_checks (dk_no_deferred); |
18184 | tree default_argument = cp_parser_type_id (parser, |
18185 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
18186 | NULL); |
18187 | pop_deferring_access_checks (); |
18188 | |
18189 | if (flag_concepts && type_uses_auto (default_argument)) |
18190 | { |
18191 | error_at (token->location, |
18192 | "invalid use of %<auto%> in default template argument" ); |
18193 | return error_mark_node; |
18194 | } |
18195 | |
18196 | return default_argument; |
18197 | } |
18198 | |
18199 | /* Parse a default argument for a template template-parameter. */ |
18200 | |
18201 | static tree |
18202 | cp_parser_default_template_template_argument (cp_parser *parser) |
18203 | { |
18204 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ)); |
18205 | |
18206 | bool is_template; |
18207 | |
18208 | /* Consume the `='. */ |
18209 | cp_lexer_consume_token (lexer: parser->lexer); |
18210 | /* Parse the id-expression. */ |
18211 | push_deferring_access_checks (dk_no_deferred); |
18212 | /* save token before parsing the id-expression, for error |
18213 | reporting */ |
18214 | const cp_token* token = cp_lexer_peek_token (lexer: parser->lexer); |
18215 | tree default_argument |
18216 | = cp_parser_id_expression (parser, |
18217 | /*template_keyword_p=*/false, |
18218 | /*check_dependency_p=*/true, |
18219 | /*template_p=*/&is_template, |
18220 | /*declarator_p=*/false, |
18221 | /*optional_p=*/false); |
18222 | if (TREE_CODE (default_argument) == TYPE_DECL) |
18223 | /* If the id-expression was a template-id that refers to |
18224 | a template-class, we already have the declaration here, |
18225 | so no further lookup is needed. */ |
18226 | ; |
18227 | else |
18228 | /* Look up the name. */ |
18229 | default_argument |
18230 | = cp_parser_lookup_name (parser, default_argument, |
18231 | none_type, |
18232 | /*is_template=*/is_template, |
18233 | /*is_namespace=*/false, |
18234 | /*check_dependency=*/true, |
18235 | /*ambiguous_decls=*/NULL, |
18236 | token->location); |
18237 | /* See if the default argument is valid. */ |
18238 | default_argument = check_template_template_default_arg (default_argument); |
18239 | pop_deferring_access_checks (); |
18240 | return default_argument; |
18241 | } |
18242 | |
18243 | /* Parse a template-parameter. |
18244 | |
18245 | template-parameter: |
18246 | type-parameter |
18247 | parameter-declaration |
18248 | |
18249 | If all goes well, returns a TREE_LIST. The TREE_VALUE represents |
18250 | the parameter. The TREE_PURPOSE is the default value, if any. |
18251 | Returns ERROR_MARK_NODE on failure. *IS_NON_TYPE is set to true |
18252 | iff this parameter is a non-type parameter. *IS_PARAMETER_PACK is |
18253 | set to true iff this parameter is a parameter pack. */ |
18254 | |
18255 | static tree |
18256 | cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, |
18257 | bool *is_parameter_pack) |
18258 | { |
18259 | cp_token *token; |
18260 | cp_parameter_declarator *parameter_declarator; |
18261 | tree parm; |
18262 | |
18263 | /* Assume it is a type parameter or a template parameter. */ |
18264 | *is_non_type = false; |
18265 | /* Assume it not a parameter pack. */ |
18266 | *is_parameter_pack = false; |
18267 | /* Peek at the next token. */ |
18268 | token = cp_lexer_peek_token (lexer: parser->lexer); |
18269 | /* If it is `template', we have a type-parameter. */ |
18270 | if (token->keyword == RID_TEMPLATE) |
18271 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18272 | /* If it is `class' or `typename' we do not know yet whether it is a |
18273 | type parameter or a non-type parameter. Consider: |
18274 | |
18275 | template <typename T, typename T::X X> ... |
18276 | |
18277 | or: |
18278 | |
18279 | template <class C, class D*> ... |
18280 | |
18281 | Here, the first parameter is a type parameter, and the second is |
18282 | a non-type parameter. We can tell by looking at the token after |
18283 | the identifier -- if it is a `,', `=', or `>' then we have a type |
18284 | parameter. */ |
18285 | if (token->keyword == RID_TYPENAME || token->keyword == RID_CLASS) |
18286 | { |
18287 | /* Peek at the token after `class' or `typename'. */ |
18288 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
18289 | /* If it's an ellipsis, we have a template type parameter |
18290 | pack. */ |
18291 | if (token->type == CPP_ELLIPSIS) |
18292 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18293 | /* If it's an identifier, skip it. */ |
18294 | if (token->type == CPP_NAME) |
18295 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3); |
18296 | /* Now, see if the token looks like the end of a template |
18297 | parameter. */ |
18298 | if (token->type == CPP_COMMA |
18299 | || token->type == CPP_EQ |
18300 | || token->type == CPP_GREATER) |
18301 | return cp_parser_type_parameter (parser, is_parameter_pack); |
18302 | } |
18303 | |
18304 | /* Otherwise, it is a non-type parameter or a constrained parameter. |
18305 | |
18306 | [temp.param] |
18307 | |
18308 | When parsing a default template-argument for a non-type |
18309 | template-parameter, the first non-nested `>' is taken as the end |
18310 | of the template parameter-list rather than a greater-than |
18311 | operator. */ |
18312 | parameter_declarator |
18313 | = cp_parser_parameter_declaration (parser, |
18314 | CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
18315 | /*template_parm_p=*/true, |
18316 | /*parenthesized_p=*/NULL); |
18317 | |
18318 | if (!parameter_declarator) |
18319 | return error_mark_node; |
18320 | |
18321 | /* If the parameter declaration is marked as a parameter pack, set |
18322 | *IS_PARAMETER_PACK to notify the caller. */ |
18323 | if (parameter_declarator->template_parameter_pack_p) |
18324 | *is_parameter_pack = true; |
18325 | |
18326 | if (parameter_declarator->default_argument) |
18327 | { |
18328 | /* Can happen in some cases of erroneous input (c++/34892). */ |
18329 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18330 | /* Consume the `...' for better error recovery. */ |
18331 | cp_lexer_consume_token (lexer: parser->lexer); |
18332 | } |
18333 | |
18334 | /* The parameter may have been constrained type parameter. */ |
18335 | if (is_constrained_parameter (parm: parameter_declarator)) |
18336 | return finish_constrained_parameter (parser, |
18337 | parmdecl: parameter_declarator, |
18338 | is_non_type); |
18339 | |
18340 | // Now we're sure that the parameter is a non-type parameter. |
18341 | *is_non_type = true; |
18342 | |
18343 | parm = grokdeclarator (parameter_declarator->declarator, |
18344 | ¶meter_declarator->decl_specifiers, |
18345 | TPARM, /*initialized=*/0, |
18346 | /*attrlist=*/NULL); |
18347 | if (parm == error_mark_node) |
18348 | return error_mark_node; |
18349 | |
18350 | return build_tree_list (parameter_declarator->default_argument, parm); |
18351 | } |
18352 | |
18353 | /* Parse a type-parameter. |
18354 | |
18355 | type-parameter: |
18356 | class identifier [opt] |
18357 | class identifier [opt] = type-id |
18358 | typename identifier [opt] |
18359 | typename identifier [opt] = type-id |
18360 | template < template-parameter-list > class identifier [opt] |
18361 | template < template-parameter-list > class identifier [opt] |
18362 | = id-expression |
18363 | |
18364 | GNU Extension (variadic templates): |
18365 | |
18366 | type-parameter: |
18367 | class ... identifier [opt] |
18368 | typename ... identifier [opt] |
18369 | |
18370 | Returns a TREE_LIST. The TREE_VALUE is itself a TREE_LIST. The |
18371 | TREE_PURPOSE is the default-argument, if any. The TREE_VALUE is |
18372 | the declaration of the parameter. |
18373 | |
18374 | Sets *IS_PARAMETER_PACK if this is a template parameter pack. */ |
18375 | |
18376 | static tree |
18377 | cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) |
18378 | { |
18379 | cp_token *token; |
18380 | tree parameter; |
18381 | |
18382 | /* Look for a keyword to tell us what kind of parameter this is. */ |
18383 | token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_TYPENAME_TEMPLATE); |
18384 | if (!token) |
18385 | return error_mark_node; |
18386 | |
18387 | switch (token->keyword) |
18388 | { |
18389 | case RID_CLASS: |
18390 | case RID_TYPENAME: |
18391 | { |
18392 | tree identifier; |
18393 | tree default_argument; |
18394 | |
18395 | /* If the next token is an ellipsis, we have a template |
18396 | argument pack. */ |
18397 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18398 | { |
18399 | /* Consume the `...' token. */ |
18400 | cp_lexer_consume_token (lexer: parser->lexer); |
18401 | maybe_warn_variadic_templates (); |
18402 | |
18403 | *is_parameter_pack = true; |
18404 | } |
18405 | |
18406 | /* If the next token is an identifier, then it names the |
18407 | parameter. */ |
18408 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
18409 | identifier = cp_parser_identifier (parser); |
18410 | else |
18411 | identifier = NULL_TREE; |
18412 | |
18413 | /* Create the parameter. */ |
18414 | parameter = finish_template_type_parm (class_type_node, identifier); |
18415 | |
18416 | /* If the next token is an `=', we have a default argument. */ |
18417 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
18418 | { |
18419 | default_argument |
18420 | = cp_parser_default_type_template_argument (parser); |
18421 | |
18422 | /* Template parameter packs cannot have default |
18423 | arguments. */ |
18424 | if (*is_parameter_pack) |
18425 | { |
18426 | if (identifier) |
18427 | error_at (token->location, |
18428 | "template parameter pack %qD cannot have a " |
18429 | "default argument" , identifier); |
18430 | else |
18431 | error_at (token->location, |
18432 | "template parameter packs cannot have " |
18433 | "default arguments" ); |
18434 | default_argument = NULL_TREE; |
18435 | } |
18436 | else if (check_for_bare_parameter_packs (default_argument)) |
18437 | default_argument = error_mark_node; |
18438 | } |
18439 | else |
18440 | default_argument = NULL_TREE; |
18441 | |
18442 | /* Create the combined representation of the parameter and the |
18443 | default argument. */ |
18444 | parameter = build_tree_list (default_argument, parameter); |
18445 | } |
18446 | break; |
18447 | |
18448 | case RID_TEMPLATE: |
18449 | { |
18450 | tree identifier; |
18451 | tree default_argument; |
18452 | |
18453 | /* Look for the `<'. */ |
18454 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
18455 | /* Parse the template-parameter-list. */ |
18456 | cp_parser_template_parameter_list (parser); |
18457 | /* Look for the `>'. */ |
18458 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
18459 | |
18460 | /* If template requirements are present, parse them. */ |
18461 | if (flag_concepts) |
18462 | { |
18463 | tree reqs = get_shorthand_constraints (current_template_parms); |
18464 | if (tree dreqs = cp_parser_requires_clause_opt (parser, false)) |
18465 | reqs = combine_constraint_expressions (reqs, dreqs); |
18466 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
18467 | } |
18468 | |
18469 | /* Look for the `class' or 'typename' keywords. */ |
18470 | cp_parser_type_parameter_key (parser); |
18471 | /* If the next token is an ellipsis, we have a template |
18472 | argument pack. */ |
18473 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
18474 | { |
18475 | /* Consume the `...' token. */ |
18476 | cp_lexer_consume_token (lexer: parser->lexer); |
18477 | maybe_warn_variadic_templates (); |
18478 | |
18479 | *is_parameter_pack = true; |
18480 | } |
18481 | /* If the next token is an `=', then there is a |
18482 | default-argument. If the next token is a `>', we are at |
18483 | the end of the parameter-list. If the next token is a `,', |
18484 | then we are at the end of this parameter. */ |
18485 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
18486 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_GREATER) |
18487 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
18488 | { |
18489 | identifier = cp_parser_identifier (parser); |
18490 | /* Treat invalid names as if the parameter were nameless. */ |
18491 | if (identifier == error_mark_node) |
18492 | identifier = NULL_TREE; |
18493 | } |
18494 | else |
18495 | identifier = NULL_TREE; |
18496 | |
18497 | /* Create the template parameter. */ |
18498 | parameter = finish_template_template_parm (class_type_node, |
18499 | identifier); |
18500 | |
18501 | /* If the next token is an `=', then there is a |
18502 | default-argument. */ |
18503 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
18504 | { |
18505 | default_argument |
18506 | = cp_parser_default_template_template_argument (parser); |
18507 | |
18508 | /* Template parameter packs cannot have default |
18509 | arguments. */ |
18510 | if (*is_parameter_pack) |
18511 | { |
18512 | if (identifier) |
18513 | error_at (token->location, |
18514 | "template parameter pack %qD cannot " |
18515 | "have a default argument" , |
18516 | identifier); |
18517 | else |
18518 | error_at (token->location, "template parameter packs cannot " |
18519 | "have default arguments" ); |
18520 | default_argument = NULL_TREE; |
18521 | } |
18522 | } |
18523 | else |
18524 | default_argument = NULL_TREE; |
18525 | |
18526 | /* Create the combined representation of the parameter and the |
18527 | default argument. */ |
18528 | parameter = build_tree_list (default_argument, parameter); |
18529 | } |
18530 | break; |
18531 | |
18532 | default: |
18533 | gcc_unreachable (); |
18534 | break; |
18535 | } |
18536 | |
18537 | return parameter; |
18538 | } |
18539 | |
18540 | /* Parse a template-id. |
18541 | |
18542 | template-id: |
18543 | template-name < template-argument-list [opt] > |
18544 | |
18545 | If TEMPLATE_KEYWORD_P is TRUE, then we have just seen the |
18546 | `template' keyword. In this case, a TEMPLATE_ID_EXPR will be |
18547 | returned. Otherwise, if the template-name names a function, or set |
18548 | of functions, returns a TEMPLATE_ID_EXPR. If the template-name |
18549 | names a class, returns a TYPE_DECL for the specialization. |
18550 | |
18551 | If CHECK_DEPENDENCY_P is FALSE, names are looked up in |
18552 | uninstantiated templates. */ |
18553 | |
18554 | static tree |
18555 | cp_parser_template_id (cp_parser *parser, |
18556 | bool template_keyword_p, |
18557 | bool check_dependency_p, |
18558 | enum tag_types tag_type, |
18559 | bool is_declaration) |
18560 | { |
18561 | tree templ; |
18562 | tree arguments; |
18563 | tree template_id; |
18564 | cp_token_position start_of_id = 0; |
18565 | cp_token *next_token = NULL, *next_token_2 = NULL; |
18566 | bool is_identifier; |
18567 | |
18568 | /* If the next token corresponds to a template-id, there is no need |
18569 | to reparse it. */ |
18570 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
18571 | |
18572 | if (token->type == CPP_TEMPLATE_ID) |
18573 | { |
18574 | cp_lexer_consume_token (lexer: parser->lexer); |
18575 | return saved_checks_value (check_value: token->u.tree_check_value); |
18576 | } |
18577 | |
18578 | /* Avoid performing name lookup if there is no possibility of |
18579 | finding a template-id. */ |
18580 | if ((token->type != CPP_NAME && token->keyword != RID_OPERATOR) |
18581 | || (token->type == CPP_NAME |
18582 | && !cp_parser_nth_token_starts_template_argument_list_p |
18583 | (parser, 2))) |
18584 | { |
18585 | cp_parser_error (parser, gmsgid: "expected template-id" ); |
18586 | return error_mark_node; |
18587 | } |
18588 | |
18589 | /* Remember where the template-id starts. */ |
18590 | if (cp_parser_uncommitted_to_tentative_parse_p (parser)) |
18591 | start_of_id = cp_lexer_token_position (lexer: parser->lexer, previous_p: false); |
18592 | |
18593 | push_deferring_access_checks (dk_deferred); |
18594 | |
18595 | /* Parse the template-name. */ |
18596 | is_identifier = false; |
18597 | templ = cp_parser_template_name (parser, template_keyword_p, |
18598 | check_dependency_p, |
18599 | is_declaration, |
18600 | tag_type, |
18601 | &is_identifier); |
18602 | |
18603 | /* Push any access checks inside the firewall we're about to create. */ |
18604 | vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks (); |
18605 | pop_deferring_access_checks (); |
18606 | if (templ == error_mark_node || is_identifier) |
18607 | return templ; |
18608 | |
18609 | /* Since we're going to preserve any side-effects from this parse, set up a |
18610 | firewall to protect our callers from cp_parser_commit_to_tentative_parse |
18611 | in the template arguments. */ |
18612 | tentative_firewall firewall (parser); |
18613 | reopen_deferring_access_checks (checks); |
18614 | |
18615 | /* If we find the sequence `[:' after a template-name, it's probably |
18616 | a digraph-typo for `< ::'. Substitute the tokens and check if we can |
18617 | parse correctly the argument list. */ |
18618 | if (((next_token = cp_lexer_peek_token (lexer: parser->lexer))->type |
18619 | == CPP_OPEN_SQUARE) |
18620 | && next_token->flags & DIGRAPH |
18621 | && ((next_token_2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))->type |
18622 | == CPP_COLON) |
18623 | && !(next_token_2->flags & PREV_WHITE)) |
18624 | { |
18625 | cp_parser_parse_tentatively (parser); |
18626 | /* Change `:' into `::'. */ |
18627 | next_token_2->type = CPP_SCOPE; |
18628 | /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is |
18629 | CPP_LESS. */ |
18630 | cp_lexer_consume_token (lexer: parser->lexer); |
18631 | |
18632 | /* Parse the arguments. */ |
18633 | arguments = cp_parser_enclosed_template_argument_list (parser); |
18634 | if (!cp_parser_parse_definitely (parser)) |
18635 | { |
18636 | /* If we couldn't parse an argument list, then we revert our changes |
18637 | and return simply an error. Maybe this is not a template-id |
18638 | after all. */ |
18639 | next_token_2->type = CPP_COLON; |
18640 | cp_parser_error (parser, gmsgid: "expected %<<%>" ); |
18641 | pop_deferring_access_checks (); |
18642 | return error_mark_node; |
18643 | } |
18644 | /* Otherwise, emit an error about the invalid digraph, but continue |
18645 | parsing because we got our argument list. */ |
18646 | if (permerror (next_token->location, |
18647 | "%<<::%> cannot begin a template-argument list" )) |
18648 | { |
18649 | static bool hint = false; |
18650 | inform (next_token->location, |
18651 | "%<<:%> is an alternate spelling for %<[%>." |
18652 | " Insert whitespace between %<<%> and %<::%>" ); |
18653 | if (!hint && !flag_permissive) |
18654 | { |
18655 | inform (next_token->location, "(if you use %<-fpermissive%> " |
18656 | "or %<-std=c++11%>, or %<-std=gnu++11%> G++ will " |
18657 | "accept your code)" ); |
18658 | hint = true; |
18659 | } |
18660 | } |
18661 | } |
18662 | else |
18663 | { |
18664 | /* Look for the `<' that starts the template-argument-list. */ |
18665 | if (!cp_parser_require (parser, CPP_LESS, RT_LESS)) |
18666 | { |
18667 | pop_deferring_access_checks (); |
18668 | return error_mark_node; |
18669 | } |
18670 | /* Parse the arguments. */ |
18671 | arguments = cp_parser_enclosed_template_argument_list (parser); |
18672 | |
18673 | if ((cxx_dialect > cxx17) |
18674 | && (TREE_CODE (templ) == FUNCTION_DECL || identifier_p (t: templ)) |
18675 | && !template_keyword_p |
18676 | && (cp_parser_error_occurred (parser) |
18677 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN))) |
18678 | { |
18679 | /* This didn't go well. */ |
18680 | if (TREE_CODE (templ) == FUNCTION_DECL) |
18681 | { |
18682 | /* C++20 says that "function-name < a;" is now ill-formed. */ |
18683 | if (cp_parser_error_occurred (parser)) |
18684 | { |
18685 | error_at (token->location, "invalid template-argument-list" ); |
18686 | inform (token->location, "function name as the left hand " |
18687 | "operand of %<<%> is ill-formed in C++20; wrap the " |
18688 | "function name in %<()%>" ); |
18689 | } |
18690 | else |
18691 | /* We expect "f<targs>" to be followed by "(args)". */ |
18692 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
18693 | "expected %<(%> after template-argument-list" ); |
18694 | if (start_of_id) |
18695 | /* Purge all subsequent tokens. */ |
18696 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_of_id); |
18697 | } |
18698 | else |
18699 | cp_parser_simulate_error (parser); |
18700 | pop_deferring_access_checks (); |
18701 | return error_mark_node; |
18702 | } |
18703 | } |
18704 | |
18705 | /* Set the location to be of the form: |
18706 | template-name < template-argument-list [opt] > |
18707 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
18708 | with caret == start at the start of the template-name, |
18709 | ranging until the closing '>'. */ |
18710 | location_t combined_loc |
18711 | = make_location (caret: token->location, start: token->location, lexer: parser->lexer); |
18712 | |
18713 | /* Check for concepts autos where they don't belong. We could |
18714 | identify types in some cases of identifier TEMPL, looking ahead |
18715 | for a CPP_SCOPE, but that would buy us nothing: we accept auto in |
18716 | types. We reject them in functions, but if what we have is an |
18717 | identifier, even with none_type we can't conclude it's NOT a |
18718 | type, we have to wait for template substitution. */ |
18719 | if (flag_concepts && check_auto_in_tmpl_args (templ, arguments)) |
18720 | template_id = error_mark_node; |
18721 | /* Build a representation of the specialization. */ |
18722 | else if (identifier_p (t: templ)) |
18723 | template_id = build_min_nt_loc (combined_loc, |
18724 | TEMPLATE_ID_EXPR, |
18725 | templ, arguments); |
18726 | else if (DECL_TYPE_TEMPLATE_P (templ) |
18727 | || DECL_TEMPLATE_TEMPLATE_PARM_P (templ)) |
18728 | { |
18729 | /* In "template <typename T> ... A<T>::", A<T> is the abstract A |
18730 | template (rather than some instantiation thereof) only if |
18731 | is not nested within some other construct. For example, in |
18732 | "template <typename T> void f(T) { A<T>::", A<T> is just an |
18733 | instantiation of A. */ |
18734 | bool entering_scope |
18735 | = (template_parm_scope_p () |
18736 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)); |
18737 | template_id |
18738 | = finish_template_type (templ, arguments, entering_scope); |
18739 | } |
18740 | else if (concept_definition_p (t: templ)) |
18741 | { |
18742 | /* The caller will decide whether this is a concept check or type |
18743 | constraint. */ |
18744 | template_id = build2_loc (loc: combined_loc, code: TEMPLATE_ID_EXPR, |
18745 | boolean_type_node, arg0: templ, arg1: arguments); |
18746 | } |
18747 | else if (variable_template_p (t: templ)) |
18748 | { |
18749 | template_id = lookup_template_variable (templ, arguments, tf_warning_or_error); |
18750 | if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR) |
18751 | SET_EXPR_LOCATION (template_id, combined_loc); |
18752 | } |
18753 | else if (TREE_CODE (templ) == TYPE_DECL |
18754 | && TREE_CODE (TREE_TYPE (templ)) == TYPENAME_TYPE) |
18755 | { |
18756 | /* Some type template in dependent scope. */ |
18757 | tree &name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (templ)); |
18758 | name = build_min_nt_loc (combined_loc, |
18759 | TEMPLATE_ID_EXPR, |
18760 | name, arguments); |
18761 | template_id = templ; |
18762 | } |
18763 | else |
18764 | { |
18765 | /* If it's not a class-template or a template-template, it should be |
18766 | a function-template. */ |
18767 | gcc_assert (OVL_P (templ) || BASELINK_P (templ)); |
18768 | |
18769 | template_id = lookup_template_function (templ, arguments); |
18770 | if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR) |
18771 | SET_EXPR_LOCATION (template_id, combined_loc); |
18772 | } |
18773 | |
18774 | /* If parsing tentatively, replace the sequence of tokens that makes |
18775 | up the template-id with a CPP_TEMPLATE_ID token. That way, |
18776 | should we re-parse the token stream, we will not have to repeat |
18777 | the effort required to do the parse, nor will we issue duplicate |
18778 | error messages about problems during instantiation of the |
18779 | template. */ |
18780 | if (start_of_id |
18781 | /* Don't do this if we had a parse error in a declarator; re-parsing |
18782 | might succeed if a name changes meaning (60361). */ |
18783 | && !(cp_parser_error_occurred (parser) |
18784 | && cp_parser_parsing_tentatively (parser) |
18785 | && parser->in_declarator_p)) |
18786 | { |
18787 | /* Reset the contents of the START_OF_ID token. */ |
18788 | token->type = CPP_TEMPLATE_ID; |
18789 | token->location = combined_loc; |
18790 | |
18791 | /* Retrieve any deferred checks. Do not pop this access checks yet |
18792 | so the memory will not be reclaimed during token replacing below. */ |
18793 | token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> (); |
18794 | token->tree_check_p = true; |
18795 | token->u.tree_check_value->value = template_id; |
18796 | token->u.tree_check_value->checks = get_deferred_access_checks (); |
18797 | token->keyword = RID_MAX; |
18798 | |
18799 | /* Purge all subsequent tokens. */ |
18800 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start_of_id); |
18801 | |
18802 | /* ??? Can we actually assume that, if template_id == |
18803 | error_mark_node, we will have issued a diagnostic to the |
18804 | user, as opposed to simply marking the tentative parse as |
18805 | failed? */ |
18806 | if (cp_parser_error_occurred (parser) && template_id != error_mark_node) |
18807 | error_at (token->location, "parse error in template argument list" ); |
18808 | } |
18809 | |
18810 | pop_to_parent_deferring_access_checks (); |
18811 | return template_id; |
18812 | } |
18813 | |
18814 | /* Like cp_parser_template_id, called in non-type context. */ |
18815 | |
18816 | static tree |
18817 | cp_parser_template_id_expr (cp_parser *parser, |
18818 | bool template_keyword_p, |
18819 | bool check_dependency_p, |
18820 | bool is_declaration) |
18821 | { |
18822 | tree x = cp_parser_template_id (parser, template_keyword_p, check_dependency_p, |
18823 | tag_type: none_type, is_declaration); |
18824 | if (TREE_CODE (x) == TEMPLATE_ID_EXPR |
18825 | && concept_check_p (t: x)) |
18826 | /* We didn't check the arguments in cp_parser_template_id; do that now. */ |
18827 | return build_concept_id (x); |
18828 | return x; |
18829 | } |
18830 | |
18831 | /* Parse a template-name. |
18832 | |
18833 | template-name: |
18834 | identifier |
18835 | |
18836 | The standard should actually say: |
18837 | |
18838 | template-name: |
18839 | identifier |
18840 | operator-function-id |
18841 | |
18842 | A defect report has been filed about this issue. |
18843 | |
18844 | A conversion-function-id cannot be a template name because they cannot |
18845 | be part of a template-id. In fact, looking at this code: |
18846 | |
18847 | a.operator K<int>() |
18848 | |
18849 | the conversion-function-id is "operator K<int>", and K<int> is a type-id. |
18850 | It is impossible to call a templated conversion-function-id with an |
18851 | explicit argument list, since the only allowed template parameter is |
18852 | the type to which it is converting. |
18853 | |
18854 | If TEMPLATE_KEYWORD_P is true, then we have just seen the |
18855 | `template' keyword, in a construction like: |
18856 | |
18857 | T::template f<3>() |
18858 | |
18859 | In that case `f' is taken to be a template-name, even though there |
18860 | is no way of knowing for sure. |
18861 | |
18862 | Returns the TEMPLATE_DECL for the template, or an OVERLOAD if the |
18863 | name refers to a set of overloaded functions, at least one of which |
18864 | is a template, or an IDENTIFIER_NODE with the name of the template, |
18865 | if TEMPLATE_KEYWORD_P is true. If CHECK_DEPENDENCY_P is FALSE, |
18866 | names are looked up inside uninstantiated templates. */ |
18867 | |
18868 | static tree |
18869 | cp_parser_template_name (cp_parser* parser, |
18870 | bool template_keyword_p, |
18871 | bool check_dependency_p, |
18872 | bool is_declaration, |
18873 | enum tag_types tag_type, |
18874 | bool *is_identifier) |
18875 | { |
18876 | tree identifier; |
18877 | tree decl; |
18878 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
18879 | |
18880 | /* If the next token is `operator', then we have either an |
18881 | operator-function-id or a conversion-function-id. */ |
18882 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_OPERATOR)) |
18883 | { |
18884 | /* We don't know whether we're looking at an |
18885 | operator-function-id or a conversion-function-id. */ |
18886 | cp_parser_parse_tentatively (parser); |
18887 | /* Try an operator-function-id. */ |
18888 | identifier = cp_parser_operator_function_id (parser); |
18889 | /* If that didn't work, try a conversion-function-id. */ |
18890 | if (!cp_parser_parse_definitely (parser)) |
18891 | { |
18892 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
18893 | return error_mark_node; |
18894 | } |
18895 | } |
18896 | /* Look for the identifier. */ |
18897 | else |
18898 | identifier = cp_parser_identifier (parser); |
18899 | |
18900 | /* If we didn't find an identifier, we don't have a template-id. */ |
18901 | if (identifier == error_mark_node) |
18902 | return error_mark_node; |
18903 | |
18904 | /* If the name immediately followed the `template' keyword, then it |
18905 | is a template-name. However, if the next token is not `<', then |
18906 | we do not treat it as a template-name, since it is not being used |
18907 | as part of a template-id. This enables us to handle constructs |
18908 | like: |
18909 | |
18910 | template <typename T> struct S { S(); }; |
18911 | template <typename T> S<T>::S(); |
18912 | |
18913 | correctly. We would treat `S' as a template -- if it were `S<T>' |
18914 | -- but we do not if there is no `<'. */ |
18915 | |
18916 | if (processing_template_decl |
18917 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1)) |
18918 | { |
18919 | /* In a declaration, in a dependent context, we pretend that the |
18920 | "template" keyword was present in order to improve error |
18921 | recovery. For example, given: |
18922 | |
18923 | template <typename T> void f(T::X<int>); |
18924 | |
18925 | we want to treat "X<int>" as a template-id. */ |
18926 | if (is_declaration |
18927 | && !template_keyword_p |
18928 | && parser->scope && TYPE_P (parser->scope) |
18929 | && check_dependency_p |
18930 | && dependent_scope_p (parser->scope) |
18931 | /* Do not do this for dtors (or ctors), since they never |
18932 | need the template keyword before their name. */ |
18933 | && !constructor_name_p (identifier, parser->scope)) |
18934 | { |
18935 | cp_token_position start = 0; |
18936 | |
18937 | /* Explain what went wrong. */ |
18938 | error_at (token->location, "non-template %qD used as template" , |
18939 | identifier); |
18940 | inform (token->location, "use %<%T::template %D%> to indicate that it is a template" , |
18941 | parser->scope, identifier); |
18942 | /* If parsing tentatively, find the location of the "<" token. */ |
18943 | if (cp_parser_simulate_error (parser)) |
18944 | start = cp_lexer_token_position (lexer: parser->lexer, previous_p: true); |
18945 | /* Parse the template arguments so that we can issue error |
18946 | messages about them. */ |
18947 | cp_lexer_consume_token (lexer: parser->lexer); |
18948 | cp_parser_enclosed_template_argument_list (parser); |
18949 | /* Skip tokens until we find a good place from which to |
18950 | continue parsing. */ |
18951 | cp_parser_skip_to_closing_parenthesis (parser, |
18952 | /*recovering=*/true, |
18953 | /*or_comma=*/true, |
18954 | /*consume_paren=*/false); |
18955 | /* If parsing tentatively, permanently remove the |
18956 | template argument list. That will prevent duplicate |
18957 | error messages from being issued about the missing |
18958 | "template" keyword. */ |
18959 | if (start) |
18960 | cp_lexer_purge_tokens_after (lexer: parser->lexer, tok: start); |
18961 | if (is_identifier) |
18962 | *is_identifier = true; |
18963 | parser->context->object_type = NULL_TREE; |
18964 | return identifier; |
18965 | } |
18966 | |
18967 | /* If the "template" keyword is present, then there is generally |
18968 | no point in doing name-lookup, so we just return IDENTIFIER. |
18969 | But, if the qualifying scope is non-dependent then we can |
18970 | (and must) do name-lookup normally. */ |
18971 | if (template_keyword_p) |
18972 | { |
18973 | tree scope = (parser->scope ? parser->scope |
18974 | : parser->context->object_type); |
18975 | if (scope && TYPE_P (scope) |
18976 | && (!CLASS_TYPE_P (scope) |
18977 | || (check_dependency_p && dependent_scope_p (scope)))) |
18978 | { |
18979 | /* We're optimizing away the call to cp_parser_lookup_name, but |
18980 | we still need to do this. */ |
18981 | parser->object_scope = parser->context->object_type; |
18982 | parser->context->object_type = NULL_TREE; |
18983 | return identifier; |
18984 | } |
18985 | } |
18986 | } |
18987 | |
18988 | /* cp_parser_lookup_name clears OBJECT_TYPE. */ |
18989 | tree scope = (parser->scope ? parser->scope |
18990 | : parser->context->object_type); |
18991 | |
18992 | /* Look up the name. */ |
18993 | decl = cp_parser_lookup_name (parser, identifier, |
18994 | tag_type, |
18995 | /*is_template=*/1 + template_keyword_p, |
18996 | /*is_namespace=*/false, |
18997 | check_dependency_p, |
18998 | /*ambiguous_decls=*/NULL, |
18999 | token->location); |
19000 | |
19001 | decl = strip_using_decl (decl); |
19002 | |
19003 | /* 13.3 [temp.names] A < is interpreted as the delimiter of a |
19004 | template-argument-list if it follows a name that is not a |
19005 | conversion-function-id and |
19006 | - that follows the keyword template or a ~ after a nested-name-specifier or |
19007 | in a class member access expression, or |
19008 | - for which name lookup finds the injected-class-name of a class template |
19009 | or finds any declaration of a template, or |
19010 | - that is an unqualified name for which name lookup either finds one or |
19011 | more functions or finds nothing, or |
19012 | - that is a terminal name in a using-declarator (9.9), in a declarator-id |
19013 | (9.3.4), or in a type-only context other than a nested-name-specifier |
19014 | (13.8). */ |
19015 | |
19016 | /* Handle injected-class-name. */ |
19017 | decl = maybe_get_template_decl_from_type_decl (decl); |
19018 | |
19019 | /* If DECL is a template, then the name was a template-name. */ |
19020 | if (TREE_CODE (decl) == TEMPLATE_DECL) |
19021 | { |
19022 | if ((TREE_DEPRECATED (decl) || TREE_UNAVAILABLE (decl)) |
19023 | && deprecated_state != UNAVAILABLE_DEPRECATED_SUPPRESS) |
19024 | { |
19025 | tree d = DECL_TEMPLATE_RESULT (decl); |
19026 | tree attr; |
19027 | if (TREE_CODE (d) == TYPE_DECL) |
19028 | attr = TYPE_ATTRIBUTES (TREE_TYPE (d)); |
19029 | else |
19030 | attr = DECL_ATTRIBUTES (d); |
19031 | if (TREE_UNAVAILABLE (decl)) |
19032 | { |
19033 | attr = lookup_attribute (attr_name: "unavailable" , list: attr); |
19034 | error_unavailable_use (decl, attr); |
19035 | } |
19036 | else if (TREE_DEPRECATED (decl) |
19037 | && deprecated_state != DEPRECATED_SUPPRESS) |
19038 | { |
19039 | attr = lookup_attribute (attr_name: "deprecated" , list: attr); |
19040 | warn_deprecated_use (decl, attr); |
19041 | } |
19042 | } |
19043 | } |
19044 | else |
19045 | { |
19046 | /* Look through an overload set for any templates. */ |
19047 | bool found = false; |
19048 | |
19049 | for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (decl)); |
19050 | !found && iter; ++iter) |
19051 | if (TREE_CODE (*iter) == TEMPLATE_DECL) |
19052 | found = true; |
19053 | |
19054 | /* "an unqualified name for which name lookup either finds one or more |
19055 | functions or finds nothing". */ |
19056 | if (!found |
19057 | && (cxx_dialect > cxx17) |
19058 | && !scope |
19059 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS) |
19060 | && tag_type == none_type) |
19061 | { |
19062 | /* The "more functions" case. Just use the OVERLOAD as normally. |
19063 | We don't use is_overloaded_fn here to avoid considering |
19064 | BASELINKs. */ |
19065 | if (TREE_CODE (decl) == OVERLOAD |
19066 | /* Name lookup found one function. */ |
19067 | || TREE_CODE (decl) == FUNCTION_DECL |
19068 | /* Name lookup found nothing. */ |
19069 | || decl == error_mark_node) |
19070 | found = true; |
19071 | } |
19072 | |
19073 | /* "that follows the keyword template"..."in a type-only context" */ |
19074 | if (!found && scope |
19075 | && (template_keyword_p || tag_type != none_type) |
19076 | && dependentish_scope_p (scope) |
19077 | && cp_parser_nth_token_starts_template_argument_list_p (parser, 1)) |
19078 | found = true; |
19079 | |
19080 | if (!found) |
19081 | { |
19082 | /* The name does not name a template. */ |
19083 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
19084 | return error_mark_node; |
19085 | } |
19086 | else if ((!DECL_P (decl) && !is_overloaded_fn (decl)) |
19087 | || TREE_CODE (decl) == USING_DECL |
19088 | /* cp_parser_template_id can only handle some TYPE_DECLs. */ |
19089 | || (TREE_CODE (decl) == TYPE_DECL |
19090 | && TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)) |
19091 | /* Repeat the lookup at instantiation time. */ |
19092 | decl = identifier; |
19093 | } |
19094 | |
19095 | return decl; |
19096 | } |
19097 | |
19098 | /* Parse a template-argument-list. |
19099 | |
19100 | template-argument-list: |
19101 | template-argument ... [opt] |
19102 | template-argument-list , template-argument ... [opt] |
19103 | |
19104 | Returns a TREE_VEC containing the arguments. */ |
19105 | |
19106 | static tree |
19107 | cp_parser_template_argument_list (cp_parser* parser) |
19108 | { |
19109 | bool saved_in_template_argument_list_p; |
19110 | bool saved_ice_p; |
19111 | bool saved_non_ice_p; |
19112 | |
19113 | /* Don't create location wrapper nodes within a template-argument-list. */ |
19114 | auto_suppress_location_wrappers sentinel; |
19115 | |
19116 | saved_in_template_argument_list_p = parser->in_template_argument_list_p; |
19117 | parser->in_template_argument_list_p = true; |
19118 | /* Even if the template-id appears in an integral |
19119 | constant-expression, the contents of the argument list do |
19120 | not. */ |
19121 | saved_ice_p = parser->integral_constant_expression_p; |
19122 | parser->integral_constant_expression_p = false; |
19123 | saved_non_ice_p = parser->non_integral_constant_expression_p; |
19124 | parser->non_integral_constant_expression_p = false; |
19125 | |
19126 | /* Parse the arguments. */ |
19127 | auto_vec<tree, 10> args; |
19128 | do |
19129 | { |
19130 | if (!args.is_empty ()) |
19131 | /* Consume the comma. */ |
19132 | cp_lexer_consume_token (lexer: parser->lexer); |
19133 | |
19134 | /* Parse the template-argument. */ |
19135 | tree argument = cp_parser_template_argument (parser); |
19136 | |
19137 | /* If the next token is an ellipsis, we're expanding a template |
19138 | argument pack. */ |
19139 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
19140 | { |
19141 | if (argument == error_mark_node) |
19142 | { |
19143 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
19144 | error_at (token->location, |
19145 | "expected parameter pack before %<...%>" ); |
19146 | } |
19147 | /* Consume the `...' token. */ |
19148 | cp_lexer_consume_token (lexer: parser->lexer); |
19149 | |
19150 | /* Make the argument into a TYPE_PACK_EXPANSION or |
19151 | EXPR_PACK_EXPANSION. */ |
19152 | argument = make_pack_expansion (argument); |
19153 | } |
19154 | |
19155 | args.safe_push (obj: argument); |
19156 | } |
19157 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
19158 | |
19159 | int n_args = args.length (); |
19160 | tree vec = make_tree_vec (n_args); |
19161 | |
19162 | for (int i = 0; i < n_args; i++) |
19163 | TREE_VEC_ELT (vec, i) = args[i]; |
19164 | |
19165 | parser->non_integral_constant_expression_p = saved_non_ice_p; |
19166 | parser->integral_constant_expression_p = saved_ice_p; |
19167 | parser->in_template_argument_list_p = saved_in_template_argument_list_p; |
19168 | if (CHECKING_P) |
19169 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec)); |
19170 | return vec; |
19171 | } |
19172 | |
19173 | /* Parse a template-argument. |
19174 | |
19175 | template-argument: |
19176 | assignment-expression |
19177 | type-id |
19178 | id-expression |
19179 | |
19180 | The representation is that of an assignment-expression, type-id, or |
19181 | id-expression -- except that the qualified id-expression is |
19182 | evaluated, so that the value returned is either a DECL or an |
19183 | OVERLOAD. |
19184 | |
19185 | Although the standard says "assignment-expression", it forbids |
19186 | throw-expressions or assignments in the template argument. |
19187 | Therefore, we use "conditional-expression" instead. */ |
19188 | |
19189 | static tree |
19190 | cp_parser_template_argument (cp_parser* parser) |
19191 | { |
19192 | tree argument; |
19193 | bool template_p; |
19194 | bool address_p; |
19195 | bool maybe_type_id = false; |
19196 | cp_token *token = NULL, *argument_start_token = NULL; |
19197 | location_t loc = 0; |
19198 | cp_id_kind idk; |
19199 | |
19200 | /* There's really no way to know what we're looking at, so we just |
19201 | try each alternative in order. |
19202 | |
19203 | [temp.arg] |
19204 | |
19205 | In a template-argument, an ambiguity between a type-id and an |
19206 | expression is resolved to a type-id, regardless of the form of |
19207 | the corresponding template-parameter. |
19208 | |
19209 | Therefore, we try a type-id first. */ |
19210 | cp_parser_parse_tentatively (parser); |
19211 | argument = cp_parser_template_type_arg (parser); |
19212 | /* If there was no error parsing the type-id but the next token is a |
19213 | '>>', our behavior depends on which dialect of C++ we're |
19214 | parsing. In C++98, we probably found a typo for '> >'. But there |
19215 | are type-id which are also valid expressions. For instance: |
19216 | |
19217 | struct X { int operator >> (int); }; |
19218 | template <int V> struct Foo {}; |
19219 | Foo<X () >> 5> r; |
19220 | |
19221 | Here 'X()' is a valid type-id of a function type, but the user just |
19222 | wanted to write the expression "X() >> 5". Thus, we remember that we |
19223 | found a valid type-id, but we still try to parse the argument as an |
19224 | expression to see what happens. |
19225 | |
19226 | In C++0x, the '>>' will be considered two separate '>' |
19227 | tokens. */ |
19228 | if (!cp_parser_error_occurred (parser) |
19229 | && ((cxx_dialect == cxx98 |
19230 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT)) |
19231 | /* Similarly for >= which |
19232 | cp_parser_next_token_ends_template_argument_p treats for |
19233 | diagnostics purposes as mistyped > =, but can be valid |
19234 | after a type-id. */ |
19235 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ))) |
19236 | { |
19237 | maybe_type_id = true; |
19238 | cp_parser_abort_tentative_parse (parser); |
19239 | } |
19240 | else |
19241 | { |
19242 | /* If the next token isn't a `,' or a `>', then this argument wasn't |
19243 | really finished. This means that the argument is not a valid |
19244 | type-id. */ |
19245 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19246 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19247 | /* If that worked, we're done. */ |
19248 | if (cp_parser_parse_definitely (parser)) |
19249 | return argument; |
19250 | } |
19251 | /* We're still not sure what the argument will be. */ |
19252 | cp_parser_parse_tentatively (parser); |
19253 | /* Try a template. */ |
19254 | argument_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
19255 | argument = cp_parser_id_expression (parser, |
19256 | /*template_keyword_p=*/false, |
19257 | /*check_dependency_p=*/true, |
19258 | template_p: &template_p, |
19259 | /*declarator_p=*/false, |
19260 | /*optional_p=*/false); |
19261 | /* If the next token isn't a `,' or a `>', then this argument wasn't |
19262 | really finished. */ |
19263 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19264 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19265 | if (!cp_parser_error_occurred (parser)) |
19266 | { |
19267 | /* Figure out what is being referred to. If the id-expression |
19268 | was for a class template specialization, then we will have a |
19269 | TYPE_DECL at this point. There is no need to do name lookup |
19270 | at this point in that case. */ |
19271 | if (TREE_CODE (argument) != TYPE_DECL) |
19272 | argument = cp_parser_lookup_name (parser, argument, |
19273 | none_type, |
19274 | /*is_template=*/template_p, |
19275 | /*is_namespace=*/false, |
19276 | /*check_dependency=*/true, |
19277 | /*ambiguous_decls=*/NULL, |
19278 | argument_start_token->location); |
19279 | if (TREE_CODE (argument) != TEMPLATE_DECL |
19280 | && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) |
19281 | cp_parser_error (parser, gmsgid: "expected template-name" ); |
19282 | } |
19283 | if (cp_parser_parse_definitely (parser)) |
19284 | { |
19285 | if (TREE_UNAVAILABLE (argument)) |
19286 | error_unavailable_use (argument, NULL_TREE); |
19287 | else if (TREE_DEPRECATED (argument)) |
19288 | warn_deprecated_use (argument, NULL_TREE); |
19289 | return argument; |
19290 | } |
19291 | /* It must be a non-type argument. In C++17 any constant-expression is |
19292 | allowed. */ |
19293 | if (cxx_dialect > cxx14) |
19294 | goto general_expr; |
19295 | |
19296 | /* Otherwise, the permitted cases are given in [temp.arg.nontype]: |
19297 | |
19298 | -- an integral constant-expression of integral or enumeration |
19299 | type; or |
19300 | |
19301 | -- the name of a non-type template-parameter; or |
19302 | |
19303 | -- the name of an object or function with external linkage... |
19304 | |
19305 | -- the address of an object or function with external linkage... |
19306 | |
19307 | -- a pointer to member... */ |
19308 | /* Look for a non-type template parameter. */ |
19309 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
19310 | { |
19311 | cp_parser_parse_tentatively (parser); |
19312 | argument = cp_parser_primary_expression (parser, |
19313 | /*address_p=*/false, |
19314 | /*cast_p=*/false, |
19315 | /*template_arg_p=*/true, |
19316 | idk: &idk); |
19317 | if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX |
19318 | || !cp_parser_next_token_ends_template_argument_p (parser)) |
19319 | cp_parser_simulate_error (parser); |
19320 | if (cp_parser_parse_definitely (parser)) |
19321 | return argument; |
19322 | } |
19323 | |
19324 | /* If the next token is "&", the argument must be the address of an |
19325 | object or function with external linkage. */ |
19326 | address_p = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND); |
19327 | if (address_p) |
19328 | { |
19329 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
19330 | cp_lexer_consume_token (lexer: parser->lexer); |
19331 | } |
19332 | /* See if we might have an id-expression. */ |
19333 | token = cp_lexer_peek_token (lexer: parser->lexer); |
19334 | if (token->type == CPP_NAME |
19335 | || token->keyword == RID_OPERATOR |
19336 | || token->type == CPP_SCOPE |
19337 | || token->type == CPP_TEMPLATE_ID |
19338 | || token->type == CPP_NESTED_NAME_SPECIFIER) |
19339 | { |
19340 | cp_parser_parse_tentatively (parser); |
19341 | argument = cp_parser_primary_expression (parser, |
19342 | address_p, |
19343 | /*cast_p=*/false, |
19344 | /*template_arg_p=*/true, |
19345 | idk: &idk); |
19346 | if (cp_parser_error_occurred (parser) |
19347 | || !cp_parser_next_token_ends_template_argument_p (parser)) |
19348 | cp_parser_abort_tentative_parse (parser); |
19349 | else |
19350 | { |
19351 | tree probe; |
19352 | |
19353 | if (INDIRECT_REF_P (argument)) |
19354 | { |
19355 | /* Strip the dereference temporarily. */ |
19356 | gcc_assert (REFERENCE_REF_P (argument)); |
19357 | argument = TREE_OPERAND (argument, 0); |
19358 | } |
19359 | |
19360 | /* If we're in a template, we represent a qualified-id referring |
19361 | to a static data member as a SCOPE_REF even if the scope isn't |
19362 | dependent so that we can check access control later. */ |
19363 | probe = argument; |
19364 | if (TREE_CODE (probe) == SCOPE_REF) |
19365 | probe = TREE_OPERAND (probe, 1); |
19366 | if (VAR_P (probe)) |
19367 | { |
19368 | /* A variable without external linkage might still be a |
19369 | valid constant-expression, so no error is issued here |
19370 | if the external-linkage check fails. */ |
19371 | if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe)) |
19372 | cp_parser_simulate_error (parser); |
19373 | } |
19374 | else if (is_overloaded_fn (argument)) |
19375 | /* All overloaded functions are allowed; if the external |
19376 | linkage test does not pass, an error will be issued |
19377 | later. */ |
19378 | ; |
19379 | else if (address_p |
19380 | && (TREE_CODE (argument) == OFFSET_REF |
19381 | || TREE_CODE (argument) == SCOPE_REF)) |
19382 | /* A pointer-to-member. */ |
19383 | ; |
19384 | else if (TREE_CODE (argument) == TEMPLATE_PARM_INDEX) |
19385 | ; |
19386 | else |
19387 | cp_parser_simulate_error (parser); |
19388 | |
19389 | if (cp_parser_parse_definitely (parser)) |
19390 | { |
19391 | if (address_p) |
19392 | argument = build_x_unary_op (loc, ADDR_EXPR, argument, |
19393 | NULL_TREE, tf_warning_or_error); |
19394 | else |
19395 | argument = convert_from_reference (argument); |
19396 | return argument; |
19397 | } |
19398 | } |
19399 | } |
19400 | /* If the argument started with "&", there are no other valid |
19401 | alternatives at this point. */ |
19402 | if (address_p) |
19403 | { |
19404 | cp_parser_error (parser, gmsgid: "invalid non-type template argument" ); |
19405 | return error_mark_node; |
19406 | } |
19407 | |
19408 | general_expr: |
19409 | /* If the argument wasn't successfully parsed as a type-id followed |
19410 | by '>>', the argument can only be a constant expression now. |
19411 | Otherwise, we try parsing the constant-expression tentatively, |
19412 | because the argument could really be a type-id. */ |
19413 | if (maybe_type_id) |
19414 | cp_parser_parse_tentatively (parser); |
19415 | |
19416 | if (cxx_dialect <= cxx14) |
19417 | argument = cp_parser_constant_expression (parser); |
19418 | else |
19419 | { |
19420 | /* In C++20, we can encounter a braced-init-list. */ |
19421 | if (cxx_dialect >= cxx20 |
19422 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
19423 | return cp_parser_braced_list (parser); |
19424 | |
19425 | /* With C++17 generalized non-type template arguments we need to handle |
19426 | lvalue constant expressions, too. */ |
19427 | argument = cp_parser_assignment_expression (parser); |
19428 | require_potential_constant_expression (argument); |
19429 | } |
19430 | |
19431 | if (!maybe_type_id) |
19432 | return argument; |
19433 | if (!cp_parser_next_token_ends_template_argument_p (parser)) |
19434 | cp_parser_error (parser, gmsgid: "expected template-argument" ); |
19435 | if (cp_parser_parse_definitely (parser)) |
19436 | return argument; |
19437 | /* We did our best to parse the argument as a non type-id, but that |
19438 | was the only alternative that matched (albeit with a '>' after |
19439 | it). We can assume it's just a typo from the user, and a |
19440 | diagnostic will then be issued. */ |
19441 | return cp_parser_template_type_arg (parser); |
19442 | } |
19443 | |
19444 | /* Parse an explicit-instantiation. |
19445 | |
19446 | explicit-instantiation: |
19447 | template declaration |
19448 | |
19449 | Although the standard says `declaration', what it really means is: |
19450 | |
19451 | explicit-instantiation: |
19452 | template decl-specifier-seq [opt] declarator [opt] ; |
19453 | |
19454 | Things like `template int S<int>::i = 5, int S<double>::j;' are not |
19455 | supposed to be allowed. A defect report has been filed about this |
19456 | issue. |
19457 | |
19458 | GNU Extension: |
19459 | |
19460 | explicit-instantiation: |
19461 | storage-class-specifier template |
19462 | decl-specifier-seq [opt] declarator [opt] ; |
19463 | function-specifier template |
19464 | decl-specifier-seq [opt] declarator [opt] ; */ |
19465 | |
19466 | static void |
19467 | cp_parser_explicit_instantiation (cp_parser* parser) |
19468 | { |
19469 | int declares_class_or_enum; |
19470 | cp_decl_specifier_seq decl_specifiers; |
19471 | tree extension_specifier = NULL_TREE; |
19472 | |
19473 | auto_timevar tv (TV_TEMPLATE_INST); |
19474 | |
19475 | /* Look for an (optional) storage-class-specifier or |
19476 | function-specifier. */ |
19477 | if (cp_parser_allow_gnu_extensions_p (parser)) |
19478 | { |
19479 | extension_specifier |
19480 | = cp_parser_storage_class_specifier_opt (parser); |
19481 | if (!extension_specifier) |
19482 | extension_specifier |
19483 | = cp_parser_function_specifier_opt (parser, |
19484 | /*decl_specs=*/NULL); |
19485 | } |
19486 | |
19487 | /* Look for the `template' keyword. */ |
19488 | cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE); |
19489 | /* Let the front end know that we are processing an explicit |
19490 | instantiation. */ |
19491 | begin_explicit_instantiation (); |
19492 | /* [temp.explicit] says that we are supposed to ignore access |
19493 | control while processing explicit instantiation directives. */ |
19494 | push_deferring_access_checks (dk_no_check); |
19495 | /* Parse a decl-specifier-seq. */ |
19496 | cp_parser_decl_specifier_seq (parser, |
19497 | flags: CP_PARSER_FLAGS_OPTIONAL, |
19498 | decl_specs: &decl_specifiers, |
19499 | declares_class_or_enum: &declares_class_or_enum); |
19500 | |
19501 | cp_omp_declare_simd_data odsd; |
19502 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
19503 | cp_parser_handle_directive_omp_attributes (parser, |
19504 | pattrs: &decl_specifiers.attributes, |
19505 | data: &odsd, start: true); |
19506 | |
19507 | /* If there was exactly one decl-specifier, and it declared a class, |
19508 | and there's no declarator, then we have an explicit type |
19509 | instantiation. */ |
19510 | if (declares_class_or_enum && cp_parser_declares_only_class_p (parser)) |
19511 | { |
19512 | tree type = check_tag_decl (&decl_specifiers, |
19513 | /*explicit_type_instantiation_p=*/true); |
19514 | /* Turn access control back on for names used during |
19515 | template instantiation. */ |
19516 | pop_deferring_access_checks (); |
19517 | if (type) |
19518 | do_type_instantiation (type, extension_specifier, |
19519 | /*complain=*/tf_error); |
19520 | } |
19521 | else |
19522 | { |
19523 | cp_declarator *declarator; |
19524 | tree decl; |
19525 | |
19526 | /* Parse the declarator. */ |
19527 | declarator |
19528 | = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
19529 | CP_PARSER_FLAGS_NONE, |
19530 | /*ctor_dtor_or_conv_p=*/NULL, |
19531 | /*parenthesized_p=*/NULL, |
19532 | /*member_p=*/false, |
19533 | /*friend_p=*/false, |
19534 | /*static_p=*/false); |
19535 | if (declares_class_or_enum & 2) |
19536 | cp_parser_check_for_definition_in_return_type (declarator, |
19537 | type: decl_specifiers.type, |
19538 | type_location: decl_specifiers.locations[ds_type_spec]); |
19539 | if (declarator != cp_error_declarator) |
19540 | { |
19541 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_inline)) |
19542 | permerror (decl_specifiers.locations[ds_inline], |
19543 | "explicit instantiation shall not use" |
19544 | " %<inline%> specifier" ); |
19545 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_constexpr)) |
19546 | permerror (decl_specifiers.locations[ds_constexpr], |
19547 | "explicit instantiation shall not use" |
19548 | " %<constexpr%> specifier" ); |
19549 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_consteval)) |
19550 | permerror (decl_specifiers.locations[ds_consteval], |
19551 | "explicit instantiation shall not use" |
19552 | " %<consteval%> specifier" ); |
19553 | |
19554 | decl = grokdeclarator (declarator, &decl_specifiers, |
19555 | NORMAL, 0, &decl_specifiers.attributes); |
19556 | /* Turn access control back on for names used during |
19557 | template instantiation. */ |
19558 | pop_deferring_access_checks (); |
19559 | /* Do the explicit instantiation. */ |
19560 | do_decl_instantiation (decl, extension_specifier); |
19561 | } |
19562 | else |
19563 | { |
19564 | pop_deferring_access_checks (); |
19565 | /* Skip the body of the explicit instantiation. */ |
19566 | cp_parser_skip_to_end_of_statement (parser); |
19567 | } |
19568 | } |
19569 | /* We're done with the instantiation. */ |
19570 | end_explicit_instantiation (); |
19571 | |
19572 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
19573 | |
19574 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
19575 | } |
19576 | |
19577 | /* Parse an explicit-specialization. |
19578 | |
19579 | explicit-specialization: |
19580 | template < > declaration |
19581 | |
19582 | Although the standard says `declaration', what it really means is: |
19583 | |
19584 | explicit-specialization: |
19585 | template <> decl-specifier [opt] init-declarator [opt] ; |
19586 | template <> function-definition |
19587 | template <> explicit-specialization |
19588 | template <> template-declaration */ |
19589 | |
19590 | static void |
19591 | cp_parser_explicit_specialization (cp_parser* parser) |
19592 | { |
19593 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
19594 | |
19595 | /* Look for the `template' keyword. */ |
19596 | cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE); |
19597 | /* Look for the `<'. */ |
19598 | cp_parser_require (parser, CPP_LESS, RT_LESS); |
19599 | /* Look for the `>'. */ |
19600 | cp_parser_require (parser, CPP_GREATER, RT_GREATER); |
19601 | /* We have processed another parameter list. */ |
19602 | ++parser->num_template_parameter_lists; |
19603 | |
19604 | /* [temp] |
19605 | |
19606 | A template ... explicit specialization ... shall not have C |
19607 | linkage. */ |
19608 | bool need_lang_pop = current_lang_name == lang_name_c; |
19609 | if (need_lang_pop) |
19610 | { |
19611 | error_at (token->location, "template specialization with C linkage" ); |
19612 | maybe_show_extern_c_location (); |
19613 | |
19614 | /* Give it C++ linkage to avoid confusing other parts of the |
19615 | front end. */ |
19616 | push_lang_context (lang_name_cplusplus); |
19617 | } |
19618 | |
19619 | /* Let the front end know that we are beginning a specialization. */ |
19620 | if (begin_specialization ()) |
19621 | { |
19622 | /* If the next keyword is `template', we need to figure out |
19623 | whether or not we're looking a template-declaration. */ |
19624 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
19625 | { |
19626 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_LESS |
19627 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type != CPP_GREATER) |
19628 | cp_parser_template_declaration_after_export (parser, |
19629 | /*member_p=*/false); |
19630 | else |
19631 | cp_parser_explicit_specialization (parser); |
19632 | } |
19633 | else |
19634 | /* Parse the dependent declaration. */ |
19635 | cp_parser_single_declaration (parser, |
19636 | /*checks=*/NULL, |
19637 | /*member_p=*/false, |
19638 | /*explicit_specialization_p=*/true, |
19639 | /*friend_p=*/NULL); |
19640 | } |
19641 | |
19642 | /* We're done with the specialization. */ |
19643 | end_specialization (); |
19644 | |
19645 | /* For the erroneous case of a template with C linkage, we pushed an |
19646 | implicit C++ linkage scope; exit that scope now. */ |
19647 | if (need_lang_pop) |
19648 | pop_lang_context (); |
19649 | |
19650 | /* We're done with this parameter list. */ |
19651 | --parser->num_template_parameter_lists; |
19652 | } |
19653 | |
19654 | /* Preserve the attributes across a garbage collect (by making it a GC |
19655 | root), which can occur when parsing a member function. */ |
19656 | |
19657 | static GTY(()) vec<tree, va_gc> *cp_parser_decl_specs_attrs; |
19658 | |
19659 | /* Parse a type-specifier. |
19660 | |
19661 | type-specifier: |
19662 | simple-type-specifier |
19663 | class-specifier |
19664 | enum-specifier |
19665 | elaborated-type-specifier |
19666 | cv-qualifier |
19667 | |
19668 | GNU Extension: |
19669 | |
19670 | type-specifier: |
19671 | __complex__ |
19672 | |
19673 | Returns a representation of the type-specifier. For a |
19674 | class-specifier, enum-specifier, or elaborated-type-specifier, a |
19675 | TREE_TYPE is returned; otherwise, a TYPE_DECL is returned. |
19676 | |
19677 | The parser flags FLAGS is used to control type-specifier parsing. |
19678 | |
19679 | If IS_DECLARATION is TRUE, then this type-specifier is appearing |
19680 | in a decl-specifier-seq. |
19681 | |
19682 | If DECLARES_CLASS_OR_ENUM is non-NULL, and the type-specifier is a |
19683 | class-specifier, enum-specifier, or elaborated-type-specifier, then |
19684 | *DECLARES_CLASS_OR_ENUM is set to a nonzero value. The value is 1 |
19685 | if a type is declared; 2 if it is defined. Otherwise, it is set to |
19686 | zero. |
19687 | |
19688 | If IS_CV_QUALIFIER is non-NULL, and the type-specifier is a |
19689 | cv-qualifier, then IS_CV_QUALIFIER is set to TRUE. Otherwise, it |
19690 | is set to FALSE. */ |
19691 | |
19692 | static tree |
19693 | cp_parser_type_specifier (cp_parser* parser, |
19694 | cp_parser_flags flags, |
19695 | cp_decl_specifier_seq *decl_specs, |
19696 | bool is_declaration, |
19697 | int* declares_class_or_enum, |
19698 | bool* is_cv_qualifier) |
19699 | { |
19700 | tree type_spec = NULL_TREE; |
19701 | cp_token *token; |
19702 | enum rid keyword; |
19703 | cp_decl_spec ds = ds_last; |
19704 | |
19705 | /* Assume this type-specifier does not declare a new type. */ |
19706 | if (declares_class_or_enum) |
19707 | *declares_class_or_enum = 0; |
19708 | /* And that it does not specify a cv-qualifier. */ |
19709 | if (is_cv_qualifier) |
19710 | *is_cv_qualifier = false; |
19711 | /* Peek at the next token. */ |
19712 | token = cp_lexer_peek_token (lexer: parser->lexer); |
19713 | |
19714 | /* If we're looking at a keyword, we can use that to guide the |
19715 | production we choose. */ |
19716 | keyword = token->keyword; |
19717 | switch (keyword) |
19718 | { |
19719 | case RID_ENUM: |
19720 | if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS)) |
19721 | goto elaborated_type_specifier; |
19722 | |
19723 | /* Look for the enum-specifier. */ |
19724 | type_spec = cp_parser_enum_specifier (parser); |
19725 | /* If that worked, we're done. */ |
19726 | if (type_spec) |
19727 | { |
19728 | if (declares_class_or_enum) |
19729 | *declares_class_or_enum = 2; |
19730 | if (decl_specs) |
19731 | cp_parser_set_decl_spec_type (decl_specs, |
19732 | type_spec, |
19733 | token, |
19734 | /*type_definition_p=*/true); |
19735 | return type_spec; |
19736 | } |
19737 | else |
19738 | goto elaborated_type_specifier; |
19739 | |
19740 | /* Any of these indicate either a class-specifier, or an |
19741 | elaborated-type-specifier. */ |
19742 | case RID_CLASS: |
19743 | case RID_STRUCT: |
19744 | case RID_UNION: |
19745 | if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS)) |
19746 | goto elaborated_type_specifier; |
19747 | |
19748 | /* Parse tentatively so that we can back up if we don't find a |
19749 | class-specifier. */ |
19750 | cp_parser_parse_tentatively (parser); |
19751 | if (decl_specs->attributes) |
19752 | vec_safe_push (v&: cp_parser_decl_specs_attrs, obj: decl_specs->attributes); |
19753 | /* Look for the class-specifier. */ |
19754 | type_spec = cp_parser_class_specifier (parser); |
19755 | if (decl_specs->attributes) |
19756 | cp_parser_decl_specs_attrs->pop (); |
19757 | invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: type_spec); |
19758 | /* If that worked, we're done. */ |
19759 | if (cp_parser_parse_definitely (parser)) |
19760 | { |
19761 | if (declares_class_or_enum) |
19762 | *declares_class_or_enum = 2; |
19763 | if (decl_specs) |
19764 | cp_parser_set_decl_spec_type (decl_specs, |
19765 | type_spec, |
19766 | token, |
19767 | /*type_definition_p=*/true); |
19768 | return type_spec; |
19769 | } |
19770 | |
19771 | /* Fall through. */ |
19772 | elaborated_type_specifier: |
19773 | /* We're declaring (not defining) a class or enum. */ |
19774 | if (declares_class_or_enum) |
19775 | *declares_class_or_enum = 1; |
19776 | |
19777 | /* Fall through. */ |
19778 | case RID_TYPENAME: |
19779 | /* Look for an elaborated-type-specifier. */ |
19780 | type_spec |
19781 | = (cp_parser_elaborated_type_specifier |
19782 | (parser, |
19783 | decl_spec_seq_has_spec_p (decl_specs, ds_friend), |
19784 | is_declaration)); |
19785 | if (decl_specs) |
19786 | cp_parser_set_decl_spec_type (decl_specs, |
19787 | type_spec, |
19788 | token, |
19789 | /*type_definition_p=*/false); |
19790 | return type_spec; |
19791 | |
19792 | case RID_CONST: |
19793 | ds = ds_const; |
19794 | if (is_cv_qualifier) |
19795 | *is_cv_qualifier = true; |
19796 | break; |
19797 | |
19798 | case RID_VOLATILE: |
19799 | ds = ds_volatile; |
19800 | if (is_cv_qualifier) |
19801 | *is_cv_qualifier = true; |
19802 | break; |
19803 | |
19804 | case RID_RESTRICT: |
19805 | ds = ds_restrict; |
19806 | if (is_cv_qualifier) |
19807 | *is_cv_qualifier = true; |
19808 | break; |
19809 | |
19810 | case RID_COMPLEX: |
19811 | /* The `__complex__' keyword is a GNU extension. */ |
19812 | ds = ds_complex; |
19813 | break; |
19814 | |
19815 | default: |
19816 | break; |
19817 | } |
19818 | |
19819 | /* Handle simple keywords. */ |
19820 | if (ds != ds_last) |
19821 | { |
19822 | if (decl_specs) |
19823 | { |
19824 | set_and_check_decl_spec_loc (decl_specs, ds, token); |
19825 | decl_specs->any_specifiers_p = true; |
19826 | } |
19827 | return cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
19828 | } |
19829 | |
19830 | /* If we do not already have a type-specifier, assume we are looking |
19831 | at a simple-type-specifier. */ |
19832 | type_spec = cp_parser_simple_type_specifier (parser, |
19833 | decl_specs, |
19834 | flags); |
19835 | |
19836 | /* If we didn't find a type-specifier, and a type-specifier was not |
19837 | optional in this context, issue an error message. */ |
19838 | if (!type_spec && !(flags & CP_PARSER_FLAGS_OPTIONAL)) |
19839 | { |
19840 | cp_parser_error (parser, gmsgid: "expected type specifier" ); |
19841 | return error_mark_node; |
19842 | } |
19843 | |
19844 | return type_spec; |
19845 | } |
19846 | |
19847 | /* Parse a simple-type-specifier. |
19848 | |
19849 | simple-type-specifier: |
19850 | :: [opt] nested-name-specifier [opt] type-name |
19851 | :: [opt] nested-name-specifier template template-id |
19852 | char |
19853 | wchar_t |
19854 | bool |
19855 | short |
19856 | int |
19857 | long |
19858 | signed |
19859 | unsigned |
19860 | float |
19861 | double |
19862 | void |
19863 | |
19864 | C++11 Extension: |
19865 | |
19866 | simple-type-specifier: |
19867 | auto |
19868 | decltype ( expression ) |
19869 | char16_t |
19870 | char32_t |
19871 | __underlying_type ( type-id ) |
19872 | |
19873 | C++17 extension: |
19874 | |
19875 | nested-name-specifier(opt) template-name |
19876 | |
19877 | GNU Extension: |
19878 | |
19879 | simple-type-specifier: |
19880 | __int128 |
19881 | __typeof__ unary-expression |
19882 | __typeof__ ( type-id ) |
19883 | __typeof__ ( type-id ) { initializer-list , [opt] } |
19884 | |
19885 | Concepts Extension: |
19886 | |
19887 | simple-type-specifier: |
19888 | constrained-type-specifier |
19889 | |
19890 | Returns the indicated TYPE_DECL. If DECL_SPECS is not NULL, it is |
19891 | appropriately updated. */ |
19892 | |
19893 | static tree |
19894 | cp_parser_simple_type_specifier (cp_parser* parser, |
19895 | cp_decl_specifier_seq *decl_specs, |
19896 | cp_parser_flags flags) |
19897 | { |
19898 | tree type = NULL_TREE; |
19899 | cp_token *token; |
19900 | int idx; |
19901 | |
19902 | /* Peek at the next token. */ |
19903 | token = cp_lexer_peek_token (lexer: parser->lexer); |
19904 | |
19905 | /* If we're looking at a keyword, things are easy. */ |
19906 | switch (token->keyword) |
19907 | { |
19908 | case RID_CHAR: |
19909 | if (decl_specs) |
19910 | decl_specs->explicit_char_p = true; |
19911 | type = char_type_node; |
19912 | break; |
19913 | case RID_CHAR8: |
19914 | type = char8_type_node; |
19915 | break; |
19916 | case RID_CHAR16: |
19917 | type = char16_type_node; |
19918 | break; |
19919 | case RID_CHAR32: |
19920 | type = char32_type_node; |
19921 | break; |
19922 | case RID_WCHAR: |
19923 | type = wchar_type_node; |
19924 | break; |
19925 | case RID_BOOL: |
19926 | type = boolean_type_node; |
19927 | break; |
19928 | case RID_SHORT: |
19929 | set_and_check_decl_spec_loc (decl_specs, ds: ds_short, token); |
19930 | type = short_integer_type_node; |
19931 | break; |
19932 | case RID_INT: |
19933 | if (decl_specs) |
19934 | decl_specs->explicit_int_p = true; |
19935 | type = integer_type_node; |
19936 | break; |
19937 | case RID_INT_N_0: |
19938 | case RID_INT_N_1: |
19939 | case RID_INT_N_2: |
19940 | case RID_INT_N_3: |
19941 | idx = token->keyword - RID_INT_N_0; |
19942 | if (! int_n_enabled_p [idx]) |
19943 | break; |
19944 | if (decl_specs) |
19945 | { |
19946 | decl_specs->explicit_intN_p = true; |
19947 | decl_specs->int_n_idx = idx; |
19948 | /* Check if the alternate "__intN__" form has been used instead of |
19949 | "__intN". */ |
19950 | if (startswith (IDENTIFIER_POINTER (token->u.value) |
19951 | + (IDENTIFIER_LENGTH (token->u.value) - 2), prefix: "__" )) |
19952 | decl_specs->int_n_alt = true; |
19953 | } |
19954 | type = int_n_trees [idx].signed_type; |
19955 | break; |
19956 | case RID_LONG: |
19957 | if (decl_specs) |
19958 | set_and_check_decl_spec_loc (decl_specs, ds: ds_long, token); |
19959 | type = long_integer_type_node; |
19960 | break; |
19961 | case RID_SIGNED: |
19962 | set_and_check_decl_spec_loc (decl_specs, ds: ds_signed, token); |
19963 | type = integer_type_node; |
19964 | break; |
19965 | case RID_UNSIGNED: |
19966 | set_and_check_decl_spec_loc (decl_specs, ds: ds_unsigned, token); |
19967 | type = unsigned_type_node; |
19968 | break; |
19969 | case RID_FLOAT: |
19970 | type = float_type_node; |
19971 | break; |
19972 | case RID_DOUBLE: |
19973 | type = double_type_node; |
19974 | break; |
19975 | CASE_RID_FLOATN_NX: |
19976 | type = FLOATN_NX_TYPE_NODE (token->keyword - RID_FLOATN_NX_FIRST); |
19977 | if (type == NULL_TREE) |
19978 | error ("%<_Float%d%s%> is not supported on this target" , |
19979 | floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].n, |
19980 | floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].extended |
19981 | ? "x" : "" ); |
19982 | break; |
19983 | case RID_VOID: |
19984 | type = void_type_node; |
19985 | break; |
19986 | |
19987 | case RID_AUTO: |
19988 | maybe_warn_cpp0x (str: CPP0X_AUTO); |
19989 | if (parser->auto_is_implicit_function_template_parm_p) |
19990 | { |
19991 | /* The 'auto' might be the placeholder return type for a function decl |
19992 | with trailing return type. */ |
19993 | bool have_trailing_return_fn_decl = false; |
19994 | |
19995 | cp_parser_parse_tentatively (parser); |
19996 | cp_lexer_consume_token (lexer: parser->lexer); |
19997 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ) |
19998 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
19999 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
20000 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EOF)) |
20001 | { |
20002 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
20003 | { |
20004 | cp_lexer_consume_token (lexer: parser->lexer); |
20005 | cp_parser_skip_to_closing_parenthesis (parser, |
20006 | /*recovering*/false, |
20007 | /*or_comma*/false, |
20008 | /*consume_paren*/true); |
20009 | continue; |
20010 | } |
20011 | |
20012 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
20013 | { |
20014 | have_trailing_return_fn_decl = true; |
20015 | break; |
20016 | } |
20017 | |
20018 | cp_lexer_consume_token (lexer: parser->lexer); |
20019 | } |
20020 | cp_parser_abort_tentative_parse (parser); |
20021 | |
20022 | if (have_trailing_return_fn_decl) |
20023 | { |
20024 | type = make_auto (); |
20025 | break; |
20026 | } |
20027 | |
20028 | if (cxx_dialect >= cxx14) |
20029 | { |
20030 | type = synthesize_implicit_template_parm (parser, NULL_TREE); |
20031 | type = TREE_TYPE (type); |
20032 | } |
20033 | else |
20034 | type = error_mark_node; |
20035 | |
20036 | if (current_class_type && LAMBDA_TYPE_P (current_class_type)) |
20037 | { |
20038 | if (cxx_dialect < cxx14) |
20039 | error_at (token->location, |
20040 | "use of %<auto%> in lambda parameter declaration " |
20041 | "only available with " |
20042 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
20043 | } |
20044 | else if (!flag_concepts_ts && parser->in_template_argument_list_p) |
20045 | pedwarn (token->location, 0, |
20046 | "use of %<auto%> in template argument " |
20047 | "only available with %<-fconcepts-ts%>" ); |
20048 | else if (!flag_concepts) |
20049 | pedwarn (token->location, 0, |
20050 | "use of %<auto%> in parameter declaration " |
20051 | "only available with %<-std=c++20%> or %<-fconcepts%>" ); |
20052 | else if (cxx_dialect < cxx14) |
20053 | error_at (token->location, |
20054 | "use of %<auto%> in parameter declaration " |
20055 | "only available with " |
20056 | "%<-std=c++14%> or %<-std=gnu++14%>" ); |
20057 | } |
20058 | else |
20059 | type = make_auto (); |
20060 | break; |
20061 | |
20062 | case RID_DECLTYPE: |
20063 | /* Since DR 743, decltype can either be a simple-type-specifier by |
20064 | itself or begin a nested-name-specifier. Parsing it will replace |
20065 | it with a CPP_DECLTYPE, so just rewind and let the CPP_DECLTYPE |
20066 | handling below decide what to do. */ |
20067 | cp_parser_decltype (parser); |
20068 | cp_lexer_set_token_position (lexer: parser->lexer, pos: token); |
20069 | break; |
20070 | |
20071 | case RID_TYPEOF: |
20072 | /* Consume the `typeof' token. */ |
20073 | cp_lexer_consume_token (lexer: parser->lexer); |
20074 | /* Parse the operand to `typeof'. */ |
20075 | type = cp_parser_sizeof_operand (parser, RID_TYPEOF); |
20076 | /* If it is not already a TYPE, take its type. */ |
20077 | if (!TYPE_P (type)) |
20078 | type = finish_typeof (type); |
20079 | |
20080 | if (decl_specs) |
20081 | cp_parser_set_decl_spec_type (decl_specs, type, |
20082 | token, |
20083 | /*type_definition_p=*/false); |
20084 | |
20085 | return type; |
20086 | |
20087 | #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ |
20088 | case RID_##CODE: |
20089 | #include "cp-trait.def" |
20090 | #undef DEFTRAIT_TYPE |
20091 | type = cp_parser_trait (parser, keyword: token->keyword); |
20092 | if (decl_specs) |
20093 | cp_parser_set_decl_spec_type (decl_specs, type, |
20094 | token, |
20095 | /*type_definition_p=*/false); |
20096 | |
20097 | return type; |
20098 | |
20099 | default: |
20100 | break; |
20101 | } |
20102 | |
20103 | /* If token is an already-parsed decltype not followed by ::, |
20104 | it's a simple-type-specifier. */ |
20105 | if (token->type == CPP_DECLTYPE |
20106 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_SCOPE) |
20107 | { |
20108 | type = saved_checks_value (check_value: token->u.tree_check_value); |
20109 | if (decl_specs) |
20110 | { |
20111 | cp_parser_set_decl_spec_type (decl_specs, type, |
20112 | token, |
20113 | /*type_definition_p=*/false); |
20114 | /* Remember that we are handling a decltype in order to |
20115 | implement the resolution of DR 1510 when the argument |
20116 | isn't instantiation dependent. */ |
20117 | decl_specs->decltype_p = true; |
20118 | } |
20119 | cp_lexer_consume_token (lexer: parser->lexer); |
20120 | return type; |
20121 | } |
20122 | |
20123 | /* If the type-specifier was for a built-in type, we're done. */ |
20124 | if (type) |
20125 | { |
20126 | /* Record the type. */ |
20127 | if (decl_specs |
20128 | && (token->keyword != RID_SIGNED |
20129 | && token->keyword != RID_UNSIGNED |
20130 | && token->keyword != RID_SHORT |
20131 | && token->keyword != RID_LONG)) |
20132 | cp_parser_set_decl_spec_type (decl_specs, |
20133 | type, |
20134 | token, |
20135 | /*type_definition_p=*/false); |
20136 | if (decl_specs) |
20137 | decl_specs->any_specifiers_p = true; |
20138 | |
20139 | /* Consume the token. */ |
20140 | cp_lexer_consume_token (lexer: parser->lexer); |
20141 | |
20142 | if (type == error_mark_node) |
20143 | return error_mark_node; |
20144 | |
20145 | /* There is no valid C++ program where a non-template type is |
20146 | followed by a "<". That usually indicates that the user thought |
20147 | that the type was a template. */ |
20148 | cp_parser_check_for_invalid_template_id (parser, type, tag_type: none_type, |
20149 | location: token->location); |
20150 | |
20151 | return TYPE_NAME (type); |
20152 | } |
20153 | |
20154 | /* The type-specifier must be a user-defined type. */ |
20155 | if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES)) |
20156 | { |
20157 | bool qualified_p; |
20158 | bool global_p; |
20159 | const bool typename_p = (cxx_dialect >= cxx20 |
20160 | && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
20161 | |
20162 | /* Don't gobble tokens or issue error messages if this is an |
20163 | optional type-specifier. */ |
20164 | if (flags & CP_PARSER_FLAGS_OPTIONAL) |
20165 | cp_parser_parse_tentatively (parser); |
20166 | |
20167 | /* Remember current tentative parsing state -- if we know we need |
20168 | a type, we can give better diagnostics here. */ |
20169 | bool tent = cp_parser_parsing_tentatively (parser); |
20170 | |
20171 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20172 | |
20173 | /* Look for the optional `::' operator. */ |
20174 | global_p |
20175 | = (cp_parser_global_scope_opt (parser, |
20176 | /*current_scope_valid_p=*/false) |
20177 | != NULL_TREE); |
20178 | /* Look for the nested-name specifier. */ |
20179 | qualified_p |
20180 | = (cp_parser_nested_name_specifier_opt (parser, |
20181 | /*typename_keyword_p=*/false, |
20182 | /*check_dependency_p=*/true, |
20183 | /*type_p=*/false, |
20184 | /*is_declaration=*/false) |
20185 | != NULL_TREE); |
20186 | /* If we have seen a nested-name-specifier, and the next token |
20187 | is `template', then we are using the template-id production. */ |
20188 | if (parser->scope |
20189 | && cp_parser_optional_template_keyword (parser)) |
20190 | { |
20191 | /* Look for the template-id. */ |
20192 | type = cp_parser_template_id (parser, |
20193 | /*template_keyword_p=*/true, |
20194 | /*check_dependency_p=*/true, |
20195 | tag_type: none_type, |
20196 | /*is_declaration=*/false); |
20197 | /* If the template-id did not name a type, we are out of |
20198 | luck. */ |
20199 | if (TREE_CODE (type) != TYPE_DECL) |
20200 | { |
20201 | /* ...unless we pretend we have seen 'typename'. */ |
20202 | if (typename_p) |
20203 | type = cp_parser_make_typename_type (parser, id: type, |
20204 | id_location: token->location); |
20205 | else |
20206 | { |
20207 | cp_parser_error (parser, gmsgid: "expected template-id for type" ); |
20208 | type = error_mark_node; |
20209 | } |
20210 | } |
20211 | } |
20212 | /* DR 1812: A < following a qualified-id in a typename-specifier |
20213 | could safely be assumed to begin a template argument list, so |
20214 | the template keyword should be optional. */ |
20215 | else if (parser->scope |
20216 | && qualified_p |
20217 | && typename_p |
20218 | && cp_lexer_next_token_is (lexer: parser->lexer, CPP_TEMPLATE_ID)) |
20219 | { |
20220 | cp_parser_parse_tentatively (parser); |
20221 | |
20222 | type = cp_parser_template_id (parser, |
20223 | /*template_keyword_p=*/true, |
20224 | /*check_dependency_p=*/true, |
20225 | tag_type: none_type, |
20226 | /*is_declaration=*/false); |
20227 | /* This is handled below, so back off. */ |
20228 | if (type && concept_check_p (t: type)) |
20229 | cp_parser_simulate_error (parser); |
20230 | |
20231 | if (!cp_parser_parse_definitely (parser)) |
20232 | type = NULL_TREE; |
20233 | else if (TREE_CODE (type) == TEMPLATE_ID_EXPR) |
20234 | type = make_typename_type (parser->scope, type, typename_type, |
20235 | /*complain=*/tf_error); |
20236 | else if (TREE_CODE (type) != TYPE_DECL) |
20237 | type = NULL_TREE; |
20238 | } |
20239 | |
20240 | /* Otherwise, look for a type-name. */ |
20241 | if (!type) |
20242 | { |
20243 | if (cxx_dialect >= cxx17 || flag_concepts) |
20244 | cp_parser_parse_tentatively (parser); |
20245 | |
20246 | type = cp_parser_type_name (parser, (qualified_p && typename_p)); |
20247 | |
20248 | if ((cxx_dialect >= cxx17 || flag_concepts) |
20249 | && !cp_parser_parse_definitely (parser)) |
20250 | type = NULL_TREE; |
20251 | } |
20252 | |
20253 | if (!type && flag_concepts && decl_specs) |
20254 | { |
20255 | /* Try for a type-constraint with template arguments. We check |
20256 | decl_specs here to avoid trying this for a functional cast. */ |
20257 | |
20258 | cp_parser_parse_tentatively (parser); |
20259 | |
20260 | type = cp_parser_template_id (parser, |
20261 | /*template_keyword_p=*/false, |
20262 | /*check_dependency_p=*/true, |
20263 | tag_type: none_type, |
20264 | /*is_declaration=*/false); |
20265 | if (type && concept_check_p (t: type)) |
20266 | { |
20267 | location_t loc = EXPR_LOCATION (type); |
20268 | type = cp_parser_placeholder_type_specifier (parser, loc, |
20269 | type, tent); |
20270 | if (tent && type == error_mark_node) |
20271 | /* Perhaps it's a concept-check expression. */ |
20272 | cp_parser_simulate_error (parser); |
20273 | } |
20274 | else |
20275 | cp_parser_simulate_error (parser); |
20276 | |
20277 | if (!cp_parser_parse_definitely (parser)) |
20278 | type = NULL_TREE; |
20279 | } |
20280 | |
20281 | if (!type && cxx_dialect >= cxx17) |
20282 | { |
20283 | /* Try class template argument deduction or type-constraint without |
20284 | template arguments. */ |
20285 | tree name = cp_parser_identifier (parser); |
20286 | if (name && TREE_CODE (name) == IDENTIFIER_NODE |
20287 | && parser->scope != error_mark_node) |
20288 | { |
20289 | location_t loc |
20290 | = cp_lexer_previous_token (lexer: parser->lexer)->location; |
20291 | tree tmpl = cp_parser_lookup_name (parser, name, |
20292 | none_type, |
20293 | /*is_template=*/false, |
20294 | /*is_namespace=*/false, |
20295 | /*check_dependency=*/true, |
20296 | /*ambiguous_decls=*/NULL, |
20297 | token->location); |
20298 | if (tmpl && tmpl != error_mark_node |
20299 | && ctad_template_p (tmpl)) |
20300 | type = make_template_placeholder (tmpl); |
20301 | else if (flag_concepts && tmpl && concept_definition_p (t: tmpl)) |
20302 | type = cp_parser_placeholder_type_specifier (parser, loc, |
20303 | tmpl, tent); |
20304 | else |
20305 | { |
20306 | type = error_mark_node; |
20307 | if (!cp_parser_simulate_error (parser)) |
20308 | cp_parser_name_lookup_error (parser, name, decl: tmpl, |
20309 | desired: NLE_TYPE, location: token->location); |
20310 | } |
20311 | } |
20312 | else |
20313 | type = error_mark_node; |
20314 | } |
20315 | |
20316 | /* If it didn't work out, we don't have a TYPE. */ |
20317 | if ((flags & CP_PARSER_FLAGS_OPTIONAL) |
20318 | && !cp_parser_parse_definitely (parser)) |
20319 | type = NULL_TREE; |
20320 | |
20321 | /* Keep track of all name-lookups performed in class scopes. */ |
20322 | if (type |
20323 | && !global_p |
20324 | && !qualified_p |
20325 | && TREE_CODE (type) == TYPE_DECL |
20326 | && identifier_p (DECL_NAME (type))) |
20327 | maybe_note_name_used_in_class (DECL_NAME (type), type); |
20328 | |
20329 | if (type && decl_specs) |
20330 | cp_parser_set_decl_spec_type (decl_specs, type, |
20331 | token, |
20332 | /*type_definition_p=*/false); |
20333 | } |
20334 | |
20335 | /* If we didn't get a type-name, issue an error message. */ |
20336 | if (!type && !(flags & CP_PARSER_FLAGS_OPTIONAL)) |
20337 | { |
20338 | cp_parser_error (parser, gmsgid: "expected type-name" ); |
20339 | return error_mark_node; |
20340 | } |
20341 | |
20342 | if (type && type != error_mark_node) |
20343 | { |
20344 | /* See if TYPE is an Objective-C type, and if so, parse and |
20345 | accept any protocol references following it. Do this before |
20346 | the cp_parser_check_for_invalid_template_id() call, because |
20347 | Objective-C types can be followed by '<...>' which would |
20348 | enclose protocol names rather than template arguments, and so |
20349 | everything is fine. */ |
20350 | if (c_dialect_objc () && !parser->scope |
20351 | && (objc_is_id (type) || objc_is_class_name (type))) |
20352 | { |
20353 | tree protos = cp_parser_objc_protocol_refs_opt (parser); |
20354 | tree qual_type = objc_get_protocol_qualified_type (type, protos); |
20355 | |
20356 | /* Clobber the "unqualified" type previously entered into |
20357 | DECL_SPECS with the new, improved protocol-qualified version. */ |
20358 | if (decl_specs) |
20359 | decl_specs->type = qual_type; |
20360 | |
20361 | return qual_type; |
20362 | } |
20363 | |
20364 | /* There is no valid C++ program where a non-template type is |
20365 | followed by a "<". That usually indicates that the user |
20366 | thought that the type was a template. */ |
20367 | cp_parser_check_for_invalid_template_id (parser, type, |
20368 | tag_type: none_type, |
20369 | location: token->location); |
20370 | } |
20371 | |
20372 | return type; |
20373 | } |
20374 | |
20375 | /* Parse the remainder of a placholder-type-specifier. |
20376 | |
20377 | placeholder-type-specifier: |
20378 | type-constraint_opt auto |
20379 | type-constraint_opt decltype(auto) |
20380 | |
20381 | The raw form of the constraint is parsed in cp_parser_simple_type_specifier |
20382 | and passed as TMPL. This function converts TMPL to an actual type-constraint, |
20383 | parses the placeholder type, and performs some contextual syntactic analysis. |
20384 | |
20385 | LOC provides the location of the template name. |
20386 | |
20387 | TENTATIVE is true if the type-specifier parsing is tentative; in that case, |
20388 | don't give an error if TMPL isn't a valid type-constraint, as the template-id |
20389 | might actually be a concept-check, |
20390 | |
20391 | Note that the Concepts TS allows the auto or decltype(auto) to be |
20392 | omitted in a constrained-type-specifier. */ |
20393 | |
20394 | static tree |
20395 | cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, |
20396 | tree tmpl, bool tentative) |
20397 | { |
20398 | if (tmpl == error_mark_node) |
20399 | return error_mark_node; |
20400 | |
20401 | tree orig_tmpl = tmpl; |
20402 | |
20403 | /* Get the arguments as written for subsequent analysis. */ |
20404 | tree args = NULL_TREE; |
20405 | if (TREE_CODE (tmpl) == TEMPLATE_ID_EXPR) |
20406 | { |
20407 | args = TREE_OPERAND (tmpl, 1); |
20408 | tmpl = TREE_OPERAND (tmpl, 0); |
20409 | } |
20410 | else |
20411 | /* A concept-name with no arguments can't be an expression. */ |
20412 | tentative = false; |
20413 | |
20414 | tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error; |
20415 | |
20416 | /* Get the concept and prototype parameter for the constraint. */ |
20417 | tree_pair info = finish_type_constraints (tmpl, args, complain); |
20418 | tree con = info.first; |
20419 | tree proto = info.second; |
20420 | if (con == error_mark_node) |
20421 | return error_mark_node; |
20422 | |
20423 | /* As per the standard, require auto or decltype(auto), except in some |
20424 | cases (template parameter lists, -fconcepts-ts enabled). */ |
20425 | cp_token *placeholder = NULL, *close_paren = NULL; |
20426 | if (cxx_dialect >= cxx20) |
20427 | { |
20428 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
20429 | placeholder = cp_lexer_consume_token (lexer: parser->lexer); |
20430 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DECLTYPE)) |
20431 | { |
20432 | placeholder = cp_lexer_consume_token (lexer: parser->lexer); |
20433 | matching_parens parens; |
20434 | parens.require_open (parser); |
20435 | cp_parser_require_keyword (parser, RID_AUTO, RT_AUTO); |
20436 | close_paren = parens.require_close (parser); |
20437 | } |
20438 | } |
20439 | |
20440 | /* A type constraint constrains a contextually determined type or type |
20441 | parameter pack. However, the Concepts TS does allow concepts |
20442 | to introduce non-type and template template parameters. */ |
20443 | if (TREE_CODE (proto) != TYPE_DECL) |
20444 | { |
20445 | if (!flag_concepts_ts |
20446 | || !processing_template_parmlist) |
20447 | { |
20448 | if (!tentative) |
20449 | { |
20450 | error_at (loc, "%qE does not constrain a type" , DECL_NAME (con)); |
20451 | inform (DECL_SOURCE_LOCATION (con), "concept defined here" ); |
20452 | } |
20453 | return error_mark_node; |
20454 | } |
20455 | } |
20456 | |
20457 | /* In a template parameter list, a type-parameter can be introduced |
20458 | by type-constraints alone. */ |
20459 | if (processing_template_parmlist && !placeholder) |
20460 | { |
20461 | /* In a default argument we may not be creating new parameters. */ |
20462 | if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) |
20463 | { |
20464 | /* If this assert turns out to be false, do error() instead. */ |
20465 | gcc_assert (tentative); |
20466 | return error_mark_node; |
20467 | } |
20468 | return build_constrained_parameter (con, proto, args); |
20469 | } |
20470 | |
20471 | /* Diagnose issues placeholder issues. */ |
20472 | if (!flag_concepts_ts |
20473 | && !parser->in_result_type_constraint_p |
20474 | && !placeholder) |
20475 | { |
20476 | if (tentative) |
20477 | /* Perhaps it's a concept-check expression (c++/91073). */ |
20478 | return error_mark_node; |
20479 | |
20480 | tree id = build_nt (TEMPLATE_ID_EXPR, tmpl, args); |
20481 | tree expr = DECL_P (orig_tmpl) ? DECL_NAME (con) : id; |
20482 | error_at (input_location, |
20483 | "expected %<auto%> or %<decltype(auto)%> after %qE" , expr); |
20484 | /* Fall through. This is an error of omission. */ |
20485 | } |
20486 | else if (parser->in_result_type_constraint_p && placeholder) |
20487 | { |
20488 | /* A trailing return type only allows type-constraints. */ |
20489 | error_at (input_location, |
20490 | "unexpected placeholder in constrained result type" ); |
20491 | } |
20492 | |
20493 | /* In a parameter-declaration-clause, a placeholder-type-specifier |
20494 | results in an invented template parameter. */ |
20495 | if (parser->auto_is_implicit_function_template_parm_p) |
20496 | { |
20497 | if (close_paren) |
20498 | { |
20499 | location_t loc = make_location (caret: placeholder->location, |
20500 | start: placeholder->location, |
20501 | finish: close_paren->location); |
20502 | error_at (loc, "cannot declare a parameter with %<decltype(auto)%>" ); |
20503 | return error_mark_node; |
20504 | } |
20505 | tree parm = build_constrained_parameter (con, proto, args); |
20506 | return synthesize_implicit_template_parm (parser, parm); |
20507 | } |
20508 | |
20509 | /* Determine if the type should be deduced using template argument |
20510 | deduction or decltype deduction. Note that the latter is always |
20511 | used for type-constraints in trailing return types. */ |
20512 | bool decltype_p = placeholder |
20513 | ? placeholder->keyword == RID_DECLTYPE |
20514 | : parser->in_result_type_constraint_p; |
20515 | |
20516 | /* Otherwise, this is the type of a variable or return type. */ |
20517 | if (decltype_p) |
20518 | return make_constrained_decltype_auto (con, args); |
20519 | else |
20520 | return make_constrained_auto (con, args); |
20521 | } |
20522 | |
20523 | /* Parse a type-name. |
20524 | |
20525 | type-name: |
20526 | class-name |
20527 | enum-name |
20528 | typedef-name |
20529 | simple-template-id [in c++0x] |
20530 | |
20531 | enum-name: |
20532 | identifier |
20533 | |
20534 | typedef-name: |
20535 | identifier |
20536 | |
20537 | Concepts: |
20538 | |
20539 | type-name: |
20540 | concept-name |
20541 | partial-concept-id |
20542 | |
20543 | concept-name: |
20544 | identifier |
20545 | |
20546 | Returns a TYPE_DECL for the type. */ |
20547 | |
20548 | static tree |
20549 | cp_parser_type_name (cp_parser* parser, bool typename_keyword_p) |
20550 | { |
20551 | tree type_decl; |
20552 | |
20553 | /* We can't know yet whether it is a class-name or not. */ |
20554 | cp_parser_parse_tentatively (parser); |
20555 | /* Try a class-name. */ |
20556 | type_decl = cp_parser_class_name (parser, |
20557 | typename_keyword_p, |
20558 | /*template_keyword_p=*/false, |
20559 | none_type, |
20560 | /*check_dependency_p=*/true, |
20561 | /*class_head_p=*/false, |
20562 | /*is_declaration=*/false); |
20563 | /* If it's not a class-name, keep looking. */ |
20564 | if (!cp_parser_parse_definitely (parser)) |
20565 | { |
20566 | if (cxx_dialect < cxx11) |
20567 | /* It must be a typedef-name or an enum-name. */ |
20568 | return cp_parser_nonclass_name (parser); |
20569 | |
20570 | cp_parser_parse_tentatively (parser); |
20571 | /* It is either a simple-template-id representing an |
20572 | instantiation of an alias template... */ |
20573 | type_decl = cp_parser_template_id (parser, |
20574 | /*template_keyword_p=*/false, |
20575 | /*check_dependency_p=*/true, |
20576 | tag_type: none_type, |
20577 | /*is_declaration=*/false); |
20578 | /* Note that this must be an instantiation of an alias template |
20579 | because [temp.names]/6 says: |
20580 | |
20581 | A template-id that names an alias template specialization |
20582 | is a type-name. |
20583 | |
20584 | Whereas [temp.names]/7 says: |
20585 | |
20586 | A simple-template-id that names a class template |
20587 | specialization is a class-name. |
20588 | |
20589 | With concepts, this could also be a partial-concept-id that |
20590 | declares a non-type template parameter. */ |
20591 | if (type_decl != NULL_TREE |
20592 | && TREE_CODE (type_decl) == TYPE_DECL |
20593 | && TYPE_DECL_ALIAS_P (type_decl)) |
20594 | gcc_assert (DECL_TEMPLATE_INSTANTIATION (type_decl)); |
20595 | else |
20596 | cp_parser_simulate_error (parser); |
20597 | |
20598 | if (!cp_parser_parse_definitely (parser)) |
20599 | /* ... Or a typedef-name or an enum-name. */ |
20600 | return cp_parser_nonclass_name (parser); |
20601 | } |
20602 | |
20603 | return type_decl; |
20604 | } |
20605 | |
20606 | /* Parse a non-class type-name, that is, either an enum-name, a typedef-name, |
20607 | or a concept-name. |
20608 | |
20609 | enum-name: |
20610 | identifier |
20611 | |
20612 | typedef-name: |
20613 | identifier |
20614 | |
20615 | concept-name: |
20616 | identifier |
20617 | |
20618 | Returns a TYPE_DECL for the type. */ |
20619 | |
20620 | static tree |
20621 | cp_parser_nonclass_name (cp_parser* parser) |
20622 | { |
20623 | tree type_decl; |
20624 | tree identifier; |
20625 | |
20626 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
20627 | identifier = cp_parser_identifier (parser); |
20628 | if (identifier == error_mark_node) |
20629 | return error_mark_node; |
20630 | |
20631 | /* Look up the type-name. */ |
20632 | type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); |
20633 | |
20634 | type_decl = strip_using_decl (type_decl); |
20635 | |
20636 | if (TREE_CODE (type_decl) != TYPE_DECL |
20637 | && (objc_is_id (identifier) || objc_is_class_name (identifier))) |
20638 | { |
20639 | /* See if this is an Objective-C type. */ |
20640 | tree protos = cp_parser_objc_protocol_refs_opt (parser); |
20641 | tree type = objc_get_protocol_qualified_type (identifier, protos); |
20642 | if (type) |
20643 | type_decl = TYPE_NAME (type); |
20644 | } |
20645 | |
20646 | /* Issue an error if we did not find a type-name. */ |
20647 | if (TREE_CODE (type_decl) != TYPE_DECL |
20648 | /* In Objective-C, we have the complication that class names are |
20649 | normally type names and start declarations (eg, the |
20650 | "NSObject" in "NSObject *object;"), but can be used in an |
20651 | Objective-C 2.0 dot-syntax (as in "NSObject.version") which |
20652 | is an expression. So, a classname followed by a dot is not a |
20653 | valid type-name. */ |
20654 | || (objc_is_class_name (TREE_TYPE (type_decl)) |
20655 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT)) |
20656 | { |
20657 | if (!cp_parser_simulate_error (parser)) |
20658 | cp_parser_name_lookup_error (parser, name: identifier, decl: type_decl, |
20659 | desired: NLE_TYPE, location: token->location); |
20660 | return error_mark_node; |
20661 | } |
20662 | /* Remember that the name was used in the definition of the |
20663 | current class so that we can check later to see if the |
20664 | meaning would have been different after the class was |
20665 | entirely defined. */ |
20666 | else if (type_decl != error_mark_node |
20667 | && !parser->scope) |
20668 | maybe_note_name_used_in_class (identifier, type_decl); |
20669 | |
20670 | return type_decl; |
20671 | } |
20672 | |
20673 | /* Parse an elaborated-type-specifier. Note that the grammar given |
20674 | here incorporates the resolution to DR68. |
20675 | |
20676 | elaborated-type-specifier: |
20677 | class-key :: [opt] nested-name-specifier [opt] identifier |
20678 | class-key :: [opt] nested-name-specifier [opt] template [opt] template-id |
20679 | enum-key :: [opt] nested-name-specifier [opt] identifier |
20680 | typename :: [opt] nested-name-specifier identifier |
20681 | typename :: [opt] nested-name-specifier template [opt] |
20682 | template-id |
20683 | |
20684 | GNU extension: |
20685 | |
20686 | elaborated-type-specifier: |
20687 | class-key attributes :: [opt] nested-name-specifier [opt] identifier |
20688 | class-key attributes :: [opt] nested-name-specifier [opt] |
20689 | template [opt] template-id |
20690 | enum attributes :: [opt] nested-name-specifier [opt] identifier |
20691 | |
20692 | If IS_FRIEND is TRUE, then this elaborated-type-specifier is being |
20693 | declared `friend'. If IS_DECLARATION is TRUE, then this |
20694 | elaborated-type-specifier appears in a decl-specifiers-seq, i.e., |
20695 | something is being declared. |
20696 | |
20697 | Returns the TYPE specified. */ |
20698 | |
20699 | static tree |
20700 | cp_parser_elaborated_type_specifier (cp_parser* parser, |
20701 | bool is_friend, |
20702 | bool is_declaration) |
20703 | { |
20704 | enum tag_types tag_type; |
20705 | tree identifier; |
20706 | tree type = NULL_TREE; |
20707 | tree attributes = NULL_TREE; |
20708 | tree globalscope; |
20709 | cp_token *token = NULL; |
20710 | |
20711 | /* For class and enum types the location of the class-key or enum-key. */ |
20712 | location_t key_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
20713 | /* For a scoped enum, the 'class' or 'struct' keyword id. */ |
20714 | rid scoped_key = RID_MAX; |
20715 | |
20716 | /* See if we're looking at the `enum' keyword. */ |
20717 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ENUM)) |
20718 | { |
20719 | /* Consume the `enum' token. */ |
20720 | cp_lexer_consume_token (lexer: parser->lexer); |
20721 | /* Remember that it's an enumeration type. */ |
20722 | tag_type = enum_type; |
20723 | /* Issue a warning if the `struct' or `class' key (for C++0x scoped |
20724 | enums) is used here. */ |
20725 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
20726 | if (cp_parser_is_keyword (token, keyword: scoped_key = RID_CLASS) |
20727 | || cp_parser_is_keyword (token, keyword: scoped_key = RID_STRUCT)) |
20728 | { |
20729 | location_t loc = token->location; |
20730 | gcc_rich_location richloc (loc); |
20731 | richloc.add_range (loc: input_location); |
20732 | richloc.add_fixit_remove (); |
20733 | pedwarn (&richloc, 0, "elaborated-type-specifier for " |
20734 | "a scoped enum must not use the %qD keyword" , |
20735 | token->u.value); |
20736 | /* Consume the `struct' or `class' and parse it anyway. */ |
20737 | cp_lexer_consume_token (lexer: parser->lexer); |
20738 | /* Create a combined location for the whole scoped-enum-key. */ |
20739 | key_loc = make_location (caret: key_loc, start: key_loc, finish: loc); |
20740 | } |
20741 | else |
20742 | scoped_key = RID_MAX; |
20743 | |
20744 | /* Parse the attributes. */ |
20745 | attributes = cp_parser_attributes_opt (parser); |
20746 | } |
20747 | /* Or, it might be `typename'. */ |
20748 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
20749 | keyword: RID_TYPENAME)) |
20750 | { |
20751 | /* Consume the `typename' token. */ |
20752 | cp_lexer_consume_token (lexer: parser->lexer); |
20753 | /* Remember that it's a `typename' type. */ |
20754 | tag_type = typename_type; |
20755 | } |
20756 | /* Otherwise it must be a class-key. */ |
20757 | else |
20758 | { |
20759 | key_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
20760 | tag_type = cp_parser_class_key (parser); |
20761 | if (tag_type == none_type) |
20762 | return error_mark_node; |
20763 | /* Parse the attributes. */ |
20764 | attributes = cp_parser_attributes_opt (parser); |
20765 | } |
20766 | |
20767 | /* Look for the `::' operator. */ |
20768 | globalscope = cp_parser_global_scope_opt (parser, |
20769 | /*current_scope_valid_p=*/false); |
20770 | /* Look for the nested-name-specifier. */ |
20771 | tree nested_name_specifier; |
20772 | if (tag_type == typename_type && !globalscope) |
20773 | { |
20774 | nested_name_specifier |
20775 | = cp_parser_nested_name_specifier (parser, |
20776 | /*typename_keyword_p=*/true, |
20777 | /*check_dependency_p=*/true, |
20778 | /*type_p=*/true, |
20779 | is_declaration); |
20780 | if (!nested_name_specifier) |
20781 | return error_mark_node; |
20782 | } |
20783 | else |
20784 | /* Even though `typename' is not present, the proposed resolution |
20785 | to Core Issue 180 says that in `class A<T>::B', `B' should be |
20786 | considered a type-name, even if `A<T>' is dependent. */ |
20787 | nested_name_specifier |
20788 | = cp_parser_nested_name_specifier_opt (parser, |
20789 | /*typename_keyword_p=*/true, |
20790 | /*check_dependency_p=*/true, |
20791 | /*type_p=*/true, |
20792 | is_declaration); |
20793 | /* For everything but enumeration types, consider a template-id. |
20794 | For an enumeration type, consider only a plain identifier. */ |
20795 | if (tag_type != enum_type) |
20796 | { |
20797 | bool template_p = false; |
20798 | tree decl; |
20799 | |
20800 | /* Allow the `template' keyword. */ |
20801 | template_p = cp_parser_optional_template_keyword (parser); |
20802 | /* If we didn't see `template', we don't know if there's a |
20803 | template-id or not. */ |
20804 | if (!template_p) |
20805 | cp_parser_parse_tentatively (parser); |
20806 | /* The `template' keyword must follow a nested-name-specifier. */ |
20807 | else if (!nested_name_specifier && !globalscope) |
20808 | { |
20809 | cp_parser_error (parser, gmsgid: "%<template%> must follow a nested-" |
20810 | "name-specifier" ); |
20811 | return error_mark_node; |
20812 | } |
20813 | |
20814 | /* Parse the template-id. */ |
20815 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20816 | decl = cp_parser_template_id (parser, template_keyword_p: template_p, |
20817 | /*check_dependency_p=*/true, |
20818 | tag_type, |
20819 | is_declaration); |
20820 | /* If we didn't find a template-id, look for an ordinary |
20821 | identifier. */ |
20822 | if (!template_p && !cp_parser_parse_definitely (parser)) |
20823 | ; |
20824 | /* We can get here when cp_parser_template_id, called by |
20825 | cp_parser_class_name with tag_type == none_type, succeeds |
20826 | and caches a BASELINK. Then, when called again here, |
20827 | instead of failing and returning an error_mark_node |
20828 | returns it (see template/typename17.C in C++11). |
20829 | ??? Could we diagnose this earlier? */ |
20830 | else if (tag_type == typename_type && BASELINK_P (decl)) |
20831 | { |
20832 | cp_parser_diagnose_invalid_type_name (parser, id: decl, location: token->location); |
20833 | type = error_mark_node; |
20834 | } |
20835 | /* If DECL is a TEMPLATE_ID_EXPR, and the `typename' keyword is |
20836 | in effect, then we must assume that, upon instantiation, the |
20837 | template will correspond to a class. */ |
20838 | else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR |
20839 | && tag_type == typename_type) |
20840 | type = make_typename_type (parser->scope, decl, |
20841 | typename_type, |
20842 | /*complain=*/tf_error); |
20843 | /* If the `typename' keyword is in effect and DECL is not a type |
20844 | decl, then type is non existent. */ |
20845 | else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL) |
20846 | ; |
20847 | else if (TREE_CODE (decl) == TYPE_DECL) |
20848 | { |
20849 | type = check_elaborated_type_specifier (tag_type, decl, |
20850 | /*allow_template_p=*/true); |
20851 | |
20852 | /* If the next token is a semicolon, this must be a specialization, |
20853 | instantiation, or friend declaration. Check the scope while we |
20854 | still know whether or not we had a nested-name-specifier. */ |
20855 | if (type != error_mark_node |
20856 | && !nested_name_specifier && !is_friend |
20857 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
20858 | check_unqualified_spec_or_inst (type, token->location); |
20859 | } |
20860 | else if (decl == error_mark_node) |
20861 | type = error_mark_node; |
20862 | } |
20863 | |
20864 | if (!type) |
20865 | { |
20866 | token = cp_lexer_peek_token (lexer: parser->lexer); |
20867 | identifier = cp_parser_identifier (parser); |
20868 | |
20869 | if (identifier == error_mark_node) |
20870 | { |
20871 | parser->scope = NULL_TREE; |
20872 | return error_mark_node; |
20873 | } |
20874 | |
20875 | /* For a `typename', we needn't call xref_tag. */ |
20876 | if (tag_type == typename_type |
20877 | && TREE_CODE (parser->scope) != NAMESPACE_DECL) |
20878 | return cp_parser_make_typename_type (parser, id: identifier, |
20879 | id_location: token->location); |
20880 | |
20881 | /* Template parameter lists apply only if we are not within a |
20882 | function parameter list. */ |
20883 | bool template_parm_lists_apply |
20884 | = parser->num_template_parameter_lists; |
20885 | if (template_parm_lists_apply) |
20886 | for (cp_binding_level *s = current_binding_level; |
20887 | s && s->kind != sk_template_parms; |
20888 | s = s->level_chain) |
20889 | if (s->kind == sk_function_parms) |
20890 | template_parm_lists_apply = false; |
20891 | |
20892 | /* Look up a qualified name in the usual way. */ |
20893 | if (parser->scope) |
20894 | { |
20895 | tree decl; |
20896 | tree ambiguous_decls; |
20897 | |
20898 | decl = cp_parser_lookup_name (parser, identifier, |
20899 | tag_type, |
20900 | /*is_template=*/false, |
20901 | /*is_namespace=*/false, |
20902 | /*check_dependency=*/true, |
20903 | &ambiguous_decls, |
20904 | token->location); |
20905 | |
20906 | /* If the lookup was ambiguous, an error will already have been |
20907 | issued. */ |
20908 | if (ambiguous_decls) |
20909 | return error_mark_node; |
20910 | |
20911 | /* If we are parsing friend declaration, DECL may be a |
20912 | TEMPLATE_DECL tree node here. However, we need to check |
20913 | whether this TEMPLATE_DECL results in valid code. Consider |
20914 | the following example: |
20915 | |
20916 | namespace N { |
20917 | template <class T> class C {}; |
20918 | } |
20919 | class X { |
20920 | template <class T> friend class N::C; // #1, valid code |
20921 | }; |
20922 | template <class T> class Y { |
20923 | friend class N::C; // #2, invalid code |
20924 | }; |
20925 | |
20926 | For both case #1 and #2, we arrive at a TEMPLATE_DECL after |
20927 | name lookup of `N::C'. We see that friend declaration must |
20928 | be template for the code to be valid. Note that |
20929 | processing_template_decl does not work here since it is |
20930 | always 1 for the above two cases. */ |
20931 | |
20932 | decl = (cp_parser_maybe_treat_template_as_class |
20933 | (decl, /*tag_name_p=*/is_friend |
20934 | && template_parm_lists_apply)); |
20935 | |
20936 | if (TREE_CODE (decl) != TYPE_DECL) |
20937 | { |
20938 | cp_parser_diagnose_invalid_type_name (parser, |
20939 | id: identifier, |
20940 | location: token->location); |
20941 | return error_mark_node; |
20942 | } |
20943 | |
20944 | if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE) |
20945 | { |
20946 | bool allow_template = (template_parm_lists_apply |
20947 | || DECL_SELF_REFERENCE_P (decl)); |
20948 | type = check_elaborated_type_specifier (tag_type, decl, |
20949 | allow_template); |
20950 | |
20951 | if (type == error_mark_node) |
20952 | return error_mark_node; |
20953 | } |
20954 | |
20955 | /* Forward declarations of nested types, such as |
20956 | |
20957 | class C1::C2; |
20958 | class C1::C2::C3; |
20959 | |
20960 | are invalid unless all components preceding the final '::' |
20961 | are complete. If all enclosing types are complete, these |
20962 | declarations become merely pointless. |
20963 | |
20964 | Invalid forward declarations of nested types are errors |
20965 | caught elsewhere in parsing. Those that are pointless arrive |
20966 | here. */ |
20967 | |
20968 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
20969 | && !is_friend && is_declaration |
20970 | && !processing_explicit_instantiation) |
20971 | warning (0, "declaration %qD does not declare anything" , decl); |
20972 | |
20973 | type = TREE_TYPE (decl); |
20974 | } |
20975 | else |
20976 | { |
20977 | /* An elaborated-type-specifier sometimes introduces a new type and |
20978 | sometimes names an existing type. Normally, the rule is that it |
20979 | introduces a new type only if there is not an existing type of |
20980 | the same name already in scope. For example, given: |
20981 | |
20982 | struct S {}; |
20983 | void f() { struct S s; } |
20984 | |
20985 | the `struct S' in the body of `f' is the same `struct S' as in |
20986 | the global scope; the existing definition is used. However, if |
20987 | there were no global declaration, this would introduce a new |
20988 | local class named `S'. |
20989 | |
20990 | An exception to this rule applies to the following code: |
20991 | |
20992 | namespace N { struct S; } |
20993 | |
20994 | Here, the elaborated-type-specifier names a new type |
20995 | unconditionally; even if there is already an `S' in the |
20996 | containing scope this declaration names a new type. |
20997 | This exception only applies if the elaborated-type-specifier |
20998 | forms the complete declaration: |
20999 | |
21000 | [class.name] |
21001 | |
21002 | A declaration consisting solely of `class-key identifier ;' is |
21003 | either a redeclaration of the name in the current scope or a |
21004 | forward declaration of the identifier as a class name. It |
21005 | introduces the name into the current scope. |
21006 | |
21007 | We are in this situation precisely when the next token is a `;'. |
21008 | |
21009 | An exception to the exception is that a `friend' declaration does |
21010 | *not* name a new type; i.e., given: |
21011 | |
21012 | struct S { friend struct T; }; |
21013 | |
21014 | `T' is not a new type in the scope of `S'. |
21015 | |
21016 | Also, `new struct S' or `sizeof (struct S)' never results in the |
21017 | definition of a new type; a new type can only be declared in a |
21018 | declaration context. */ |
21019 | |
21020 | TAG_how how; |
21021 | |
21022 | if (is_friend) |
21023 | /* Friends have special name lookup rules. */ |
21024 | how = TAG_how::HIDDEN_FRIEND; |
21025 | else if (is_declaration |
21026 | && cp_lexer_next_token_is (lexer: parser->lexer, |
21027 | type: CPP_SEMICOLON)) |
21028 | /* This is a `class-key identifier ;' */ |
21029 | how = TAG_how::CURRENT_ONLY; |
21030 | else |
21031 | how = TAG_how::GLOBAL; |
21032 | |
21033 | bool template_p = |
21034 | (template_parm_lists_apply |
21035 | && (cp_parser_next_token_starts_class_definition_p (parser) |
21036 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON))); |
21037 | /* An unqualified name was used to reference this type, so |
21038 | there were no qualifying templates. */ |
21039 | if (template_parm_lists_apply |
21040 | && !cp_parser_check_template_parameters (parser, |
21041 | /*num_templates=*/0, |
21042 | /*template_id*/false, |
21043 | token->location, |
21044 | /*declarator=*/NULL)) |
21045 | return error_mark_node; |
21046 | |
21047 | type = xref_tag (tag_type, identifier, how, tpl_header_p: template_p); |
21048 | } |
21049 | } |
21050 | |
21051 | if (type == error_mark_node) |
21052 | return error_mark_node; |
21053 | |
21054 | /* Allow attributes on forward declarations of classes. */ |
21055 | if (attributes) |
21056 | { |
21057 | if (TREE_CODE (type) == TYPENAME_TYPE) |
21058 | warning (OPT_Wattributes, |
21059 | "attributes ignored on uninstantiated type" ); |
21060 | else if (tag_type != enum_type |
21061 | && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM |
21062 | && CLASSTYPE_TEMPLATE_INSTANTIATION (type) |
21063 | && ! processing_explicit_instantiation) |
21064 | warning (OPT_Wattributes, |
21065 | "attributes ignored on template instantiation" ); |
21066 | else if (is_friend && cxx11_attribute_p (attributes)) |
21067 | { |
21068 | if (warning (OPT_Wattributes, "attribute ignored" )) |
21069 | inform (input_location, "an attribute that appertains to a friend " |
21070 | "declaration that is not a definition is ignored" ); |
21071 | } |
21072 | else if (is_declaration && cp_parser_declares_only_class_p (parser)) |
21073 | cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); |
21074 | else |
21075 | warning (OPT_Wattributes, |
21076 | "attributes ignored on elaborated-type-specifier that is " |
21077 | "not a forward declaration" ); |
21078 | } |
21079 | |
21080 | if (tag_type == enum_type) |
21081 | cp_parser_maybe_warn_enum_key (parser, key_loc, type, scoped_key); |
21082 | else |
21083 | { |
21084 | /* Diagnose class/struct/union mismatches. IS_DECLARATION is false |
21085 | for alias definition. */ |
21086 | bool decl_class = (is_declaration |
21087 | && cp_parser_declares_only_class_p (parser)); |
21088 | cp_parser_check_class_key (parser, key_loc, tag_type, type, false, |
21089 | decl_class); |
21090 | |
21091 | /* Indicate whether this class was declared as a `class' or as a |
21092 | `struct'. */ |
21093 | if (CLASS_TYPE_P (type) && !currently_open_class (type)) |
21094 | CLASSTYPE_DECLARED_CLASS (type) = (tag_type == class_type); |
21095 | } |
21096 | |
21097 | /* A "<" cannot follow an elaborated type specifier. If that |
21098 | happens, the user was probably trying to form a template-id. */ |
21099 | cp_parser_check_for_invalid_template_id (parser, type, tag_type, |
21100 | location: token->location); |
21101 | |
21102 | return type; |
21103 | } |
21104 | |
21105 | /* Parse an enum-specifier. |
21106 | |
21107 | enum-specifier: |
21108 | enum-head { enumerator-list [opt] } |
21109 | enum-head { enumerator-list , } [C++0x] |
21110 | |
21111 | enum-head: |
21112 | enum-key identifier [opt] enum-base [opt] |
21113 | enum-key nested-name-specifier identifier enum-base [opt] |
21114 | |
21115 | enum-key: |
21116 | enum |
21117 | enum class [C++0x] |
21118 | enum struct [C++0x] |
21119 | |
21120 | enum-base: [C++0x] |
21121 | : type-specifier-seq |
21122 | |
21123 | opaque-enum-specifier: |
21124 | enum-key identifier enum-base [opt] ; |
21125 | |
21126 | GNU Extensions: |
21127 | enum-key attributes[opt] identifier [opt] enum-base [opt] |
21128 | { enumerator-list [opt] }attributes[opt] |
21129 | enum-key attributes[opt] identifier [opt] enum-base [opt] |
21130 | { enumerator-list, }attributes[opt] [C++0x] |
21131 | |
21132 | Returns an ENUM_TYPE representing the enumeration, or NULL_TREE |
21133 | if the token stream isn't an enum-specifier after all. */ |
21134 | |
21135 | static tree |
21136 | cp_parser_enum_specifier (cp_parser* parser) |
21137 | { |
21138 | tree identifier; |
21139 | tree type = NULL_TREE; |
21140 | tree prev_scope; |
21141 | tree nested_name_specifier = NULL_TREE; |
21142 | tree attributes; |
21143 | bool scoped_enum_p = false; |
21144 | bool has_underlying_type = false; |
21145 | bool nested_being_defined = false; |
21146 | bool new_value_list = false; |
21147 | bool is_new_type = false; |
21148 | bool is_unnamed = false; |
21149 | tree underlying_type = NULL_TREE; |
21150 | cp_token *type_start_token = NULL; |
21151 | auto cleanup = make_temp_override (var&: parser->colon_corrects_to_scope_p, overrider: false); |
21152 | |
21153 | /* Parse tentatively so that we can back up if we don't find a |
21154 | enum-specifier. */ |
21155 | cp_parser_parse_tentatively (parser); |
21156 | |
21157 | /* Caller guarantees that the current token is 'enum', an identifier |
21158 | possibly follows, and the token after that is an opening brace. |
21159 | If we don't have an identifier, fabricate an anonymous name for |
21160 | the enumeration being defined. */ |
21161 | cp_lexer_consume_token (lexer: parser->lexer); |
21162 | |
21163 | /* Parse the "class" or "struct", which indicates a scoped |
21164 | enumeration type in C++0x. */ |
21165 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CLASS) |
21166 | || cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STRUCT)) |
21167 | { |
21168 | if (cxx_dialect < cxx11) |
21169 | maybe_warn_cpp0x (str: CPP0X_SCOPED_ENUMS); |
21170 | |
21171 | /* Consume the `struct' or `class' token. */ |
21172 | cp_lexer_consume_token (lexer: parser->lexer); |
21173 | |
21174 | scoped_enum_p = true; |
21175 | } |
21176 | |
21177 | attributes = cp_parser_attributes_opt (parser); |
21178 | |
21179 | /* Clear the qualification. */ |
21180 | parser->scope = NULL_TREE; |
21181 | parser->qualifying_scope = NULL_TREE; |
21182 | parser->object_scope = NULL_TREE; |
21183 | |
21184 | /* Figure out in what scope the declaration is being placed. */ |
21185 | prev_scope = current_scope (); |
21186 | |
21187 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
21188 | |
21189 | push_deferring_access_checks (dk_no_check); |
21190 | nested_name_specifier |
21191 | = cp_parser_nested_name_specifier_opt (parser, |
21192 | /*typename_keyword_p=*/true, |
21193 | /*check_dependency_p=*/false, |
21194 | /*type_p=*/false, |
21195 | /*is_declaration=*/false); |
21196 | |
21197 | if (nested_name_specifier) |
21198 | { |
21199 | tree name; |
21200 | |
21201 | identifier = cp_parser_identifier (parser); |
21202 | name = cp_parser_lookup_name (parser, identifier, |
21203 | enum_type, |
21204 | /*is_template=*/false, |
21205 | /*is_namespace=*/false, |
21206 | /*check_dependency=*/true, |
21207 | /*ambiguous_decls=*/NULL, |
21208 | input_location); |
21209 | if (name && name != error_mark_node) |
21210 | { |
21211 | type = TREE_TYPE (name); |
21212 | if (TREE_CODE (type) == TYPENAME_TYPE) |
21213 | { |
21214 | /* Are template enums allowed in ISO? */ |
21215 | if (template_parm_scope_p ()) |
21216 | pedwarn (type_start_token->location, OPT_Wpedantic, |
21217 | "%qD is an enumeration template" , name); |
21218 | /* ignore a typename reference, for it will be solved by name |
21219 | in start_enum. */ |
21220 | type = NULL_TREE; |
21221 | } |
21222 | } |
21223 | else if (nested_name_specifier == error_mark_node) |
21224 | /* We already issued an error. */; |
21225 | else |
21226 | { |
21227 | error_at (type_start_token->location, |
21228 | "%qD does not name an enumeration in %qT" , |
21229 | identifier, nested_name_specifier); |
21230 | nested_name_specifier = error_mark_node; |
21231 | } |
21232 | } |
21233 | else |
21234 | { |
21235 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
21236 | identifier = cp_parser_identifier (parser); |
21237 | else |
21238 | { |
21239 | identifier = make_anon_name (); |
21240 | is_unnamed = true; |
21241 | if (scoped_enum_p) |
21242 | error_at (type_start_token->location, |
21243 | "unnamed scoped enum is not allowed" ); |
21244 | } |
21245 | } |
21246 | pop_deferring_access_checks (); |
21247 | |
21248 | /* Check for the `:' that denotes a specified underlying type in C++0x. |
21249 | Note that a ':' could also indicate a bitfield width, however. */ |
21250 | location_t colon_loc = UNKNOWN_LOCATION; |
21251 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
21252 | { |
21253 | cp_decl_specifier_seq type_specifiers; |
21254 | |
21255 | /* Consume the `:'. */ |
21256 | colon_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21257 | cp_lexer_consume_token (lexer: parser->lexer); |
21258 | |
21259 | auto tdf |
21260 | = make_temp_override (var&: parser->type_definition_forbidden_message, |
21261 | G_("types may not be defined in enum-base" )); |
21262 | |
21263 | /* Parse the type-specifier-seq. */ |
21264 | cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE, |
21265 | /*is_declaration=*/false, |
21266 | /*is_trailing_return=*/false, |
21267 | &type_specifiers); |
21268 | |
21269 | /* At this point this is surely not elaborated type specifier. */ |
21270 | if (!cp_parser_parse_definitely (parser)) |
21271 | return NULL_TREE; |
21272 | |
21273 | if (cxx_dialect < cxx11) |
21274 | maybe_warn_cpp0x (str: CPP0X_SCOPED_ENUMS); |
21275 | |
21276 | has_underlying_type = true; |
21277 | |
21278 | /* If that didn't work, stop. */ |
21279 | if (type_specifiers.type != error_mark_node) |
21280 | { |
21281 | underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME, |
21282 | /*initialized=*/0, NULL); |
21283 | if (underlying_type == error_mark_node |
21284 | || check_for_bare_parameter_packs (underlying_type)) |
21285 | underlying_type = NULL_TREE; |
21286 | } |
21287 | } |
21288 | |
21289 | /* Look for the `{' but don't consume it yet. */ |
21290 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
21291 | { |
21292 | if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type)) |
21293 | { |
21294 | if (has_underlying_type) |
21295 | cp_parser_commit_to_tentative_parse (parser); |
21296 | cp_parser_error (parser, gmsgid: "expected %<{%>" ); |
21297 | if (has_underlying_type) |
21298 | return error_mark_node; |
21299 | } |
21300 | /* An opaque-enum-specifier must have a ';' here. */ |
21301 | if ((scoped_enum_p || underlying_type) |
21302 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
21303 | { |
21304 | if (has_underlying_type) |
21305 | pedwarn (colon_loc, |
21306 | OPT_Welaborated_enum_base, |
21307 | "declaration of enumeration with " |
21308 | "fixed underlying type and no enumerator list is " |
21309 | "only permitted as a standalone declaration" ); |
21310 | else |
21311 | cp_parser_error (parser, gmsgid: "expected %<;%> or %<{%>" ); |
21312 | } |
21313 | } |
21314 | |
21315 | if (!has_underlying_type && !cp_parser_parse_definitely (parser)) |
21316 | return NULL_TREE; |
21317 | |
21318 | if (nested_name_specifier) |
21319 | { |
21320 | if (CLASS_TYPE_P (nested_name_specifier)) |
21321 | { |
21322 | nested_being_defined = TYPE_BEING_DEFINED (nested_name_specifier); |
21323 | TYPE_BEING_DEFINED (nested_name_specifier) = 1; |
21324 | push_scope (nested_name_specifier); |
21325 | } |
21326 | else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL) |
21327 | push_nested_namespace (nested_name_specifier); |
21328 | } |
21329 | |
21330 | /* Issue an error message if type-definitions are forbidden here. */ |
21331 | if (!cp_parser_check_type_definition (parser)) |
21332 | type = error_mark_node; |
21333 | else |
21334 | /* Create the new type. We do this before consuming the opening |
21335 | brace so the enum will be recorded as being on the line of its |
21336 | tag (or the 'enum' keyword, if there is no tag). */ |
21337 | type = start_enum (identifier, type, underlying_type, |
21338 | attributes, scoped_enum_p, &is_new_type); |
21339 | |
21340 | /* If the next token is not '{' it is an opaque-enum-specifier or an |
21341 | elaborated-type-specifier. */ |
21342 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
21343 | { |
21344 | auto_timevar tv (TV_PARSE_ENUM); |
21345 | |
21346 | if (nested_name_specifier |
21347 | && nested_name_specifier != error_mark_node) |
21348 | { |
21349 | /* The following catches invalid code such as: |
21350 | enum class S<int>::E { A, B, C }; */ |
21351 | if (!processing_specialization |
21352 | && CLASS_TYPE_P (nested_name_specifier) |
21353 | && CLASSTYPE_USE_TEMPLATE (nested_name_specifier)) |
21354 | error_at (type_start_token->location, "cannot add an enumerator " |
21355 | "list to a template instantiation" ); |
21356 | |
21357 | if (TREE_CODE (nested_name_specifier) == TYPENAME_TYPE) |
21358 | { |
21359 | error_at (type_start_token->location, |
21360 | "%<%T::%E%> has not been declared" , |
21361 | TYPE_CONTEXT (nested_name_specifier), |
21362 | nested_name_specifier); |
21363 | type = error_mark_node; |
21364 | } |
21365 | else if (TREE_CODE (nested_name_specifier) != NAMESPACE_DECL |
21366 | && !CLASS_TYPE_P (nested_name_specifier)) |
21367 | { |
21368 | error_at (type_start_token->location, "nested name specifier " |
21369 | "%qT for enum declaration does not name a class " |
21370 | "or namespace" , nested_name_specifier); |
21371 | type = error_mark_node; |
21372 | } |
21373 | /* If that scope does not contain the scope in which the |
21374 | class was originally declared, the program is invalid. */ |
21375 | else if (prev_scope && !is_ancestor (ancestor: prev_scope, |
21376 | descendant: nested_name_specifier)) |
21377 | { |
21378 | if (at_namespace_scope_p ()) |
21379 | error_at (type_start_token->location, |
21380 | "declaration of %qD in namespace %qD which does not " |
21381 | "enclose %qD" , |
21382 | type, prev_scope, nested_name_specifier); |
21383 | else |
21384 | error_at (type_start_token->location, |
21385 | "declaration of %qD in %qD which does not " |
21386 | "enclose %qD" , |
21387 | type, prev_scope, nested_name_specifier); |
21388 | type = error_mark_node; |
21389 | } |
21390 | /* If that scope is the scope where the declaration is being placed |
21391 | the program is invalid. */ |
21392 | else if (CLASS_TYPE_P (nested_name_specifier) |
21393 | && CLASS_TYPE_P (prev_scope) |
21394 | && same_type_p (nested_name_specifier, prev_scope)) |
21395 | { |
21396 | permerror (type_start_token->location, |
21397 | "extra qualification not allowed" ); |
21398 | nested_name_specifier = NULL_TREE; |
21399 | } |
21400 | } |
21401 | |
21402 | if (scoped_enum_p) |
21403 | begin_scope (sk_scoped_enum, type); |
21404 | |
21405 | /* Consume the opening brace. */ |
21406 | matching_braces braces; |
21407 | braces.consume_open (parser); |
21408 | |
21409 | if (type == error_mark_node) |
21410 | ; /* Nothing to add */ |
21411 | else if (OPAQUE_ENUM_P (type) |
21412 | || (cxx_dialect > cxx98 && processing_specialization)) |
21413 | { |
21414 | new_value_list = true; |
21415 | SET_OPAQUE_ENUM_P (type, false); |
21416 | DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; |
21417 | } |
21418 | else |
21419 | { |
21420 | error_at (type_start_token->location, |
21421 | "multiple definition of %q#T" , type); |
21422 | inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)), |
21423 | "previous definition here" ); |
21424 | type = error_mark_node; |
21425 | } |
21426 | |
21427 | if (type == error_mark_node) |
21428 | cp_parser_skip_to_end_of_block_or_statement (parser); |
21429 | /* If the next token is not '}', then there are some enumerators. */ |
21430 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
21431 | { |
21432 | if (is_unnamed && !scoped_enum_p |
21433 | /* Don't warn for enum {} a; here. */ |
21434 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SEMICOLON)) |
21435 | pedwarn (type_start_token->location, OPT_Wpedantic, |
21436 | "ISO C++ forbids empty unnamed enum" ); |
21437 | } |
21438 | else |
21439 | { |
21440 | /* We've seen a '{' so we know we're in an enum-specifier. |
21441 | Commit to any tentative parse to get syntax errors. */ |
21442 | cp_parser_commit_to_tentative_parse (parser); |
21443 | cp_parser_enumerator_list (parser, type); |
21444 | } |
21445 | |
21446 | /* Consume the final '}'. */ |
21447 | braces.require_close (parser); |
21448 | |
21449 | if (scoped_enum_p) |
21450 | finish_scope (); |
21451 | } |
21452 | else |
21453 | { |
21454 | /* If a ';' follows, then it is an opaque-enum-specifier |
21455 | and additional restrictions apply. */ |
21456 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
21457 | { |
21458 | if (is_unnamed) |
21459 | error_at (type_start_token->location, |
21460 | "opaque-enum-specifier without name" ); |
21461 | else if (nested_name_specifier) |
21462 | error_at (type_start_token->location, |
21463 | "opaque-enum-specifier must use a simple identifier" ); |
21464 | } |
21465 | } |
21466 | |
21467 | /* Look for trailing attributes to apply to this enumeration, and |
21468 | apply them if appropriate. */ |
21469 | if (cp_parser_allow_gnu_extensions_p (parser)) |
21470 | { |
21471 | tree trailing_attr = cp_parser_gnu_attributes_opt (parser); |
21472 | cplus_decl_attributes (&type, |
21473 | trailing_attr, |
21474 | (int) ATTR_FLAG_TYPE_IN_PLACE); |
21475 | } |
21476 | |
21477 | /* Finish up the enumeration. */ |
21478 | if (type != error_mark_node) |
21479 | { |
21480 | if (new_value_list) |
21481 | finish_enum_value_list (type); |
21482 | if (is_new_type) |
21483 | finish_enum (type); |
21484 | } |
21485 | |
21486 | if (nested_name_specifier) |
21487 | { |
21488 | if (CLASS_TYPE_P (nested_name_specifier)) |
21489 | { |
21490 | TYPE_BEING_DEFINED (nested_name_specifier) = nested_being_defined; |
21491 | pop_scope (nested_name_specifier); |
21492 | } |
21493 | else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL) |
21494 | pop_nested_namespace (nested_name_specifier); |
21495 | } |
21496 | return type; |
21497 | } |
21498 | |
21499 | /* Parse an enumerator-list. The enumerators all have the indicated |
21500 | TYPE. |
21501 | |
21502 | enumerator-list: |
21503 | enumerator-definition |
21504 | enumerator-list , enumerator-definition */ |
21505 | |
21506 | static void |
21507 | cp_parser_enumerator_list (cp_parser* parser, tree type) |
21508 | { |
21509 | while (true) |
21510 | { |
21511 | /* Parse an enumerator-definition. */ |
21512 | cp_parser_enumerator_definition (parser, type); |
21513 | |
21514 | /* If the next token is not a ',', we've reached the end of |
21515 | the list. */ |
21516 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
21517 | break; |
21518 | /* Otherwise, consume the `,' and keep going. */ |
21519 | cp_lexer_consume_token (lexer: parser->lexer); |
21520 | /* If the next token is a `}', there is a trailing comma. */ |
21521 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
21522 | { |
21523 | if (cxx_dialect < cxx11) |
21524 | pedwarn (input_location, OPT_Wpedantic, |
21525 | "comma at end of enumerator list" ); |
21526 | break; |
21527 | } |
21528 | } |
21529 | } |
21530 | |
21531 | /* Parse an enumerator-definition. The enumerator has the indicated |
21532 | TYPE. |
21533 | |
21534 | enumerator-definition: |
21535 | enumerator |
21536 | enumerator = constant-expression |
21537 | |
21538 | enumerator: |
21539 | identifier |
21540 | |
21541 | GNU Extensions: |
21542 | |
21543 | enumerator-definition: |
21544 | enumerator attributes [opt] |
21545 | enumerator attributes [opt] = constant-expression */ |
21546 | |
21547 | static void |
21548 | cp_parser_enumerator_definition (cp_parser* parser, tree type) |
21549 | { |
21550 | tree identifier; |
21551 | tree value; |
21552 | location_t loc; |
21553 | |
21554 | /* Save the input location because we are interested in the location |
21555 | of the identifier and not the location of the explicit value. */ |
21556 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
21557 | |
21558 | /* Look for the identifier. */ |
21559 | identifier = cp_parser_identifier (parser); |
21560 | if (identifier == error_mark_node) |
21561 | return; |
21562 | |
21563 | /* Parse any specified attributes. */ |
21564 | tree attrs = cp_parser_attributes_opt (parser); |
21565 | |
21566 | /* If the next token is an '=', then there is an explicit value. */ |
21567 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
21568 | { |
21569 | /* Consume the `=' token. */ |
21570 | cp_lexer_consume_token (lexer: parser->lexer); |
21571 | /* Parse the value. */ |
21572 | value = cp_parser_constant_expression (parser); |
21573 | } |
21574 | else |
21575 | value = NULL_TREE; |
21576 | |
21577 | /* If we are processing a template, make sure the initializer of the |
21578 | enumerator doesn't contain any bare template parameter pack. */ |
21579 | if (current_lambda_expr ()) |
21580 | { |
21581 | /* In a lambda it should work, but doesn't currently. */ |
21582 | if (uses_parameter_packs (value)) |
21583 | { |
21584 | sorry ("unexpanded parameter pack in enumerator in lambda" ); |
21585 | value = error_mark_node; |
21586 | } |
21587 | } |
21588 | else if (check_for_bare_parameter_packs (value)) |
21589 | value = error_mark_node; |
21590 | |
21591 | /* Create the enumerator. */ |
21592 | build_enumerator (identifier, value, type, attrs, loc); |
21593 | } |
21594 | |
21595 | /* Parse a namespace-name. |
21596 | |
21597 | namespace-name: |
21598 | original-namespace-name |
21599 | namespace-alias |
21600 | |
21601 | Returns the NAMESPACE_DECL for the namespace. */ |
21602 | |
21603 | static tree |
21604 | cp_parser_namespace_name (cp_parser* parser) |
21605 | { |
21606 | tree identifier; |
21607 | tree namespace_decl; |
21608 | |
21609 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
21610 | |
21611 | /* Get the name of the namespace. */ |
21612 | identifier = cp_parser_identifier (parser); |
21613 | if (identifier == error_mark_node) |
21614 | return error_mark_node; |
21615 | |
21616 | /* Look up the identifier in the currently active scope. Look only |
21617 | for namespaces, due to: |
21618 | |
21619 | [basic.lookup.udir] |
21620 | |
21621 | When looking up a namespace-name in a using-directive or alias |
21622 | definition, only namespace names are considered. |
21623 | |
21624 | And: |
21625 | |
21626 | [basic.lookup.qual] |
21627 | |
21628 | During the lookup of a name preceding the :: scope resolution |
21629 | operator, object, function, and enumerator names are ignored. |
21630 | |
21631 | (Note that cp_parser_qualifying_entity only calls this |
21632 | function if the token after the name is the scope resolution |
21633 | operator.) */ |
21634 | namespace_decl = cp_parser_lookup_name (parser, identifier, |
21635 | none_type, |
21636 | /*is_template=*/false, |
21637 | /*is_namespace=*/true, |
21638 | /*check_dependency=*/true, |
21639 | /*ambiguous_decls=*/NULL, |
21640 | token->location); |
21641 | /* If it's not a namespace, issue an error. */ |
21642 | if (namespace_decl == error_mark_node |
21643 | || TREE_CODE (namespace_decl) != NAMESPACE_DECL) |
21644 | { |
21645 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
21646 | { |
21647 | auto_diagnostic_group d; |
21648 | name_hint hint; |
21649 | if (namespace_decl == error_mark_node |
21650 | && parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL) |
21651 | hint = suggest_alternative_in_explicit_scope (token->location, |
21652 | identifier, |
21653 | parser->scope); |
21654 | if (const char *suggestion = hint.suggestion ()) |
21655 | { |
21656 | gcc_rich_location richloc (token->location); |
21657 | richloc.add_fixit_replace (new_content: suggestion); |
21658 | error_at (&richloc, |
21659 | "%qD is not a namespace-name; did you mean %qs?" , |
21660 | identifier, suggestion); |
21661 | } |
21662 | else |
21663 | error_at (token->location, "%qD is not a namespace-name" , |
21664 | identifier); |
21665 | } |
21666 | else |
21667 | cp_parser_error (parser, gmsgid: "expected namespace-name" ); |
21668 | namespace_decl = error_mark_node; |
21669 | } |
21670 | |
21671 | return namespace_decl; |
21672 | } |
21673 | |
21674 | /* Parse a namespace-definition. |
21675 | |
21676 | namespace-definition: |
21677 | named-namespace-definition |
21678 | unnamed-namespace-definition |
21679 | |
21680 | named-namespace-definition: |
21681 | original-namespace-definition |
21682 | extension-namespace-definition |
21683 | |
21684 | original-namespace-definition: |
21685 | namespace identifier { namespace-body } |
21686 | |
21687 | extension-namespace-definition: |
21688 | namespace original-namespace-name { namespace-body } |
21689 | |
21690 | unnamed-namespace-definition: |
21691 | namespace { namespace-body } */ |
21692 | |
21693 | static void |
21694 | cp_parser_namespace_definition (cp_parser* parser) |
21695 | { |
21696 | tree identifier; |
21697 | int nested_definition_count = 0; |
21698 | |
21699 | cp_ensure_no_omp_declare_simd (parser); |
21700 | cp_ensure_no_oacc_routine (parser); |
21701 | |
21702 | bool is_inline = cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_INLINE); |
21703 | const bool topmost_inline_p = is_inline; |
21704 | |
21705 | if (is_inline) |
21706 | { |
21707 | maybe_warn_cpp0x (str: CPP0X_INLINE_NAMESPACES); |
21708 | cp_lexer_consume_token (lexer: parser->lexer); |
21709 | } |
21710 | |
21711 | /* Look for the `namespace' keyword. */ |
21712 | cp_token* token |
21713 | = cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
21714 | |
21715 | /* Parse any specified attributes before the identifier. */ |
21716 | tree attribs = cp_parser_attributes_opt (parser); |
21717 | |
21718 | for (;;) |
21719 | { |
21720 | identifier = NULL_TREE; |
21721 | |
21722 | bool nested_inline_p = cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
21723 | keyword: RID_INLINE); |
21724 | if (nested_inline_p && nested_definition_count != 0) |
21725 | { |
21726 | if (pedantic && cxx_dialect < cxx20) |
21727 | pedwarn (cp_lexer_peek_token (lexer: parser->lexer)->location, |
21728 | OPT_Wc__20_extensions, "nested inline namespace " |
21729 | "definitions only available with %<-std=c++20%> or " |
21730 | "%<-std=gnu++20%>" ); |
21731 | cp_lexer_consume_token (lexer: parser->lexer); |
21732 | } |
21733 | |
21734 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
21735 | { |
21736 | identifier = cp_parser_identifier (parser); |
21737 | |
21738 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
21739 | pedwarn (input_location, OPT_Wpedantic, |
21740 | "standard attributes on namespaces must precede " |
21741 | "the namespace name" ); |
21742 | |
21743 | /* Parse any attributes specified after the identifier. */ |
21744 | attribs = attr_chainon (attrs: attribs, attr: cp_parser_attributes_opt (parser)); |
21745 | } |
21746 | |
21747 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SCOPE)) |
21748 | { |
21749 | /* Don't forget that the innermost namespace might have been |
21750 | marked as inline. Use |= because we cannot overwrite |
21751 | IS_INLINE in case the outermost namespace is inline, but |
21752 | there are no nested inlines. */ |
21753 | is_inline |= nested_inline_p; |
21754 | break; |
21755 | } |
21756 | |
21757 | if (!nested_definition_count && pedantic && cxx_dialect < cxx17) |
21758 | pedwarn (input_location, OPT_Wc__17_extensions, |
21759 | "nested namespace definitions only available with " |
21760 | "%<-std=c++17%> or %<-std=gnu++17%>" ); |
21761 | |
21762 | /* Nested namespace names can create new namespaces (unlike |
21763 | other qualified-ids). */ |
21764 | if (int count = (identifier |
21765 | ? push_namespace (identifier, make_inline: nested_inline_p) |
21766 | : 0)) |
21767 | nested_definition_count += count; |
21768 | else |
21769 | cp_parser_error (parser, gmsgid: "nested namespace name required" ); |
21770 | cp_lexer_consume_token (lexer: parser->lexer); |
21771 | } |
21772 | |
21773 | if (nested_definition_count && !identifier) |
21774 | cp_parser_error (parser, gmsgid: "namespace name required" ); |
21775 | |
21776 | if (nested_definition_count && attribs) |
21777 | error_at (token->location, |
21778 | "a nested namespace definition cannot have attributes" ); |
21779 | if (nested_definition_count && topmost_inline_p) |
21780 | error_at (token->location, |
21781 | "a nested namespace definition cannot be inline" ); |
21782 | |
21783 | /* Start the namespace. */ |
21784 | nested_definition_count += push_namespace (identifier, make_inline: is_inline); |
21785 | |
21786 | bool has_visibility = handle_namespace_attrs (current_namespace, attribs); |
21787 | |
21788 | warning (OPT_Wnamespaces, "namespace %qD entered" , current_namespace); |
21789 | |
21790 | /* Look for the `{' to validate starting the namespace. */ |
21791 | matching_braces braces; |
21792 | if (braces.require_open (parser)) |
21793 | { |
21794 | /* Parse the body of the namespace. */ |
21795 | cp_parser_namespace_body (parser); |
21796 | |
21797 | /* Look for the final `}'. */ |
21798 | braces.require_close (parser); |
21799 | } |
21800 | |
21801 | if (has_visibility) |
21802 | pop_visibility (1); |
21803 | |
21804 | /* Pop the nested namespace definitions. */ |
21805 | while (nested_definition_count--) |
21806 | pop_namespace (); |
21807 | } |
21808 | |
21809 | /* Parse a namespace-body. |
21810 | |
21811 | namespace-body: |
21812 | declaration-seq [opt] */ |
21813 | |
21814 | static void |
21815 | cp_parser_namespace_body (cp_parser* parser) |
21816 | { |
21817 | cp_parser_declaration_seq_opt (parser); |
21818 | } |
21819 | |
21820 | /* Parse a namespace-alias-definition. |
21821 | |
21822 | namespace-alias-definition: |
21823 | namespace identifier = qualified-namespace-specifier ; */ |
21824 | |
21825 | static void |
21826 | cp_parser_namespace_alias_definition (cp_parser* parser) |
21827 | { |
21828 | tree identifier; |
21829 | tree namespace_specifier; |
21830 | |
21831 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
21832 | |
21833 | /* Look for the `namespace' keyword. */ |
21834 | cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
21835 | /* Look for the identifier. */ |
21836 | identifier = cp_parser_identifier (parser); |
21837 | if (identifier == error_mark_node) |
21838 | return; |
21839 | /* Look for the `=' token. */ |
21840 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser) |
21841 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
21842 | { |
21843 | error_at (token->location, "%<namespace%> definition is not allowed here" ); |
21844 | /* Skip the definition. */ |
21845 | cp_lexer_consume_token (lexer: parser->lexer); |
21846 | if (cp_parser_skip_to_closing_brace (parser)) |
21847 | cp_lexer_consume_token (lexer: parser->lexer); |
21848 | return; |
21849 | } |
21850 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
21851 | /* Look for the qualified-namespace-specifier. */ |
21852 | namespace_specifier |
21853 | = cp_parser_qualified_namespace_specifier (parser); |
21854 | cp_warn_deprecated_use_scopes (namespace_specifier); |
21855 | /* Look for the `;' token. */ |
21856 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
21857 | |
21858 | /* Register the alias in the symbol table. */ |
21859 | do_namespace_alias (identifier, namespace_specifier); |
21860 | } |
21861 | |
21862 | /* Parse a qualified-namespace-specifier. |
21863 | |
21864 | qualified-namespace-specifier: |
21865 | :: [opt] nested-name-specifier [opt] namespace-name |
21866 | |
21867 | Returns a NAMESPACE_DECL corresponding to the specified |
21868 | namespace. */ |
21869 | |
21870 | static tree |
21871 | cp_parser_qualified_namespace_specifier (cp_parser* parser) |
21872 | { |
21873 | /* Look for the optional `::'. */ |
21874 | cp_parser_global_scope_opt (parser, |
21875 | /*current_scope_valid_p=*/false); |
21876 | |
21877 | /* Look for the optional nested-name-specifier. */ |
21878 | cp_parser_nested_name_specifier_opt (parser, |
21879 | /*typename_keyword_p=*/false, |
21880 | /*check_dependency_p=*/true, |
21881 | /*type_p=*/false, |
21882 | /*is_declaration=*/true); |
21883 | |
21884 | return cp_parser_namespace_name (parser); |
21885 | } |
21886 | |
21887 | /* Subroutine of cp_parser_using_declaration. */ |
21888 | |
21889 | static tree |
21890 | finish_using_decl (tree qscope, tree identifier, bool typename_p = false) |
21891 | { |
21892 | tree decl = NULL_TREE; |
21893 | if (at_class_scope_p ()) |
21894 | { |
21895 | /* Create the USING_DECL. */ |
21896 | decl = do_class_using_decl (qscope, identifier); |
21897 | |
21898 | if (check_for_bare_parameter_packs (decl)) |
21899 | return error_mark_node; |
21900 | |
21901 | if (decl && typename_p) |
21902 | USING_DECL_TYPENAME_P (decl) = 1; |
21903 | |
21904 | /* Add it to the list of members in this class. */ |
21905 | finish_member_declaration (decl); |
21906 | } |
21907 | else |
21908 | finish_nonmember_using_decl (scope: qscope, name: identifier); |
21909 | return decl; |
21910 | } |
21911 | |
21912 | /* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an |
21913 | access declaration. |
21914 | |
21915 | using-declaration: |
21916 | using typename [opt] :: [opt] nested-name-specifier unqualified-id ; |
21917 | using :: unqualified-id ; |
21918 | |
21919 | access-declaration: |
21920 | qualified-id ; |
21921 | |
21922 | */ |
21923 | |
21924 | static bool |
21925 | cp_parser_using_declaration (cp_parser* parser, |
21926 | bool access_declaration_p) |
21927 | { |
21928 | cp_token *token; |
21929 | bool typename_p = false; |
21930 | bool global_scope_p; |
21931 | tree identifier; |
21932 | tree qscope; |
21933 | int oldcount = errorcount; |
21934 | cp_token *diag_token = NULL; |
21935 | |
21936 | if (access_declaration_p) |
21937 | { |
21938 | diag_token = cp_lexer_peek_token (lexer: parser->lexer); |
21939 | cp_parser_parse_tentatively (parser); |
21940 | } |
21941 | else |
21942 | { |
21943 | /* Look for the `using' keyword. */ |
21944 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
21945 | |
21946 | again: |
21947 | /* Peek at the next token. */ |
21948 | token = cp_lexer_peek_token (lexer: parser->lexer); |
21949 | /* See if it's `typename'. */ |
21950 | if (token->keyword == RID_TYPENAME) |
21951 | { |
21952 | /* Remember that we've seen it. */ |
21953 | typename_p = true; |
21954 | /* Consume the `typename' token. */ |
21955 | cp_lexer_consume_token (lexer: parser->lexer); |
21956 | } |
21957 | } |
21958 | |
21959 | /* Look for the optional global scope qualification. */ |
21960 | global_scope_p |
21961 | = (cp_parser_global_scope_opt (parser, |
21962 | /*current_scope_valid_p=*/false) |
21963 | != NULL_TREE); |
21964 | |
21965 | /* If we saw `typename', or didn't see `::', then there must be a |
21966 | nested-name-specifier present. */ |
21967 | if (typename_p || !global_scope_p) |
21968 | { |
21969 | qscope = cp_parser_nested_name_specifier (parser, typename_keyword_p: typename_p, |
21970 | /*check_dependency_p=*/true, |
21971 | /*type_p=*/false, |
21972 | /*is_declaration=*/true); |
21973 | if (!qscope && !cp_parser_uncommitted_to_tentative_parse_p (parser)) |
21974 | { |
21975 | cp_parser_skip_to_end_of_block_or_statement (parser); |
21976 | return false; |
21977 | } |
21978 | } |
21979 | /* Otherwise, we could be in either of the two productions. In that |
21980 | case, treat the nested-name-specifier as optional. */ |
21981 | else |
21982 | qscope = cp_parser_nested_name_specifier_opt (parser, |
21983 | /*typename_keyword_p=*/false, |
21984 | /*check_dependency_p=*/true, |
21985 | /*type_p=*/false, |
21986 | /*is_declaration=*/true); |
21987 | if (!qscope) |
21988 | qscope = global_namespace; |
21989 | |
21990 | cp_warn_deprecated_use_scopes (qscope); |
21991 | |
21992 | if (access_declaration_p |
21993 | && !MAYBE_CLASS_TYPE_P (qscope) |
21994 | && TREE_CODE (qscope) != ENUMERAL_TYPE) |
21995 | /* If the qualifying scope of an access-declaration isn't a class |
21996 | or enumeration type then it can't be valid. */ |
21997 | cp_parser_simulate_error (parser); |
21998 | |
21999 | if (access_declaration_p && cp_parser_error_occurred (parser)) |
22000 | /* Something has already gone wrong; there's no need to parse |
22001 | further. Since an error has occurred, the return value of |
22002 | cp_parser_parse_definitely will be false, as required. */ |
22003 | return cp_parser_parse_definitely (parser); |
22004 | |
22005 | token = cp_lexer_peek_token (lexer: parser->lexer); |
22006 | /* Parse the unqualified-id. */ |
22007 | identifier = cp_parser_unqualified_id (parser, |
22008 | /*template_keyword_p=*/false, |
22009 | /*check_dependency_p=*/true, |
22010 | /*declarator_p=*/true, |
22011 | /*optional_p=*/false); |
22012 | |
22013 | if (access_declaration_p) |
22014 | { |
22015 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
22016 | cp_parser_simulate_error (parser); |
22017 | if (!cp_parser_parse_definitely (parser)) |
22018 | return false; |
22019 | } |
22020 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
22021 | { |
22022 | cp_token *ell = cp_lexer_consume_token (lexer: parser->lexer); |
22023 | if (cxx_dialect < cxx17) |
22024 | pedwarn (ell->location, OPT_Wc__17_extensions, |
22025 | "pack expansion in using-declaration only available " |
22026 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
22027 | |
22028 | /* A parameter pack can appear in the qualifying scope, and/or in the |
22029 | terminal name (if naming a conversion function). Logically they're |
22030 | part of a single pack expansion of the overall USING_DECL, but we |
22031 | express them as separate pack expansions within the USING_DECL since |
22032 | we can't create a pack expansion over a USING_DECL. */ |
22033 | bool saw_parm_pack = false; |
22034 | if (uses_parameter_packs (qscope)) |
22035 | { |
22036 | qscope = make_pack_expansion (qscope); |
22037 | saw_parm_pack = true; |
22038 | } |
22039 | if (identifier_p (t: identifier) |
22040 | && IDENTIFIER_CONV_OP_P (identifier) |
22041 | && uses_parameter_packs (TREE_TYPE (identifier))) |
22042 | { |
22043 | identifier = make_conv_op_name (make_pack_expansion |
22044 | (TREE_TYPE (identifier))); |
22045 | saw_parm_pack = true; |
22046 | } |
22047 | if (!saw_parm_pack) |
22048 | { |
22049 | /* Issue an error in terms using a SCOPE_REF that includes both |
22050 | components. */ |
22051 | tree name |
22052 | = build_qualified_name (NULL_TREE, qscope, identifier, false); |
22053 | make_pack_expansion (name); |
22054 | gcc_assert (seen_error ()); |
22055 | qscope = identifier = error_mark_node; |
22056 | } |
22057 | } |
22058 | |
22059 | /* The function we call to handle a using-declaration is different |
22060 | depending on what scope we are in. */ |
22061 | if (qscope == error_mark_node || identifier == error_mark_node) |
22062 | ; |
22063 | else if (!identifier_p (t: identifier) |
22064 | && TREE_CODE (identifier) != BIT_NOT_EXPR) |
22065 | /* [namespace.udecl] |
22066 | |
22067 | A using declaration shall not name a template-id. */ |
22068 | error_at (token->location, |
22069 | "a template-id may not appear in a using-declaration" ); |
22070 | else |
22071 | { |
22072 | tree decl = finish_using_decl (qscope, identifier, typename_p); |
22073 | |
22074 | if (decl == error_mark_node) |
22075 | { |
22076 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22077 | return false; |
22078 | } |
22079 | } |
22080 | |
22081 | if (!access_declaration_p |
22082 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
22083 | { |
22084 | cp_token *comma = cp_lexer_consume_token (lexer: parser->lexer); |
22085 | if (cxx_dialect < cxx17) |
22086 | pedwarn (comma->location, OPT_Wc__17_extensions, |
22087 | "comma-separated list in using-declaration only available " |
22088 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
22089 | goto again; |
22090 | } |
22091 | |
22092 | /* Look for the final `;'. */ |
22093 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22094 | |
22095 | if (access_declaration_p && errorcount == oldcount) |
22096 | warning_at (diag_token->location, OPT_Wdeprecated, |
22097 | "access declarations are deprecated " |
22098 | "in favour of using-declarations; " |
22099 | "suggestion: add the %<using%> keyword" ); |
22100 | |
22101 | return true; |
22102 | } |
22103 | |
22104 | /* C++20 using enum declaration. |
22105 | |
22106 | using-enum-declaration : |
22107 | using elaborated-enum-specifier ; */ |
22108 | |
22109 | static void |
22110 | cp_parser_using_enum (cp_parser *parser) |
22111 | { |
22112 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22113 | |
22114 | /* Using cp_parser_elaborated_type_specifier rejects typedef-names, which |
22115 | breaks one of the motivating examples in using-enum-5.C. |
22116 | cp_parser_simple_type_specifier seems to be closer to what we actually |
22117 | want, though that hasn't been properly specified yet. */ |
22118 | |
22119 | /* Consume 'enum'. */ |
22120 | gcc_checking_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM)); |
22121 | cp_lexer_consume_token (lexer: parser->lexer); |
22122 | |
22123 | cp_token *start = cp_lexer_peek_token (lexer: parser->lexer); |
22124 | |
22125 | tree type = (cp_parser_simple_type_specifier |
22126 | (parser, NULL, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
22127 | |
22128 | cp_token *end = cp_lexer_previous_token (lexer: parser->lexer); |
22129 | |
22130 | if (type == error_mark_node |
22131 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
22132 | { |
22133 | cp_parser_skip_to_end_of_block_or_statement (parser); |
22134 | return; |
22135 | } |
22136 | if (TREE_CODE (type) == TYPE_DECL) |
22137 | type = TREE_TYPE (type); |
22138 | |
22139 | /* The elaborated-enum-specifier shall not name a dependent type and the type |
22140 | shall have a reachable enum-specifier. */ |
22141 | const char *msg = nullptr; |
22142 | if (cxx_dialect < cxx20) |
22143 | msg = G_("%<using enum%> " |
22144 | "only available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
22145 | else if (dependent_type_p (type)) |
22146 | msg = G_("%<using enum%> of dependent type %qT" ); |
22147 | else if (TREE_CODE (type) != ENUMERAL_TYPE) |
22148 | msg = G_("%<using enum%> of non-enumeration type %q#T" ); |
22149 | else if (!COMPLETE_TYPE_P (type)) |
22150 | msg = G_("%<using enum%> of incomplete type %qT" ); |
22151 | else if (OPAQUE_ENUM_P (type)) |
22152 | msg = G_("%<using enum%> of %qT before its enum-specifier" ); |
22153 | if (msg) |
22154 | { |
22155 | location_t loc = make_location (caret: start, start, end); |
22156 | auto_diagnostic_group g; |
22157 | error_at (loc, msg, type); |
22158 | loc = location_of (type); |
22159 | if (cxx_dialect < cxx20 || loc == input_location) |
22160 | ; |
22161 | else if (OPAQUE_ENUM_P (type)) |
22162 | inform (loc, "opaque-enum-declaration here" ); |
22163 | else |
22164 | inform (loc, "declared here" ); |
22165 | } |
22166 | |
22167 | /* A using-enum-declaration introduces the enumerator names of the named |
22168 | enumeration as if by a using-declaration for each enumerator. */ |
22169 | if (TREE_CODE (type) == ENUMERAL_TYPE) |
22170 | for (tree v = TYPE_VALUES (type); v; v = TREE_CHAIN (v)) |
22171 | finish_using_decl (qscope: type, DECL_NAME (TREE_VALUE (v))); |
22172 | } |
22173 | |
22174 | /* Parse an alias-declaration. |
22175 | |
22176 | alias-declaration: |
22177 | using identifier attribute-specifier-seq [opt] = type-id */ |
22178 | |
22179 | static tree |
22180 | cp_parser_alias_declaration (cp_parser* parser) |
22181 | { |
22182 | tree id, type, decl, pushed_scope = NULL_TREE, attributes; |
22183 | location_t id_location, type_location; |
22184 | cp_declarator *declarator; |
22185 | cp_decl_specifier_seq decl_specs; |
22186 | bool member_p; |
22187 | const char *saved_message = NULL; |
22188 | |
22189 | /* Look for the `using' keyword. */ |
22190 | cp_token *using_token |
22191 | = cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22192 | if (using_token == NULL) |
22193 | return error_mark_node; |
22194 | |
22195 | id_location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
22196 | id = cp_parser_identifier (parser); |
22197 | if (id == error_mark_node) |
22198 | return error_mark_node; |
22199 | |
22200 | cp_token *attrs_token = cp_lexer_peek_token (lexer: parser->lexer); |
22201 | attributes = cp_parser_attributes_opt (parser); |
22202 | if (attributes == error_mark_node) |
22203 | return error_mark_node; |
22204 | |
22205 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
22206 | |
22207 | if (cp_parser_error_occurred (parser)) |
22208 | return error_mark_node; |
22209 | |
22210 | cp_parser_commit_to_tentative_parse (parser); |
22211 | |
22212 | /* Now we are going to parse the type-id of the declaration. */ |
22213 | |
22214 | /* |
22215 | [dcl.type]/3 says: |
22216 | |
22217 | "A type-specifier-seq shall not define a class or enumeration |
22218 | unless it appears in the type-id of an alias-declaration (7.1.3) that |
22219 | is not the declaration of a template-declaration." |
22220 | |
22221 | In other words, if we currently are in an alias template, the |
22222 | type-id should not define a type. |
22223 | |
22224 | So let's set parser->type_definition_forbidden_message in that |
22225 | case; cp_parser_check_type_definition (called by |
22226 | cp_parser_class_specifier) will then emit an error if a type is |
22227 | defined in the type-id. */ |
22228 | if (parser->num_template_parameter_lists) |
22229 | { |
22230 | saved_message = parser->type_definition_forbidden_message; |
22231 | parser->type_definition_forbidden_message = |
22232 | G_("types may not be defined in alias template declarations" ); |
22233 | } |
22234 | |
22235 | type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
22236 | &type_location); |
22237 | |
22238 | /* Restore the error message if need be. */ |
22239 | if (parser->num_template_parameter_lists) |
22240 | parser->type_definition_forbidden_message = saved_message; |
22241 | |
22242 | if (type == error_mark_node |
22243 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) |
22244 | { |
22245 | cp_parser_skip_to_end_of_block_or_statement (parser); |
22246 | return error_mark_node; |
22247 | } |
22248 | |
22249 | /* A typedef-name can also be introduced by an alias-declaration. The |
22250 | identifier following the using keyword becomes a typedef-name. It has |
22251 | the same semantics as if it were introduced by the typedef |
22252 | specifier. In particular, it does not define a new type and it shall |
22253 | not appear in the type-id. */ |
22254 | |
22255 | clear_decl_specs (decl_specs: &decl_specs); |
22256 | decl_specs.type = type; |
22257 | if (attributes != NULL_TREE) |
22258 | { |
22259 | decl_specs.attributes = attributes; |
22260 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22261 | ds: ds_attribute, |
22262 | attrs_token); |
22263 | } |
22264 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22265 | ds: ds_typedef, |
22266 | using_token); |
22267 | set_and_check_decl_spec_loc (decl_specs: &decl_specs, |
22268 | ds: ds_alias, |
22269 | using_token); |
22270 | decl_specs.locations[ds_type_spec] = type_location; |
22271 | |
22272 | if (parser->num_template_parameter_lists |
22273 | && !cp_parser_check_template_parameters (parser, |
22274 | /*num_templates=*/0, |
22275 | /*template_id*/false, |
22276 | id_location, |
22277 | /*declarator=*/NULL)) |
22278 | return error_mark_node; |
22279 | |
22280 | declarator = make_id_declarator (NULL_TREE, unqualified_name: id, sfk: sfk_none, id_location); |
22281 | |
22282 | member_p = at_class_scope_p (); |
22283 | if (member_p) |
22284 | decl = grokfield (declarator, &decl_specs, NULL_TREE, false, |
22285 | NULL_TREE, attributes); |
22286 | else |
22287 | decl = start_decl (declarator, &decl_specs, 0, |
22288 | attributes, NULL_TREE, &pushed_scope); |
22289 | if (decl == error_mark_node) |
22290 | return decl; |
22291 | |
22292 | cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0); |
22293 | |
22294 | if (pushed_scope) |
22295 | pop_scope (pushed_scope); |
22296 | |
22297 | /* If decl is a template, return its TEMPLATE_DECL so that it gets |
22298 | added into the symbol table; otherwise, return the TYPE_DECL. */ |
22299 | if (DECL_LANG_SPECIFIC (decl) |
22300 | && DECL_TEMPLATE_INFO (decl) |
22301 | && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) |
22302 | { |
22303 | decl = DECL_TI_TEMPLATE (decl); |
22304 | if (member_p) |
22305 | check_member_template (decl); |
22306 | } |
22307 | |
22308 | return decl; |
22309 | } |
22310 | |
22311 | /* Parse a using-directive. |
22312 | |
22313 | using-directive: |
22314 | attribute-specifier-seq [opt] using namespace :: [opt] |
22315 | nested-name-specifier [opt] namespace-name ; */ |
22316 | |
22317 | static void |
22318 | cp_parser_using_directive (cp_parser* parser) |
22319 | { |
22320 | tree namespace_decl; |
22321 | tree attribs = cp_parser_std_attribute_spec_seq (parser); |
22322 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
22323 | { |
22324 | /* Error during attribute parsing that resulted in skipping |
22325 | to next semicolon. */ |
22326 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22327 | return; |
22328 | } |
22329 | |
22330 | /* Look for the `using' keyword. */ |
22331 | cp_parser_require_keyword (parser, RID_USING, RT_USING); |
22332 | /* And the `namespace' keyword. */ |
22333 | cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); |
22334 | /* Look for the optional `::' operator. */ |
22335 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
22336 | /* And the optional nested-name-specifier. */ |
22337 | cp_parser_nested_name_specifier_opt (parser, |
22338 | /*typename_keyword_p=*/false, |
22339 | /*check_dependency_p=*/true, |
22340 | /*type_p=*/false, |
22341 | /*is_declaration=*/true); |
22342 | /* Get the namespace being used. */ |
22343 | namespace_decl = cp_parser_namespace_name (parser); |
22344 | cp_warn_deprecated_use_scopes (namespace_decl); |
22345 | /* And any specified GNU attributes. */ |
22346 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
22347 | attribs = chainon (attribs, cp_parser_gnu_attributes_opt (parser)); |
22348 | |
22349 | /* Update the symbol table. */ |
22350 | finish_using_directive (target: namespace_decl, attribs); |
22351 | |
22352 | /* Look for the final `;'. */ |
22353 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22354 | } |
22355 | |
22356 | /* Parse an asm-definition. |
22357 | |
22358 | asm-qualifier: |
22359 | volatile |
22360 | inline |
22361 | goto |
22362 | |
22363 | asm-qualifier-list: |
22364 | asm-qualifier |
22365 | asm-qualifier-list asm-qualifier |
22366 | |
22367 | asm-definition: |
22368 | asm ( string-literal ) ; |
22369 | |
22370 | GNU Extension: |
22371 | |
22372 | asm-definition: |
22373 | asm asm-qualifier-list [opt] ( string-literal ) ; |
22374 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] ) ; |
22375 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] |
22376 | : asm-operand-list [opt] ) ; |
22377 | asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] |
22378 | : asm-operand-list [opt] |
22379 | : asm-clobber-list [opt] ) ; |
22380 | asm asm-qualifier-list [opt] ( string-literal : : asm-operand-list [opt] |
22381 | : asm-clobber-list [opt] |
22382 | : asm-goto-list ) ; |
22383 | |
22384 | The form with asm-goto-list is valid if and only if the asm-qualifier-list |
22385 | contains goto, and is the only allowed form in that case. No duplicates are |
22386 | allowed in an asm-qualifier-list. */ |
22387 | |
22388 | static void |
22389 | cp_parser_asm_definition (cp_parser* parser) |
22390 | { |
22391 | tree outputs = NULL_TREE; |
22392 | tree inputs = NULL_TREE; |
22393 | tree clobbers = NULL_TREE; |
22394 | tree labels = NULL_TREE; |
22395 | tree asm_stmt; |
22396 | bool extended_p = false; |
22397 | bool invalid_inputs_p = false; |
22398 | bool invalid_outputs_p = false; |
22399 | required_token missing = RT_NONE; |
22400 | location_t asm_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
22401 | |
22402 | /* Look for the `asm' keyword. */ |
22403 | cp_parser_require_keyword (parser, RID_ASM, RT_ASM); |
22404 | |
22405 | /* In C++20, unevaluated inline assembly is permitted in constexpr |
22406 | functions. */ |
22407 | if (parser->in_function_body |
22408 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
22409 | && cxx_dialect < cxx20) |
22410 | pedwarn (asm_loc, OPT_Wc__20_extensions, "%<asm%> in %<constexpr%> " |
22411 | "function only available with %<-std=c++20%> or " |
22412 | "%<-std=gnu++20%>" ); |
22413 | |
22414 | /* Handle the asm-qualifier-list. */ |
22415 | location_t volatile_loc = UNKNOWN_LOCATION; |
22416 | location_t inline_loc = UNKNOWN_LOCATION; |
22417 | location_t goto_loc = UNKNOWN_LOCATION; |
22418 | location_t first_loc = UNKNOWN_LOCATION; |
22419 | |
22420 | if (cp_parser_allow_gnu_extensions_p (parser)) |
22421 | for (;;) |
22422 | { |
22423 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
22424 | location_t loc = token->location; |
22425 | switch (cp_lexer_peek_token (lexer: parser->lexer)->keyword) |
22426 | { |
22427 | case RID_VOLATILE: |
22428 | if (volatile_loc) |
22429 | { |
22430 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22431 | token->u.value); |
22432 | inform (volatile_loc, "first seen here" ); |
22433 | } |
22434 | else |
22435 | { |
22436 | if (!parser->in_function_body) |
22437 | warning_at (loc, 0, "%<asm%> qualifier %qT ignored " |
22438 | "outside of function body" , token->u.value); |
22439 | volatile_loc = loc; |
22440 | } |
22441 | cp_lexer_consume_token (lexer: parser->lexer); |
22442 | continue; |
22443 | |
22444 | case RID_INLINE: |
22445 | if (inline_loc) |
22446 | { |
22447 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22448 | token->u.value); |
22449 | inform (inline_loc, "first seen here" ); |
22450 | } |
22451 | else |
22452 | inline_loc = loc; |
22453 | if (!first_loc) |
22454 | first_loc = loc; |
22455 | cp_lexer_consume_token (lexer: parser->lexer); |
22456 | continue; |
22457 | |
22458 | case RID_GOTO: |
22459 | if (goto_loc) |
22460 | { |
22461 | error_at (loc, "duplicate %<asm%> qualifier %qT" , |
22462 | token->u.value); |
22463 | inform (goto_loc, "first seen here" ); |
22464 | } |
22465 | else |
22466 | goto_loc = loc; |
22467 | if (!first_loc) |
22468 | first_loc = loc; |
22469 | cp_lexer_consume_token (lexer: parser->lexer); |
22470 | continue; |
22471 | |
22472 | case RID_CONST: |
22473 | case RID_RESTRICT: |
22474 | error_at (loc, "%qT is not an %<asm%> qualifier" , token->u.value); |
22475 | cp_lexer_consume_token (lexer: parser->lexer); |
22476 | continue; |
22477 | |
22478 | default: |
22479 | break; |
22480 | } |
22481 | break; |
22482 | } |
22483 | |
22484 | bool volatile_p = (volatile_loc != UNKNOWN_LOCATION); |
22485 | bool inline_p = (inline_loc != UNKNOWN_LOCATION); |
22486 | bool goto_p = (goto_loc != UNKNOWN_LOCATION); |
22487 | |
22488 | if (!parser->in_function_body && (inline_p || goto_p)) |
22489 | { |
22490 | error_at (first_loc, "%<asm%> qualifier outside of function body" ); |
22491 | inline_p = goto_p = false; |
22492 | } |
22493 | |
22494 | /* Look for the opening `('. */ |
22495 | if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) |
22496 | return; |
22497 | /* Look for the string. */ |
22498 | tree string = cp_parser_string_literal (parser, /*translate=*/false, |
22499 | /*wide_ok=*/false); |
22500 | if (string == error_mark_node) |
22501 | { |
22502 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
22503 | /*consume_paren=*/true); |
22504 | return; |
22505 | } |
22506 | |
22507 | /* If we're allowing GNU extensions, check for the extended assembly |
22508 | syntax. Unfortunately, the `:' tokens need not be separated by |
22509 | a space in C, and so, for compatibility, we tolerate that here |
22510 | too. Doing that means that we have to treat the `::' operator as |
22511 | two `:' tokens. */ |
22512 | if (cp_parser_allow_gnu_extensions_p (parser) |
22513 | && parser->in_function_body |
22514 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
22515 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE))) |
22516 | { |
22517 | bool inputs_p = false; |
22518 | bool clobbers_p = false; |
22519 | bool labels_p = false; |
22520 | |
22521 | /* The extended syntax was used. */ |
22522 | extended_p = true; |
22523 | |
22524 | /* Look for outputs. */ |
22525 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22526 | { |
22527 | /* Consume the `:'. */ |
22528 | cp_lexer_consume_token (lexer: parser->lexer); |
22529 | /* Parse the output-operands. */ |
22530 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22531 | type: CPP_COLON) |
22532 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22533 | type: CPP_SCOPE) |
22534 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22535 | type: CPP_CLOSE_PAREN)) |
22536 | { |
22537 | outputs = cp_parser_asm_operand_list (parser); |
22538 | if (outputs == error_mark_node) |
22539 | invalid_outputs_p = true; |
22540 | } |
22541 | } |
22542 | /* If the next token is `::', there are no outputs, and the |
22543 | next token is the beginning of the inputs. */ |
22544 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22545 | /* The inputs are coming next. */ |
22546 | inputs_p = true; |
22547 | |
22548 | /* Look for inputs. */ |
22549 | if (inputs_p |
22550 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22551 | { |
22552 | /* Consume the `:' or `::'. */ |
22553 | cp_lexer_consume_token (lexer: parser->lexer); |
22554 | /* Parse the output-operands. */ |
22555 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22556 | type: CPP_COLON) |
22557 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22558 | type: CPP_SCOPE) |
22559 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22560 | type: CPP_CLOSE_PAREN)) |
22561 | { |
22562 | inputs = cp_parser_asm_operand_list (parser); |
22563 | if (inputs == error_mark_node) |
22564 | invalid_inputs_p = true; |
22565 | } |
22566 | } |
22567 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22568 | /* The clobbers are coming next. */ |
22569 | clobbers_p = true; |
22570 | |
22571 | /* Look for clobbers. */ |
22572 | if (clobbers_p |
22573 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
22574 | { |
22575 | clobbers_p = true; |
22576 | /* Consume the `:' or `::'. */ |
22577 | cp_lexer_consume_token (lexer: parser->lexer); |
22578 | /* Parse the clobbers. */ |
22579 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
22580 | type: CPP_COLON) |
22581 | && cp_lexer_next_token_is_not (lexer: parser->lexer, |
22582 | type: CPP_CLOSE_PAREN)) |
22583 | clobbers = cp_parser_asm_clobber_list (parser); |
22584 | } |
22585 | else if (goto_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
22586 | /* The labels are coming next. */ |
22587 | labels_p = true; |
22588 | |
22589 | /* Look for labels. */ |
22590 | if (labels_p |
22591 | || (goto_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON))) |
22592 | { |
22593 | labels_p = true; |
22594 | /* Consume the `:' or `::'. */ |
22595 | cp_lexer_consume_token (lexer: parser->lexer); |
22596 | /* Parse the labels. */ |
22597 | labels = cp_parser_asm_label_list (parser); |
22598 | } |
22599 | |
22600 | if (goto_p && !labels_p) |
22601 | missing = clobbers_p ? RT_COLON : RT_COLON_SCOPE; |
22602 | } |
22603 | else if (goto_p) |
22604 | missing = RT_COLON_SCOPE; |
22605 | |
22606 | /* Look for the closing `)'. */ |
22607 | if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN, |
22608 | missing ? missing : RT_CLOSE_PAREN)) |
22609 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
22610 | /*consume_paren=*/true); |
22611 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
22612 | |
22613 | if (!invalid_inputs_p && !invalid_outputs_p) |
22614 | { |
22615 | /* Create the ASM_EXPR. */ |
22616 | if (parser->in_function_body) |
22617 | { |
22618 | asm_stmt = finish_asm_stmt (asm_loc, volatile_p, string, outputs, |
22619 | inputs, clobbers, labels, inline_p); |
22620 | /* If the extended syntax was not used, mark the ASM_EXPR. */ |
22621 | if (!extended_p) |
22622 | { |
22623 | tree temp = asm_stmt; |
22624 | if (TREE_CODE (temp) == CLEANUP_POINT_EXPR) |
22625 | temp = TREE_OPERAND (temp, 0); |
22626 | |
22627 | ASM_INPUT_P (temp) = 1; |
22628 | } |
22629 | } |
22630 | else |
22631 | symtab->finalize_toplevel_asm (asm_str: string); |
22632 | } |
22633 | } |
22634 | |
22635 | /* Given the type TYPE of a declaration with declarator DECLARATOR, return the |
22636 | type that comes from the decl-specifier-seq. */ |
22637 | |
22638 | static tree |
22639 | strip_declarator_types (tree type, cp_declarator *declarator) |
22640 | { |
22641 | for (cp_declarator *d = declarator; d;) |
22642 | switch (d->kind) |
22643 | { |
22644 | case cdk_id: |
22645 | case cdk_decomp: |
22646 | case cdk_error: |
22647 | d = NULL; |
22648 | break; |
22649 | |
22650 | default: |
22651 | if (TYPE_PTRMEMFUNC_P (type)) |
22652 | type = TYPE_PTRMEMFUNC_FN_TYPE (type); |
22653 | type = TREE_TYPE (type); |
22654 | d = d->declarator; |
22655 | break; |
22656 | } |
22657 | |
22658 | return type; |
22659 | } |
22660 | |
22661 | /* Warn about the most vexing parse syntactic ambiguity, i.e., warn when |
22662 | a construct looks like a variable definition but is actually a function |
22663 | declaration. DECL_SPECIFIERS is the decl-specifier-seq and DECLARATOR |
22664 | is the declarator for this function declaration. */ |
22665 | |
22666 | static void |
22667 | warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers, |
22668 | const cp_declarator *declarator) |
22669 | { |
22670 | /* Only warn if we are declaring a function at block scope. */ |
22671 | if (!at_function_scope_p ()) |
22672 | return; |
22673 | |
22674 | /* And only if there is no storage class specified. */ |
22675 | if (decl_specifiers->storage_class != sc_none |
22676 | || decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef)) |
22677 | return; |
22678 | |
22679 | if (declarator->kind != cdk_function |
22680 | || !declarator->declarator |
22681 | || declarator->declarator->kind != cdk_id |
22682 | || !identifier_p (t: get_unqualified_id |
22683 | (declarator: const_cast<cp_declarator *>(declarator)))) |
22684 | return; |
22685 | |
22686 | /* Don't warn when the whole declarator (not just the declarator-id!) |
22687 | was parenthesized. That is, don't warn for int(n()) but do warn |
22688 | for int(f)(). */ |
22689 | if (declarator->parenthesized != UNKNOWN_LOCATION) |
22690 | return; |
22691 | |
22692 | tree type; |
22693 | if (decl_specifiers->type) |
22694 | { |
22695 | type = decl_specifiers->type; |
22696 | if (TREE_CODE (type) == TYPE_DECL) |
22697 | type = TREE_TYPE (type); |
22698 | |
22699 | /* If the return type is void there is no ambiguity. */ |
22700 | if (same_type_p (type, void_type_node)) |
22701 | return; |
22702 | } |
22703 | else if (decl_specifiers->any_type_specifiers_p) |
22704 | /* Code like long f(); will have null ->type. If we have any |
22705 | type-specifiers, pretend we've seen int. */ |
22706 | type = integer_type_node; |
22707 | else |
22708 | return; |
22709 | |
22710 | auto_diagnostic_group d; |
22711 | location_t loc = declarator->u.function.parens_loc; |
22712 | tree params = declarator->u.function.parameters; |
22713 | const bool has_list_ctor_p = CLASS_TYPE_P (type) && TYPE_HAS_LIST_CTOR (type); |
22714 | |
22715 | /* The T t() case. */ |
22716 | if (params == void_list_node) |
22717 | { |
22718 | if (warning_at (loc, OPT_Wvexing_parse, |
22719 | "empty parentheses were disambiguated as a function " |
22720 | "declaration" )) |
22721 | { |
22722 | /* () means value-initialization (C++03 and up); {} (C++11 and up) |
22723 | means value-initialization or aggregate-initialization, nothing |
22724 | means default-initialization. We can only suggest removing the |
22725 | parentheses/adding {} if T has a default constructor. */ |
22726 | if (!CLASS_TYPE_P (type) || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) |
22727 | { |
22728 | gcc_rich_location iloc (loc); |
22729 | iloc.add_fixit_remove (); |
22730 | inform (&iloc, "remove parentheses to default-initialize " |
22731 | "a variable" ); |
22732 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
22733 | { |
22734 | if (CP_AGGREGATE_TYPE_P (type)) |
22735 | inform (loc, "or replace parentheses with braces to " |
22736 | "aggregate-initialize a variable" ); |
22737 | else |
22738 | inform (loc, "or replace parentheses with braces to " |
22739 | "value-initialize a variable" ); |
22740 | } |
22741 | } |
22742 | } |
22743 | return; |
22744 | } |
22745 | |
22746 | /* If we had (...) or the parameter-list wasn't parenthesized, |
22747 | we're done. */ |
22748 | if (params == NULL_TREE || !PARENTHESIZED_LIST_P (params)) |
22749 | return; |
22750 | |
22751 | /* The T t(X()) case. */ |
22752 | if (list_length (params) == 2) |
22753 | { |
22754 | if (warning_at (loc, OPT_Wvexing_parse, |
22755 | "parentheses were disambiguated as a function " |
22756 | "declaration" )) |
22757 | { |
22758 | gcc_rich_location iloc (loc); |
22759 | /* {}-initialization means that we can use an initializer-list |
22760 | constructor if no default constructor is available, so don't |
22761 | suggest using {} for classes that have an initializer_list |
22762 | constructor. */ |
22763 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
22764 | { |
22765 | iloc.add_fixit_replace (where: get_start (loc), new_content: "{" ); |
22766 | iloc.add_fixit_replace (where: get_finish (loc), new_content: "}" ); |
22767 | inform (&iloc, "replace parentheses with braces to declare a " |
22768 | "variable" ); |
22769 | } |
22770 | else |
22771 | { |
22772 | iloc.add_fixit_insert_after (where: get_start (loc), new_content: "(" ); |
22773 | iloc.add_fixit_insert_before (where: get_finish (loc), new_content: ")" ); |
22774 | inform (&iloc, "add parentheses to declare a variable" ); |
22775 | } |
22776 | } |
22777 | } |
22778 | /* The T t(X(), X()) case. */ |
22779 | else if (warning_at (loc, OPT_Wvexing_parse, |
22780 | "parentheses were disambiguated as a function " |
22781 | "declaration" )) |
22782 | { |
22783 | gcc_rich_location iloc (loc); |
22784 | if (cxx_dialect >= cxx11 && !has_list_ctor_p) |
22785 | { |
22786 | iloc.add_fixit_replace (where: get_start (loc), new_content: "{" ); |
22787 | iloc.add_fixit_replace (where: get_finish (loc), new_content: "}" ); |
22788 | inform (&iloc, "replace parentheses with braces to declare a " |
22789 | "variable" ); |
22790 | } |
22791 | } |
22792 | } |
22793 | |
22794 | /* If DECLARATOR with DECL_SPECS is a function declarator that has |
22795 | the form of a deduction guide, tag it as such. CTOR_DTOR_OR_CONV_P |
22796 | has the same meaning as in cp_parser_declarator. */ |
22797 | |
22798 | static void |
22799 | cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser, |
22800 | cp_decl_specifier_seq *decl_specs, |
22801 | cp_declarator *declarator, |
22802 | int *ctor_dtor_or_conv_p) |
22803 | { |
22804 | if (cxx_dialect >= cxx17 |
22805 | && *ctor_dtor_or_conv_p <= 0 |
22806 | && !decl_specs->type |
22807 | && !decl_specs->any_type_specifiers_p |
22808 | && function_declarator_p (declarator)) |
22809 | { |
22810 | cp_declarator *id = get_id_declarator (declarator); |
22811 | tree name = id->u.id.unqualified_name; |
22812 | parser->scope = id->u.id.qualifying_scope; |
22813 | tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc); |
22814 | if (tmpl |
22815 | && (DECL_CLASS_TEMPLATE_P (tmpl) |
22816 | || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))) |
22817 | { |
22818 | id->u.id.unqualified_name = dguide_name (tmpl); |
22819 | id->u.id.sfk = sfk_deduction_guide; |
22820 | *ctor_dtor_or_conv_p = 1; |
22821 | } |
22822 | } |
22823 | } |
22824 | |
22825 | /* Declarators [gram.dcl.decl] */ |
22826 | |
22827 | /* Parse an init-declarator. |
22828 | |
22829 | init-declarator: |
22830 | declarator initializer [opt] |
22831 | |
22832 | GNU Extension: |
22833 | |
22834 | init-declarator: |
22835 | declarator asm-specification [opt] attributes [opt] initializer [opt] |
22836 | |
22837 | function-definition: |
22838 | decl-specifier-seq [opt] declarator ctor-initializer [opt] |
22839 | function-body |
22840 | decl-specifier-seq [opt] declarator function-try-block |
22841 | |
22842 | GNU Extension: |
22843 | |
22844 | function-definition: |
22845 | __extension__ function-definition |
22846 | |
22847 | TM Extension: |
22848 | |
22849 | function-definition: |
22850 | decl-specifier-seq [opt] declarator function-transaction-block |
22851 | |
22852 | The parser flags FLAGS is used to control type-specifier parsing. |
22853 | |
22854 | The DECL_SPECIFIERS apply to this declarator. Returns a |
22855 | representation of the entity declared. If MEMBER_P is TRUE, then |
22856 | this declarator appears in a class scope. The new DECL created by |
22857 | this declarator is returned. |
22858 | |
22859 | The CHECKS are access checks that should be performed once we know |
22860 | what entity is being declared (and, therefore, what classes have |
22861 | befriended it). |
22862 | |
22863 | If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and |
22864 | for a function-definition here as well. If the declarator is a |
22865 | declarator for a function-definition, *FUNCTION_DEFINITION_P will |
22866 | be TRUE upon return. By that point, the function-definition will |
22867 | have been completely parsed. |
22868 | |
22869 | FUNCTION_DEFINITION_P may be NULL if FUNCTION_DEFINITION_ALLOWED_P |
22870 | is FALSE. |
22871 | |
22872 | If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the |
22873 | parsed declaration if it is an uninitialized single declarator not followed |
22874 | by a `;', or to error_mark_node otherwise. Either way, the trailing `;', |
22875 | if present, will not be consumed. If returned, this declarator will be |
22876 | created with SD_INITIALIZED but will not call cp_finish_decl. |
22877 | |
22878 | If INIT_LOC is not NULL, and *INIT_LOC is equal to UNKNOWN_LOCATION, |
22879 | and there is an initializer, the pointed location_t is set to the |
22880 | location of the '=' or `(', or '{' in C++11 token introducing the |
22881 | initializer. */ |
22882 | |
22883 | static tree |
22884 | cp_parser_init_declarator (cp_parser* parser, |
22885 | cp_parser_flags flags, |
22886 | cp_decl_specifier_seq *decl_specifiers, |
22887 | vec<deferred_access_check, va_gc> *checks, |
22888 | bool function_definition_allowed_p, |
22889 | bool member_p, |
22890 | int declares_class_or_enum, |
22891 | bool* function_definition_p, |
22892 | tree* maybe_range_for_decl, |
22893 | location_t* init_loc, |
22894 | tree* auto_result) |
22895 | { |
22896 | cp_token *token = NULL, *asm_spec_start_token = NULL, |
22897 | *attributes_start_token = NULL; |
22898 | cp_declarator *declarator; |
22899 | tree prefix_attributes; |
22900 | tree attributes = NULL; |
22901 | tree asm_specification; |
22902 | tree initializer; |
22903 | tree decl = NULL_TREE; |
22904 | tree scope; |
22905 | int is_initialized; |
22906 | /* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if |
22907 | initialized with "= ..", CPP_OPEN_PAREN if initialized with |
22908 | "(...)". */ |
22909 | enum cpp_ttype initialization_kind; |
22910 | bool is_direct_init = false; |
22911 | bool is_non_constant_init; |
22912 | int ctor_dtor_or_conv_p; |
22913 | bool friend_p = cp_parser_friend_p (decl_specifiers); |
22914 | bool static_p = decl_specifiers->storage_class == sc_static; |
22915 | tree pushed_scope = NULL_TREE; |
22916 | bool range_for_decl_p = false; |
22917 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
22918 | location_t tmp_init_loc = UNKNOWN_LOCATION; |
22919 | |
22920 | if (decl_spec_seq_has_spec_p (decl_specifiers, ds_consteval)) |
22921 | flags |= CP_PARSER_FLAGS_CONSTEVAL; |
22922 | |
22923 | /* Assume that this is not the declarator for a function |
22924 | definition. */ |
22925 | if (function_definition_p) |
22926 | *function_definition_p = false; |
22927 | |
22928 | /* Default arguments are only permitted for function parameters. */ |
22929 | if (decl_spec_seq_has_spec_p (decl_specifiers, ds_typedef)) |
22930 | parser->default_arg_ok_p = false; |
22931 | |
22932 | /* Defer access checks while parsing the declarator; we cannot know |
22933 | what names are accessible until we know what is being |
22934 | declared. */ |
22935 | resume_deferring_access_checks (); |
22936 | |
22937 | token = cp_lexer_peek_token (lexer: parser->lexer); |
22938 | |
22939 | /* Parse the declarator. */ |
22940 | declarator |
22941 | = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, |
22942 | flags, &ctor_dtor_or_conv_p, |
22943 | /*parenthesized_p=*/NULL, |
22944 | member_p, friend_p, static_p); |
22945 | /* Gather up the deferred checks. */ |
22946 | stop_deferring_access_checks (); |
22947 | |
22948 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
22949 | |
22950 | /* If the DECLARATOR was erroneous, there's no need to go |
22951 | further. */ |
22952 | if (declarator == cp_error_declarator) |
22953 | return error_mark_node; |
22954 | |
22955 | /* Check that the number of template-parameter-lists is OK. */ |
22956 | if (!cp_parser_check_declarator_template_parameters (parser, declarator, |
22957 | token->location)) |
22958 | return error_mark_node; |
22959 | |
22960 | if (declares_class_or_enum & 2) |
22961 | cp_parser_check_for_definition_in_return_type (declarator, |
22962 | type: decl_specifiers->type, |
22963 | type_location: decl_specifiers->locations[ds_type_spec]); |
22964 | |
22965 | /* Figure out what scope the entity declared by the DECLARATOR is |
22966 | located in. `grokdeclarator' sometimes changes the scope, so |
22967 | we compute it now. */ |
22968 | scope = get_scope_of_declarator (declarator); |
22969 | |
22970 | /* Perform any lookups in the declared type which were thought to be |
22971 | dependent, but are not in the scope of the declarator. */ |
22972 | decl_specifiers->type |
22973 | = maybe_update_decl_type (decl_specifiers->type, scope); |
22974 | |
22975 | /* If we're allowing GNU extensions, look for an |
22976 | asm-specification. */ |
22977 | if (cp_parser_allow_gnu_extensions_p (parser)) |
22978 | { |
22979 | /* Look for an asm-specification. */ |
22980 | asm_spec_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
22981 | asm_specification = cp_parser_asm_specification_opt (parser); |
22982 | } |
22983 | else |
22984 | asm_specification = NULL_TREE; |
22985 | |
22986 | /* Gather the attributes that were provided with the |
22987 | decl-specifiers. */ |
22988 | prefix_attributes = decl_specifiers->attributes; |
22989 | |
22990 | /* Look for attributes. */ |
22991 | attributes_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
22992 | attributes = cp_parser_attributes_opt (parser); |
22993 | |
22994 | /* Peek at the next token. */ |
22995 | token = cp_lexer_peek_token (lexer: parser->lexer); |
22996 | |
22997 | bool bogus_implicit_tmpl = false; |
22998 | |
22999 | if (function_declarator_p (declarator)) |
23000 | { |
23001 | /* Handle C++17 deduction guides. Note that class-scope |
23002 | non-template deduction guides are instead handled in |
23003 | cp_parser_member_declaration. */ |
23004 | cp_parser_maybe_adjust_declarator_for_dguide (parser, |
23005 | decl_specs: decl_specifiers, |
23006 | declarator, |
23007 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p); |
23008 | |
23009 | if (!member_p && !cp_parser_error_occurred (parser)) |
23010 | warn_about_ambiguous_parse (decl_specifiers, declarator); |
23011 | |
23012 | /* Check to see if the token indicates the start of a |
23013 | function-definition. */ |
23014 | if (cp_parser_token_starts_function_definition_p (token)) |
23015 | { |
23016 | if (!function_definition_allowed_p) |
23017 | { |
23018 | /* If a function-definition should not appear here, issue an |
23019 | error message. */ |
23020 | cp_parser_error (parser, |
23021 | gmsgid: "a function-definition is not allowed here" ); |
23022 | return error_mark_node; |
23023 | } |
23024 | |
23025 | location_t func_brace_location |
23026 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
23027 | |
23028 | /* Neither attributes nor an asm-specification are allowed |
23029 | on a function-definition. */ |
23030 | if (asm_specification) |
23031 | error_at (asm_spec_start_token->location, |
23032 | "an %<asm%> specification is not allowed " |
23033 | "on a function-definition" ); |
23034 | if (attributes) |
23035 | error_at (attributes_start_token->location, |
23036 | "attributes are not allowed " |
23037 | "on a function-definition" ); |
23038 | /* This is a function-definition. */ |
23039 | *function_definition_p = true; |
23040 | |
23041 | /* Parse the function definition. */ |
23042 | if (member_p) |
23043 | decl = cp_parser_save_member_function_body (parser, |
23044 | decl_specifiers, |
23045 | declarator, |
23046 | prefix_attributes); |
23047 | else |
23048 | decl = |
23049 | (cp_parser_function_definition_from_specifiers_and_declarator |
23050 | (parser, decl_specifiers, prefix_attributes, declarator)); |
23051 | |
23052 | if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl)) |
23053 | { |
23054 | /* This is where the prologue starts... */ |
23055 | DECL_STRUCT_FUNCTION (decl)->function_start_locus |
23056 | = func_brace_location; |
23057 | } |
23058 | |
23059 | return decl; |
23060 | } |
23061 | } |
23062 | else if (parser->fully_implicit_function_template_p) |
23063 | { |
23064 | /* A non-template declaration involving a function parameter list |
23065 | containing an implicit template parameter will be made into a |
23066 | template. If the resulting declaration is not going to be an |
23067 | actual function then finish the template scope here to prevent it. |
23068 | An error message will be issued once we have a decl to talk about. |
23069 | |
23070 | FIXME probably we should do type deduction rather than create an |
23071 | implicit template, but the standard currently doesn't allow it. */ |
23072 | bogus_implicit_tmpl = true; |
23073 | finish_fully_implicit_template (parser, NULL_TREE); |
23074 | } |
23075 | |
23076 | /* [dcl.dcl] |
23077 | |
23078 | Only in function declarations for constructors, destructors, type |
23079 | conversions, and deduction guides can the decl-specifier-seq be omitted. |
23080 | |
23081 | We explicitly postpone this check past the point where we handle |
23082 | function-definitions because we tolerate function-definitions |
23083 | that are missing their return types in some modes. */ |
23084 | if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0) |
23085 | { |
23086 | cp_parser_error (parser, |
23087 | gmsgid: "expected constructor, destructor, or type conversion" ); |
23088 | return error_mark_node; |
23089 | } |
23090 | |
23091 | /* An `=' or an '{' in C++11, indicate an initializer. An '(' may indicate |
23092 | an initializer as well. */ |
23093 | if (token->type == CPP_EQ |
23094 | || token->type == CPP_OPEN_PAREN |
23095 | || token->type == CPP_OPEN_BRACE) |
23096 | { |
23097 | /* Don't get fooled into thinking that F(i)(1)(2) is an initializer. |
23098 | It isn't; it's an expression. (Here '(i)' would have already been |
23099 | parsed as a declarator.) */ |
23100 | if (token->type == CPP_OPEN_PAREN |
23101 | && cp_parser_uncommitted_to_tentative_parse_p (parser)) |
23102 | { |
23103 | cp_lexer_save_tokens (lexer: parser->lexer); |
23104 | cp_lexer_consume_token (lexer: parser->lexer); |
23105 | cp_parser_skip_to_closing_parenthesis (parser, |
23106 | /*recovering*/false, |
23107 | /*or_comma*/false, |
23108 | /*consume_paren*/true); |
23109 | /* If this is an initializer, only a ',' or ';' can follow: either |
23110 | we have another init-declarator, or we're at the end of an |
23111 | init-declarator-list which can only be followed by a ';'. */ |
23112 | bool ok = (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
23113 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
23114 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
23115 | if (UNLIKELY (!ok)) |
23116 | /* Not an init-declarator. */ |
23117 | return error_mark_node; |
23118 | } |
23119 | is_initialized = SD_INITIALIZED; |
23120 | initialization_kind = token->type; |
23121 | declarator->init_loc = token->location; |
23122 | if (maybe_range_for_decl) |
23123 | *maybe_range_for_decl = error_mark_node; |
23124 | tmp_init_loc = token->location; |
23125 | if (init_loc && *init_loc == UNKNOWN_LOCATION) |
23126 | *init_loc = tmp_init_loc; |
23127 | |
23128 | if (token->type == CPP_EQ |
23129 | && function_declarator_p (declarator)) |
23130 | { |
23131 | cp_token *t2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
23132 | if (t2->keyword == RID_DEFAULT) |
23133 | is_initialized = SD_DEFAULTED; |
23134 | else if (t2->keyword == RID_DELETE) |
23135 | is_initialized = SD_DELETED; |
23136 | } |
23137 | } |
23138 | else |
23139 | { |
23140 | /* If the init-declarator isn't initialized and isn't followed by a |
23141 | `,' or `;', it's not a valid init-declarator. */ |
23142 | if (token->type != CPP_COMMA |
23143 | && token->type != CPP_SEMICOLON) |
23144 | { |
23145 | if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node) |
23146 | range_for_decl_p = true; |
23147 | else |
23148 | { |
23149 | if (!maybe_range_for_decl) |
23150 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
23151 | return error_mark_node; |
23152 | } |
23153 | } |
23154 | is_initialized = SD_UNINITIALIZED; |
23155 | initialization_kind = CPP_EOF; |
23156 | } |
23157 | |
23158 | /* Because start_decl has side-effects, we should only call it if we |
23159 | know we're going ahead. By this point, we know that we cannot |
23160 | possibly be looking at any other construct. */ |
23161 | cp_parser_commit_to_tentative_parse (parser); |
23162 | |
23163 | /* Enter the newly declared entry in the symbol table. If we're |
23164 | processing a declaration in a class-specifier, we wait until |
23165 | after processing the initializer. */ |
23166 | if (!member_p) |
23167 | { |
23168 | if (parser->in_unbraced_linkage_specification_p) |
23169 | decl_specifiers->storage_class = sc_extern; |
23170 | decl = start_decl (declarator, decl_specifiers, |
23171 | range_for_decl_p? SD_INITIALIZED : is_initialized, |
23172 | attributes, prefix_attributes, &pushed_scope); |
23173 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
23174 | cp_finalize_oacc_routine (parser, decl, false); |
23175 | /* Adjust location of decl if declarator->id_loc is more appropriate: |
23176 | set, and decl wasn't merged with another decl, in which case its |
23177 | location would be different from input_location, and more accurate. */ |
23178 | if (DECL_P (decl) |
23179 | && declarator->id_loc != UNKNOWN_LOCATION |
23180 | && DECL_SOURCE_LOCATION (decl) == input_location) |
23181 | DECL_SOURCE_LOCATION (decl) = declarator->id_loc; |
23182 | } |
23183 | else if (scope) |
23184 | /* Enter the SCOPE. That way unqualified names appearing in the |
23185 | initializer will be looked up in SCOPE. */ |
23186 | pushed_scope = push_scope (scope); |
23187 | |
23188 | /* Perform deferred access control checks, now that we know in which |
23189 | SCOPE the declared entity resides. */ |
23190 | if (!member_p && decl) |
23191 | { |
23192 | tree saved_current_function_decl = NULL_TREE; |
23193 | |
23194 | /* If the entity being declared is a function, pretend that we |
23195 | are in its scope. If it is a `friend', it may have access to |
23196 | things that would not otherwise be accessible. */ |
23197 | if (TREE_CODE (decl) == FUNCTION_DECL) |
23198 | { |
23199 | saved_current_function_decl = current_function_decl; |
23200 | current_function_decl = decl; |
23201 | } |
23202 | |
23203 | /* Perform access checks for template parameters. */ |
23204 | cp_parser_perform_template_parameter_access_checks (checks); |
23205 | |
23206 | /* Perform the access control checks for the declarator and the |
23207 | decl-specifiers. */ |
23208 | perform_deferred_access_checks (tf_warning_or_error); |
23209 | |
23210 | /* Restore the saved value. */ |
23211 | if (TREE_CODE (decl) == FUNCTION_DECL) |
23212 | current_function_decl = saved_current_function_decl; |
23213 | } |
23214 | |
23215 | /* Parse the initializer. */ |
23216 | initializer = NULL_TREE; |
23217 | is_direct_init = false; |
23218 | is_non_constant_init = true; |
23219 | if (is_initialized) |
23220 | { |
23221 | if (function_declarator_p (declarator)) |
23222 | { |
23223 | if (initialization_kind == CPP_EQ) |
23224 | initializer = cp_parser_pure_specifier (parser); |
23225 | else |
23226 | { |
23227 | /* If the declaration was erroneous, we don't really |
23228 | know what the user intended, so just silently |
23229 | consume the initializer. */ |
23230 | if (decl != error_mark_node) |
23231 | error_at (tmp_init_loc, "initializer provided for function" ); |
23232 | cp_parser_skip_to_closing_parenthesis (parser, |
23233 | /*recovering=*/true, |
23234 | /*or_comma=*/false, |
23235 | /*consume_paren=*/true); |
23236 | } |
23237 | } |
23238 | else |
23239 | { |
23240 | /* We want to record the extra mangling scope for in-class |
23241 | initializers of class members and initializers of static |
23242 | data member templates and namespace-scope initializers. |
23243 | The former involves deferring parsing of the initializer |
23244 | until end of class as with default arguments. So right |
23245 | here we only handle the latter two. */ |
23246 | bool has_lambda_scope = false; |
23247 | |
23248 | if (decl != error_mark_node |
23249 | && !member_p |
23250 | && (processing_template_decl || DECL_NAMESPACE_SCOPE_P (decl))) |
23251 | has_lambda_scope = true; |
23252 | |
23253 | if (has_lambda_scope) |
23254 | start_lambda_scope (decl); |
23255 | initializer = cp_parser_initializer (parser, |
23256 | &is_direct_init, |
23257 | &is_non_constant_init); |
23258 | if (has_lambda_scope) |
23259 | finish_lambda_scope (); |
23260 | if (initializer == error_mark_node) |
23261 | cp_parser_skip_to_end_of_statement (parser); |
23262 | } |
23263 | } |
23264 | |
23265 | /* The old parser allows attributes to appear after a parenthesized |
23266 | initializer. Mark Mitchell proposed removing this functionality |
23267 | on the GCC mailing lists on 2002-08-13. This parser accepts the |
23268 | attributes -- but ignores them. Made a permerror in GCC 8. */ |
23269 | if (cp_parser_allow_gnu_extensions_p (parser) |
23270 | && initialization_kind == CPP_OPEN_PAREN |
23271 | && cp_parser_attributes_opt (parser) |
23272 | && permerror (input_location, |
23273 | "attributes after parenthesized initializer ignored" )) |
23274 | { |
23275 | static bool hint; |
23276 | if (flag_permissive && !hint) |
23277 | { |
23278 | hint = true; |
23279 | inform (input_location, |
23280 | "this flexibility is deprecated and will be removed" ); |
23281 | } |
23282 | } |
23283 | |
23284 | /* And now complain about a non-function implicit template. */ |
23285 | if (bogus_implicit_tmpl && decl != error_mark_node) |
23286 | error_at (DECL_SOURCE_LOCATION (decl), |
23287 | "non-function %qD declared as implicit template" , decl); |
23288 | |
23289 | /* For an in-class declaration, use `grokfield' to create the |
23290 | declaration. */ |
23291 | if (member_p) |
23292 | { |
23293 | if (pushed_scope) |
23294 | { |
23295 | pop_scope (pushed_scope); |
23296 | pushed_scope = NULL_TREE; |
23297 | } |
23298 | decl = grokfield (declarator, decl_specifiers, |
23299 | initializer, !is_non_constant_init, |
23300 | /*asmspec=*/NULL_TREE, |
23301 | attr_chainon (attrs: attributes, attr: prefix_attributes)); |
23302 | if (decl && TREE_CODE (decl) == FUNCTION_DECL) |
23303 | cp_parser_save_default_args (parser, decl); |
23304 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
23305 | cp_finalize_oacc_routine (parser, decl, false); |
23306 | } |
23307 | |
23308 | /* Finish processing the declaration. But, skip member |
23309 | declarations. */ |
23310 | if (!member_p && decl && decl != error_mark_node && !range_for_decl_p) |
23311 | { |
23312 | cp_finish_decl (decl, |
23313 | initializer, !is_non_constant_init, |
23314 | asm_specification, |
23315 | /* If the initializer is in parentheses, then this is |
23316 | a direct-initialization, which means that an |
23317 | `explicit' constructor is OK. Otherwise, an |
23318 | `explicit' constructor cannot be used. */ |
23319 | ((is_direct_init || !is_initialized) |
23320 | ? LOOKUP_NORMAL : LOOKUP_IMPLICIT)); |
23321 | } |
23322 | else if ((cxx_dialect != cxx98) && friend_p |
23323 | && decl && TREE_CODE (decl) == FUNCTION_DECL) |
23324 | /* Core issue #226 (C++0x only): A default template-argument |
23325 | shall not be specified in a friend class template |
23326 | declaration. */ |
23327 | check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true, |
23328 | /*is_partial=*/false, /*is_friend_decl=*/1); |
23329 | |
23330 | if (!friend_p && pushed_scope) |
23331 | pop_scope (pushed_scope); |
23332 | |
23333 | if (function_declarator_p (declarator) |
23334 | && parser->fully_implicit_function_template_p) |
23335 | { |
23336 | if (member_p) |
23337 | decl = finish_fully_implicit_template (parser, decl); |
23338 | else |
23339 | finish_fully_implicit_template (parser, /*member_decl_opt=*/0); |
23340 | } |
23341 | |
23342 | if (auto_result && is_initialized && decl_specifiers->type |
23343 | && type_uses_auto (decl_specifiers->type)) |
23344 | *auto_result = strip_declarator_types (TREE_TYPE (decl), declarator); |
23345 | |
23346 | return decl; |
23347 | } |
23348 | |
23349 | /* Parse a declarator. |
23350 | |
23351 | declarator: |
23352 | direct-declarator |
23353 | ptr-operator declarator |
23354 | |
23355 | abstract-declarator: |
23356 | ptr-operator abstract-declarator [opt] |
23357 | direct-abstract-declarator |
23358 | |
23359 | GNU Extensions: |
23360 | |
23361 | declarator: |
23362 | attributes [opt] direct-declarator |
23363 | attributes [opt] ptr-operator declarator |
23364 | |
23365 | abstract-declarator: |
23366 | attributes [opt] ptr-operator abstract-declarator [opt] |
23367 | attributes [opt] direct-abstract-declarator |
23368 | |
23369 | The parser flags FLAGS is used to control type-specifier parsing. |
23370 | |
23371 | If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to |
23372 | detect constructors, destructors, deduction guides, or conversion operators. |
23373 | It is set to -1 if the declarator is a name, and +1 if it is a |
23374 | function. Otherwise it is set to zero. Usually you just want to |
23375 | test for >0, but internally the negative value is used. |
23376 | |
23377 | (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have |
23378 | a decl-specifier-seq unless it declares a constructor, destructor, |
23379 | or conversion. It might seem that we could check this condition in |
23380 | semantic analysis, rather than parsing, but that makes it difficult |
23381 | to handle something like `f()'. We want to notice that there are |
23382 | no decl-specifiers, and therefore realize that this is an |
23383 | expression, not a declaration.) |
23384 | |
23385 | If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff |
23386 | the declarator is a direct-declarator of the form "(...)". |
23387 | |
23388 | MEMBER_P is true iff this declarator is a member-declarator. |
23389 | |
23390 | FRIEND_P is true iff this declarator is a friend. |
23391 | |
23392 | STATIC_P is true iff the keyword static was seen. */ |
23393 | |
23394 | static cp_declarator * |
23395 | cp_parser_declarator (cp_parser* parser, |
23396 | cp_parser_declarator_kind dcl_kind, |
23397 | cp_parser_flags flags, |
23398 | int* ctor_dtor_or_conv_p, |
23399 | bool* parenthesized_p, |
23400 | bool member_p, bool friend_p, bool static_p) |
23401 | { |
23402 | cp_declarator *declarator; |
23403 | enum tree_code code; |
23404 | cp_cv_quals cv_quals; |
23405 | tree class_type; |
23406 | tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE; |
23407 | |
23408 | /* Assume this is not a constructor, destructor, or type-conversion |
23409 | operator. */ |
23410 | if (ctor_dtor_or_conv_p) |
23411 | *ctor_dtor_or_conv_p = 0; |
23412 | |
23413 | if (cp_parser_allow_gnu_extensions_p (parser)) |
23414 | gnu_attributes = cp_parser_gnu_attributes_opt (parser); |
23415 | |
23416 | /* Check for the ptr-operator production. */ |
23417 | cp_parser_parse_tentatively (parser); |
23418 | /* Parse the ptr-operator. */ |
23419 | code = cp_parser_ptr_operator (parser, |
23420 | &class_type, |
23421 | &cv_quals, |
23422 | &std_attributes); |
23423 | |
23424 | /* If that worked, then we have a ptr-operator. */ |
23425 | if (cp_parser_parse_definitely (parser)) |
23426 | { |
23427 | /* If a ptr-operator was found, then this declarator was not |
23428 | parenthesized. */ |
23429 | if (parenthesized_p) |
23430 | *parenthesized_p = false; |
23431 | /* The dependent declarator is optional if we are parsing an |
23432 | abstract-declarator. */ |
23433 | if (dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
23434 | cp_parser_parse_tentatively (parser); |
23435 | |
23436 | /* Parse the dependent declarator. */ |
23437 | declarator = cp_parser_declarator (parser, dcl_kind, flags, |
23438 | /*ctor_dtor_or_conv_p=*/NULL, |
23439 | /*parenthesized_p=*/NULL, |
23440 | member_p, friend_p, static_p); |
23441 | |
23442 | /* If we are parsing an abstract-declarator, we must handle the |
23443 | case where the dependent declarator is absent. */ |
23444 | if (dcl_kind != CP_PARSER_DECLARATOR_NAMED |
23445 | && !cp_parser_parse_definitely (parser)) |
23446 | declarator = NULL; |
23447 | |
23448 | declarator = cp_parser_make_indirect_declarator |
23449 | (code, class_type, cv_qualifiers: cv_quals, target: declarator, attributes: std_attributes); |
23450 | } |
23451 | /* Everything else is a direct-declarator. */ |
23452 | else |
23453 | { |
23454 | if (parenthesized_p) |
23455 | *parenthesized_p = cp_lexer_next_token_is (lexer: parser->lexer, |
23456 | type: CPP_OPEN_PAREN); |
23457 | declarator = cp_parser_direct_declarator (parser, dcl_kind, |
23458 | flags, ctor_dtor_or_conv_p, |
23459 | member_p, friend_p, static_p); |
23460 | } |
23461 | |
23462 | if (gnu_attributes && declarator && declarator != cp_error_declarator) |
23463 | declarator->attributes = gnu_attributes; |
23464 | return declarator; |
23465 | } |
23466 | |
23467 | /* Parse a direct-declarator or direct-abstract-declarator. |
23468 | |
23469 | direct-declarator: |
23470 | declarator-id |
23471 | direct-declarator ( parameter-declaration-clause ) |
23472 | cv-qualifier-seq [opt] |
23473 | ref-qualifier [opt] |
23474 | exception-specification [opt] |
23475 | direct-declarator [ constant-expression [opt] ] |
23476 | ( declarator ) |
23477 | |
23478 | direct-abstract-declarator: |
23479 | direct-abstract-declarator [opt] |
23480 | ( parameter-declaration-clause ) |
23481 | cv-qualifier-seq [opt] |
23482 | ref-qualifier [opt] |
23483 | exception-specification [opt] |
23484 | direct-abstract-declarator [opt] [ constant-expression [opt] ] |
23485 | ( abstract-declarator ) |
23486 | |
23487 | Returns a representation of the declarator. DCL_KIND is |
23488 | CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a |
23489 | direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if |
23490 | we are parsing a direct-declarator. It is |
23491 | CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case |
23492 | of ambiguity we prefer an abstract declarator, as per |
23493 | [dcl.ambig.res]. |
23494 | The parser flags FLAGS is used to control type-specifier parsing. |
23495 | CTOR_DTOR_OR_CONV_P, MEMBER_P, FRIEND_P, and STATIC_P are |
23496 | as for cp_parser_declarator. */ |
23497 | |
23498 | static cp_declarator * |
23499 | cp_parser_direct_declarator (cp_parser* parser, |
23500 | cp_parser_declarator_kind dcl_kind, |
23501 | cp_parser_flags flags, |
23502 | int* ctor_dtor_or_conv_p, |
23503 | bool member_p, bool friend_p, bool static_p) |
23504 | { |
23505 | cp_token *token; |
23506 | cp_declarator *declarator = NULL; |
23507 | tree scope = NULL_TREE; |
23508 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
23509 | bool saved_in_declarator_p = parser->in_declarator_p; |
23510 | bool first = true; |
23511 | tree pushed_scope = NULL_TREE; |
23512 | cp_token *open_paren = NULL, *close_paren = NULL; |
23513 | |
23514 | while (true) |
23515 | { |
23516 | /* Peek at the next token. */ |
23517 | token = cp_lexer_peek_token (lexer: parser->lexer); |
23518 | if (token->type == CPP_OPEN_PAREN) |
23519 | { |
23520 | /* This is either a parameter-declaration-clause, or a |
23521 | parenthesized declarator. When we know we are parsing a |
23522 | named declarator, it must be a parenthesized declarator |
23523 | if FIRST is true. For instance, `(int)' is a |
23524 | parameter-declaration-clause, with an omitted |
23525 | direct-abstract-declarator. But `((*))', is a |
23526 | parenthesized abstract declarator. Finally, when T is a |
23527 | template parameter `(T)' is a |
23528 | parameter-declaration-clause, and not a parenthesized |
23529 | named declarator. |
23530 | |
23531 | We first try and parse a parameter-declaration-clause, |
23532 | and then try a nested declarator (if FIRST is true). |
23533 | |
23534 | It is not an error for it not to be a |
23535 | parameter-declaration-clause, even when FIRST is |
23536 | false. Consider, |
23537 | |
23538 | int i (int); |
23539 | int i (3); |
23540 | |
23541 | The first is the declaration of a function while the |
23542 | second is the definition of a variable, including its |
23543 | initializer. |
23544 | |
23545 | Having seen only the parenthesis, we cannot know which of |
23546 | these two alternatives should be selected. Even more |
23547 | complex are examples like: |
23548 | |
23549 | int i (int (a)); |
23550 | int i (int (3)); |
23551 | |
23552 | The former is a function-declaration; the latter is a |
23553 | variable initialization. |
23554 | |
23555 | Thus again, we try a parameter-declaration-clause, and if |
23556 | that fails, we back out and return. */ |
23557 | |
23558 | if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
23559 | { |
23560 | tree params; |
23561 | bool is_declarator = false; |
23562 | |
23563 | open_paren = NULL; |
23564 | |
23565 | /* In a member-declarator, the only valid interpretation |
23566 | of a parenthesis is the start of a |
23567 | parameter-declaration-clause. (It is invalid to |
23568 | initialize a static data member with a parenthesized |
23569 | initializer; only the "=" form of initialization is |
23570 | permitted.) */ |
23571 | if (!member_p) |
23572 | cp_parser_parse_tentatively (parser); |
23573 | |
23574 | /* Consume the `('. */ |
23575 | const location_t parens_start = token->location; |
23576 | matching_parens parens; |
23577 | parens.consume_open (parser); |
23578 | if (first) |
23579 | { |
23580 | /* If this is going to be an abstract declarator, we're |
23581 | in a declarator and we can't have default args. */ |
23582 | parser->default_arg_ok_p = false; |
23583 | parser->in_declarator_p = true; |
23584 | } |
23585 | |
23586 | begin_scope (sk_function_parms, NULL_TREE); |
23587 | |
23588 | /* Parse the parameter-declaration-clause. */ |
23589 | params |
23590 | = cp_parser_parameter_declaration_clause (parser, flags); |
23591 | const location_t parens_end |
23592 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
23593 | |
23594 | /* Consume the `)'. */ |
23595 | parens.require_close (parser); |
23596 | |
23597 | /* If all went well, parse the cv-qualifier-seq, |
23598 | ref-qualifier and the exception-specification. */ |
23599 | if (member_p || cp_parser_parse_definitely (parser)) |
23600 | { |
23601 | cp_cv_quals cv_quals; |
23602 | cp_virt_specifiers virt_specifiers; |
23603 | cp_ref_qualifier ref_qual; |
23604 | tree exception_specification; |
23605 | tree late_return; |
23606 | tree attrs; |
23607 | bool memfn = (member_p || (pushed_scope |
23608 | && CLASS_TYPE_P (pushed_scope))); |
23609 | unsigned char local_variables_forbidden_p |
23610 | = parser->local_variables_forbidden_p; |
23611 | /* 'this' is not allowed in static member functions. */ |
23612 | if (static_p || friend_p) |
23613 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
23614 | |
23615 | is_declarator = true; |
23616 | |
23617 | if (ctor_dtor_or_conv_p) |
23618 | *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; |
23619 | first = false; |
23620 | |
23621 | /* Parse the cv-qualifier-seq. */ |
23622 | cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
23623 | /* Parse the ref-qualifier. */ |
23624 | ref_qual = cp_parser_ref_qualifier_opt (parser); |
23625 | /* Parse the tx-qualifier. */ |
23626 | tree tx_qual = cp_parser_tx_qualifier_opt (parser); |
23627 | |
23628 | tree save_ccp = current_class_ptr; |
23629 | tree save_ccr = current_class_ref; |
23630 | if (memfn && !friend_p && !static_p) |
23631 | /* DR 1207: 'this' is in scope after the cv-quals. */ |
23632 | inject_this_parameter (current_class_type, cv_quals); |
23633 | |
23634 | /* If it turned out that this is e.g. a pointer to a |
23635 | function, we don't want to delay noexcept parsing. */ |
23636 | if (declarator == NULL || declarator->kind != cdk_id) |
23637 | flags &= ~CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
23638 | |
23639 | /* Parse the exception-specification. */ |
23640 | exception_specification |
23641 | = cp_parser_exception_specification_opt (parser, |
23642 | flags); |
23643 | |
23644 | attrs = cp_parser_std_attribute_spec_seq (parser); |
23645 | |
23646 | cp_omp_declare_simd_data odsd; |
23647 | if ((flag_openmp || flag_openmp_simd) |
23648 | && declarator |
23649 | && declarator->std_attributes |
23650 | && declarator->kind == cdk_id) |
23651 | { |
23652 | tree *pa = &declarator->std_attributes; |
23653 | cp_parser_handle_directive_omp_attributes (parser, pattrs: pa, |
23654 | data: &odsd, start: false); |
23655 | } |
23656 | |
23657 | /* In here, we handle cases where attribute is used after |
23658 | the function declaration. For example: |
23659 | void func (int x) __attribute__((vector(..))); */ |
23660 | tree gnu_attrs = NULL_TREE; |
23661 | tree requires_clause = NULL_TREE; |
23662 | late_return |
23663 | = cp_parser_late_return_type_opt (parser, declarator, |
23664 | requires_clause); |
23665 | |
23666 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
23667 | |
23668 | /* Parse the virt-specifier-seq. */ |
23669 | virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); |
23670 | |
23671 | location_t parens_loc = make_location (caret: parens_start, |
23672 | start: parens_start, |
23673 | finish: parens_end); |
23674 | /* Create the function-declarator. */ |
23675 | declarator = make_call_declarator (target: declarator, |
23676 | parms: params, |
23677 | cv_qualifiers: cv_quals, |
23678 | virt_specifiers, |
23679 | ref_qualifier: ref_qual, |
23680 | tx_qualifier: tx_qual, |
23681 | exception_specification, |
23682 | late_return_type: late_return, |
23683 | requires_clause, |
23684 | std_attrs: attrs, |
23685 | parens_loc); |
23686 | declarator->attributes = gnu_attrs; |
23687 | /* Any subsequent parameter lists are to do with |
23688 | return type, so are not those of the declared |
23689 | function. */ |
23690 | parser->default_arg_ok_p = false; |
23691 | |
23692 | current_class_ptr = save_ccp; |
23693 | current_class_ref = save_ccr; |
23694 | |
23695 | /* Restore the state of local_variables_forbidden_p. */ |
23696 | parser->local_variables_forbidden_p |
23697 | = local_variables_forbidden_p; |
23698 | } |
23699 | |
23700 | /* Remove the function parms from scope. */ |
23701 | pop_bindings_and_leave_scope (); |
23702 | |
23703 | if (is_declarator) |
23704 | /* Repeat the main loop. */ |
23705 | continue; |
23706 | } |
23707 | |
23708 | /* If this is the first, we can try a parenthesized |
23709 | declarator. */ |
23710 | if (first) |
23711 | { |
23712 | bool saved_in_type_id_in_expr_p; |
23713 | |
23714 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
23715 | parser->in_declarator_p = saved_in_declarator_p; |
23716 | |
23717 | open_paren = token; |
23718 | /* Consume the `('. */ |
23719 | matching_parens parens; |
23720 | parens.consume_open (parser); |
23721 | /* Parse the nested declarator. */ |
23722 | saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
23723 | parser->in_type_id_in_expr_p = true; |
23724 | declarator |
23725 | = cp_parser_declarator (parser, dcl_kind, flags, |
23726 | ctor_dtor_or_conv_p, |
23727 | /*parenthesized_p=*/NULL, |
23728 | member_p, friend_p, |
23729 | /*static_p=*/false); |
23730 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
23731 | first = false; |
23732 | /* Expect a `)'. */ |
23733 | close_paren = cp_lexer_peek_token (lexer: parser->lexer); |
23734 | if (!parens.require_close (parser)) |
23735 | declarator = cp_error_declarator; |
23736 | if (declarator == cp_error_declarator) |
23737 | break; |
23738 | |
23739 | goto handle_declarator; |
23740 | } |
23741 | /* Otherwise, we must be done. */ |
23742 | else |
23743 | break; |
23744 | } |
23745 | else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) |
23746 | && token->type == CPP_OPEN_SQUARE |
23747 | && !cp_next_tokens_can_be_attribute_p (parser)) |
23748 | { |
23749 | /* Parse an array-declarator. */ |
23750 | tree bounds, attrs; |
23751 | |
23752 | if (ctor_dtor_or_conv_p) |
23753 | *ctor_dtor_or_conv_p = 0; |
23754 | |
23755 | open_paren = NULL; |
23756 | first = false; |
23757 | parser->default_arg_ok_p = false; |
23758 | parser->in_declarator_p = true; |
23759 | /* Consume the `['. */ |
23760 | cp_lexer_consume_token (lexer: parser->lexer); |
23761 | /* Peek at the next token. */ |
23762 | token = cp_lexer_peek_token (lexer: parser->lexer); |
23763 | /* If the next token is `]', then there is no |
23764 | constant-expression. */ |
23765 | if (token->type != CPP_CLOSE_SQUARE) |
23766 | { |
23767 | bool non_constant_p; |
23768 | bounds |
23769 | = cp_parser_constant_expression (parser, |
23770 | /*allow_non_constant=*/allow_non_constant_p: true, |
23771 | non_constant_p: &non_constant_p); |
23772 | if (!non_constant_p) |
23773 | /* OK */; |
23774 | else if (error_operand_p (t: bounds)) |
23775 | /* Already gave an error. */; |
23776 | else if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
23777 | /* Let compute_array_index_type diagnose this. */; |
23778 | else if (!parser->in_function_body |
23779 | || parsing_function_declarator ()) |
23780 | { |
23781 | /* Normally, the array bound must be an integral constant |
23782 | expression. However, as an extension, we allow VLAs |
23783 | in function scopes as long as they aren't part of a |
23784 | parameter declaration. */ |
23785 | cp_parser_error (parser, |
23786 | gmsgid: "array bound is not an integer constant" ); |
23787 | bounds = error_mark_node; |
23788 | } |
23789 | else if (processing_template_decl |
23790 | && !type_dependent_expression_p (bounds)) |
23791 | { |
23792 | /* Remember this wasn't a constant-expression. */ |
23793 | bounds = build_nop (TREE_TYPE (bounds), bounds); |
23794 | TREE_SIDE_EFFECTS (bounds) = 1; |
23795 | } |
23796 | } |
23797 | else |
23798 | bounds = NULL_TREE; |
23799 | /* Look for the closing `]'. */ |
23800 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
23801 | { |
23802 | declarator = cp_error_declarator; |
23803 | break; |
23804 | } |
23805 | |
23806 | attrs = cp_parser_std_attribute_spec_seq (parser); |
23807 | declarator = make_array_declarator (element: declarator, bounds); |
23808 | declarator->std_attributes = attrs; |
23809 | } |
23810 | else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) |
23811 | { |
23812 | { |
23813 | tree qualifying_scope; |
23814 | tree unqualified_name; |
23815 | tree attrs; |
23816 | special_function_kind sfk; |
23817 | bool abstract_ok; |
23818 | bool pack_expansion_p = false; |
23819 | cp_token *declarator_id_start_token; |
23820 | |
23821 | /* Parse a declarator-id */ |
23822 | abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER); |
23823 | if (abstract_ok) |
23824 | { |
23825 | cp_parser_parse_tentatively (parser); |
23826 | |
23827 | /* If we see an ellipsis, we should be looking at a |
23828 | parameter pack. */ |
23829 | if (token->type == CPP_ELLIPSIS) |
23830 | { |
23831 | /* Consume the `...' */ |
23832 | cp_lexer_consume_token (lexer: parser->lexer); |
23833 | |
23834 | pack_expansion_p = true; |
23835 | } |
23836 | } |
23837 | |
23838 | declarator_id_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
23839 | unqualified_name |
23840 | = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok); |
23841 | qualifying_scope = parser->scope; |
23842 | if (abstract_ok) |
23843 | { |
23844 | bool okay = false; |
23845 | |
23846 | if (!unqualified_name && pack_expansion_p) |
23847 | { |
23848 | /* Check whether an error occurred. */ |
23849 | okay = !cp_parser_error_occurred (parser); |
23850 | |
23851 | /* We already consumed the ellipsis to mark a |
23852 | parameter pack, but we have no way to report it, |
23853 | so abort the tentative parse. We will be exiting |
23854 | immediately anyway. */ |
23855 | cp_parser_abort_tentative_parse (parser); |
23856 | } |
23857 | else |
23858 | okay = cp_parser_parse_definitely (parser); |
23859 | |
23860 | if (!okay) |
23861 | unqualified_name = error_mark_node; |
23862 | else if (unqualified_name |
23863 | && (qualifying_scope |
23864 | || (!identifier_p (t: unqualified_name)))) |
23865 | { |
23866 | cp_parser_error (parser, gmsgid: "expected unqualified-id" ); |
23867 | unqualified_name = error_mark_node; |
23868 | } |
23869 | } |
23870 | |
23871 | if (!unqualified_name) |
23872 | return NULL; |
23873 | if (unqualified_name == error_mark_node) |
23874 | { |
23875 | declarator = cp_error_declarator; |
23876 | pack_expansion_p = false; |
23877 | declarator->parameter_pack_p = false; |
23878 | break; |
23879 | } |
23880 | |
23881 | attrs = cp_parser_std_attribute_spec_seq (parser); |
23882 | |
23883 | if (qualifying_scope && at_namespace_scope_p () |
23884 | && TREE_CODE (qualifying_scope) == TYPENAME_TYPE) |
23885 | { |
23886 | /* In the declaration of a member of a template class |
23887 | outside of the class itself, the SCOPE will sometimes |
23888 | be a TYPENAME_TYPE. For example, given: |
23889 | |
23890 | template <typename T> |
23891 | int S<T>::R::i = 3; |
23892 | |
23893 | the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In |
23894 | this context, we must resolve S<T>::R to an ordinary |
23895 | type, rather than a typename type. |
23896 | |
23897 | The reason we normally avoid resolving TYPENAME_TYPEs |
23898 | is that a specialization of `S' might render |
23899 | `S<T>::R' not a type. However, if `S' is |
23900 | specialized, then this `i' will not be used, so there |
23901 | is no harm in resolving the types here. */ |
23902 | tree type; |
23903 | |
23904 | /* Resolve the TYPENAME_TYPE. */ |
23905 | type = resolve_typename_type (qualifying_scope, |
23906 | /*only_current_p=*/false); |
23907 | /* If that failed, the declarator is invalid. */ |
23908 | if (TREE_CODE (type) == TYPENAME_TYPE) |
23909 | { |
23910 | if (typedef_variant_p (type)) |
23911 | error_at (declarator_id_start_token->location, |
23912 | "cannot define member of dependent typedef " |
23913 | "%qT" , type); |
23914 | else |
23915 | error_at (declarator_id_start_token->location, |
23916 | "%<%T::%E%> is not a type" , |
23917 | TYPE_CONTEXT (qualifying_scope), |
23918 | TYPE_IDENTIFIER (qualifying_scope)); |
23919 | } |
23920 | qualifying_scope = type; |
23921 | } |
23922 | |
23923 | sfk = sfk_none; |
23924 | |
23925 | if (unqualified_name) |
23926 | { |
23927 | tree class_type; |
23928 | |
23929 | if (qualifying_scope |
23930 | && CLASS_TYPE_P (qualifying_scope)) |
23931 | class_type = qualifying_scope; |
23932 | else |
23933 | class_type = current_class_type; |
23934 | |
23935 | if (TREE_CODE (unqualified_name) == TYPE_DECL) |
23936 | { |
23937 | tree name_type = TREE_TYPE (unqualified_name); |
23938 | |
23939 | if (!class_type || !same_type_p (name_type, class_type)) |
23940 | { |
23941 | /* We do not attempt to print the declarator |
23942 | here because we do not have enough |
23943 | information about its original syntactic |
23944 | form. */ |
23945 | cp_parser_error (parser, gmsgid: "invalid declarator" ); |
23946 | declarator = cp_error_declarator; |
23947 | break; |
23948 | } |
23949 | else if (qualifying_scope |
23950 | && CLASSTYPE_USE_TEMPLATE (name_type)) |
23951 | { |
23952 | error_at (declarator_id_start_token->location, |
23953 | "invalid use of constructor as a template" ); |
23954 | inform (declarator_id_start_token->location, |
23955 | "use %<%T::%D%> instead of %<%T::%D%> to " |
23956 | "name the constructor in a qualified name" , |
23957 | class_type, |
23958 | DECL_NAME (TYPE_TI_TEMPLATE (class_type)), |
23959 | class_type, name_type); |
23960 | declarator = cp_error_declarator; |
23961 | break; |
23962 | } |
23963 | unqualified_name = constructor_name (class_type); |
23964 | } |
23965 | |
23966 | if (class_type) |
23967 | { |
23968 | if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR) |
23969 | sfk = sfk_destructor; |
23970 | else if (identifier_p (t: unqualified_name) |
23971 | && IDENTIFIER_CONV_OP_P (unqualified_name)) |
23972 | sfk = sfk_conversion; |
23973 | else if (/* There's no way to declare a constructor |
23974 | for an unnamed type, even if the type |
23975 | got a name for linkage purposes. */ |
23976 | !TYPE_WAS_UNNAMED (class_type) |
23977 | /* Handle correctly (c++/19200): |
23978 | |
23979 | struct S { |
23980 | struct T{}; |
23981 | friend void S(T); |
23982 | }; |
23983 | |
23984 | and also: |
23985 | |
23986 | namespace N { |
23987 | void S(); |
23988 | } |
23989 | |
23990 | struct S { |
23991 | friend void N::S(); |
23992 | }; */ |
23993 | && (!friend_p || class_type == qualifying_scope) |
23994 | && constructor_name_p (unqualified_name, |
23995 | class_type)) |
23996 | sfk = sfk_constructor; |
23997 | else if (is_overloaded_fn (unqualified_name) |
23998 | && DECL_CONSTRUCTOR_P (get_first_fn |
23999 | (unqualified_name))) |
24000 | sfk = sfk_constructor; |
24001 | |
24002 | if (ctor_dtor_or_conv_p && sfk != sfk_none) |
24003 | *ctor_dtor_or_conv_p = -1; |
24004 | } |
24005 | } |
24006 | declarator = make_id_declarator (qualifying_scope, |
24007 | unqualified_name, |
24008 | sfk, id_location: token->location); |
24009 | declarator->std_attributes = attrs; |
24010 | declarator->parameter_pack_p = pack_expansion_p; |
24011 | |
24012 | if (pack_expansion_p) |
24013 | maybe_warn_variadic_templates (); |
24014 | |
24015 | /* We're looking for this case in [temp.res]: |
24016 | A qualified-id is assumed to name a type if [...] |
24017 | - it is a decl-specifier of the decl-specifier-seq of a |
24018 | parameter-declaration in a declarator of a function or |
24019 | function template declaration, ... */ |
24020 | if (cxx_dialect >= cxx20 |
24021 | && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL) |
24022 | && declarator->kind == cdk_id |
24023 | && !at_class_scope_p () |
24024 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
24025 | { |
24026 | /* ...whose declarator-id is qualified. If it isn't, never |
24027 | assume the parameters to refer to types. */ |
24028 | if (qualifying_scope == NULL_TREE) |
24029 | flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
24030 | else |
24031 | { |
24032 | /* Now we have something like |
24033 | template <typename T> int C::x(S::p); |
24034 | which can be a function template declaration or a |
24035 | variable template definition. If name lookup for |
24036 | the declarator-id C::x finds one or more function |
24037 | templates, assume S::p to name a type. Otherwise, |
24038 | don't. */ |
24039 | tree decl |
24040 | = cp_parser_lookup_name (parser, unqualified_name, |
24041 | none_type, |
24042 | /*is_template=*/false, |
24043 | /*is_namespace=*/false, |
24044 | /*check_dependency=*/false, |
24045 | /*ambiguous_decls=*/NULL, |
24046 | token->location); |
24047 | |
24048 | if (!is_overloaded_fn (decl) |
24049 | /* Allow |
24050 | template<typename T> |
24051 | A<T>::A(T::type) { } */ |
24052 | && !(MAYBE_CLASS_TYPE_P (qualifying_scope) |
24053 | && constructor_name_p (unqualified_name, |
24054 | qualifying_scope))) |
24055 | flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
24056 | } |
24057 | } |
24058 | } |
24059 | |
24060 | handle_declarator:; |
24061 | scope = get_scope_of_declarator (declarator); |
24062 | if (scope) |
24063 | { |
24064 | /* Any names that appear after the declarator-id for a |
24065 | member are looked up in the containing scope. */ |
24066 | if (at_function_scope_p ()) |
24067 | { |
24068 | /* But declarations with qualified-ids can't appear in a |
24069 | function. */ |
24070 | cp_parser_error (parser, gmsgid: "qualified-id in declaration" ); |
24071 | declarator = cp_error_declarator; |
24072 | break; |
24073 | } |
24074 | pushed_scope = push_scope (scope); |
24075 | } |
24076 | parser->in_declarator_p = true; |
24077 | if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) |
24078 | || (declarator && declarator->kind == cdk_id)) |
24079 | /* Default args are only allowed on function |
24080 | declarations. */ |
24081 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
24082 | else |
24083 | parser->default_arg_ok_p = false; |
24084 | |
24085 | first = false; |
24086 | } |
24087 | /* We're done. */ |
24088 | else |
24089 | break; |
24090 | } |
24091 | |
24092 | /* For an abstract declarator, we might wind up with nothing at this |
24093 | point. That's an error; the declarator is not optional. */ |
24094 | if (!declarator) |
24095 | cp_parser_error (parser, gmsgid: "expected declarator" ); |
24096 | else if (open_paren) |
24097 | { |
24098 | /* Record overly parenthesized declarator so we can give a |
24099 | diagnostic about confusing decl/expr disambiguation. */ |
24100 | if (declarator->kind == cdk_array) |
24101 | { |
24102 | /* If the open and close parens are on different lines, this |
24103 | is probably a formatting thing, so ignore. */ |
24104 | expanded_location open = expand_location (open_paren->location); |
24105 | expanded_location close = expand_location (close_paren->location); |
24106 | if (open.line != close.line || open.file != close.file) |
24107 | open_paren = NULL; |
24108 | } |
24109 | if (open_paren) |
24110 | declarator->parenthesized = make_location (caret: open_paren->location, |
24111 | start: open_paren->location, |
24112 | finish: close_paren->location); |
24113 | } |
24114 | |
24115 | /* If we entered a scope, we must exit it now. */ |
24116 | if (pushed_scope) |
24117 | pop_scope (pushed_scope); |
24118 | |
24119 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
24120 | parser->in_declarator_p = saved_in_declarator_p; |
24121 | |
24122 | return declarator; |
24123 | } |
24124 | |
24125 | /* Parse a ptr-operator. |
24126 | |
24127 | ptr-operator: |
24128 | * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) |
24129 | * cv-qualifier-seq [opt] |
24130 | & |
24131 | :: [opt] nested-name-specifier * cv-qualifier-seq [opt] |
24132 | nested-name-specifier * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) |
24133 | |
24134 | GNU Extension: |
24135 | |
24136 | ptr-operator: |
24137 | & cv-qualifier-seq [opt] |
24138 | |
24139 | Returns INDIRECT_REF if a pointer, or pointer-to-member, was used. |
24140 | Returns ADDR_EXPR if a reference was used, or NON_LVALUE_EXPR for |
24141 | an rvalue reference. In the case of a pointer-to-member, *TYPE is |
24142 | filled in with the TYPE containing the member. *CV_QUALS is |
24143 | filled in with the cv-qualifier-seq, or TYPE_UNQUALIFIED, if there |
24144 | are no cv-qualifiers. Returns ERROR_MARK if an error occurred. |
24145 | Note that the tree codes returned by this function have nothing |
24146 | to do with the types of trees that will be eventually be created |
24147 | to represent the pointer or reference type being parsed. They are |
24148 | just constants with suggestive names. */ |
24149 | static enum tree_code |
24150 | cp_parser_ptr_operator (cp_parser* parser, |
24151 | tree* type, |
24152 | cp_cv_quals *cv_quals, |
24153 | tree *attributes) |
24154 | { |
24155 | enum tree_code code = ERROR_MARK; |
24156 | cp_token *token; |
24157 | tree attrs = NULL_TREE; |
24158 | |
24159 | /* Assume that it's not a pointer-to-member. */ |
24160 | *type = NULL_TREE; |
24161 | /* And that there are no cv-qualifiers. */ |
24162 | *cv_quals = TYPE_UNQUALIFIED; |
24163 | |
24164 | /* Peek at the next token. */ |
24165 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24166 | |
24167 | /* If it's a `*', `&' or `&&' we have a pointer or reference. */ |
24168 | if (token->type == CPP_MULT) |
24169 | code = INDIRECT_REF; |
24170 | else if (token->type == CPP_AND) |
24171 | code = ADDR_EXPR; |
24172 | else if ((cxx_dialect != cxx98) && |
24173 | token->type == CPP_AND_AND) /* C++0x only */ |
24174 | code = NON_LVALUE_EXPR; |
24175 | |
24176 | if (code != ERROR_MARK) |
24177 | { |
24178 | /* Consume the `*', `&' or `&&'. */ |
24179 | cp_lexer_consume_token (lexer: parser->lexer); |
24180 | |
24181 | /* A `*' can be followed by a cv-qualifier-seq, and so can a |
24182 | `&', if we are allowing GNU extensions. (The only qualifier |
24183 | that can legally appear after `&' is `restrict', but that is |
24184 | enforced during semantic analysis. */ |
24185 | if (code == INDIRECT_REF |
24186 | || cp_parser_allow_gnu_extensions_p (parser)) |
24187 | *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
24188 | |
24189 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24190 | if (attributes != NULL) |
24191 | *attributes = attrs; |
24192 | } |
24193 | else |
24194 | { |
24195 | /* Try the pointer-to-member case. */ |
24196 | cp_parser_parse_tentatively (parser); |
24197 | /* Look for the optional `::' operator. */ |
24198 | cp_parser_global_scope_opt (parser, |
24199 | /*current_scope_valid_p=*/false); |
24200 | /* Look for the nested-name specifier. */ |
24201 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24202 | cp_parser_nested_name_specifier (parser, |
24203 | /*typename_keyword_p=*/false, |
24204 | /*check_dependency_p=*/true, |
24205 | /*type_p=*/false, |
24206 | /*is_declaration=*/false); |
24207 | /* If we found it, and the next token is a `*', then we are |
24208 | indeed looking at a pointer-to-member operator. */ |
24209 | if (!cp_parser_error_occurred (parser) |
24210 | && cp_parser_require (parser, CPP_MULT, RT_MULT)) |
24211 | { |
24212 | /* Indicate that the `*' operator was used. */ |
24213 | code = INDIRECT_REF; |
24214 | |
24215 | if (TREE_CODE (parser->scope) == NAMESPACE_DECL) |
24216 | error_at (token->location, "%qD is a namespace" , parser->scope); |
24217 | else if (TREE_CODE (parser->scope) == ENUMERAL_TYPE) |
24218 | error_at (token->location, "cannot form pointer to member of " |
24219 | "non-class %q#T" , parser->scope); |
24220 | else |
24221 | { |
24222 | /* The type of which the member is a member is given by the |
24223 | current SCOPE. */ |
24224 | *type = parser->scope; |
24225 | /* The next name will not be qualified. */ |
24226 | parser->scope = NULL_TREE; |
24227 | parser->qualifying_scope = NULL_TREE; |
24228 | parser->object_scope = NULL_TREE; |
24229 | /* Look for optional c++11 attributes. */ |
24230 | attrs = cp_parser_std_attribute_spec_seq (parser); |
24231 | if (attributes != NULL) |
24232 | *attributes = attrs; |
24233 | /* Look for the optional cv-qualifier-seq. */ |
24234 | *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); |
24235 | } |
24236 | } |
24237 | /* If that didn't work we don't have a ptr-operator. */ |
24238 | if (!cp_parser_parse_definitely (parser)) |
24239 | cp_parser_error (parser, gmsgid: "expected ptr-operator" ); |
24240 | } |
24241 | |
24242 | return code; |
24243 | } |
24244 | |
24245 | /* Parse an (optional) cv-qualifier-seq. |
24246 | |
24247 | cv-qualifier-seq: |
24248 | cv-qualifier cv-qualifier-seq [opt] |
24249 | |
24250 | cv-qualifier: |
24251 | const |
24252 | volatile |
24253 | |
24254 | GNU Extension: |
24255 | |
24256 | cv-qualifier: |
24257 | __restrict__ |
24258 | |
24259 | Returns a bitmask representing the cv-qualifiers. */ |
24260 | |
24261 | static cp_cv_quals |
24262 | cp_parser_cv_qualifier_seq_opt (cp_parser* parser) |
24263 | { |
24264 | cp_cv_quals cv_quals = TYPE_UNQUALIFIED; |
24265 | |
24266 | while (true) |
24267 | { |
24268 | cp_token *token; |
24269 | cp_cv_quals cv_qualifier; |
24270 | |
24271 | /* Peek at the next token. */ |
24272 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24273 | /* See if it's a cv-qualifier. */ |
24274 | switch (token->keyword) |
24275 | { |
24276 | case RID_CONST: |
24277 | cv_qualifier = TYPE_QUAL_CONST; |
24278 | break; |
24279 | |
24280 | case RID_VOLATILE: |
24281 | cv_qualifier = TYPE_QUAL_VOLATILE; |
24282 | break; |
24283 | |
24284 | case RID_RESTRICT: |
24285 | cv_qualifier = TYPE_QUAL_RESTRICT; |
24286 | break; |
24287 | |
24288 | default: |
24289 | cv_qualifier = TYPE_UNQUALIFIED; |
24290 | break; |
24291 | } |
24292 | |
24293 | if (!cv_qualifier) |
24294 | break; |
24295 | |
24296 | if (cv_quals & cv_qualifier) |
24297 | { |
24298 | gcc_rich_location richloc (token->location); |
24299 | richloc.add_fixit_remove (); |
24300 | error_at (&richloc, "duplicate cv-qualifier" ); |
24301 | cp_lexer_purge_token (lexer: parser->lexer); |
24302 | } |
24303 | else |
24304 | { |
24305 | cp_lexer_consume_token (lexer: parser->lexer); |
24306 | cv_quals |= cv_qualifier; |
24307 | } |
24308 | } |
24309 | |
24310 | return cv_quals; |
24311 | } |
24312 | |
24313 | /* Parse an (optional) ref-qualifier |
24314 | |
24315 | ref-qualifier: |
24316 | & |
24317 | && |
24318 | |
24319 | Returns cp_ref_qualifier representing ref-qualifier. */ |
24320 | |
24321 | static cp_ref_qualifier |
24322 | cp_parser_ref_qualifier_opt (cp_parser* parser) |
24323 | { |
24324 | cp_ref_qualifier ref_qual = REF_QUAL_NONE; |
24325 | |
24326 | /* Don't try to parse bitwise '&' as a ref-qualifier (c++/57532). */ |
24327 | if (cxx_dialect < cxx11 && cp_parser_parsing_tentatively (parser)) |
24328 | return ref_qual; |
24329 | |
24330 | while (true) |
24331 | { |
24332 | cp_ref_qualifier curr_ref_qual = REF_QUAL_NONE; |
24333 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
24334 | |
24335 | switch (token->type) |
24336 | { |
24337 | case CPP_AND: |
24338 | curr_ref_qual = REF_QUAL_LVALUE; |
24339 | break; |
24340 | |
24341 | case CPP_AND_AND: |
24342 | curr_ref_qual = REF_QUAL_RVALUE; |
24343 | break; |
24344 | |
24345 | default: |
24346 | curr_ref_qual = REF_QUAL_NONE; |
24347 | break; |
24348 | } |
24349 | |
24350 | if (!curr_ref_qual) |
24351 | break; |
24352 | else if (ref_qual) |
24353 | { |
24354 | error_at (token->location, "multiple ref-qualifiers" ); |
24355 | cp_lexer_purge_token (lexer: parser->lexer); |
24356 | } |
24357 | else |
24358 | { |
24359 | ref_qual = curr_ref_qual; |
24360 | cp_lexer_consume_token (lexer: parser->lexer); |
24361 | } |
24362 | } |
24363 | |
24364 | return ref_qual; |
24365 | } |
24366 | |
24367 | /* Parse an optional tx-qualifier. |
24368 | |
24369 | tx-qualifier: |
24370 | transaction_safe |
24371 | transaction_safe_dynamic */ |
24372 | |
24373 | static tree |
24374 | cp_parser_tx_qualifier_opt (cp_parser *parser) |
24375 | { |
24376 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
24377 | if (token->type == CPP_NAME) |
24378 | { |
24379 | tree name = token->u.value; |
24380 | const char *p = IDENTIFIER_POINTER (name); |
24381 | const int len = strlen (s: "transaction_safe" ); |
24382 | if (startswith (str: p, prefix: "transaction_safe" )) |
24383 | { |
24384 | p += len; |
24385 | if (*p == '\0' |
24386 | || !strcmp (s1: p, s2: "_dynamic" )) |
24387 | { |
24388 | cp_lexer_consume_token (lexer: parser->lexer); |
24389 | if (!flag_tm) |
24390 | { |
24391 | error ("%qE requires %<-fgnu-tm%>" , name); |
24392 | return NULL_TREE; |
24393 | } |
24394 | else |
24395 | return name; |
24396 | } |
24397 | } |
24398 | } |
24399 | return NULL_TREE; |
24400 | } |
24401 | |
24402 | /* Parse an (optional) virt-specifier-seq. |
24403 | |
24404 | virt-specifier-seq: |
24405 | virt-specifier virt-specifier-seq [opt] |
24406 | |
24407 | virt-specifier: |
24408 | override |
24409 | final |
24410 | |
24411 | Returns a bitmask representing the virt-specifiers. */ |
24412 | |
24413 | static cp_virt_specifiers |
24414 | cp_parser_virt_specifier_seq_opt (cp_parser* parser) |
24415 | { |
24416 | cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; |
24417 | |
24418 | while (true) |
24419 | { |
24420 | cp_token *token; |
24421 | cp_virt_specifiers virt_specifier; |
24422 | |
24423 | /* Peek at the next token. */ |
24424 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24425 | /* See if it's a virt-specifier-qualifier. */ |
24426 | if (token->type != CPP_NAME) |
24427 | break; |
24428 | if (id_equal (id: token->u.value, str: "override" )) |
24429 | { |
24430 | maybe_warn_cpp0x (str: CPP0X_OVERRIDE_CONTROLS); |
24431 | virt_specifier = VIRT_SPEC_OVERRIDE; |
24432 | } |
24433 | else if (id_equal (id: token->u.value, str: "final" )) |
24434 | { |
24435 | maybe_warn_cpp0x (str: CPP0X_OVERRIDE_CONTROLS); |
24436 | virt_specifier = VIRT_SPEC_FINAL; |
24437 | } |
24438 | else if (id_equal (id: token->u.value, str: "__final" )) |
24439 | { |
24440 | virt_specifier = VIRT_SPEC_FINAL; |
24441 | } |
24442 | else |
24443 | break; |
24444 | |
24445 | if (virt_specifiers & virt_specifier) |
24446 | { |
24447 | gcc_rich_location richloc (token->location); |
24448 | richloc.add_fixit_remove (); |
24449 | error_at (&richloc, "duplicate virt-specifier" ); |
24450 | cp_lexer_purge_token (lexer: parser->lexer); |
24451 | } |
24452 | else |
24453 | { |
24454 | cp_lexer_consume_token (lexer: parser->lexer); |
24455 | virt_specifiers |= virt_specifier; |
24456 | } |
24457 | } |
24458 | return virt_specifiers; |
24459 | } |
24460 | |
24461 | /* Used by handling of trailing-return-types and NSDMI, in which 'this' |
24462 | is in scope even though it isn't real. */ |
24463 | |
24464 | void |
24465 | inject_this_parameter (tree ctype, cp_cv_quals quals) |
24466 | { |
24467 | tree this_parm; |
24468 | |
24469 | if (current_class_ptr) |
24470 | { |
24471 | /* We don't clear this between NSDMIs. Is it already what we want? */ |
24472 | tree type = TREE_TYPE (TREE_TYPE (current_class_ptr)); |
24473 | if (DECL_P (current_class_ptr) |
24474 | && DECL_CONTEXT (current_class_ptr) == NULL_TREE |
24475 | && same_type_ignoring_top_level_qualifiers_p (ctype, type) |
24476 | && cp_type_quals (type) == quals) |
24477 | return; |
24478 | } |
24479 | |
24480 | this_parm = build_this_parm (NULL_TREE, ctype, quals); |
24481 | /* Clear this first to avoid shortcut in cp_build_indirect_ref. */ |
24482 | current_class_ptr = NULL_TREE; |
24483 | current_class_ref |
24484 | = cp_build_fold_indirect_ref (this_parm); |
24485 | current_class_ptr = this_parm; |
24486 | } |
24487 | |
24488 | /* Return true iff our current scope is a non-static data member |
24489 | initializer. */ |
24490 | |
24491 | bool |
24492 | parsing_nsdmi (void) |
24493 | { |
24494 | /* We recognize NSDMI context by the context-less 'this' pointer set up |
24495 | by the function above. */ |
24496 | if (current_class_ptr |
24497 | && TREE_CODE (current_class_ptr) == PARM_DECL |
24498 | && DECL_CONTEXT (current_class_ptr) == NULL_TREE) |
24499 | return true; |
24500 | return false; |
24501 | } |
24502 | |
24503 | /* True if we're parsing a function declarator. */ |
24504 | |
24505 | bool |
24506 | parsing_function_declarator () |
24507 | { |
24508 | /* this_entity is NULL for a function parameter scope while parsing the |
24509 | declarator; it is set when parsing the body of the function. */ |
24510 | return (current_binding_level->kind == sk_function_parms |
24511 | && !current_binding_level->this_entity); |
24512 | } |
24513 | |
24514 | /* Parse a late-specified return type, if any. This is not a separate |
24515 | non-terminal, but part of a function declarator, which looks like |
24516 | |
24517 | -> trailing-type-specifier-seq abstract-declarator(opt) |
24518 | |
24519 | Returns the type indicated by the type-id. |
24520 | |
24521 | In addition to this, parse any queued up #pragma omp declare simd |
24522 | clauses, and #pragma acc routine clauses. |
24523 | |
24524 | QUALS is either a bitmask of cv_qualifiers or -1 for a non-member |
24525 | function. */ |
24526 | |
24527 | static tree |
24528 | cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator, |
24529 | tree& requires_clause) |
24530 | { |
24531 | cp_token *token; |
24532 | tree type = NULL_TREE; |
24533 | bool declare_simd_p = (parser->omp_declare_simd |
24534 | && declarator |
24535 | && declarator->kind == cdk_id); |
24536 | |
24537 | bool oacc_routine_p = (parser->oacc_routine |
24538 | && declarator |
24539 | && declarator->kind == cdk_id); |
24540 | |
24541 | /* Peek at the next token. */ |
24542 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24543 | /* A late-specified return type is indicated by an initial '->'. */ |
24544 | if (token->type != CPP_DEREF |
24545 | && token->keyword != RID_REQUIRES |
24546 | && !(token->type == CPP_NAME |
24547 | && token->u.value == ridpointers[RID_REQUIRES]) |
24548 | && !(declare_simd_p || oacc_routine_p)) |
24549 | return NULL_TREE; |
24550 | |
24551 | if (token->type == CPP_DEREF) |
24552 | { |
24553 | /* Consume the ->. */ |
24554 | cp_lexer_consume_token (lexer: parser->lexer); |
24555 | |
24556 | type = cp_parser_trailing_type_id (parser); |
24557 | } |
24558 | |
24559 | /* Function declarations may be followed by a trailing |
24560 | requires-clause. */ |
24561 | requires_clause = cp_parser_requires_clause_opt (parser, false); |
24562 | |
24563 | if (declare_simd_p) |
24564 | declarator->attributes |
24565 | = cp_parser_late_parsing_omp_declare_simd (parser, |
24566 | declarator->attributes); |
24567 | if (oacc_routine_p) |
24568 | declarator->attributes |
24569 | = cp_parser_late_parsing_oacc_routine (parser, |
24570 | declarator->attributes); |
24571 | |
24572 | return type; |
24573 | } |
24574 | |
24575 | /* Parse a declarator-id. |
24576 | |
24577 | declarator-id: |
24578 | id-expression |
24579 | :: [opt] nested-name-specifier [opt] type-name |
24580 | |
24581 | In the `id-expression' case, the value returned is as for |
24582 | cp_parser_id_expression if the id-expression was an unqualified-id. |
24583 | If the id-expression was a qualified-id, then a SCOPE_REF is |
24584 | returned. The first operand is the scope (either a NAMESPACE_DECL |
24585 | or TREE_TYPE), but the second is still just a representation of an |
24586 | unqualified-id. */ |
24587 | |
24588 | static tree |
24589 | cp_parser_declarator_id (cp_parser* parser, bool optional_p) |
24590 | { |
24591 | tree id; |
24592 | /* The expression must be an id-expression. Assume that qualified |
24593 | names are the names of types so that: |
24594 | |
24595 | template <class T> |
24596 | int S<T>::R::i = 3; |
24597 | |
24598 | will work; we must treat `S<T>::R' as the name of a type. |
24599 | Similarly, assume that qualified names are templates, where |
24600 | required, so that: |
24601 | |
24602 | template <class T> |
24603 | int S<T>::R<T>::i = 3; |
24604 | |
24605 | will work, too. */ |
24606 | id = cp_parser_id_expression (parser, |
24607 | /*template_keyword_p=*/false, |
24608 | /*check_dependency_p=*/false, |
24609 | /*template_p=*/NULL, |
24610 | /*declarator_p=*/true, |
24611 | optional_p); |
24612 | if (id && BASELINK_P (id)) |
24613 | id = BASELINK_FUNCTIONS (id); |
24614 | return id; |
24615 | } |
24616 | |
24617 | /* Parse a type-id. |
24618 | |
24619 | type-id: |
24620 | type-specifier-seq abstract-declarator [opt] |
24621 | |
24622 | The parser flags FLAGS is used to control type-specifier parsing. |
24623 | |
24624 | If IS_TEMPLATE_ARG is true, we are parsing a template argument. |
24625 | |
24626 | If IS_TRAILING_RETURN is true, we are in a trailing-return-type, |
24627 | i.e. we've just seen "->". |
24628 | |
24629 | Returns the TYPE specified. */ |
24630 | |
24631 | static tree |
24632 | cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags, |
24633 | bool is_template_arg, bool is_trailing_return, |
24634 | location_t *type_location) |
24635 | { |
24636 | cp_decl_specifier_seq type_specifier_seq; |
24637 | cp_declarator *abstract_declarator; |
24638 | |
24639 | /* Parse the type-specifier-seq. */ |
24640 | cp_parser_type_specifier_seq (parser, flags, |
24641 | /*is_declaration=*/false, |
24642 | is_trailing_return, |
24643 | &type_specifier_seq); |
24644 | if (type_location) |
24645 | *type_location = type_specifier_seq.locations[ds_type_spec]; |
24646 | |
24647 | if (is_template_arg && type_specifier_seq.type |
24648 | && TREE_CODE (type_specifier_seq.type) == TEMPLATE_TYPE_PARM |
24649 | && CLASS_PLACEHOLDER_TEMPLATE (type_specifier_seq.type)) |
24650 | /* A bare template name as a template argument is a template template |
24651 | argument, not a placeholder, so fail parsing it as a type argument. */ |
24652 | { |
24653 | gcc_assert (cp_parser_uncommitted_to_tentative_parse_p (parser)); |
24654 | cp_parser_simulate_error (parser); |
24655 | return error_mark_node; |
24656 | } |
24657 | if (type_specifier_seq.type == error_mark_node) |
24658 | return error_mark_node; |
24659 | |
24660 | /* There might or might not be an abstract declarator. */ |
24661 | cp_parser_parse_tentatively (parser); |
24662 | /* Look for the declarator. */ |
24663 | abstract_declarator |
24664 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_ABSTRACT, |
24665 | flags: CP_PARSER_FLAGS_NONE, NULL, |
24666 | /*parenthesized_p=*/NULL, |
24667 | /*member_p=*/false, |
24668 | /*friend_p=*/false, |
24669 | /*static_p=*/false); |
24670 | /* Check to see if there really was a declarator. */ |
24671 | if (!cp_parser_parse_definitely (parser)) |
24672 | abstract_declarator = NULL; |
24673 | |
24674 | bool auto_typeid_ok = false; |
24675 | /* The concepts TS allows 'auto' as a type-id. */ |
24676 | if (flag_concepts_ts) |
24677 | auto_typeid_ok = !parser->in_type_id_in_expr_p; |
24678 | /* DR 625 prohibits use of auto as a template-argument. We allow 'auto' |
24679 | outside the template-argument-list context here only for the sake of |
24680 | diagnostic: grokdeclarator then can emit a better error message for |
24681 | e.g. using T = auto. */ |
24682 | else if (flag_concepts) |
24683 | auto_typeid_ok = (!parser->in_type_id_in_expr_p |
24684 | && !parser->in_template_argument_list_p); |
24685 | |
24686 | if (type_specifier_seq.type |
24687 | && !auto_typeid_ok |
24688 | /* None of the valid uses of 'auto' in C++14 involve the type-id |
24689 | nonterminal, but it is valid in a trailing-return-type. */ |
24690 | && !(cxx_dialect >= cxx14 && is_trailing_return)) |
24691 | if (tree auto_node = type_uses_auto (type_specifier_seq.type)) |
24692 | { |
24693 | /* A type-id with type 'auto' is only ok if the abstract declarator |
24694 | is a function declarator with a late-specified return type. |
24695 | |
24696 | A type-id with 'auto' is also valid in a trailing-return-type |
24697 | in a compound-requirement. */ |
24698 | if (abstract_declarator |
24699 | && abstract_declarator->kind == cdk_function |
24700 | && abstract_declarator->u.function.late_return_type) |
24701 | /* OK */; |
24702 | else if (parser->in_result_type_constraint_p) |
24703 | /* OK */; |
24704 | else |
24705 | { |
24706 | if (!cp_parser_simulate_error (parser)) |
24707 | { |
24708 | location_t loc = type_specifier_seq.locations[ds_type_spec]; |
24709 | if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) |
24710 | { |
24711 | auto_diagnostic_group g; |
24712 | gcc_rich_location richloc (loc); |
24713 | richloc.add_fixit_insert_after (new_content: "<>" ); |
24714 | error_at (&richloc, "missing template arguments after %qE" , |
24715 | tmpl); |
24716 | inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here" , |
24717 | tmpl); |
24718 | } |
24719 | else if (parser->in_template_argument_list_p) |
24720 | error_at (loc, "%qT not permitted in template argument" , |
24721 | auto_node); |
24722 | else |
24723 | error_at (loc, "invalid use of %qT" , auto_node); |
24724 | } |
24725 | return error_mark_node; |
24726 | } |
24727 | } |
24728 | |
24729 | return groktypename (&type_specifier_seq, abstract_declarator, |
24730 | is_template_arg); |
24731 | } |
24732 | |
24733 | /* Wrapper for cp_parser_type_id_1. */ |
24734 | |
24735 | static tree |
24736 | cp_parser_type_id (cp_parser *parser, cp_parser_flags flags, |
24737 | location_t *type_location) |
24738 | { |
24739 | return cp_parser_type_id_1 (parser, flags, is_template_arg: false, is_trailing_return: false, type_location); |
24740 | } |
24741 | |
24742 | /* Wrapper for cp_parser_type_id_1. */ |
24743 | |
24744 | static tree |
24745 | cp_parser_template_type_arg (cp_parser *parser) |
24746 | { |
24747 | tree r; |
24748 | const char *saved_message = parser->type_definition_forbidden_message; |
24749 | parser->type_definition_forbidden_message |
24750 | = G_("types may not be defined in template arguments" ); |
24751 | r = cp_parser_type_id_1 (parser, flags: CP_PARSER_FLAGS_NONE, is_template_arg: true, is_trailing_return: false, NULL); |
24752 | parser->type_definition_forbidden_message = saved_message; |
24753 | return r; |
24754 | } |
24755 | |
24756 | /* Wrapper for cp_parser_type_id_1. */ |
24757 | |
24758 | static tree |
24759 | cp_parser_trailing_type_id (cp_parser *parser) |
24760 | { |
24761 | return cp_parser_type_id_1 (parser, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL, |
24762 | is_template_arg: false, is_trailing_return: true, NULL); |
24763 | } |
24764 | |
24765 | /* Parse a type-specifier-seq. |
24766 | |
24767 | type-specifier-seq: |
24768 | type-specifier type-specifier-seq [opt] |
24769 | |
24770 | GNU extension: |
24771 | |
24772 | type-specifier-seq: |
24773 | attributes type-specifier-seq [opt] |
24774 | |
24775 | The parser flags FLAGS is used to control type-specifier parsing. |
24776 | |
24777 | If IS_DECLARATION is true, we are at the start of a "condition" or |
24778 | exception-declaration, so we might be followed by a declarator-id. |
24779 | |
24780 | If IS_TRAILING_RETURN is true, we are in a trailing-return-type, |
24781 | i.e. we've just seen "->". |
24782 | |
24783 | Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */ |
24784 | |
24785 | static void |
24786 | cp_parser_type_specifier_seq (cp_parser* parser, |
24787 | cp_parser_flags flags, |
24788 | bool is_declaration, |
24789 | bool is_trailing_return, |
24790 | cp_decl_specifier_seq *type_specifier_seq) |
24791 | { |
24792 | bool seen_type_specifier = false; |
24793 | cp_token *start_token = NULL; |
24794 | |
24795 | /* Clear the TYPE_SPECIFIER_SEQ. */ |
24796 | clear_decl_specs (decl_specs: type_specifier_seq); |
24797 | |
24798 | flags |= CP_PARSER_FLAGS_OPTIONAL; |
24799 | /* In the context of a trailing return type, enum E { } is an |
24800 | elaborated-type-specifier followed by a function-body, not an |
24801 | enum-specifier. */ |
24802 | if (is_trailing_return) |
24803 | flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS; |
24804 | |
24805 | /* Parse the type-specifiers and attributes. */ |
24806 | while (true) |
24807 | { |
24808 | tree type_specifier; |
24809 | bool is_cv_qualifier; |
24810 | |
24811 | /* Check for attributes first. */ |
24812 | if (cp_next_tokens_can_be_attribute_p (parser)) |
24813 | { |
24814 | /* GNU attributes at the end of a declaration apply to the |
24815 | declaration as a whole, not to the trailing return type. So look |
24816 | ahead to see if these attributes are at the end. */ |
24817 | if (seen_type_specifier && is_trailing_return |
24818 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
24819 | { |
24820 | size_t n = cp_parser_skip_attributes_opt (parser, 1); |
24821 | cp_token *tok = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
24822 | if (tok->type == CPP_SEMICOLON || tok->type == CPP_COMMA |
24823 | || tok->type == CPP_EQ || tok->type == CPP_OPEN_BRACE) |
24824 | break; |
24825 | } |
24826 | type_specifier_seq->attributes |
24827 | = attr_chainon (attrs: type_specifier_seq->attributes, |
24828 | attr: cp_parser_attributes_opt (parser)); |
24829 | continue; |
24830 | } |
24831 | |
24832 | /* record the token of the beginning of the type specifier seq, |
24833 | for error reporting purposes*/ |
24834 | if (!start_token) |
24835 | start_token = cp_lexer_peek_token (lexer: parser->lexer); |
24836 | |
24837 | /* Look for the type-specifier. */ |
24838 | type_specifier = cp_parser_type_specifier (parser, |
24839 | flags, |
24840 | decl_specs: type_specifier_seq, |
24841 | /*is_declaration=*/false, |
24842 | NULL, |
24843 | is_cv_qualifier: &is_cv_qualifier); |
24844 | if (!type_specifier) |
24845 | { |
24846 | /* If the first type-specifier could not be found, this is not a |
24847 | type-specifier-seq at all. */ |
24848 | if (!seen_type_specifier) |
24849 | { |
24850 | /* Set in_declarator_p to avoid skipping to the semicolon. */ |
24851 | int in_decl = parser->in_declarator_p; |
24852 | parser->in_declarator_p = true; |
24853 | |
24854 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
24855 | || !cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
24856 | cp_parser_error (parser, gmsgid: "expected type-specifier" ); |
24857 | |
24858 | parser->in_declarator_p = in_decl; |
24859 | |
24860 | type_specifier_seq->type = error_mark_node; |
24861 | return; |
24862 | } |
24863 | /* If subsequent type-specifiers could not be found, the |
24864 | type-specifier-seq is complete. */ |
24865 | break; |
24866 | } |
24867 | |
24868 | seen_type_specifier = true; |
24869 | /* The standard says that a condition can be: |
24870 | |
24871 | type-specifier-seq declarator = assignment-expression |
24872 | |
24873 | However, given: |
24874 | |
24875 | struct S {}; |
24876 | if (int S = ...) |
24877 | |
24878 | we should treat the "S" as a declarator, not as a |
24879 | type-specifier. The standard doesn't say that explicitly for |
24880 | type-specifier-seq, but it does say that for |
24881 | decl-specifier-seq in an ordinary declaration. Perhaps it |
24882 | would be clearer just to allow a decl-specifier-seq here, and |
24883 | then add a semantic restriction that if any decl-specifiers |
24884 | that are not type-specifiers appear, the program is invalid. */ |
24885 | if (is_declaration && !is_cv_qualifier) |
24886 | flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; |
24887 | } |
24888 | } |
24889 | |
24890 | /* Return whether the function currently being declared has an associated |
24891 | template parameter list. */ |
24892 | |
24893 | static bool |
24894 | function_being_declared_is_template_p (cp_parser* parser) |
24895 | { |
24896 | if (!current_template_parms || processing_template_parmlist) |
24897 | return false; |
24898 | |
24899 | if (parser->implicit_template_scope) |
24900 | return true; |
24901 | |
24902 | if (at_class_scope_p () |
24903 | && TYPE_BEING_DEFINED (current_class_type)) |
24904 | return parser->num_template_parameter_lists != 0; |
24905 | |
24906 | return ((int) parser->num_template_parameter_lists > template_class_depth |
24907 | (current_class_type)); |
24908 | } |
24909 | |
24910 | /* Parse a parameter-declaration-clause. |
24911 | |
24912 | parameter-declaration-clause: |
24913 | parameter-declaration-list [opt] ... [opt] |
24914 | parameter-declaration-list , ... |
24915 | |
24916 | The parser flags FLAGS is used to control type-specifier parsing. |
24917 | |
24918 | Returns a representation for the parameter declarations. A return |
24919 | value of NULL indicates a parameter-declaration-clause consisting |
24920 | only of an ellipsis. */ |
24921 | |
24922 | static tree |
24923 | cp_parser_parameter_declaration_clause (cp_parser* parser, |
24924 | cp_parser_flags flags) |
24925 | { |
24926 | tree parameters; |
24927 | cp_token *token; |
24928 | bool ellipsis_p; |
24929 | |
24930 | auto cleanup = make_temp_override |
24931 | (var&: parser->auto_is_implicit_function_template_parm_p); |
24932 | |
24933 | if (!processing_specialization |
24934 | && !processing_template_parmlist |
24935 | && !processing_explicit_instantiation |
24936 | /* default_arg_ok_p tracks whether this is a parameter-clause for an |
24937 | actual function or a random abstract declarator. */ |
24938 | && parser->default_arg_ok_p) |
24939 | if (!current_function_decl |
24940 | || (current_class_type && LAMBDA_TYPE_P (current_class_type))) |
24941 | parser->auto_is_implicit_function_template_parm_p = true; |
24942 | |
24943 | /* Peek at the next token. */ |
24944 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24945 | /* Check for trivial parameter-declaration-clauses. */ |
24946 | if (token->type == CPP_ELLIPSIS) |
24947 | { |
24948 | /* Consume the `...' token. */ |
24949 | cp_lexer_consume_token (lexer: parser->lexer); |
24950 | return NULL_TREE; |
24951 | } |
24952 | else if (token->type == CPP_CLOSE_PAREN) |
24953 | /* There are no parameters. */ |
24954 | return void_list_node; |
24955 | /* Check for `(void)', too, which is a special case. */ |
24956 | else if (token->keyword == RID_VOID |
24957 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
24958 | == CPP_CLOSE_PAREN)) |
24959 | { |
24960 | /* Consume the `void' token. */ |
24961 | cp_lexer_consume_token (lexer: parser->lexer); |
24962 | /* There are no parameters. */ |
24963 | return explicit_void_list_node; |
24964 | } |
24965 | |
24966 | /* A vector of parameters that haven't been pushed yet. */ |
24967 | auto_vec<tree> pending_decls; |
24968 | |
24969 | /* Parse the parameter-declaration-list. */ |
24970 | parameters = cp_parser_parameter_declaration_list (parser, flags, |
24971 | &pending_decls); |
24972 | /* If a parse error occurred while parsing the |
24973 | parameter-declaration-list, then the entire |
24974 | parameter-declaration-clause is erroneous. */ |
24975 | if (parameters == error_mark_node) |
24976 | return NULL_TREE; |
24977 | |
24978 | /* Peek at the next token. */ |
24979 | token = cp_lexer_peek_token (lexer: parser->lexer); |
24980 | /* If it's a `,', the clause should terminate with an ellipsis. */ |
24981 | if (token->type == CPP_COMMA) |
24982 | { |
24983 | /* Consume the `,'. */ |
24984 | cp_lexer_consume_token (lexer: parser->lexer); |
24985 | /* Expect an ellipsis. */ |
24986 | ellipsis_p |
24987 | = (cp_parser_require (parser, CPP_ELLIPSIS, RT_ELLIPSIS) != NULL); |
24988 | } |
24989 | /* It might also be `...' if the optional trailing `,' was |
24990 | omitted. */ |
24991 | else if (token->type == CPP_ELLIPSIS) |
24992 | { |
24993 | /* Consume the `...' token. */ |
24994 | cp_lexer_consume_token (lexer: parser->lexer); |
24995 | /* And remember that we saw it. */ |
24996 | ellipsis_p = true; |
24997 | } |
24998 | else |
24999 | ellipsis_p = false; |
25000 | |
25001 | /* A valid parameter-declaration-clause can only be followed by a ')'. |
25002 | So it's time to push all the parameters we have seen now that we |
25003 | know we have a valid declaration. Note that here we may not have |
25004 | committed yet, nor should we. Pushing here will detect the error |
25005 | of redefining a parameter. */ |
25006 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
25007 | for (tree p : pending_decls) |
25008 | pushdecl (p); |
25009 | |
25010 | /* Finish the parameter list. */ |
25011 | if (!ellipsis_p) |
25012 | parameters = chainon (parameters, void_list_node); |
25013 | |
25014 | return parameters; |
25015 | } |
25016 | |
25017 | /* Parse a parameter-declaration-list. |
25018 | |
25019 | parameter-declaration-list: |
25020 | parameter-declaration |
25021 | parameter-declaration-list , parameter-declaration |
25022 | |
25023 | The parser flags FLAGS is used to control type-specifier parsing. |
25024 | PENDING_DECLS is a vector of parameters that haven't been pushed yet. |
25025 | |
25026 | Returns a representation of the parameter-declaration-list, as for |
25027 | cp_parser_parameter_declaration_clause. However, the |
25028 | `void_list_node' is never appended to the list. */ |
25029 | |
25030 | static tree |
25031 | cp_parser_parameter_declaration_list (cp_parser* parser, |
25032 | cp_parser_flags flags, |
25033 | auto_vec<tree> *pending_decls) |
25034 | { |
25035 | tree parameters = NULL_TREE; |
25036 | tree *tail = ¶meters; |
25037 | bool saved_in_unbraced_linkage_specification_p; |
25038 | int index = 0; |
25039 | |
25040 | /* The special considerations that apply to a function within an |
25041 | unbraced linkage specifications do not apply to the parameters |
25042 | to the function. */ |
25043 | saved_in_unbraced_linkage_specification_p |
25044 | = parser->in_unbraced_linkage_specification_p; |
25045 | parser->in_unbraced_linkage_specification_p = false; |
25046 | |
25047 | /* Look for more parameters. */ |
25048 | while (true) |
25049 | { |
25050 | cp_parameter_declarator *parameter; |
25051 | tree decl = error_mark_node; |
25052 | bool parenthesized_p = false; |
25053 | |
25054 | /* Parse the parameter. */ |
25055 | parameter |
25056 | = cp_parser_parameter_declaration (parser, flags, |
25057 | /*template_parm_p=*/false, |
25058 | &parenthesized_p); |
25059 | |
25060 | /* We don't know yet if the enclosing context is unavailable or deprecated, |
25061 | so wait and deal with it in grokparms if appropriate. */ |
25062 | deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS; |
25063 | |
25064 | if (parameter && !cp_parser_error_occurred (parser)) |
25065 | { |
25066 | decl = grokdeclarator (parameter->declarator, |
25067 | ¶meter->decl_specifiers, |
25068 | PARM, |
25069 | parameter->default_argument != NULL_TREE, |
25070 | ¶meter->decl_specifiers.attributes); |
25071 | if (decl != error_mark_node && parameter->loc != UNKNOWN_LOCATION) |
25072 | DECL_SOURCE_LOCATION (decl) = parameter->loc; |
25073 | } |
25074 | |
25075 | deprecated_state = DEPRECATED_NORMAL; |
25076 | |
25077 | /* If a parse error occurred parsing the parameter declaration, |
25078 | then the entire parameter-declaration-list is erroneous. */ |
25079 | if (decl == error_mark_node) |
25080 | { |
25081 | parameters = error_mark_node; |
25082 | break; |
25083 | } |
25084 | |
25085 | if (parameter->decl_specifiers.attributes) |
25086 | cplus_decl_attributes (&decl, |
25087 | parameter->decl_specifiers.attributes, |
25088 | 0); |
25089 | if (DECL_NAME (decl)) |
25090 | { |
25091 | /* We cannot always pushdecl while parsing tentatively because |
25092 | it may have side effects and we can't be sure yet if we're |
25093 | parsing a declaration, e.g.: |
25094 | |
25095 | S foo(int(x), int(x), int{x}); |
25096 | |
25097 | where it's not clear if we're dealing with a constructor call |
25098 | or a function declaration until we've seen the last argument |
25099 | which breaks it up. |
25100 | It's safe to pushdecl so long as it doesn't result in a clash |
25101 | with an already-pushed parameter. But we don't delay pushing |
25102 | different parameters to handle |
25103 | |
25104 | S foo(int(i), decltype(i) j = 42); |
25105 | |
25106 | which is valid. */ |
25107 | if (pending_decls |
25108 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25109 | /* See if PARAMETERS already contains a parameter with the same |
25110 | DECL_NAME as DECL. */ |
25111 | && [parameters, decl] { |
25112 | for (tree p = parameters; p; p = TREE_CHAIN (p)) |
25113 | if (DECL_NAME (decl) == DECL_NAME (TREE_VALUE (p))) |
25114 | return true; |
25115 | return false; |
25116 | }()) |
25117 | pending_decls->safe_push (obj: decl); |
25118 | else |
25119 | decl = pushdecl (decl); |
25120 | } |
25121 | |
25122 | if (decl != error_mark_node) |
25123 | { |
25124 | retrofit_lang_decl (decl); |
25125 | DECL_PARM_INDEX (decl) = ++index; |
25126 | DECL_PARM_LEVEL (decl) = function_parm_depth (); |
25127 | } |
25128 | |
25129 | /* Add the new parameter to the list. */ |
25130 | *tail = build_tree_list (parameter->default_argument, decl); |
25131 | tail = &TREE_CHAIN (*tail); |
25132 | |
25133 | /* If the parameters were parenthesized, it's the case of |
25134 | T foo(X(x)) which looks like a variable definition but |
25135 | is a function declaration. */ |
25136 | if (index == 1 || PARENTHESIZED_LIST_P (parameters)) |
25137 | PARENTHESIZED_LIST_P (parameters) = parenthesized_p; |
25138 | |
25139 | /* Peek at the next token. */ |
25140 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
25141 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS) |
25142 | /* These are for Objective-C++ */ |
25143 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
25144 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
25145 | /* The parameter-declaration-list is complete. */ |
25146 | break; |
25147 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
25148 | { |
25149 | cp_token *token; |
25150 | |
25151 | /* Peek at the next token. */ |
25152 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
25153 | /* If it's an ellipsis, then the list is complete. */ |
25154 | if (token->type == CPP_ELLIPSIS) |
25155 | break; |
25156 | /* Otherwise, there must be more parameters. Consume the |
25157 | `,'. */ |
25158 | cp_lexer_consume_token (lexer: parser->lexer); |
25159 | /* When parsing something like: |
25160 | |
25161 | int i(float f, double d) |
25162 | |
25163 | we can tell after seeing the declaration for "f" that we |
25164 | are not looking at an initialization of a variable "i", |
25165 | but rather at the declaration of a function "i". |
25166 | |
25167 | Due to the fact that the parsing of template arguments |
25168 | (as specified to a template-id) requires backtracking we |
25169 | cannot use this technique when inside a template argument |
25170 | list. */ |
25171 | if (!parser->in_template_argument_list_p |
25172 | && !parser->in_type_id_in_expr_p |
25173 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25174 | /* However, a parameter-declaration of the form |
25175 | "float(f)" (which is a valid declaration of a |
25176 | parameter "f") can also be interpreted as an |
25177 | expression (the conversion of "f" to "float"). */ |
25178 | && !parenthesized_p) |
25179 | cp_parser_commit_to_tentative_parse (parser); |
25180 | } |
25181 | else |
25182 | { |
25183 | cp_parser_error (parser, gmsgid: "expected %<,%> or %<...%>" ); |
25184 | if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) |
25185 | cp_parser_skip_to_closing_parenthesis (parser, |
25186 | /*recovering=*/true, |
25187 | /*or_comma=*/false, |
25188 | /*consume_paren=*/false); |
25189 | break; |
25190 | } |
25191 | } |
25192 | |
25193 | parser->in_unbraced_linkage_specification_p |
25194 | = saved_in_unbraced_linkage_specification_p; |
25195 | |
25196 | /* Reset implicit_template_scope if we are about to leave the function |
25197 | parameter list that introduced it. Note that for out-of-line member |
25198 | definitions, there will be one or more class scopes before we get to |
25199 | the template parameter scope. */ |
25200 | |
25201 | if (cp_binding_level *its = parser->implicit_template_scope) |
25202 | if (cp_binding_level *maybe_its = current_binding_level->level_chain) |
25203 | { |
25204 | while (maybe_its->kind == sk_class) |
25205 | maybe_its = maybe_its->level_chain; |
25206 | if (maybe_its == its) |
25207 | { |
25208 | parser->implicit_template_parms = 0; |
25209 | parser->implicit_template_scope = 0; |
25210 | } |
25211 | } |
25212 | |
25213 | return parameters; |
25214 | } |
25215 | |
25216 | /* Parse a parameter declaration. |
25217 | |
25218 | parameter-declaration: |
25219 | decl-specifier-seq ... [opt] declarator |
25220 | decl-specifier-seq declarator = assignment-expression |
25221 | decl-specifier-seq ... [opt] abstract-declarator [opt] |
25222 | decl-specifier-seq abstract-declarator [opt] = assignment-expression |
25223 | |
25224 | The parser flags FLAGS is used to control type-specifier parsing. |
25225 | |
25226 | If TEMPLATE_PARM_P is TRUE, then this parameter-declaration |
25227 | declares a template parameter. (In that case, a non-nested `>' |
25228 | token encountered during the parsing of the assignment-expression |
25229 | is not interpreted as a greater-than operator.) |
25230 | |
25231 | Returns a representation of the parameter, or NULL if an error |
25232 | occurs. If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to |
25233 | true iff the declarator is of the form "(p)". */ |
25234 | |
25235 | static cp_parameter_declarator * |
25236 | cp_parser_parameter_declaration (cp_parser *parser, |
25237 | cp_parser_flags flags, |
25238 | bool template_parm_p, |
25239 | bool *parenthesized_p) |
25240 | { |
25241 | int declares_class_or_enum; |
25242 | cp_decl_specifier_seq decl_specifiers; |
25243 | cp_declarator *declarator; |
25244 | tree default_argument; |
25245 | cp_token *token = NULL, *declarator_token_start = NULL; |
25246 | const char *saved_message; |
25247 | bool template_parameter_pack_p = false; |
25248 | |
25249 | /* In a template parameter, `>' is not an operator. |
25250 | |
25251 | [temp.param] |
25252 | |
25253 | When parsing a default template-argument for a non-type |
25254 | template-parameter, the first non-nested `>' is taken as the end |
25255 | of the template parameter-list rather than a greater-than |
25256 | operator. */ |
25257 | |
25258 | /* Type definitions may not appear in parameter types. */ |
25259 | saved_message = parser->type_definition_forbidden_message; |
25260 | parser->type_definition_forbidden_message |
25261 | = G_("types may not be defined in parameter types" ); |
25262 | |
25263 | int template_parm_idx = (function_being_declared_is_template_p (parser) ? |
25264 | TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS |
25265 | (current_template_parms)) : 0); |
25266 | |
25267 | /* Parse the declaration-specifiers. */ |
25268 | cp_token *decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
25269 | cp_parser_decl_specifier_seq (parser, |
25270 | flags, |
25271 | decl_specs: &decl_specifiers, |
25272 | declares_class_or_enum: &declares_class_or_enum); |
25273 | |
25274 | /* [dcl.spec.auto.general]: "A placeholder-type-specifier of the form |
25275 | type-constraint opt auto can be used as a decl-specifier of the |
25276 | decl-specifier-seq of a parameter-declaration of a function declaration |
25277 | or lambda-expression..." but we must not synthesize an implicit template |
25278 | type parameter in its declarator. That is, in "void f(auto[auto{10}]);" |
25279 | we want to synthesize only the first auto. */ |
25280 | auto cleanup = make_temp_override |
25281 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
25282 | |
25283 | /* Complain about missing 'typename' or other invalid type names. */ |
25284 | if (!decl_specifiers.any_type_specifiers_p |
25285 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
25286 | decl_specifiers.type = error_mark_node; |
25287 | |
25288 | /* If an error occurred, there's no reason to attempt to parse the |
25289 | rest of the declaration. */ |
25290 | if (cp_parser_error_occurred (parser)) |
25291 | { |
25292 | parser->type_definition_forbidden_message = saved_message; |
25293 | return NULL; |
25294 | } |
25295 | |
25296 | /* Peek at the next token. */ |
25297 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25298 | |
25299 | /* If the next token is a `)', `,', `=', `>', or `...', then there |
25300 | is no declarator. However, when variadic templates are enabled, |
25301 | there may be a declarator following `...'. */ |
25302 | if (token->type == CPP_CLOSE_PAREN |
25303 | || token->type == CPP_COMMA |
25304 | || token->type == CPP_EQ |
25305 | || token->type == CPP_GREATER) |
25306 | { |
25307 | declarator = NULL; |
25308 | if (parenthesized_p) |
25309 | *parenthesized_p = false; |
25310 | } |
25311 | /* Otherwise, there should be a declarator. */ |
25312 | else |
25313 | { |
25314 | bool saved_default_arg_ok_p = parser->default_arg_ok_p; |
25315 | parser->default_arg_ok_p = false; |
25316 | |
25317 | /* After seeing a decl-specifier-seq, if the next token is not a |
25318 | "(" or "{", there is no possibility that the code is a valid |
25319 | expression. Therefore, if parsing tentatively, we commit at |
25320 | this point. */ |
25321 | if (!parser->in_template_argument_list_p |
25322 | /* In an expression context, having seen: |
25323 | |
25324 | (int((char ... |
25325 | |
25326 | we cannot be sure whether we are looking at a |
25327 | function-type (taking a "char" as a parameter) or a cast |
25328 | of some object of type "char" to "int". */ |
25329 | && !parser->in_type_id_in_expr_p |
25330 | && cp_parser_uncommitted_to_tentative_parse_p (parser) |
25331 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
25332 | { |
25333 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
25334 | { |
25335 | if (decl_specifiers.type |
25336 | && template_placeholder_p (decl_specifiers.type)) |
25337 | /* This is a CTAD expression, not a parameter declaration. */ |
25338 | cp_parser_simulate_error (parser); |
25339 | } |
25340 | else |
25341 | cp_parser_commit_to_tentative_parse (parser); |
25342 | } |
25343 | /* Parse the declarator. */ |
25344 | declarator_token_start = token; |
25345 | declarator = cp_parser_declarator (parser, |
25346 | dcl_kind: CP_PARSER_DECLARATOR_EITHER, |
25347 | flags: CP_PARSER_FLAGS_NONE, |
25348 | /*ctor_dtor_or_conv_p=*/NULL, |
25349 | parenthesized_p, |
25350 | /*member_p=*/false, |
25351 | /*friend_p=*/false, |
25352 | /*static_p=*/false); |
25353 | parser->default_arg_ok_p = saved_default_arg_ok_p; |
25354 | /* After the declarator, allow more attributes. */ |
25355 | decl_specifiers.attributes |
25356 | = attr_chainon (attrs: decl_specifiers.attributes, |
25357 | attr: cp_parser_attributes_opt (parser)); |
25358 | |
25359 | /* If the declarator is a template parameter pack, remember that and |
25360 | clear the flag in the declarator itself so we don't get errors |
25361 | from grokdeclarator. */ |
25362 | if (template_parm_p && declarator && declarator->parameter_pack_p) |
25363 | { |
25364 | declarator->parameter_pack_p = false; |
25365 | template_parameter_pack_p = true; |
25366 | } |
25367 | } |
25368 | |
25369 | /* If the next token is an ellipsis, and we have not seen a declarator |
25370 | name, and if either the type of the declarator contains parameter |
25371 | packs but it is not a TYPE_PACK_EXPANSION or is null (this happens |
25372 | for, eg, abbreviated integral type names), then we actually have a |
25373 | parameter pack expansion expression. Otherwise, leave the ellipsis |
25374 | for a C-style variadic function. */ |
25375 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25376 | |
25377 | /* If a function parameter pack was specified and an implicit template |
25378 | parameter was introduced during cp_parser_parameter_declaration, |
25379 | change any implicit parameters introduced into packs. */ |
25380 | if (parser->implicit_template_parms |
25381 | && ((token->type == CPP_ELLIPSIS |
25382 | && declarator_can_be_parameter_pack (declarator)) |
25383 | || (declarator && declarator->parameter_pack_p))) |
25384 | { |
25385 | int latest_template_parm_idx = TREE_VEC_LENGTH |
25386 | (INNERMOST_TEMPLATE_PARMS (current_template_parms)); |
25387 | |
25388 | if (latest_template_parm_idx != template_parm_idx) |
25389 | decl_specifiers.type = convert_generic_types_to_packs |
25390 | (decl_specifiers.type, |
25391 | template_parm_idx, latest_template_parm_idx); |
25392 | } |
25393 | |
25394 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
25395 | { |
25396 | tree type = decl_specifiers.type; |
25397 | |
25398 | if (type && DECL_P (type)) |
25399 | type = TREE_TYPE (type); |
25400 | |
25401 | if (((type |
25402 | && TREE_CODE (type) != TYPE_PACK_EXPANSION |
25403 | && (template_parm_p || uses_parameter_packs (type))) |
25404 | || (!type && template_parm_p)) |
25405 | && declarator_can_be_parameter_pack (declarator)) |
25406 | { |
25407 | /* Consume the `...'. */ |
25408 | cp_lexer_consume_token (lexer: parser->lexer); |
25409 | maybe_warn_variadic_templates (); |
25410 | |
25411 | /* Build a pack expansion type */ |
25412 | if (template_parm_p) |
25413 | template_parameter_pack_p = true; |
25414 | else if (declarator) |
25415 | declarator->parameter_pack_p = true; |
25416 | else |
25417 | decl_specifiers.type = make_pack_expansion (type); |
25418 | } |
25419 | } |
25420 | |
25421 | /* The restriction on defining new types applies only to the type |
25422 | of the parameter, not to the default argument. */ |
25423 | parser->type_definition_forbidden_message = saved_message; |
25424 | |
25425 | /* If the next token is `=', then process a default argument. */ |
25426 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
25427 | { |
25428 | tree type = decl_specifiers.type; |
25429 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25430 | if (declarator) |
25431 | declarator->init_loc = token->location; |
25432 | /* If we are defining a class, then the tokens that make up the |
25433 | default argument must be saved and processed later. */ |
25434 | if (!template_parm_p && at_class_scope_p () |
25435 | && TYPE_BEING_DEFINED (current_class_type) |
25436 | && !LAMBDA_TYPE_P (current_class_type)) |
25437 | default_argument = cp_parser_cache_defarg (parser, /*nsdmi=*/false); |
25438 | |
25439 | /* A constrained-type-specifier may declare a type |
25440 | template-parameter. */ |
25441 | else if (declares_constrained_type_template_parameter (type)) |
25442 | default_argument |
25443 | = cp_parser_default_type_template_argument (parser); |
25444 | |
25445 | /* A constrained-type-specifier may declare a |
25446 | template-template-parameter. */ |
25447 | else if (declares_constrained_template_template_parameter (type)) |
25448 | default_argument |
25449 | = cp_parser_default_template_template_argument (parser); |
25450 | |
25451 | /* Outside of a class definition, we can just parse the |
25452 | assignment-expression. */ |
25453 | else |
25454 | default_argument |
25455 | = cp_parser_default_argument (parser, template_parm_p); |
25456 | |
25457 | if (!parser->default_arg_ok_p) |
25458 | { |
25459 | permerror (token->location, |
25460 | "default arguments are only " |
25461 | "permitted for function parameters" ); |
25462 | } |
25463 | else if ((declarator && declarator->parameter_pack_p) |
25464 | || template_parameter_pack_p |
25465 | || (decl_specifiers.type |
25466 | && PACK_EXPANSION_P (decl_specifiers.type))) |
25467 | { |
25468 | /* Find the name of the parameter pack. */ |
25469 | cp_declarator *id_declarator = declarator; |
25470 | while (id_declarator && id_declarator->kind != cdk_id) |
25471 | id_declarator = id_declarator->declarator; |
25472 | |
25473 | if (id_declarator && id_declarator->kind == cdk_id) |
25474 | error_at (declarator_token_start->location, |
25475 | template_parm_p |
25476 | ? G_("template parameter pack %qD " |
25477 | "cannot have a default argument" ) |
25478 | : G_("parameter pack %qD cannot have " |
25479 | "a default argument" ), |
25480 | id_declarator->u.id.unqualified_name); |
25481 | else |
25482 | error_at (declarator_token_start->location, |
25483 | template_parm_p |
25484 | ? G_("template parameter pack cannot have " |
25485 | "a default argument" ) |
25486 | : G_("parameter pack cannot have a " |
25487 | "default argument" )); |
25488 | |
25489 | default_argument = NULL_TREE; |
25490 | } |
25491 | } |
25492 | else |
25493 | default_argument = NULL_TREE; |
25494 | |
25495 | if (default_argument) |
25496 | STRIP_ANY_LOCATION_WRAPPER (default_argument); |
25497 | |
25498 | /* Generate a location for the parameter, ranging from the start of the |
25499 | initial token to the end of the final token (using input_location for |
25500 | the latter, set up by cp_lexer_set_source_position_from_token when |
25501 | consuming tokens). |
25502 | |
25503 | If we have a identifier, then use it for the caret location, e.g. |
25504 | |
25505 | extern int callee (int one, int (*two)(int, int), float three); |
25506 | ~~~~~~^~~~~~~~~~~~~~ |
25507 | |
25508 | otherwise, reuse the start location for the caret location e.g.: |
25509 | |
25510 | extern int callee (int one, int (*)(int, int), float three); |
25511 | ^~~~~~~~~~~~~~~~~ |
25512 | |
25513 | */ |
25514 | location_t caret_loc = (declarator && declarator->id_loc != UNKNOWN_LOCATION |
25515 | ? declarator->id_loc |
25516 | : decl_spec_token_start->location); |
25517 | location_t param_loc = make_location (caret: caret_loc, |
25518 | start: decl_spec_token_start->location, |
25519 | finish: input_location); |
25520 | |
25521 | return make_parameter_declarator (decl_specifiers: &decl_specifiers, |
25522 | declarator, |
25523 | default_argument, |
25524 | loc: param_loc, |
25525 | template_parameter_pack_p); |
25526 | } |
25527 | |
25528 | /* Parse a default argument and return it. |
25529 | |
25530 | TEMPLATE_PARM_P is true if this is a default argument for a |
25531 | non-type template parameter. */ |
25532 | static tree |
25533 | cp_parser_default_argument (cp_parser *parser, bool template_parm_p) |
25534 | { |
25535 | tree default_argument = NULL_TREE; |
25536 | bool saved_greater_than_is_operator_p; |
25537 | unsigned char saved_local_variables_forbidden_p; |
25538 | |
25539 | /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is |
25540 | set correctly. */ |
25541 | saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; |
25542 | parser->greater_than_is_operator_p = !template_parm_p; |
25543 | auto odsd = make_temp_override (var&: parser->omp_declare_simd, NULL); |
25544 | auto ord = make_temp_override (var&: parser->oacc_routine, NULL); |
25545 | auto oafp = make_temp_override (var&: parser->omp_attrs_forbidden_p, overrider: false); |
25546 | |
25547 | /* Local variable names (and the `this' keyword) may not |
25548 | appear in a default argument. */ |
25549 | saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; |
25550 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
25551 | /* Parse the assignment-expression. */ |
25552 | if (template_parm_p) |
25553 | push_deferring_access_checks (dk_no_deferred); |
25554 | tree saved_class_ptr = NULL_TREE; |
25555 | tree saved_class_ref = NULL_TREE; |
25556 | /* The "this" pointer is not valid in a default argument. */ |
25557 | if (cfun) |
25558 | { |
25559 | saved_class_ptr = current_class_ptr; |
25560 | cp_function_chain->x_current_class_ptr = NULL_TREE; |
25561 | saved_class_ref = current_class_ref; |
25562 | cp_function_chain->x_current_class_ref = NULL_TREE; |
25563 | } |
25564 | default_argument = cp_parser_initializer (parser); |
25565 | /* Restore the "this" pointer. */ |
25566 | if (cfun) |
25567 | { |
25568 | cp_function_chain->x_current_class_ptr = saved_class_ptr; |
25569 | cp_function_chain->x_current_class_ref = saved_class_ref; |
25570 | } |
25571 | if (BRACE_ENCLOSED_INITIALIZER_P (default_argument)) |
25572 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
25573 | if (template_parm_p) |
25574 | pop_deferring_access_checks (); |
25575 | parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; |
25576 | parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; |
25577 | |
25578 | return default_argument; |
25579 | } |
25580 | |
25581 | /* Parse a function-body. |
25582 | |
25583 | function-body: |
25584 | compound_statement */ |
25585 | |
25586 | static void |
25587 | cp_parser_function_body (cp_parser *parser, bool in_function_try_block) |
25588 | { |
25589 | cp_parser_compound_statement (parser, NULL, bcs_flags: (in_function_try_block |
25590 | ? BCS_TRY_BLOCK : BCS_NORMAL), |
25591 | function_body: true); |
25592 | } |
25593 | |
25594 | /* Parse a ctor-initializer-opt followed by a function-body. Return |
25595 | true if a ctor-initializer was present. When IN_FUNCTION_TRY_BLOCK |
25596 | is true we are parsing a function-try-block. */ |
25597 | |
25598 | static void |
25599 | cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, |
25600 | bool in_function_try_block) |
25601 | { |
25602 | tree body, list; |
25603 | const bool check_body_p |
25604 | = (DECL_CONSTRUCTOR_P (current_function_decl) |
25605 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl)); |
25606 | tree last = NULL; |
25607 | |
25608 | if (in_function_try_block |
25609 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
25610 | && cxx_dialect < cxx20) |
25611 | { |
25612 | if (DECL_CONSTRUCTOR_P (current_function_decl)) |
25613 | pedwarn (input_location, OPT_Wc__20_extensions, |
25614 | "function-try-block body of %<constexpr%> constructor only " |
25615 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
25616 | else |
25617 | pedwarn (input_location, OPT_Wc__20_extensions, |
25618 | "function-try-block body of %<constexpr%> function only " |
25619 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
25620 | } |
25621 | |
25622 | /* Begin the function body. */ |
25623 | body = begin_function_body (); |
25624 | /* Parse the optional ctor-initializer. */ |
25625 | cp_parser_ctor_initializer_opt (parser); |
25626 | |
25627 | /* If we're parsing a constexpr constructor definition, we need |
25628 | to check that the constructor body is indeed empty. However, |
25629 | before we get to cp_parser_function_body lot of junk has been |
25630 | generated, so we can't just check that we have an empty block. |
25631 | Rather we take a snapshot of the outermost block, and check whether |
25632 | cp_parser_function_body changed its state. */ |
25633 | if (check_body_p) |
25634 | { |
25635 | list = cur_stmt_list; |
25636 | if (STATEMENT_LIST_TAIL (list)) |
25637 | last = STATEMENT_LIST_TAIL (list)->stmt; |
25638 | } |
25639 | /* Parse the function-body. */ |
25640 | cp_parser_function_body (parser, in_function_try_block); |
25641 | if (check_body_p) |
25642 | check_constexpr_ctor_body (last, list, /*complain=*/true); |
25643 | /* Finish the function body. */ |
25644 | finish_function_body (body); |
25645 | } |
25646 | |
25647 | /* Parse an initializer. |
25648 | |
25649 | initializer: |
25650 | = initializer-clause |
25651 | ( expression-list ) |
25652 | |
25653 | Returns an expression representing the initializer. If no |
25654 | initializer is present, NULL_TREE is returned. |
25655 | |
25656 | *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause' |
25657 | production is used, and TRUE otherwise. *IS_DIRECT_INIT is |
25658 | set to TRUE if there is no initializer present. If there is an |
25659 | initializer, and it is not a constant-expression, *NON_CONSTANT_P |
25660 | is set to true; otherwise it is set to false. */ |
25661 | |
25662 | static tree |
25663 | cp_parser_initializer (cp_parser *parser, bool *is_direct_init /*=nullptr*/, |
25664 | bool *non_constant_p /*=nullptr*/, bool subexpression_p) |
25665 | { |
25666 | cp_token *token; |
25667 | tree init; |
25668 | |
25669 | /* Peek at the next token. */ |
25670 | token = cp_lexer_peek_token (lexer: parser->lexer); |
25671 | |
25672 | /* Let our caller know whether or not this initializer was |
25673 | parenthesized. */ |
25674 | if (is_direct_init) |
25675 | *is_direct_init = (token->type != CPP_EQ); |
25676 | /* Assume that the initializer is constant. */ |
25677 | if (non_constant_p) |
25678 | *non_constant_p = false; |
25679 | |
25680 | if (token->type == CPP_EQ) |
25681 | { |
25682 | /* Consume the `='. */ |
25683 | cp_lexer_consume_token (lexer: parser->lexer); |
25684 | /* Parse the initializer-clause. */ |
25685 | init = cp_parser_initializer_clause (parser, non_constant_p); |
25686 | } |
25687 | else if (token->type == CPP_OPEN_PAREN) |
25688 | { |
25689 | vec<tree, va_gc> *vec; |
25690 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
25691 | /*cast_p=*/false, |
25692 | /*allow_expansion_p=*/true, |
25693 | non_constant_p); |
25694 | if (vec == NULL) |
25695 | return error_mark_node; |
25696 | init = build_tree_list_vec (vec); |
25697 | release_tree_vector (vec); |
25698 | } |
25699 | else if (token->type == CPP_OPEN_BRACE) |
25700 | { |
25701 | cp_lexer_set_source_position (lexer: parser->lexer); |
25702 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
25703 | init = cp_parser_braced_list (parser, non_constant_p); |
25704 | CONSTRUCTOR_IS_DIRECT_INIT (init) = 1; |
25705 | } |
25706 | else |
25707 | { |
25708 | /* Anything else is an error. */ |
25709 | cp_parser_error (parser, gmsgid: "expected initializer" ); |
25710 | init = error_mark_node; |
25711 | } |
25712 | |
25713 | if (!subexpression_p && check_for_bare_parameter_packs (init)) |
25714 | init = error_mark_node; |
25715 | |
25716 | return init; |
25717 | } |
25718 | |
25719 | /* Parse an initializer-clause. |
25720 | |
25721 | initializer-clause: |
25722 | assignment-expression |
25723 | braced-init-list |
25724 | |
25725 | Returns an expression representing the initializer. |
25726 | |
25727 | If the `assignment-expression' production is used the value |
25728 | returned is simply a representation for the expression. |
25729 | |
25730 | Otherwise, calls cp_parser_braced_list. */ |
25731 | |
25732 | static cp_expr |
25733 | cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) |
25734 | { |
25735 | cp_expr initializer; |
25736 | |
25737 | /* Assume the expression is constant. */ |
25738 | if (non_constant_p) |
25739 | *non_constant_p = false; |
25740 | |
25741 | /* If it is not a `{', then we are looking at an |
25742 | assignment-expression. */ |
25743 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
25744 | { |
25745 | initializer |
25746 | = cp_parser_constant_expression (parser, |
25747 | /*allow_non_constant_p=*/2, |
25748 | non_constant_p); |
25749 | } |
25750 | else |
25751 | initializer = cp_parser_braced_list (parser, non_constant_p); |
25752 | |
25753 | return initializer; |
25754 | } |
25755 | |
25756 | /* Parse a brace-enclosed initializer list. |
25757 | |
25758 | braced-init-list: |
25759 | { initializer-list , [opt] } |
25760 | { designated-initializer-list , [opt] } |
25761 | { } |
25762 | |
25763 | Returns a CONSTRUCTOR. The CONSTRUCTOR_ELTS will be |
25764 | the elements of the initializer-list (or NULL, if the last |
25765 | production is used). The TREE_TYPE for the CONSTRUCTOR will be |
25766 | NULL_TREE. There is no way to detect whether or not the optional |
25767 | trailing `,' was provided. NON_CONSTANT_P is as for |
25768 | cp_parser_initializer. */ |
25769 | |
25770 | static cp_expr |
25771 | cp_parser_braced_list (cp_parser *parser, bool *non_constant_p /*=nullptr*/) |
25772 | { |
25773 | tree initializer; |
25774 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
25775 | |
25776 | /* Consume the `{' token. */ |
25777 | matching_braces braces; |
25778 | braces.require_open (parser); |
25779 | /* Create a CONSTRUCTOR to represent the braced-initializer. */ |
25780 | initializer = make_node (CONSTRUCTOR); |
25781 | /* If it's not a `}', then there is a non-trivial initializer. */ |
25782 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
25783 | { |
25784 | bool designated; |
25785 | /* Parse the initializer list. */ |
25786 | CONSTRUCTOR_ELTS (initializer) |
25787 | = cp_parser_initializer_list (parser, non_constant_p, &designated); |
25788 | CONSTRUCTOR_IS_DESIGNATED_INIT (initializer) = designated; |
25789 | /* A trailing `,' token is allowed. */ |
25790 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
25791 | cp_lexer_consume_token (lexer: parser->lexer); |
25792 | } |
25793 | else if (non_constant_p) |
25794 | *non_constant_p = false; |
25795 | /* Now, there should be a trailing `}'. */ |
25796 | location_t finish_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
25797 | braces.require_close (parser); |
25798 | TREE_TYPE (initializer) = init_list_type_node; |
25799 | recompute_constructor_flags (initializer); |
25800 | |
25801 | cp_expr result (initializer); |
25802 | /* Build a location of the form: |
25803 | { ... } |
25804 | ^~~~~~~ |
25805 | with caret==start at the open brace, finish at the close brace. */ |
25806 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc); |
25807 | result.set_location (combined_loc); |
25808 | return result; |
25809 | } |
25810 | |
25811 | /* Consume tokens up to, but not including, the next non-nested closing `]'. |
25812 | Returns true iff we found a closing `]'. */ |
25813 | |
25814 | static bool |
25815 | cp_parser_skip_up_to_closing_square_bracket (cp_parser *parser) |
25816 | { |
25817 | unsigned square_depth = 0; |
25818 | |
25819 | while (true) |
25820 | { |
25821 | cp_token * token = cp_lexer_peek_token (lexer: parser->lexer); |
25822 | |
25823 | switch (token->type) |
25824 | { |
25825 | case CPP_PRAGMA_EOL: |
25826 | if (!parser->lexer->in_pragma) |
25827 | break; |
25828 | /* FALLTHRU */ |
25829 | |
25830 | case CPP_EOF: |
25831 | /* If we've run out of tokens, then there is no closing `]'. */ |
25832 | return false; |
25833 | |
25834 | case CPP_OPEN_SQUARE: |
25835 | ++square_depth; |
25836 | break; |
25837 | |
25838 | case CPP_CLOSE_SQUARE: |
25839 | if (!square_depth--) |
25840 | return true; |
25841 | break; |
25842 | |
25843 | default: |
25844 | break; |
25845 | } |
25846 | |
25847 | /* Consume the current token, skipping it. */ |
25848 | cp_lexer_consume_token (lexer: parser->lexer); |
25849 | } |
25850 | } |
25851 | |
25852 | /* Consume tokens up to, and including, the next non-nested closing `]'. |
25853 | Returns true iff we found a closing `]'. */ |
25854 | |
25855 | static bool |
25856 | cp_parser_skip_to_closing_square_bracket (cp_parser *parser) |
25857 | { |
25858 | bool found = cp_parser_skip_up_to_closing_square_bracket (parser); |
25859 | if (found) |
25860 | cp_lexer_consume_token (lexer: parser->lexer); |
25861 | return found; |
25862 | } |
25863 | |
25864 | /* Return true if we are looking at an array-designator, false otherwise. */ |
25865 | |
25866 | static bool |
25867 | cp_parser_array_designator_p (cp_parser *parser) |
25868 | { |
25869 | /* Consume the `['. */ |
25870 | cp_lexer_consume_token (lexer: parser->lexer); |
25871 | |
25872 | cp_lexer_save_tokens (lexer: parser->lexer); |
25873 | |
25874 | /* Skip tokens until the next token is a closing square bracket. |
25875 | If we find the closing `]', and the next token is a `=', then |
25876 | we are looking at an array designator. */ |
25877 | bool array_designator_p |
25878 | = (cp_parser_skip_to_closing_square_bracket (parser) |
25879 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)); |
25880 | |
25881 | /* Roll back the tokens we skipped. */ |
25882 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
25883 | |
25884 | return array_designator_p; |
25885 | } |
25886 | |
25887 | /* Parse an initializer-list. |
25888 | |
25889 | initializer-list: |
25890 | initializer-clause ... [opt] |
25891 | initializer-list , initializer-clause ... [opt] |
25892 | |
25893 | C++20 Extension: |
25894 | |
25895 | designated-initializer-list: |
25896 | designated-initializer-clause |
25897 | designated-initializer-list , designated-initializer-clause |
25898 | |
25899 | designated-initializer-clause: |
25900 | designator brace-or-equal-initializer |
25901 | |
25902 | designator: |
25903 | . identifier |
25904 | |
25905 | GNU Extension: |
25906 | |
25907 | initializer-list: |
25908 | designation initializer-clause ...[opt] |
25909 | initializer-list , designation initializer-clause ...[opt] |
25910 | |
25911 | designation: |
25912 | . identifier = |
25913 | identifier : |
25914 | [ constant-expression ] = |
25915 | |
25916 | Returns a vec of constructor_elt. The VALUE of each elt is an expression |
25917 | for the initializer. If the INDEX of the elt is non-NULL, it is the |
25918 | IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is |
25919 | as for cp_parser_initializer. Set *DESIGNATED to a boolean whether there |
25920 | are any designators. */ |
25921 | |
25922 | static vec<constructor_elt, va_gc> * |
25923 | cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p, |
25924 | bool *designated) |
25925 | { |
25926 | vec<constructor_elt, va_gc> *v = NULL; |
25927 | bool first_p = true; |
25928 | tree first_designator = NULL_TREE; |
25929 | |
25930 | /* Assume all of the expressions are constant. */ |
25931 | if (non_constant_p) |
25932 | *non_constant_p = false; |
25933 | |
25934 | unsigned nelts = 0; |
25935 | int suppress = suppress_location_wrappers; |
25936 | |
25937 | /* Parse the rest of the list. */ |
25938 | while (true) |
25939 | { |
25940 | cp_token *token; |
25941 | tree designator; |
25942 | tree initializer; |
25943 | bool clause_non_constant_p; |
25944 | bool direct_p = false; |
25945 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
25946 | |
25947 | /* Handle the C++20 syntax, '. id ='. */ |
25948 | if ((cxx_dialect >= cxx20 |
25949 | || cp_parser_allow_gnu_extensions_p (parser)) |
25950 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
25951 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_NAME |
25952 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_EQ |
25953 | || (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
25954 | == CPP_OPEN_BRACE))) |
25955 | { |
25956 | if (pedantic && cxx_dialect < cxx20) |
25957 | pedwarn (loc, OPT_Wc__20_extensions, |
25958 | "C++ designated initializers only available with " |
25959 | "%<-std=c++20%> or %<-std=gnu++20%>" ); |
25960 | /* Consume the `.'. */ |
25961 | cp_lexer_consume_token (lexer: parser->lexer); |
25962 | /* Consume the identifier. */ |
25963 | designator = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
25964 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
25965 | /* Consume the `='. */ |
25966 | cp_lexer_consume_token (lexer: parser->lexer); |
25967 | else |
25968 | direct_p = true; |
25969 | } |
25970 | /* Also, if the next token is an identifier and the following one is a |
25971 | colon, we are looking at the GNU designated-initializer |
25972 | syntax. */ |
25973 | else if (cp_parser_allow_gnu_extensions_p (parser) |
25974 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
25975 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
25976 | == CPP_COLON)) |
25977 | { |
25978 | /* Warn the user that they are using an extension. */ |
25979 | pedwarn (loc, OPT_Wpedantic, |
25980 | "ISO C++ does not allow GNU designated initializers" ); |
25981 | /* Consume the identifier. */ |
25982 | designator = cp_lexer_consume_token (lexer: parser->lexer)->u.value; |
25983 | /* Consume the `:'. */ |
25984 | cp_lexer_consume_token (lexer: parser->lexer); |
25985 | } |
25986 | /* Also handle C99 array designators, '[ const ] ='. */ |
25987 | else if (cp_parser_allow_gnu_extensions_p (parser) |
25988 | && !c_dialect_objc () |
25989 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
25990 | { |
25991 | /* In C++11, [ could start a lambda-introducer. */ |
25992 | bool non_const = false; |
25993 | |
25994 | cp_parser_parse_tentatively (parser); |
25995 | |
25996 | if (!cp_parser_array_designator_p (parser)) |
25997 | { |
25998 | cp_parser_simulate_error (parser); |
25999 | designator = NULL_TREE; |
26000 | } |
26001 | else |
26002 | { |
26003 | designator = cp_parser_constant_expression (parser, allow_non_constant_p: true, |
26004 | non_constant_p: &non_const); |
26005 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
26006 | cp_parser_require (parser, CPP_EQ, RT_EQ); |
26007 | } |
26008 | |
26009 | if (!cp_parser_parse_definitely (parser)) |
26010 | designator = NULL_TREE; |
26011 | else if (non_const |
26012 | && (!require_potential_rvalue_constant_expression |
26013 | (designator))) |
26014 | designator = NULL_TREE; |
26015 | if (designator) |
26016 | /* Warn the user that they are using an extension. */ |
26017 | pedwarn (loc, OPT_Wpedantic, |
26018 | "ISO C++ does not allow C99 designated initializers" ); |
26019 | } |
26020 | else |
26021 | designator = NULL_TREE; |
26022 | |
26023 | if (first_p) |
26024 | { |
26025 | first_designator = designator; |
26026 | first_p = false; |
26027 | } |
26028 | else if (cxx_dialect >= cxx20 |
26029 | && first_designator != error_mark_node |
26030 | && (!first_designator != !designator)) |
26031 | { |
26032 | error_at (loc, "either all initializer clauses should be designated " |
26033 | "or none of them should be" ); |
26034 | first_designator = error_mark_node; |
26035 | } |
26036 | else if (cxx_dialect < cxx20 && !first_designator) |
26037 | first_designator = designator; |
26038 | |
26039 | /* Parse the initializer. */ |
26040 | initializer = cp_parser_initializer_clause (parser, |
26041 | non_constant_p: (non_constant_p != nullptr |
26042 | ? &clause_non_constant_p |
26043 | : nullptr)); |
26044 | /* If any clause is non-constant, so is the entire initializer. */ |
26045 | if (non_constant_p && clause_non_constant_p) |
26046 | *non_constant_p = true; |
26047 | |
26048 | if (TREE_CODE (initializer) == CONSTRUCTOR) |
26049 | /* This uses |= rather than = because C_I_D_I could have been set in |
26050 | cp_parser_functional_cast so we must be careful not to clear the |
26051 | flag. */ |
26052 | CONSTRUCTOR_IS_DIRECT_INIT (initializer) |= direct_p; |
26053 | |
26054 | /* If we have an ellipsis, this is an initializer pack |
26055 | expansion. */ |
26056 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
26057 | { |
26058 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
26059 | |
26060 | /* Consume the `...'. */ |
26061 | cp_lexer_consume_token (lexer: parser->lexer); |
26062 | |
26063 | if (designator && cxx_dialect >= cxx20) |
26064 | error_at (loc, |
26065 | "%<...%> not allowed in designated initializer list" ); |
26066 | |
26067 | /* Turn the initializer into an initializer expansion. */ |
26068 | initializer = make_pack_expansion (initializer); |
26069 | } |
26070 | |
26071 | /* Add it to the vector. */ |
26072 | CONSTRUCTOR_APPEND_ELT (v, designator, initializer); |
26073 | |
26074 | /* If the next token is not a comma, we have reached the end of |
26075 | the list. */ |
26076 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
26077 | break; |
26078 | |
26079 | /* Peek at the next token. */ |
26080 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
26081 | /* If the next token is a `}', then we're still done. An |
26082 | initializer-clause can have a trailing `,' after the |
26083 | initializer-list and before the closing `}'. */ |
26084 | if (token->type == CPP_CLOSE_BRACE) |
26085 | break; |
26086 | |
26087 | /* Suppress location wrappers in a long initializer to save memory |
26088 | (14179). The cutoff is chosen arbitrarily. */ |
26089 | const unsigned loc_max = 256; |
26090 | unsigned incr = 1; |
26091 | if (TREE_CODE (initializer) == CONSTRUCTOR) |
26092 | /* Look one level down because it's easy. Looking deeper would require |
26093 | passing down a nelts pointer, and I don't think multi-level massive |
26094 | initializers are common enough to justify this. */ |
26095 | incr = CONSTRUCTOR_NELTS (initializer); |
26096 | nelts += incr; |
26097 | if (nelts >= loc_max && (nelts - incr) < loc_max) |
26098 | ++suppress_location_wrappers; |
26099 | |
26100 | /* Consume the `,' token. */ |
26101 | cp_lexer_consume_token (lexer: parser->lexer); |
26102 | } |
26103 | |
26104 | /* The same identifier shall not appear in multiple designators |
26105 | of a designated-initializer-list. */ |
26106 | if (first_designator) |
26107 | { |
26108 | unsigned int i; |
26109 | tree designator, val; |
26110 | FOR_EACH_CONSTRUCTOR_ELT (v, i, designator, val) |
26111 | if (designator && TREE_CODE (designator) == IDENTIFIER_NODE) |
26112 | { |
26113 | if (IDENTIFIER_MARKED (designator)) |
26114 | { |
26115 | error_at (cp_expr_loc_or_input_loc (t: val), |
26116 | "%<.%s%> designator used multiple times in " |
26117 | "the same initializer list" , |
26118 | IDENTIFIER_POINTER (designator)); |
26119 | (*v)[i].index = error_mark_node; |
26120 | } |
26121 | else |
26122 | IDENTIFIER_MARKED (designator) = 1; |
26123 | } |
26124 | FOR_EACH_CONSTRUCTOR_ELT (v, i, designator, val) |
26125 | if (designator && TREE_CODE (designator) == IDENTIFIER_NODE) |
26126 | IDENTIFIER_MARKED (designator) = 0; |
26127 | } |
26128 | |
26129 | suppress_location_wrappers = suppress; |
26130 | |
26131 | *designated = first_designator != NULL_TREE; |
26132 | return v; |
26133 | } |
26134 | |
26135 | /* Classes [gram.class] */ |
26136 | |
26137 | /* Parse a class-name. |
26138 | |
26139 | class-name: |
26140 | identifier |
26141 | template-id |
26142 | |
26143 | TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used |
26144 | to indicate that names looked up in dependent types should be |
26145 | assumed to be types. TEMPLATE_KEYWORD_P is true iff the `template' |
26146 | keyword has been used to indicate that the name that appears next |
26147 | is a template. TAG_TYPE indicates the explicit tag given before |
26148 | the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are |
26149 | looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class |
26150 | is the class being defined in a class-head. If ENUM_OK is TRUE, |
26151 | enum-names are also accepted. |
26152 | |
26153 | Returns the TYPE_DECL representing the class. */ |
26154 | |
26155 | static tree |
26156 | cp_parser_class_name (cp_parser *parser, |
26157 | bool typename_keyword_p, |
26158 | bool template_keyword_p, |
26159 | enum tag_types tag_type, |
26160 | bool check_dependency_p, |
26161 | bool class_head_p, |
26162 | bool is_declaration, |
26163 | bool enum_ok) |
26164 | { |
26165 | tree decl; |
26166 | tree identifier = NULL_TREE; |
26167 | |
26168 | /* All class-names start with an identifier. */ |
26169 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
26170 | if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID) |
26171 | { |
26172 | cp_parser_error (parser, gmsgid: "expected class-name" ); |
26173 | return error_mark_node; |
26174 | } |
26175 | |
26176 | /* PARSER->SCOPE can be cleared when parsing the template-arguments |
26177 | to a template-id, so we save it here. Consider object scope too, |
26178 | so that make_typename_type below can use it (cp_parser_template_name |
26179 | considers object scope also). This may happen with code like |
26180 | |
26181 | p->template A<T>::a() |
26182 | |
26183 | where we first want to look up A<T>::a in the class of the object |
26184 | expression, as per [basic.lookup.classref]. */ |
26185 | tree scope = parser->scope ? parser->scope : parser->context->object_type; |
26186 | /* This only checks parser->scope to avoid duplicate errors; if |
26187 | ->object_type is erroneous, go on to give a parse error. */ |
26188 | if (parser->scope == error_mark_node) |
26189 | return error_mark_node; |
26190 | |
26191 | /* Any name names a type if we're following the `typename' keyword |
26192 | in a qualified name where the enclosing scope is type-dependent. */ |
26193 | const bool typename_p = (typename_keyword_p |
26194 | && parser->scope |
26195 | && TYPE_P (parser->scope) |
26196 | && dependent_scope_p (parser->scope)); |
26197 | /* Handle the common case (an identifier, but not a template-id) |
26198 | efficiently. */ |
26199 | if (token->type == CPP_NAME |
26200 | && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) |
26201 | { |
26202 | cp_token *identifier_token; |
26203 | bool ambiguous_p; |
26204 | |
26205 | /* Look for the identifier. */ |
26206 | identifier_token = cp_lexer_peek_token (lexer: parser->lexer); |
26207 | ambiguous_p = identifier_token->error_reported; |
26208 | identifier = cp_parser_identifier (parser); |
26209 | /* If the next token isn't an identifier, we are certainly not |
26210 | looking at a class-name. */ |
26211 | if (identifier == error_mark_node) |
26212 | decl = error_mark_node; |
26213 | /* If we know this is a type-name, there's no need to look it |
26214 | up. */ |
26215 | else if (typename_p) |
26216 | decl = identifier; |
26217 | else |
26218 | { |
26219 | tree ambiguous_decls; |
26220 | /* If we already know that this lookup is ambiguous, then |
26221 | we've already issued an error message; there's no reason |
26222 | to check again. */ |
26223 | if (ambiguous_p) |
26224 | { |
26225 | cp_parser_simulate_error (parser); |
26226 | return error_mark_node; |
26227 | } |
26228 | /* If the next token is a `::', then the name must be a type |
26229 | name. |
26230 | |
26231 | [basic.lookup.qual] |
26232 | |
26233 | During the lookup for a name preceding the :: scope |
26234 | resolution operator, object, function, and enumerator |
26235 | names are ignored. */ |
26236 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
26237 | tag_type = scope_type; |
26238 | /* Look up the name. */ |
26239 | decl = cp_parser_lookup_name (parser, identifier, |
26240 | tag_type, |
26241 | /*is_template=*/false, |
26242 | /*is_namespace=*/false, |
26243 | check_dependency_p, |
26244 | &ambiguous_decls, |
26245 | identifier_token->location); |
26246 | if (ambiguous_decls) |
26247 | { |
26248 | if (cp_parser_parsing_tentatively (parser)) |
26249 | cp_parser_simulate_error (parser); |
26250 | return error_mark_node; |
26251 | } |
26252 | } |
26253 | } |
26254 | else |
26255 | { |
26256 | /* Try a template-id. */ |
26257 | decl = cp_parser_template_id (parser, template_keyword_p, |
26258 | check_dependency_p, |
26259 | tag_type, |
26260 | is_declaration); |
26261 | if (decl == error_mark_node) |
26262 | return error_mark_node; |
26263 | } |
26264 | |
26265 | decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p); |
26266 | |
26267 | /* If this is a typename, create a TYPENAME_TYPE. */ |
26268 | if (typename_p && decl != error_mark_node) |
26269 | { |
26270 | decl = make_typename_type (scope, decl, typename_type, |
26271 | /*complain=*/tf_error); |
26272 | if (decl != error_mark_node) |
26273 | decl = TYPE_NAME (decl); |
26274 | } |
26275 | |
26276 | decl = strip_using_decl (decl); |
26277 | |
26278 | /* Check to see that it is really the name of a class. */ |
26279 | if (TREE_CODE (decl) == TEMPLATE_ID_EXPR |
26280 | && identifier_p (TREE_OPERAND (decl, 0)) |
26281 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SCOPE)) |
26282 | /* Situations like this: |
26283 | |
26284 | template <typename T> struct A { |
26285 | typename T::template X<int>::I i; |
26286 | }; |
26287 | |
26288 | are problematic. Is `T::template X<int>' a class-name? The |
26289 | standard does not seem to be definitive, but there is no other |
26290 | valid interpretation of the following `::'. Therefore, those |
26291 | names are considered class-names. */ |
26292 | { |
26293 | decl = make_typename_type (scope, decl, tag_type, tf_error); |
26294 | if (decl != error_mark_node) |
26295 | decl = TYPE_NAME (decl); |
26296 | } |
26297 | else if (TREE_CODE (decl) != TYPE_DECL |
26298 | || TREE_TYPE (decl) == error_mark_node |
26299 | || !(MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)) |
26300 | || (enum_ok && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)) |
26301 | /* In Objective-C 2.0, a classname followed by '.' starts a |
26302 | dot-syntax expression, and it's not a type-name. */ |
26303 | || (c_dialect_objc () |
26304 | && cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_DOT |
26305 | && objc_is_class_name (decl))) |
26306 | decl = error_mark_node; |
26307 | |
26308 | if (decl == error_mark_node) |
26309 | cp_parser_error (parser, gmsgid: "expected class-name" ); |
26310 | else if (identifier && !parser->scope) |
26311 | maybe_note_name_used_in_class (identifier, decl); |
26312 | |
26313 | return decl; |
26314 | } |
26315 | |
26316 | /* Make sure that any member-function parameters are in scope. |
26317 | For instance, a function's noexcept-specifier can use the function's |
26318 | parameters: |
26319 | |
26320 | struct S { |
26321 | void fn (int p) noexcept(noexcept(p)); |
26322 | }; |
26323 | |
26324 | so we need to make sure name lookup can find them. This is used |
26325 | when we delay parsing of the noexcept-specifier. */ |
26326 | |
26327 | static void |
26328 | inject_parm_decls (tree decl) |
26329 | { |
26330 | begin_scope (sk_function_parms, decl); |
26331 | tree args = DECL_ARGUMENTS (decl); |
26332 | |
26333 | do_push_parm_decls (decl, args, /*nonparms=*/NULL); |
26334 | |
26335 | if (args && is_this_parameter (args)) |
26336 | { |
26337 | gcc_checking_assert (current_class_ptr == NULL_TREE); |
26338 | current_class_ref = cp_build_fold_indirect_ref (args); |
26339 | current_class_ptr = args; |
26340 | } |
26341 | } |
26342 | |
26343 | /* Undo the effects of inject_parm_decls. */ |
26344 | |
26345 | static void |
26346 | pop_injected_parms (void) |
26347 | { |
26348 | pop_bindings_and_leave_scope (); |
26349 | current_class_ptr = current_class_ref = NULL_TREE; |
26350 | } |
26351 | |
26352 | /* Parse a class-specifier. |
26353 | |
26354 | class-specifier: |
26355 | class-head { member-specification [opt] } |
26356 | |
26357 | Returns the TREE_TYPE representing the class. */ |
26358 | |
26359 | tree |
26360 | cp_parser_class_specifier (cp_parser* parser) |
26361 | { |
26362 | auto_timevar tv (TV_PARSE_STRUCT); |
26363 | |
26364 | tree type; |
26365 | tree attributes = NULL_TREE; |
26366 | bool nested_name_specifier_p; |
26367 | unsigned saved_num_template_parameter_lists; |
26368 | bool saved_in_function_body; |
26369 | unsigned char in_statement; |
26370 | bool in_switch_statement_p; |
26371 | bool saved_in_unbraced_linkage_specification_p; |
26372 | tree old_scope = NULL_TREE; |
26373 | tree scope = NULL_TREE; |
26374 | cp_token *closing_brace; |
26375 | |
26376 | push_deferring_access_checks (dk_no_deferred); |
26377 | |
26378 | /* Parse the class-head. */ |
26379 | type = cp_parser_class_head (parser, |
26380 | &nested_name_specifier_p); |
26381 | /* If the class-head was a semantic disaster, skip the entire body |
26382 | of the class. */ |
26383 | if (!type) |
26384 | { |
26385 | cp_parser_skip_to_end_of_block_or_statement (parser); |
26386 | pop_deferring_access_checks (); |
26387 | return error_mark_node; |
26388 | } |
26389 | |
26390 | /* Look for the `{'. */ |
26391 | matching_braces braces; |
26392 | if (!braces.require_open (parser)) |
26393 | { |
26394 | pop_deferring_access_checks (); |
26395 | return error_mark_node; |
26396 | } |
26397 | |
26398 | cp_ensure_no_omp_declare_simd (parser); |
26399 | cp_ensure_no_oacc_routine (parser); |
26400 | |
26401 | /* Issue an error message if type-definitions are forbidden here. */ |
26402 | bool type_definition_ok_p = cp_parser_check_type_definition (parser); |
26403 | /* Remember that we are defining one more class. */ |
26404 | ++parser->num_classes_being_defined; |
26405 | /* Inside the class, surrounding template-parameter-lists do not |
26406 | apply. */ |
26407 | saved_num_template_parameter_lists |
26408 | = parser->num_template_parameter_lists; |
26409 | parser->num_template_parameter_lists = 0; |
26410 | /* We are not in a function body. */ |
26411 | saved_in_function_body = parser->in_function_body; |
26412 | parser->in_function_body = false; |
26413 | /* Or in a loop. */ |
26414 | in_statement = parser->in_statement; |
26415 | parser->in_statement = 0; |
26416 | /* Or in a switch. */ |
26417 | in_switch_statement_p = parser->in_switch_statement_p; |
26418 | parser->in_switch_statement_p = false; |
26419 | /* We are not immediately inside an extern "lang" block. */ |
26420 | saved_in_unbraced_linkage_specification_p |
26421 | = parser->in_unbraced_linkage_specification_p; |
26422 | parser->in_unbraced_linkage_specification_p = false; |
26423 | /* 'this' from an enclosing non-static member function is unavailable. */ |
26424 | tree saved_ccp = current_class_ptr; |
26425 | tree saved_ccr = current_class_ref; |
26426 | current_class_ptr = NULL_TREE; |
26427 | current_class_ref = NULL_TREE; |
26428 | |
26429 | /* Start the class. */ |
26430 | if (nested_name_specifier_p) |
26431 | { |
26432 | scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); |
26433 | /* SCOPE must be a scope nested inside current scope. */ |
26434 | if (is_nested_namespace (current_namespace, |
26435 | descendant: decl_namespace_context (scope))) |
26436 | old_scope = push_inner_scope (scope); |
26437 | else |
26438 | nested_name_specifier_p = false; |
26439 | } |
26440 | type = begin_class_definition (type); |
26441 | |
26442 | if (type == error_mark_node) |
26443 | /* If the type is erroneous, skip the entire body of the class. */ |
26444 | cp_parser_skip_to_closing_brace (parser); |
26445 | else |
26446 | /* Parse the member-specification. */ |
26447 | cp_parser_member_specification_opt (parser); |
26448 | |
26449 | /* Look for the trailing `}'. */ |
26450 | closing_brace = braces.require_close (parser); |
26451 | /* Look for trailing attributes to apply to this class. */ |
26452 | if (cp_parser_allow_gnu_extensions_p (parser)) |
26453 | attributes = cp_parser_gnu_attributes_opt (parser); |
26454 | if (type != error_mark_node) |
26455 | type = finish_struct (type, attributes); |
26456 | if (nested_name_specifier_p) |
26457 | pop_inner_scope (old_scope, scope); |
26458 | |
26459 | /* We've finished a type definition. Check for the common syntax |
26460 | error of forgetting a semicolon after the definition. We need to |
26461 | be careful, as we can't just check for not-a-semicolon and be done |
26462 | with it; the user might have typed: |
26463 | |
26464 | class X { } c = ...; |
26465 | class X { } *p = ...; |
26466 | |
26467 | and so forth. Instead, enumerate all the possible tokens that |
26468 | might follow this production; if we don't see one of them, then |
26469 | complain and silently insert the semicolon. */ |
26470 | { |
26471 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
26472 | bool want_semicolon = true; |
26473 | |
26474 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
26475 | /* Don't try to parse c++11 attributes here. As per the |
26476 | grammar, that should be a task for |
26477 | cp_parser_decl_specifier_seq. */ |
26478 | want_semicolon = false; |
26479 | |
26480 | switch (token->type) |
26481 | { |
26482 | case CPP_NAME: |
26483 | case CPP_SEMICOLON: |
26484 | case CPP_MULT: |
26485 | case CPP_AND: |
26486 | case CPP_OPEN_PAREN: |
26487 | case CPP_CLOSE_PAREN: |
26488 | case CPP_COMMA: |
26489 | case CPP_SCOPE: |
26490 | want_semicolon = false; |
26491 | break; |
26492 | |
26493 | /* While it's legal for type qualifiers and storage class |
26494 | specifiers to follow type definitions in the grammar, only |
26495 | compiler testsuites contain code like that. Assume that if |
26496 | we see such code, then what we're really seeing is a case |
26497 | like: |
26498 | |
26499 | class X { } |
26500 | const <type> var = ...; |
26501 | |
26502 | or |
26503 | |
26504 | class Y { } |
26505 | static <type> func (...) ... |
26506 | |
26507 | i.e. the qualifier or specifier applies to the next |
26508 | declaration. To do so, however, we need to look ahead one |
26509 | more token to see if *that* token is a type specifier. |
26510 | |
26511 | This code could be improved to handle: |
26512 | |
26513 | class Z { } |
26514 | static const <type> var = ...; */ |
26515 | case CPP_KEYWORD: |
26516 | if (keyword_is_decl_specifier (token->keyword)) |
26517 | { |
26518 | cp_token *lookahead = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
26519 | |
26520 | /* Handling user-defined types here would be nice, but very |
26521 | tricky. */ |
26522 | want_semicolon |
26523 | = (lookahead->type == CPP_KEYWORD |
26524 | && keyword_begins_type_specifier (lookahead->keyword)); |
26525 | } |
26526 | break; |
26527 | default: |
26528 | break; |
26529 | } |
26530 | |
26531 | /* If we don't have a type, then something is very wrong and we |
26532 | shouldn't try to do anything clever. Likewise for not seeing the |
26533 | closing brace. */ |
26534 | if (closing_brace && TYPE_P (type) && want_semicolon) |
26535 | { |
26536 | /* Locate the closing brace. */ |
26537 | cp_token_position prev |
26538 | = cp_lexer_previous_token_position (lexer: parser->lexer); |
26539 | cp_token *prev_token = cp_lexer_token_at (parser->lexer, pos: prev); |
26540 | location_t loc = prev_token->location; |
26541 | |
26542 | /* We want to suggest insertion of a ';' immediately *after* the |
26543 | closing brace, so, if we can, offset the location by 1 column. */ |
26544 | location_t next_loc = loc; |
26545 | if (!linemap_location_from_macro_expansion_p (line_table, loc)) |
26546 | next_loc = linemap_position_for_loc_and_offset (set: line_table, loc, offset: 1); |
26547 | |
26548 | rich_location richloc (line_table, next_loc); |
26549 | |
26550 | /* If we successfully offset the location, suggest the fix-it. */ |
26551 | if (next_loc != loc) |
26552 | richloc.add_fixit_insert_before (where: next_loc, new_content: ";" ); |
26553 | |
26554 | if (CLASSTYPE_DECLARED_CLASS (type)) |
26555 | error_at (&richloc, |
26556 | "expected %<;%> after class definition" ); |
26557 | else if (TREE_CODE (type) == RECORD_TYPE) |
26558 | error_at (&richloc, |
26559 | "expected %<;%> after struct definition" ); |
26560 | else if (TREE_CODE (type) == UNION_TYPE) |
26561 | error_at (&richloc, |
26562 | "expected %<;%> after union definition" ); |
26563 | else |
26564 | gcc_unreachable (); |
26565 | |
26566 | /* Unget one token and smash it to look as though we encountered |
26567 | a semicolon in the input stream. */ |
26568 | cp_lexer_set_token_position (lexer: parser->lexer, pos: prev); |
26569 | token = cp_lexer_peek_token (lexer: parser->lexer); |
26570 | token->type = CPP_SEMICOLON; |
26571 | token->keyword = RID_MAX; |
26572 | } |
26573 | } |
26574 | |
26575 | /* If this class is not itself within the scope of another class, |
26576 | then we need to parse the bodies of all of the queued function |
26577 | definitions. Note that the queued functions defined in a class |
26578 | are not always processed immediately following the |
26579 | class-specifier for that class. Consider: |
26580 | |
26581 | struct A { |
26582 | struct B { void f() { sizeof (A); } }; |
26583 | }; |
26584 | |
26585 | If `f' were processed before the processing of `A' were |
26586 | completed, there would be no way to compute the size of `A'. |
26587 | Note that the nesting we are interested in here is lexical -- |
26588 | not the semantic nesting given by TYPE_CONTEXT. In particular, |
26589 | for: |
26590 | |
26591 | struct A { struct B; }; |
26592 | struct A::B { void f() { } }; |
26593 | |
26594 | there is no need to delay the parsing of `A::B::f'. */ |
26595 | if (--parser->num_classes_being_defined == 0) |
26596 | { |
26597 | tree decl; |
26598 | tree class_type = NULL_TREE; |
26599 | tree pushed_scope = NULL_TREE; |
26600 | unsigned ix; |
26601 | cp_default_arg_entry *e; |
26602 | |
26603 | if (!type_definition_ok_p || any_erroneous_template_args_p (type)) |
26604 | { |
26605 | /* Skip default arguments, NSDMIs, etc, in order to improve |
26606 | error recovery (c++/71169, c++/71832). */ |
26607 | vec_safe_truncate (unparsed_funs_with_default_args, size: 0); |
26608 | vec_safe_truncate (unparsed_nsdmis, size: 0); |
26609 | vec_safe_truncate (unparsed_funs_with_definitions, size: 0); |
26610 | } |
26611 | |
26612 | /* In a first pass, parse default arguments to the functions. |
26613 | Then, in a second pass, parse the bodies of the functions. |
26614 | This two-phased approach handles cases like: |
26615 | |
26616 | struct S { |
26617 | void f() { g(); } |
26618 | void g(int i = 3); |
26619 | }; |
26620 | |
26621 | */ |
26622 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_default_args, ix, e) |
26623 | { |
26624 | decl = e->decl; |
26625 | /* If there are default arguments that have not yet been processed, |
26626 | take care of them now. */ |
26627 | if (class_type != e->class_type) |
26628 | { |
26629 | if (pushed_scope) |
26630 | pop_scope (pushed_scope); |
26631 | class_type = e->class_type; |
26632 | pushed_scope = push_scope (class_type); |
26633 | } |
26634 | /* Make sure that any template parameters are in scope. */ |
26635 | maybe_begin_member_template_processing (decl); |
26636 | /* Parse the default argument expressions. */ |
26637 | cp_parser_late_parsing_default_args (parser, decl); |
26638 | /* Remove any template parameters from the symbol table. */ |
26639 | maybe_end_member_template_processing (); |
26640 | } |
26641 | vec_safe_truncate (unparsed_funs_with_default_args, size: 0); |
26642 | |
26643 | /* If there are noexcept-specifiers that have not yet been processed, |
26644 | take care of them now. Do this before processing NSDMIs as they |
26645 | may depend on noexcept-specifiers already having been processed. */ |
26646 | FOR_EACH_VEC_SAFE_ELT (unparsed_noexcepts, ix, decl) |
26647 | { |
26648 | tree ctx = DECL_CONTEXT (decl); |
26649 | if (class_type != ctx) |
26650 | { |
26651 | if (pushed_scope) |
26652 | pop_scope (pushed_scope); |
26653 | class_type = ctx; |
26654 | pushed_scope = push_scope (class_type); |
26655 | } |
26656 | |
26657 | tree def_parse = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); |
26658 | def_parse = TREE_PURPOSE (def_parse); |
26659 | |
26660 | /* Make sure that any template parameters are in scope. */ |
26661 | maybe_begin_member_template_processing (decl); |
26662 | |
26663 | /* Make sure that any member-function parameters are in scope. |
26664 | This function doesn't expect ccp to be set. */ |
26665 | current_class_ptr = current_class_ref = NULL_TREE; |
26666 | inject_parm_decls (decl); |
26667 | |
26668 | /* 'this' is not allowed in static member functions. */ |
26669 | unsigned char local_variables_forbidden_p |
26670 | = parser->local_variables_forbidden_p; |
26671 | if (DECL_THIS_STATIC (decl)) |
26672 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
26673 | |
26674 | /* Now we can parse the noexcept-specifier. */ |
26675 | tree spec = cp_parser_late_noexcept_specifier (parser, def_parse); |
26676 | |
26677 | if (spec == error_mark_node) |
26678 | spec = NULL_TREE; |
26679 | |
26680 | /* Update the fn's type directly -- it might have escaped |
26681 | beyond this decl :( */ |
26682 | fixup_deferred_exception_variants (TREE_TYPE (decl), spec); |
26683 | /* Update any instantiations we've already created. We must |
26684 | keep the new noexcept-specifier wrapped in a DEFERRED_NOEXCEPT |
26685 | so that maybe_instantiate_noexcept can tsubst the NOEXCEPT_EXPR |
26686 | in the pattern. */ |
26687 | for (tree i : DEFPARSE_INSTANTIATIONS (def_parse)) |
26688 | DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (i)) |
26689 | = spec ? TREE_PURPOSE (spec) : error_mark_node; |
26690 | |
26691 | /* Restore the state of local_variables_forbidden_p. */ |
26692 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
26693 | |
26694 | /* The finish_struct call above performed various override checking, |
26695 | but it skipped unparsed noexcept-specifier operands. Now that we |
26696 | have resolved them, check again. */ |
26697 | noexcept_override_late_checks (decl); |
26698 | |
26699 | /* Remove any member-function parameters from the symbol table. */ |
26700 | pop_injected_parms (); |
26701 | |
26702 | /* Remove any template parameters from the symbol table. */ |
26703 | maybe_end_member_template_processing (); |
26704 | } |
26705 | vec_safe_truncate (unparsed_noexcepts, size: 0); |
26706 | |
26707 | /* Now parse any NSDMIs. */ |
26708 | FOR_EACH_VEC_SAFE_ELT (unparsed_nsdmis, ix, decl) |
26709 | { |
26710 | tree ctx = type_context_for_name_lookup (decl); |
26711 | if (class_type != ctx) |
26712 | { |
26713 | if (pushed_scope) |
26714 | pop_scope (pushed_scope); |
26715 | class_type = ctx; |
26716 | pushed_scope = push_scope (class_type); |
26717 | } |
26718 | inject_this_parameter (ctype: class_type, quals: TYPE_UNQUALIFIED); |
26719 | cp_parser_late_parsing_nsdmi (parser, decl); |
26720 | } |
26721 | vec_safe_truncate (unparsed_nsdmis, size: 0); |
26722 | |
26723 | /* Now contract attributes. */ |
26724 | FOR_EACH_VEC_SAFE_ELT (unparsed_contracts, ix, decl) |
26725 | { |
26726 | tree ctx = DECL_CONTEXT (decl); |
26727 | if (class_type != ctx) |
26728 | { |
26729 | if (pushed_scope) |
26730 | pop_scope (pushed_scope); |
26731 | class_type = ctx; |
26732 | pushed_scope = push_scope (class_type); |
26733 | } |
26734 | |
26735 | temp_override<tree> cfd(current_function_decl, decl); |
26736 | |
26737 | /* Make sure that any template parameters are in scope. */ |
26738 | maybe_begin_member_template_processing (decl); |
26739 | |
26740 | /* Make sure that any member-function parameters are in scope. |
26741 | This function doesn't expect ccp to be set. */ |
26742 | current_class_ptr = current_class_ref = NULL_TREE; |
26743 | inject_parm_decls (decl); |
26744 | |
26745 | /* 'this' is not allowed in static member functions. */ |
26746 | unsigned char local_variables_forbidden_p |
26747 | = parser->local_variables_forbidden_p; |
26748 | if (DECL_THIS_STATIC (decl)) |
26749 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
26750 | |
26751 | /* Now we can parse contract conditions. */ |
26752 | for (tree a = DECL_ATTRIBUTES (decl); a; a = TREE_CHAIN (a)) |
26753 | { |
26754 | if (cxx_contract_attribute_p (a)) |
26755 | cp_parser_late_contract_condition (parser, decl, a); |
26756 | } |
26757 | |
26758 | /* Restore the state of local_variables_forbidden_p. */ |
26759 | parser->local_variables_forbidden_p = local_variables_forbidden_p; |
26760 | |
26761 | /* Remove any member-function parameters from the symbol table. */ |
26762 | pop_injected_parms (); |
26763 | |
26764 | /* Remove any template parameters from the symbol table. */ |
26765 | maybe_end_member_template_processing (); |
26766 | |
26767 | /* Perform any deferred contract matching. */ |
26768 | match_deferred_contracts (decl); |
26769 | } |
26770 | vec_safe_truncate (unparsed_contracts, size: 0); |
26771 | |
26772 | current_class_ptr = NULL_TREE; |
26773 | current_class_ref = NULL_TREE; |
26774 | if (pushed_scope) |
26775 | pop_scope (pushed_scope); |
26776 | |
26777 | /* Now parse the body of the functions. */ |
26778 | if (flag_openmp) |
26779 | { |
26780 | /* OpenMP UDRs need to be parsed before all other functions. */ |
26781 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
26782 | if (DECL_OMP_DECLARE_REDUCTION_P (decl)) |
26783 | cp_parser_late_parsing_for_member (parser, decl); |
26784 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
26785 | if (!DECL_OMP_DECLARE_REDUCTION_P (decl)) |
26786 | cp_parser_late_parsing_for_member (parser, decl); |
26787 | } |
26788 | else |
26789 | FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl) |
26790 | cp_parser_late_parsing_for_member (parser, decl); |
26791 | vec_safe_truncate (unparsed_funs_with_definitions, size: 0); |
26792 | } |
26793 | |
26794 | /* Put back any saved access checks. */ |
26795 | pop_deferring_access_checks (); |
26796 | |
26797 | /* Restore saved state. */ |
26798 | parser->in_switch_statement_p = in_switch_statement_p; |
26799 | parser->in_statement = in_statement; |
26800 | parser->in_function_body = saved_in_function_body; |
26801 | parser->num_template_parameter_lists |
26802 | = saved_num_template_parameter_lists; |
26803 | parser->in_unbraced_linkage_specification_p |
26804 | = saved_in_unbraced_linkage_specification_p; |
26805 | current_class_ptr = saved_ccp; |
26806 | current_class_ref = saved_ccr; |
26807 | |
26808 | return type; |
26809 | } |
26810 | |
26811 | /* Parse a class-head. |
26812 | |
26813 | class-head: |
26814 | class-key identifier [opt] base-clause [opt] |
26815 | class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt] |
26816 | class-key nested-name-specifier [opt] template-id |
26817 | base-clause [opt] |
26818 | |
26819 | class-virt-specifier: |
26820 | final |
26821 | |
26822 | GNU Extensions: |
26823 | class-key attributes identifier [opt] base-clause [opt] |
26824 | class-key attributes nested-name-specifier identifier base-clause [opt] |
26825 | class-key attributes nested-name-specifier [opt] template-id |
26826 | base-clause [opt] |
26827 | |
26828 | Upon return BASES is initialized to the list of base classes (or |
26829 | NULL, if there are none) in the same form returned by |
26830 | cp_parser_base_clause. |
26831 | |
26832 | Returns the TYPE of the indicated class. Sets |
26833 | *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions |
26834 | involving a nested-name-specifier was used, and FALSE otherwise. |
26835 | |
26836 | Returns error_mark_node if this is not a class-head. |
26837 | |
26838 | Returns NULL_TREE if the class-head is syntactically valid, but |
26839 | semantically invalid in a way that means we should skip the entire |
26840 | body of the class. */ |
26841 | |
26842 | static tree |
26843 | cp_parser_class_head (cp_parser* parser, |
26844 | bool* nested_name_specifier_p) |
26845 | { |
26846 | tree nested_name_specifier; |
26847 | enum tag_types class_key; |
26848 | tree id = NULL_TREE; |
26849 | tree type = NULL_TREE; |
26850 | tree attributes; |
26851 | tree bases; |
26852 | cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; |
26853 | bool template_id_p = false; |
26854 | bool qualified_p = false; |
26855 | bool invalid_nested_name_p = false; |
26856 | bool invalid_explicit_specialization_p = false; |
26857 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
26858 | tree pushed_scope = NULL_TREE; |
26859 | unsigned num_templates; |
26860 | cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL; |
26861 | /* Assume no nested-name-specifier will be present. */ |
26862 | *nested_name_specifier_p = false; |
26863 | /* Assume no template parameter lists will be used in defining the |
26864 | type. */ |
26865 | num_templates = 0; |
26866 | parser->colon_corrects_to_scope_p = false; |
26867 | |
26868 | /* Look for the class-key. */ |
26869 | class_key = cp_parser_class_key (parser); |
26870 | if (class_key == none_type) |
26871 | return error_mark_node; |
26872 | |
26873 | location_t class_head_start_location = input_location; |
26874 | |
26875 | /* Parse the attributes. */ |
26876 | attributes = cp_parser_attributes_opt (parser); |
26877 | if (find_contract (attrs: attributes)) |
26878 | diagnose_misapplied_contracts (attributes); |
26879 | |
26880 | /* If the next token is `::', that is invalid -- but sometimes |
26881 | people do try to write: |
26882 | |
26883 | struct ::S {}; |
26884 | |
26885 | Handle this gracefully by accepting the extra qualifier, and then |
26886 | issuing an error about it later if this really is a |
26887 | class-head. If it turns out just to be an elaborated type |
26888 | specifier, remain silent. */ |
26889 | if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)) |
26890 | qualified_p = true; |
26891 | |
26892 | /* It is OK to define an inaccessible class; for example: |
26893 | |
26894 | class A { class B; }; |
26895 | class A::B {}; |
26896 | |
26897 | So we want to ignore access when parsing the class name. |
26898 | However, we might be tentatively parsing what is really an |
26899 | elaborated-type-specifier naming a template-id, e.g. |
26900 | |
26901 | struct C<&D::m> c; |
26902 | |
26903 | In this case the tentative parse as a class-head will fail, but not |
26904 | before cp_parser_template_id splices in a CPP_TEMPLATE_ID token. |
26905 | Since dk_no_check is sticky, we must instead use dk_deferred so that |
26906 | any such CPP_TEMPLATE_ID token created during this tentative parse |
26907 | will correctly capture the access checks imposed by the template-id . */ |
26908 | push_deferring_access_checks (dk_deferred); |
26909 | |
26910 | /* Determine the name of the class. Begin by looking for an |
26911 | optional nested-name-specifier. */ |
26912 | nested_name_specifier_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
26913 | nested_name_specifier |
26914 | = cp_parser_nested_name_specifier_opt (parser, |
26915 | /*typename_keyword_p=*/false, |
26916 | /*check_dependency_p=*/false, |
26917 | /*type_p=*/true, |
26918 | /*is_declaration=*/false); |
26919 | /* If there was a nested-name-specifier, then there *must* be an |
26920 | identifier. */ |
26921 | |
26922 | cp_token *bad_template_keyword = NULL; |
26923 | |
26924 | if (nested_name_specifier) |
26925 | { |
26926 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
26927 | /* Although the grammar says `identifier', it really means |
26928 | `class-name' or `template-name'. You are only allowed to |
26929 | define a class that has already been declared with this |
26930 | syntax. |
26931 | |
26932 | The proposed resolution for Core Issue 180 says that wherever |
26933 | you see `class T::X' you should treat `X' as a type-name. |
26934 | |
26935 | We do not know if we will see a class-name, or a |
26936 | template-name. We look for a class-name first, in case the |
26937 | class-name is a template-id; if we looked for the |
26938 | template-name first we would stop after the template-name. */ |
26939 | cp_parser_parse_tentatively (parser); |
26940 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
26941 | bad_template_keyword = cp_lexer_consume_token (lexer: parser->lexer); |
26942 | type = cp_parser_class_name (parser, |
26943 | /*typename_keyword_p=*/false, |
26944 | /*template_keyword_p=*/false, |
26945 | tag_type: class_type, |
26946 | /*check_dependency_p=*/false, |
26947 | /*class_head_p=*/true, |
26948 | /*is_declaration=*/false); |
26949 | /* If that didn't work, ignore the nested-name-specifier. */ |
26950 | if (!cp_parser_parse_definitely (parser)) |
26951 | { |
26952 | invalid_nested_name_p = true; |
26953 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
26954 | id = cp_parser_identifier (parser); |
26955 | if (id == error_mark_node) |
26956 | id = NULL_TREE; |
26957 | } |
26958 | /* If we could not find a corresponding TYPE, treat this |
26959 | declaration like an unqualified declaration. */ |
26960 | if (type == error_mark_node) |
26961 | nested_name_specifier = NULL_TREE; |
26962 | /* Otherwise, count the number of templates used in TYPE and its |
26963 | containing scopes. */ |
26964 | else |
26965 | num_templates = num_template_headers_for_class (TREE_TYPE (type)); |
26966 | } |
26967 | /* Otherwise, the identifier is optional. */ |
26968 | else |
26969 | { |
26970 | /* We don't know whether what comes next is a template-id, |
26971 | an identifier, or nothing at all. */ |
26972 | cp_parser_parse_tentatively (parser); |
26973 | /* Check for a template-id. */ |
26974 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
26975 | id = cp_parser_template_id (parser, |
26976 | /*template_keyword_p=*/false, |
26977 | /*check_dependency_p=*/true, |
26978 | tag_type: class_key, |
26979 | /*is_declaration=*/true); |
26980 | /* If that didn't work, it could still be an identifier. */ |
26981 | if (!cp_parser_parse_definitely (parser)) |
26982 | { |
26983 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
26984 | { |
26985 | type_start_token = cp_lexer_peek_token (lexer: parser->lexer); |
26986 | id = cp_parser_identifier (parser); |
26987 | } |
26988 | else |
26989 | id = NULL_TREE; |
26990 | } |
26991 | else |
26992 | { |
26993 | template_id_p = true; |
26994 | ++num_templates; |
26995 | } |
26996 | } |
26997 | |
26998 | pop_deferring_access_checks (); |
26999 | |
27000 | if (id) |
27001 | { |
27002 | cp_parser_check_for_invalid_template_id (parser, type: id, |
27003 | tag_type: class_key, |
27004 | location: type_start_token->location); |
27005 | } |
27006 | virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); |
27007 | |
27008 | /* If it's not a `:' or a `{' then we can't really be looking at a |
27009 | class-head, since a class-head only appears as part of a |
27010 | class-specifier. We have to detect this situation before calling |
27011 | xref_tag, since that has irreversible side-effects. */ |
27012 | if (!cp_parser_next_token_starts_class_definition_p (parser)) |
27013 | { |
27014 | cp_parser_error (parser, gmsgid: "expected %<{%> or %<:%>" ); |
27015 | type = error_mark_node; |
27016 | goto out; |
27017 | } |
27018 | |
27019 | /* At this point, we're going ahead with the class-specifier, even |
27020 | if some other problem occurs. */ |
27021 | cp_parser_commit_to_tentative_parse (parser); |
27022 | if (virt_specifiers & VIRT_SPEC_OVERRIDE) |
27023 | { |
27024 | cp_parser_error (parser, |
27025 | gmsgid: "cannot specify %<override%> for a class" ); |
27026 | type = error_mark_node; |
27027 | goto out; |
27028 | } |
27029 | /* Issue the error about the overly-qualified name now. */ |
27030 | if (qualified_p) |
27031 | { |
27032 | cp_parser_error (parser, |
27033 | gmsgid: "global qualification of class name is invalid" ); |
27034 | type = error_mark_node; |
27035 | goto out; |
27036 | } |
27037 | else if (invalid_nested_name_p) |
27038 | { |
27039 | cp_parser_error (parser, |
27040 | gmsgid: "qualified name does not name a class" ); |
27041 | type = error_mark_node; |
27042 | goto out; |
27043 | } |
27044 | else if (nested_name_specifier) |
27045 | { |
27046 | tree scope; |
27047 | |
27048 | if (bad_template_keyword) |
27049 | /* [temp.names]: in a qualified-id formed by a class-head-name, the |
27050 | keyword template shall not appear at the top level. */ |
27051 | pedwarn (bad_template_keyword->location, OPT_Wpedantic, |
27052 | "keyword %<template%> not allowed in class-head-name" ); |
27053 | |
27054 | /* Reject typedef-names in class heads. */ |
27055 | if (!DECL_IMPLICIT_TYPEDEF_P (type)) |
27056 | { |
27057 | error_at (type_start_token->location, |
27058 | "invalid class name in declaration of %qD" , |
27059 | type); |
27060 | type = NULL_TREE; |
27061 | goto done; |
27062 | } |
27063 | |
27064 | /* Figure out in what scope the declaration is being placed. */ |
27065 | scope = current_scope (); |
27066 | /* If that scope does not contain the scope in which the |
27067 | class was originally declared, the program is invalid. */ |
27068 | if (scope && !is_ancestor (ancestor: scope, descendant: nested_name_specifier)) |
27069 | { |
27070 | if (at_namespace_scope_p ()) |
27071 | error_at (type_start_token->location, |
27072 | "declaration of %qD in namespace %qD which does not " |
27073 | "enclose %qD" , |
27074 | type, scope, nested_name_specifier); |
27075 | else |
27076 | error_at (type_start_token->location, |
27077 | "declaration of %qD in %qD which does not enclose %qD" , |
27078 | type, scope, nested_name_specifier); |
27079 | type = NULL_TREE; |
27080 | goto done; |
27081 | } |
27082 | /* [dcl.meaning] |
27083 | |
27084 | A declarator-id shall not be qualified except for the |
27085 | definition of a ... nested class outside of its class |
27086 | ... [or] the definition or explicit instantiation of a |
27087 | class member of a namespace outside of its namespace. */ |
27088 | if (scope == nested_name_specifier) |
27089 | permerror (nested_name_specifier_token_start->location, |
27090 | "extra qualification not allowed" ); |
27091 | } |
27092 | /* An explicit-specialization must be preceded by "template <>". If |
27093 | it is not, try to recover gracefully. */ |
27094 | if (at_namespace_scope_p () |
27095 | && parser->num_template_parameter_lists == 0 |
27096 | && !processing_template_parmlist |
27097 | && template_id_p) |
27098 | { |
27099 | /* Build a location of this form: |
27100 | struct typename <ARGS> |
27101 | ^~~~~~~~~~~~~~~~~~~~~~ |
27102 | with caret==start at the start token, and |
27103 | finishing at the end of the type. */ |
27104 | location_t reported_loc |
27105 | = make_location (caret: class_head_start_location, |
27106 | start: class_head_start_location, |
27107 | finish: get_finish (loc: type_start_token->location)); |
27108 | rich_location richloc (line_table, reported_loc); |
27109 | richloc.add_fixit_insert_before (where: class_head_start_location, |
27110 | new_content: "template <> " ); |
27111 | error_at (&richloc, |
27112 | "an explicit specialization must be preceded by" |
27113 | " %<template <>%>" ); |
27114 | invalid_explicit_specialization_p = true; |
27115 | /* Take the same action that would have been taken by |
27116 | cp_parser_explicit_specialization. */ |
27117 | ++parser->num_template_parameter_lists; |
27118 | begin_specialization (); |
27119 | } |
27120 | /* There must be no "return" statements between this point and the |
27121 | end of this function; set "type "to the correct return value and |
27122 | use "goto done;" to return. */ |
27123 | /* Make sure that the right number of template parameters were |
27124 | present. */ |
27125 | if (!cp_parser_check_template_parameters (parser, num_templates, |
27126 | template_id_p, |
27127 | type_start_token->location, |
27128 | /*declarator=*/NULL)) |
27129 | { |
27130 | /* If something went wrong, there is no point in even trying to |
27131 | process the class-definition. */ |
27132 | type = NULL_TREE; |
27133 | goto done; |
27134 | } |
27135 | |
27136 | /* Look up the type. */ |
27137 | if (template_id_p) |
27138 | { |
27139 | if (TREE_CODE (id) == TEMPLATE_ID_EXPR |
27140 | && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0)) |
27141 | || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD)) |
27142 | { |
27143 | error_at (type_start_token->location, |
27144 | "function template %qD redeclared as a class template" , id); |
27145 | type = error_mark_node; |
27146 | } |
27147 | else |
27148 | { |
27149 | type = TREE_TYPE (id); |
27150 | type = maybe_process_partial_specialization (type); |
27151 | |
27152 | /* Check the scope while we still know whether or not we had a |
27153 | nested-name-specifier. */ |
27154 | if (type != error_mark_node) |
27155 | check_unqualified_spec_or_inst (type, type_start_token->location); |
27156 | } |
27157 | if (nested_name_specifier) |
27158 | pushed_scope = push_scope (nested_name_specifier); |
27159 | } |
27160 | else if (nested_name_specifier) |
27161 | { |
27162 | type = TREE_TYPE (type); |
27163 | |
27164 | /* Given: |
27165 | |
27166 | template <typename T> struct S { struct T }; |
27167 | template <typename T> struct S<T>::T { }; |
27168 | |
27169 | we will get a TYPENAME_TYPE when processing the definition of |
27170 | `S::T'. We need to resolve it to the actual type before we |
27171 | try to define it. */ |
27172 | if (TREE_CODE (type) == TYPENAME_TYPE) |
27173 | { |
27174 | type = resolve_typename_type (type, /*only_current_p=*/false); |
27175 | if (TREE_CODE (type) == TYPENAME_TYPE) |
27176 | { |
27177 | cp_parser_error (parser, gmsgid: "could not resolve typename type" ); |
27178 | type = error_mark_node; |
27179 | } |
27180 | } |
27181 | |
27182 | type = maybe_process_partial_specialization (type); |
27183 | if (type == error_mark_node) |
27184 | { |
27185 | type = NULL_TREE; |
27186 | goto done; |
27187 | } |
27188 | |
27189 | /* Enter the scope indicated by the nested-name-specifier. */ |
27190 | pushed_scope = push_scope (nested_name_specifier); |
27191 | /* Get the canonical version of this type. */ |
27192 | type = TYPE_MAIN_DECL (type); |
27193 | /* Call push_template_decl if it seems like we should be defining a |
27194 | template either from the template headers or the type we're |
27195 | defining, so that we diagnose both extra and missing headers. */ |
27196 | if ((PROCESSING_REAL_TEMPLATE_DECL_P () |
27197 | || CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (type))) |
27198 | && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (type))) |
27199 | { |
27200 | type = push_template_decl (type); |
27201 | if (type == error_mark_node) |
27202 | { |
27203 | type = NULL_TREE; |
27204 | goto done; |
27205 | } |
27206 | } |
27207 | |
27208 | type = TREE_TYPE (type); |
27209 | *nested_name_specifier_p = true; |
27210 | } |
27211 | else /* The name is not a nested name. */ |
27212 | { |
27213 | /* If the class was unnamed, create a dummy name. */ |
27214 | if (!id) |
27215 | id = make_anon_name (); |
27216 | TAG_how how = (parser->in_type_id_in_expr_p |
27217 | ? TAG_how::INNERMOST_NON_CLASS |
27218 | : TAG_how::CURRENT_ONLY); |
27219 | type = xref_tag (class_key, id, how, |
27220 | tpl_header_p: parser->num_template_parameter_lists); |
27221 | } |
27222 | |
27223 | /* Diagnose class/struct/union mismatches. */ |
27224 | cp_parser_check_class_key (parser, UNKNOWN_LOCATION, class_key, type, |
27225 | true, true); |
27226 | |
27227 | /* Indicate whether this class was declared as a `class' or as a |
27228 | `struct'. */ |
27229 | if (TREE_CODE (type) == RECORD_TYPE) |
27230 | CLASSTYPE_DECLARED_CLASS (type) = class_key == class_type; |
27231 | |
27232 | /* If this type was already complete, and we see another definition, |
27233 | that's an error. Likewise if the type is already being defined: |
27234 | this can happen, eg, when it's defined from within an expression |
27235 | (c++/84605). */ |
27236 | if (type != error_mark_node |
27237 | && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type))) |
27238 | { |
27239 | error_at (type_start_token->location, "redefinition of %q#T" , |
27240 | type); |
27241 | inform (location_of (type), "previous definition of %q#T" , |
27242 | type); |
27243 | type = NULL_TREE; |
27244 | goto done; |
27245 | } |
27246 | else if (type == error_mark_node) |
27247 | type = NULL_TREE; |
27248 | |
27249 | if (type) |
27250 | { |
27251 | if (current_lambda_expr () |
27252 | && uses_parameter_packs (attributes)) |
27253 | { |
27254 | /* In a lambda this should work, but doesn't currently. */ |
27255 | sorry ("unexpanded parameter pack in local class in lambda" ); |
27256 | attributes = NULL_TREE; |
27257 | } |
27258 | |
27259 | /* Apply attributes now, before any use of the class as a template |
27260 | argument in its base list. */ |
27261 | cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); |
27262 | fixup_attribute_variants (type); |
27263 | } |
27264 | |
27265 | /* Associate constraints with the type. */ |
27266 | if (flag_concepts) |
27267 | type = associate_classtype_constraints (type); |
27268 | |
27269 | /* We will have entered the scope containing the class; the names of |
27270 | base classes should be looked up in that context. For example: |
27271 | |
27272 | struct A { struct B {}; struct C; }; |
27273 | struct A::C : B {}; |
27274 | |
27275 | is valid. */ |
27276 | |
27277 | /* Get the list of base-classes, if there is one. Defer access checking |
27278 | until the entire list has been seen, as per [class.access.general]. */ |
27279 | push_deferring_access_checks (dk_deferred); |
27280 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
27281 | { |
27282 | if (type) |
27283 | pushclass (type); |
27284 | bases = cp_parser_base_clause (parser); |
27285 | if (type) |
27286 | popclass (); |
27287 | } |
27288 | else |
27289 | bases = NULL_TREE; |
27290 | |
27291 | /* If we're really defining a class, process the base classes. |
27292 | If they're invalid, fail. */ |
27293 | if (type && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
27294 | xref_basetypes (type, bases); |
27295 | |
27296 | /* Now that all bases have been seen and attached to the class, check |
27297 | accessibility of the types named in the base-clause. This must be |
27298 | done relative to the class scope, so that we accept e.g. |
27299 | |
27300 | struct A { protected: struct B {}; }; |
27301 | struct C : A::B, A {}; // OK: A::B is accessible via base A |
27302 | |
27303 | as per [class.access.general]. */ |
27304 | if (type) |
27305 | pushclass (type); |
27306 | pop_to_parent_deferring_access_checks (); |
27307 | if (type) |
27308 | popclass (); |
27309 | |
27310 | done: |
27311 | /* Leave the scope given by the nested-name-specifier. We will |
27312 | enter the class scope itself while processing the members. */ |
27313 | if (pushed_scope) |
27314 | pop_scope (pushed_scope); |
27315 | |
27316 | if (invalid_explicit_specialization_p) |
27317 | { |
27318 | end_specialization (); |
27319 | --parser->num_template_parameter_lists; |
27320 | } |
27321 | |
27322 | if (type) |
27323 | DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; |
27324 | if (type && (virt_specifiers & VIRT_SPEC_FINAL)) |
27325 | CLASSTYPE_FINAL (type) = 1; |
27326 | out: |
27327 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
27328 | return type; |
27329 | } |
27330 | |
27331 | /* Parse a class-key. |
27332 | |
27333 | class-key: |
27334 | class |
27335 | struct |
27336 | union |
27337 | |
27338 | Returns the kind of class-key specified, or none_type to indicate |
27339 | error. */ |
27340 | |
27341 | static enum tag_types |
27342 | cp_parser_class_key (cp_parser* parser) |
27343 | { |
27344 | cp_token *token; |
27345 | enum tag_types tag_type; |
27346 | |
27347 | /* Look for the class-key. */ |
27348 | token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_KEY); |
27349 | if (!token) |
27350 | return none_type; |
27351 | |
27352 | /* Check to see if the TOKEN is a class-key. */ |
27353 | tag_type = cp_parser_token_is_class_key (token); |
27354 | if (!tag_type) |
27355 | cp_parser_error (parser, gmsgid: "expected class-key" ); |
27356 | return tag_type; |
27357 | } |
27358 | |
27359 | /* Parse a type-parameter-key. |
27360 | |
27361 | type-parameter-key: |
27362 | class |
27363 | typename |
27364 | */ |
27365 | |
27366 | static void |
27367 | cp_parser_type_parameter_key (cp_parser* parser) |
27368 | { |
27369 | /* Look for the type-parameter-key. */ |
27370 | enum tag_types tag_type = none_type; |
27371 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
27372 | if ((tag_type = cp_parser_token_is_type_parameter_key (token)) != none_type) |
27373 | { |
27374 | cp_lexer_consume_token (lexer: parser->lexer); |
27375 | if (pedantic && tag_type == typename_type |
27376 | && cxx_dialect < cxx17) |
27377 | /* typename is not allowed in a template template parameter |
27378 | by the standard until C++17. */ |
27379 | pedwarn (token->location, OPT_Wc__17_extensions, |
27380 | "ISO C++ forbids typename key in template template parameter;" |
27381 | " use %<-std=c++17%> or %<-std=gnu++17%>" ); |
27382 | } |
27383 | else |
27384 | cp_parser_error (parser, gmsgid: "expected %<class%> or %<typename%>" ); |
27385 | |
27386 | return; |
27387 | } |
27388 | |
27389 | /* Parse an (optional) member-specification. |
27390 | |
27391 | member-specification: |
27392 | member-declaration member-specification [opt] |
27393 | access-specifier : member-specification [opt] */ |
27394 | |
27395 | static void |
27396 | cp_parser_member_specification_opt (cp_parser* parser) |
27397 | { |
27398 | while (true) |
27399 | { |
27400 | cp_token *token; |
27401 | enum rid keyword; |
27402 | |
27403 | /* Peek at the next token. */ |
27404 | token = cp_lexer_peek_token (lexer: parser->lexer); |
27405 | /* If it's a `}', or EOF then we've seen all the members. */ |
27406 | if (token->type == CPP_CLOSE_BRACE |
27407 | || token->type == CPP_EOF |
27408 | || token->type == CPP_PRAGMA_EOL) |
27409 | break; |
27410 | |
27411 | /* See if this token is a keyword. */ |
27412 | keyword = token->keyword; |
27413 | switch (keyword) |
27414 | { |
27415 | case RID_PUBLIC: |
27416 | case RID_PROTECTED: |
27417 | case RID_PRIVATE: |
27418 | /* Consume the access-specifier. */ |
27419 | cp_lexer_consume_token (lexer: parser->lexer); |
27420 | /* Remember which access-specifier is active. */ |
27421 | current_access_specifier = token->u.value; |
27422 | /* Look for the `:'. */ |
27423 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
27424 | break; |
27425 | |
27426 | default: |
27427 | /* Accept #pragmas at class scope. */ |
27428 | if (token->type == CPP_PRAGMA) |
27429 | { |
27430 | cp_parser_pragma (parser, pragma_member, NULL); |
27431 | break; |
27432 | } |
27433 | |
27434 | /* Otherwise, the next construction must be a |
27435 | member-declaration. */ |
27436 | cp_parser_member_declaration (parser); |
27437 | } |
27438 | } |
27439 | } |
27440 | |
27441 | /* Parse a member-declaration. |
27442 | |
27443 | member-declaration: |
27444 | decl-specifier-seq [opt] member-declarator-list [opt] ; |
27445 | function-definition ; [opt] |
27446 | :: [opt] nested-name-specifier template [opt] unqualified-id ; |
27447 | using-declaration |
27448 | template-declaration |
27449 | alias-declaration |
27450 | |
27451 | member-declarator-list: |
27452 | member-declarator |
27453 | member-declarator-list , member-declarator |
27454 | |
27455 | member-declarator: |
27456 | declarator pure-specifier [opt] |
27457 | declarator constant-initializer [opt] |
27458 | identifier [opt] : constant-expression |
27459 | |
27460 | GNU Extensions: |
27461 | |
27462 | member-declaration: |
27463 | __extension__ member-declaration |
27464 | |
27465 | member-declarator: |
27466 | declarator attributes [opt] pure-specifier [opt] |
27467 | declarator attributes [opt] constant-initializer [opt] |
27468 | identifier [opt] attributes [opt] : constant-expression |
27469 | |
27470 | C++0x Extensions: |
27471 | |
27472 | member-declaration: |
27473 | static_assert-declaration */ |
27474 | |
27475 | static void |
27476 | cp_parser_member_declaration (cp_parser* parser) |
27477 | { |
27478 | cp_decl_specifier_seq decl_specifiers; |
27479 | tree prefix_attributes; |
27480 | tree decl; |
27481 | int declares_class_or_enum; |
27482 | bool friend_p; |
27483 | cp_token *token = NULL; |
27484 | cp_token *decl_spec_token_start = NULL; |
27485 | cp_token *initializer_token_start = NULL; |
27486 | int saved_pedantic; |
27487 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
27488 | |
27489 | /* Check for the `__extension__' keyword. */ |
27490 | if (cp_parser_extension_opt (parser, &saved_pedantic)) |
27491 | { |
27492 | /* Recurse. */ |
27493 | cp_parser_member_declaration (parser); |
27494 | /* Restore the old value of the PEDANTIC flag. */ |
27495 | pedantic = saved_pedantic; |
27496 | |
27497 | return; |
27498 | } |
27499 | |
27500 | /* Check for a template-declaration. */ |
27501 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
27502 | { |
27503 | /* An explicit specialization here is an error condition, and we |
27504 | expect the specialization handler to detect and report this. */ |
27505 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_LESS |
27506 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type == CPP_GREATER) |
27507 | cp_parser_explicit_specialization (parser); |
27508 | else |
27509 | cp_parser_template_declaration (parser, /*member_p=*/true); |
27510 | |
27511 | return; |
27512 | } |
27513 | /* Check for a template introduction. */ |
27514 | else if (cp_parser_template_declaration_after_export (parser, true)) |
27515 | return; |
27516 | |
27517 | /* Check for a using-declaration. */ |
27518 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
27519 | { |
27520 | if (cxx_dialect < cxx11) |
27521 | /* Parse the using-declaration. */ |
27522 | cp_parser_using_declaration (parser, /*access_declaration_p=*/false); |
27523 | else if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_ENUM)) |
27524 | cp_parser_using_enum (parser); |
27525 | else |
27526 | { |
27527 | tree decl; |
27528 | bool alias_decl_expected; |
27529 | cp_parser_parse_tentatively (parser); |
27530 | decl = cp_parser_alias_declaration (parser); |
27531 | /* Note that if we actually see the '=' token after the |
27532 | identifier, cp_parser_alias_declaration commits the |
27533 | tentative parse. In that case, we really expect an |
27534 | alias-declaration. Otherwise, we expect a using |
27535 | declaration. */ |
27536 | alias_decl_expected = |
27537 | !cp_parser_uncommitted_to_tentative_parse_p (parser); |
27538 | cp_parser_parse_definitely (parser); |
27539 | |
27540 | if (alias_decl_expected) |
27541 | finish_member_declaration (decl); |
27542 | else |
27543 | cp_parser_using_declaration (parser, |
27544 | /*access_declaration_p=*/false); |
27545 | } |
27546 | return; |
27547 | } |
27548 | |
27549 | /* Check for @defs. */ |
27550 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_DEFS)) |
27551 | { |
27552 | tree ivar, member; |
27553 | tree ivar_chains = cp_parser_objc_defs_expression (parser); |
27554 | ivar = ivar_chains; |
27555 | while (ivar) |
27556 | { |
27557 | member = ivar; |
27558 | ivar = TREE_CHAIN (member); |
27559 | TREE_CHAIN (member) = NULL_TREE; |
27560 | finish_member_declaration (member); |
27561 | } |
27562 | return; |
27563 | } |
27564 | |
27565 | /* If the next token is `static_assert' we have a static assertion. */ |
27566 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC_ASSERT)) |
27567 | { |
27568 | cp_parser_static_assert (parser, /*member_p=*/true); |
27569 | return; |
27570 | } |
27571 | |
27572 | parser->colon_corrects_to_scope_p = false; |
27573 | |
27574 | cp_omp_declare_simd_data odsd; |
27575 | if (cp_parser_using_declaration (parser, /*access_declaration=*/access_declaration_p: true)) |
27576 | goto out; |
27577 | |
27578 | /* Parse the decl-specifier-seq. */ |
27579 | decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
27580 | cp_parser_decl_specifier_seq (parser, |
27581 | flags: (CP_PARSER_FLAGS_OPTIONAL |
27582 | | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), |
27583 | decl_specs: &decl_specifiers, |
27584 | declares_class_or_enum: &declares_class_or_enum); |
27585 | |
27586 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
27587 | cp_parser_handle_directive_omp_attributes (parser, |
27588 | pattrs: &decl_specifiers.attributes, |
27589 | data: &odsd, start: true); |
27590 | |
27591 | /* Check for an invalid type-name. */ |
27592 | if (!decl_specifiers.any_type_specifiers_p |
27593 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
27594 | goto out; |
27595 | /* If there is no declarator, then the decl-specifier-seq should |
27596 | specify a type. */ |
27597 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
27598 | { |
27599 | /* If there was no decl-specifier-seq, and the next token is a |
27600 | `;', then we have something like: |
27601 | |
27602 | struct S { ; }; |
27603 | |
27604 | [class.mem] |
27605 | |
27606 | Each member-declaration shall declare at least one member |
27607 | name of the class. */ |
27608 | if (!decl_specifiers.any_specifiers_p) |
27609 | { |
27610 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
27611 | if (!in_system_header_at (loc: token->location)) |
27612 | { |
27613 | gcc_rich_location richloc (token->location); |
27614 | richloc.add_fixit_remove (); |
27615 | pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>" ); |
27616 | } |
27617 | } |
27618 | else |
27619 | { |
27620 | /* See if this declaration is a friend. */ |
27621 | friend_p = cp_parser_friend_p (&decl_specifiers); |
27622 | /* If there were decl-specifiers, check to see if there was |
27623 | a class-declaration. */ |
27624 | tree type = check_tag_decl (&decl_specifiers, |
27625 | /*explicit_type_instantiation_p=*/false); |
27626 | /* Nested classes have already been added to the class, but |
27627 | a `friend' needs to be explicitly registered. */ |
27628 | if (friend_p) |
27629 | { |
27630 | /* If the `friend' keyword was present, the friend must |
27631 | be introduced with a class-key. */ |
27632 | if (!declares_class_or_enum && cxx_dialect < cxx11) |
27633 | pedwarn (decl_spec_token_start->location, OPT_Wpedantic, |
27634 | "in C++03 a class-key must be used " |
27635 | "when declaring a friend" ); |
27636 | /* In this case: |
27637 | |
27638 | template <typename T> struct A { |
27639 | friend struct A<T>::B; |
27640 | }; |
27641 | |
27642 | A<T>::B will be represented by a TYPENAME_TYPE, and |
27643 | therefore not recognized by check_tag_decl. */ |
27644 | if (!type) |
27645 | { |
27646 | type = decl_specifiers.type; |
27647 | if (type && TREE_CODE (type) == TYPE_DECL) |
27648 | type = TREE_TYPE (type); |
27649 | } |
27650 | /* Warn if an attribute cannot appear here, as per |
27651 | [dcl.attr.grammar]/5. But not when declares_class_or_enum: |
27652 | we ignore attributes in elaborated-type-specifiers. */ |
27653 | if (!declares_class_or_enum |
27654 | && cxx11_attribute_p (decl_specifiers.attributes)) |
27655 | { |
27656 | decl_specifiers.attributes = NULL_TREE; |
27657 | if (warning_at (decl_spec_token_start->location, |
27658 | OPT_Wattributes, "attribute ignored" )) |
27659 | inform (decl_spec_token_start->location, "an attribute " |
27660 | "that appertains to a friend declaration that " |
27661 | "is not a definition is ignored" ); |
27662 | } |
27663 | if (!type || !TYPE_P (type)) |
27664 | error_at (decl_spec_token_start->location, |
27665 | "friend declaration does not name a class or " |
27666 | "function" ); |
27667 | else |
27668 | make_friend_class (current_class_type, type, |
27669 | /*complain=*/true); |
27670 | } |
27671 | /* If there is no TYPE, an error message will already have |
27672 | been issued. */ |
27673 | else if (!type || type == error_mark_node) |
27674 | ; |
27675 | /* An anonymous aggregate has to be handled specially; such |
27676 | a declaration really declares a data member (with a |
27677 | particular type), as opposed to a nested class. */ |
27678 | else if (ANON_AGGR_TYPE_P (type)) |
27679 | { |
27680 | /* C++11 9.5/6. */ |
27681 | if (decl_specifiers.storage_class != sc_none) |
27682 | error_at (decl_spec_token_start->location, |
27683 | "a storage class on an anonymous aggregate " |
27684 | "in class scope is not allowed" ); |
27685 | |
27686 | /* Remove constructors and such from TYPE, now that we |
27687 | know it is an anonymous aggregate. */ |
27688 | fixup_anonymous_aggr (type); |
27689 | /* And make the corresponding data member. */ |
27690 | decl = build_decl (decl_spec_token_start->location, |
27691 | FIELD_DECL, NULL_TREE, type); |
27692 | /* Add it to the class. */ |
27693 | finish_member_declaration (decl); |
27694 | } |
27695 | else |
27696 | cp_parser_check_access_in_redeclaration |
27697 | (TYPE_NAME (type), |
27698 | location: decl_spec_token_start->location); |
27699 | } |
27700 | } |
27701 | else |
27702 | { |
27703 | bool assume_semicolon = false; |
27704 | |
27705 | /* Clear attributes from the decl_specifiers but keep them |
27706 | around as prefix attributes that apply them to the entity |
27707 | being declared. */ |
27708 | prefix_attributes = decl_specifiers.attributes; |
27709 | decl_specifiers.attributes = NULL_TREE; |
27710 | if (parser->omp_declare_simd |
27711 | && (parser->omp_declare_simd->attribs[0] |
27712 | == &decl_specifiers.attributes)) |
27713 | parser->omp_declare_simd->attribs[0] = &prefix_attributes; |
27714 | |
27715 | /* See if these declarations will be friends. */ |
27716 | friend_p = cp_parser_friend_p (&decl_specifiers); |
27717 | |
27718 | /* Keep going until we hit the `;' at the end of the |
27719 | declaration. */ |
27720 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
27721 | { |
27722 | tree attributes = NULL_TREE; |
27723 | tree first_attribute; |
27724 | tree initializer; |
27725 | bool named_bitfld = false; |
27726 | |
27727 | /* Peek at the next token. */ |
27728 | token = cp_lexer_peek_token (lexer: parser->lexer); |
27729 | |
27730 | /* The following code wants to know early if it is a bit-field |
27731 | or some other declaration. Attributes can appear before |
27732 | the `:' token. Skip over them without consuming any tokens |
27733 | to peek if they are followed by `:'. */ |
27734 | if (cp_next_tokens_can_be_attribute_p (parser) |
27735 | || (token->type == CPP_NAME |
27736 | && cp_nth_tokens_can_be_attribute_p (parser, 2) |
27737 | && (named_bitfld = true))) |
27738 | { |
27739 | size_t n |
27740 | = cp_parser_skip_attributes_opt (parser, 1 + named_bitfld); |
27741 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
27742 | } |
27743 | |
27744 | /* Check for a bitfield declaration. */ |
27745 | if (token->type == CPP_COLON |
27746 | || (token->type == CPP_NAME |
27747 | && token == cp_lexer_peek_token (lexer: parser->lexer) |
27748 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON) |
27749 | && (named_bitfld = true))) |
27750 | { |
27751 | tree identifier; |
27752 | tree width; |
27753 | tree late_attributes = NULL_TREE; |
27754 | location_t id_location |
27755 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
27756 | |
27757 | if (named_bitfld) |
27758 | identifier = cp_parser_identifier (parser); |
27759 | else |
27760 | identifier = NULL_TREE; |
27761 | |
27762 | /* Look for attributes that apply to the bitfield. */ |
27763 | attributes = cp_parser_attributes_opt (parser); |
27764 | |
27765 | /* Consume the `:' token. */ |
27766 | cp_lexer_consume_token (lexer: parser->lexer); |
27767 | |
27768 | /* Get the width of the bitfield. */ |
27769 | width = cp_parser_constant_expression (parser, allow_non_constant_p: false, NULL, |
27770 | strict_p: cxx_dialect >= cxx11); |
27771 | |
27772 | /* In C++20 and as extension for C++11 and above we allow |
27773 | default member initializers for bit-fields. */ |
27774 | initializer = NULL_TREE; |
27775 | if (cxx_dialect >= cxx11 |
27776 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ) |
27777 | || cp_lexer_next_token_is (lexer: parser->lexer, |
27778 | type: CPP_OPEN_BRACE))) |
27779 | { |
27780 | location_t loc |
27781 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
27782 | if (cxx_dialect < cxx20 |
27783 | && identifier != NULL_TREE) |
27784 | pedwarn (loc, OPT_Wc__20_extensions, |
27785 | "default member initializers for bit-fields " |
27786 | "only available with %<-std=c++20%> or " |
27787 | "%<-std=gnu++20%>" ); |
27788 | |
27789 | initializer = cp_parser_save_nsdmi (parser); |
27790 | if (identifier == NULL_TREE) |
27791 | { |
27792 | error_at (loc, "default member initializer for " |
27793 | "unnamed bit-field" ); |
27794 | initializer = NULL_TREE; |
27795 | } |
27796 | } |
27797 | else |
27798 | { |
27799 | /* Look for attributes that apply to the bitfield after |
27800 | the `:' token and width. This is where GCC used to |
27801 | parse attributes in the past, pedwarn if there is |
27802 | a std attribute. */ |
27803 | if (cp_next_tokens_can_be_std_attribute_p (parser)) |
27804 | pedwarn (input_location, OPT_Wpedantic, |
27805 | "ISO C++ allows bit-field attributes only " |
27806 | "before the %<:%> token" ); |
27807 | |
27808 | late_attributes = cp_parser_attributes_opt (parser); |
27809 | } |
27810 | |
27811 | attributes = attr_chainon (attrs: attributes, attr: late_attributes); |
27812 | |
27813 | /* Remember which attributes are prefix attributes and |
27814 | which are not. */ |
27815 | first_attribute = attributes; |
27816 | /* Combine the attributes. */ |
27817 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
27818 | |
27819 | /* Create the bitfield declaration. */ |
27820 | decl = grokbitfield (identifier |
27821 | ? make_id_declarator (NULL_TREE, |
27822 | unqualified_name: identifier, |
27823 | sfk: sfk_none, |
27824 | id_location) |
27825 | : NULL, |
27826 | &decl_specifiers, |
27827 | width, initializer, |
27828 | attributes); |
27829 | } |
27830 | else |
27831 | { |
27832 | cp_declarator *declarator; |
27833 | tree asm_specification; |
27834 | int ctor_dtor_or_conv_p; |
27835 | bool static_p = (decl_specifiers.storage_class == sc_static); |
27836 | cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
27837 | /* We can't delay parsing for friends, |
27838 | alias-declarations, and typedefs, even though the |
27839 | standard seems to require it. */ |
27840 | if (!friend_p |
27841 | && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) |
27842 | flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
27843 | |
27844 | /* Parse the declarator. */ |
27845 | declarator |
27846 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
27847 | flags, |
27848 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
27849 | /*parenthesized_p=*/NULL, |
27850 | /*member_p=*/true, |
27851 | friend_p, static_p); |
27852 | |
27853 | /* If something went wrong parsing the declarator, make sure |
27854 | that we at least consume some tokens. */ |
27855 | if (declarator == cp_error_declarator) |
27856 | { |
27857 | /* Skip to the end of the statement. */ |
27858 | cp_parser_skip_to_end_of_statement (parser); |
27859 | /* If the next token is not a semicolon, that is |
27860 | probably because we just skipped over the body of |
27861 | a function. So, we consume a semicolon if |
27862 | present, but do not issue an error message if it |
27863 | is not present. */ |
27864 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
27865 | type: CPP_SEMICOLON)) |
27866 | cp_lexer_consume_token (lexer: parser->lexer); |
27867 | goto out; |
27868 | } |
27869 | |
27870 | /* Handle class-scope non-template C++17 deduction guides. */ |
27871 | cp_parser_maybe_adjust_declarator_for_dguide (parser, |
27872 | decl_specs: &decl_specifiers, |
27873 | declarator, |
27874 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p); |
27875 | |
27876 | if (declares_class_or_enum & 2) |
27877 | cp_parser_check_for_definition_in_return_type |
27878 | (declarator, type: decl_specifiers.type, |
27879 | type_location: decl_specifiers.locations[ds_type_spec]); |
27880 | |
27881 | /* Look for an asm-specification. */ |
27882 | asm_specification = cp_parser_asm_specification_opt (parser); |
27883 | /* Look for attributes that apply to the declaration. */ |
27884 | attributes = cp_parser_attributes_opt (parser); |
27885 | /* Remember which attributes are prefix attributes and |
27886 | which are not. */ |
27887 | first_attribute = attributes; |
27888 | /* Combine the attributes. */ |
27889 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
27890 | |
27891 | /* If it's an `=', then we have a constant-initializer or a |
27892 | pure-specifier. It is not correct to parse the |
27893 | initializer before registering the member declaration |
27894 | since the member declaration should be in scope while |
27895 | its initializer is processed. However, the rest of the |
27896 | front end does not yet provide an interface that allows |
27897 | us to handle this correctly. */ |
27898 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
27899 | { |
27900 | /* In [class.mem]: |
27901 | |
27902 | A pure-specifier shall be used only in the declaration of |
27903 | a virtual function. |
27904 | |
27905 | A member-declarator can contain a constant-initializer |
27906 | only if it declares a static member of integral or |
27907 | enumeration type. |
27908 | |
27909 | Therefore, if the DECLARATOR is for a function, we look |
27910 | for a pure-specifier; otherwise, we look for a |
27911 | constant-initializer. When we call `grokfield', it will |
27912 | perform more stringent semantics checks. */ |
27913 | initializer_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
27914 | declarator->init_loc = initializer_token_start->location; |
27915 | if (function_declarator_p (declarator) |
27916 | || (decl_specifiers.type |
27917 | && TREE_CODE (decl_specifiers.type) == TYPE_DECL |
27918 | && declarator->kind == cdk_id |
27919 | && (TREE_CODE (TREE_TYPE (decl_specifiers.type)) |
27920 | == FUNCTION_TYPE))) |
27921 | initializer = cp_parser_pure_specifier (parser); |
27922 | else if (decl_specifiers.storage_class != sc_static) |
27923 | initializer = cp_parser_save_nsdmi (parser); |
27924 | else if (cxx_dialect >= cxx11) |
27925 | { |
27926 | /* Don't require a constant rvalue in C++11, since we |
27927 | might want a reference constant. We'll enforce |
27928 | constancy later. */ |
27929 | cp_lexer_consume_token (lexer: parser->lexer); |
27930 | /* Parse the initializer. */ |
27931 | initializer = cp_parser_initializer_clause (parser); |
27932 | } |
27933 | else |
27934 | /* Parse the initializer. */ |
27935 | initializer = cp_parser_constant_initializer (parser); |
27936 | } |
27937 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE) |
27938 | && !function_declarator_p (declarator)) |
27939 | { |
27940 | declarator->init_loc |
27941 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
27942 | if (decl_specifiers.storage_class != sc_static) |
27943 | initializer = cp_parser_save_nsdmi (parser); |
27944 | else |
27945 | initializer = cp_parser_initializer (parser); |
27946 | } |
27947 | /* Detect invalid bit-field cases such as |
27948 | |
27949 | int *p : 4; |
27950 | int &&r : 3; |
27951 | |
27952 | and similar. */ |
27953 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON) |
27954 | /* If there were no type specifiers, it was a |
27955 | constructor. */ |
27956 | && decl_specifiers.any_type_specifiers_p) |
27957 | { |
27958 | /* This is called for a decent diagnostic only. */ |
27959 | tree d = grokdeclarator (declarator, &decl_specifiers, |
27960 | BITFIELD, /*initialized=*/false, |
27961 | &attributes); |
27962 | if (!error_operand_p (t: d)) |
27963 | error_at (DECL_SOURCE_LOCATION (d), |
27964 | "bit-field %qD has non-integral type %qT" , |
27965 | d, TREE_TYPE (d)); |
27966 | cp_parser_skip_to_end_of_statement (parser); |
27967 | /* Avoid "extra ;" pedwarns. */ |
27968 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
27969 | type: CPP_SEMICOLON)) |
27970 | cp_lexer_consume_token (lexer: parser->lexer); |
27971 | goto out; |
27972 | } |
27973 | /* Otherwise, there is no initializer. */ |
27974 | else |
27975 | initializer = NULL_TREE; |
27976 | |
27977 | /* See if we are probably looking at a function |
27978 | definition. We are certainly not looking at a |
27979 | member-declarator. Calling `grokfield' has |
27980 | side-effects, so we must not do it unless we are sure |
27981 | that we are looking at a member-declarator. */ |
27982 | if (cp_parser_token_starts_function_definition_p |
27983 | (cp_lexer_peek_token (lexer: parser->lexer))) |
27984 | { |
27985 | /* The grammar does not allow a pure-specifier to be |
27986 | used when a member function is defined. (It is |
27987 | possible that this fact is an oversight in the |
27988 | standard, since a pure function may be defined |
27989 | outside of the class-specifier. */ |
27990 | if (initializer && initializer_token_start) |
27991 | error_at (initializer_token_start->location, |
27992 | "pure-specifier on function-definition" ); |
27993 | decl = cp_parser_save_member_function_body (parser, |
27994 | &decl_specifiers, |
27995 | declarator, |
27996 | attributes); |
27997 | |
27998 | if (parser->fully_implicit_function_template_p) |
27999 | decl = finish_fully_implicit_template (parser, decl); |
28000 | /* If the member was not a friend, declare it here. */ |
28001 | if (!friend_p) |
28002 | finish_member_declaration (decl); |
28003 | /* Peek at the next token. */ |
28004 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28005 | /* If the next token is a semicolon, consume it. */ |
28006 | if (token->type == CPP_SEMICOLON) |
28007 | { |
28008 | location_t semicolon_loc |
28009 | = cp_lexer_consume_token (lexer: parser->lexer)->location; |
28010 | gcc_rich_location richloc (semicolon_loc); |
28011 | richloc.add_fixit_remove (); |
28012 | warning_at (&richloc, OPT_Wextra_semi, |
28013 | "extra %<;%> after in-class " |
28014 | "function definition" ); |
28015 | } |
28016 | goto out; |
28017 | } |
28018 | else |
28019 | if (declarator->kind == cdk_function) |
28020 | declarator->id_loc = token->location; |
28021 | |
28022 | /* Create the declaration. */ |
28023 | decl = grokfield (declarator, &decl_specifiers, |
28024 | initializer, /*init_const_expr_p=*/true, |
28025 | asm_specification, attributes); |
28026 | |
28027 | if (parser->fully_implicit_function_template_p) |
28028 | { |
28029 | if (friend_p) |
28030 | finish_fully_implicit_template (parser, 0); |
28031 | else |
28032 | decl = finish_fully_implicit_template (parser, decl); |
28033 | } |
28034 | } |
28035 | |
28036 | cp_finalize_omp_declare_simd (parser, fndecl: decl); |
28037 | cp_finalize_oacc_routine (parser, decl, false); |
28038 | |
28039 | /* Reset PREFIX_ATTRIBUTES. */ |
28040 | if (attributes != error_mark_node) |
28041 | { |
28042 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
28043 | attributes = TREE_CHAIN (attributes); |
28044 | if (attributes) |
28045 | TREE_CHAIN (attributes) = NULL_TREE; |
28046 | } |
28047 | |
28048 | /* If there is any qualification still in effect, clear it |
28049 | now; we will be starting fresh with the next declarator. */ |
28050 | parser->scope = NULL_TREE; |
28051 | parser->qualifying_scope = NULL_TREE; |
28052 | parser->object_scope = NULL_TREE; |
28053 | /* If it's a `,', then there are more declarators. */ |
28054 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
28055 | { |
28056 | cp_lexer_consume_token (lexer: parser->lexer); |
28057 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
28058 | { |
28059 | cp_token *token = cp_lexer_previous_token (lexer: parser->lexer); |
28060 | gcc_rich_location richloc (token->location); |
28061 | richloc.add_fixit_remove (); |
28062 | error_at (&richloc, "stray %<,%> at end of " |
28063 | "member declaration" ); |
28064 | } |
28065 | } |
28066 | /* If the next token isn't a `;', then we have a parse error. */ |
28067 | else if (cp_lexer_next_token_is_not (lexer: parser->lexer, |
28068 | type: CPP_SEMICOLON)) |
28069 | { |
28070 | /* The next token might be a ways away from where the |
28071 | actual semicolon is missing. Find the previous token |
28072 | and use that for our error position. */ |
28073 | cp_token *token = cp_lexer_previous_token (lexer: parser->lexer); |
28074 | gcc_rich_location richloc (token->location); |
28075 | richloc.add_fixit_insert_after (new_content: ";" ); |
28076 | error_at (&richloc, "expected %<;%> at end of " |
28077 | "member declaration" ); |
28078 | |
28079 | /* Assume that the user meant to provide a semicolon. If |
28080 | we were to cp_parser_skip_to_end_of_statement, we might |
28081 | skip to a semicolon inside a member function definition |
28082 | and issue nonsensical error messages. */ |
28083 | assume_semicolon = true; |
28084 | } |
28085 | |
28086 | if (decl) |
28087 | { |
28088 | /* Add DECL to the list of members. */ |
28089 | if (!friend_p |
28090 | /* Explicitly include, eg, NSDMIs, for better error |
28091 | recovery (c++/58650). */ |
28092 | || !DECL_DECLARES_FUNCTION_P (decl)) |
28093 | finish_member_declaration (decl); |
28094 | |
28095 | if (DECL_DECLARES_FUNCTION_P (decl)) |
28096 | cp_parser_save_default_args (parser, STRIP_TEMPLATE (decl)); |
28097 | else if (TREE_CODE (decl) == FIELD_DECL |
28098 | && DECL_INITIAL (decl)) |
28099 | /* Add DECL to the queue of NSDMI to be parsed later. */ |
28100 | vec_safe_push (unparsed_nsdmis, obj: decl); |
28101 | } |
28102 | |
28103 | if (assume_semicolon) |
28104 | goto out; |
28105 | } |
28106 | } |
28107 | |
28108 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
28109 | out: |
28110 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
28111 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
28112 | } |
28113 | |
28114 | /* Parse a pure-specifier. |
28115 | |
28116 | pure-specifier: |
28117 | = 0 |
28118 | |
28119 | Returns INTEGER_ZERO_NODE if a pure specifier is found. |
28120 | Otherwise, ERROR_MARK_NODE is returned. */ |
28121 | |
28122 | static tree |
28123 | cp_parser_pure_specifier (cp_parser* parser) |
28124 | { |
28125 | cp_token *token; |
28126 | |
28127 | /* Look for the `=' token. */ |
28128 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
28129 | return error_mark_node; |
28130 | /* Look for the `0' token. */ |
28131 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28132 | |
28133 | if (token->type == CPP_EOF |
28134 | || token->type == CPP_PRAGMA_EOL) |
28135 | return error_mark_node; |
28136 | |
28137 | cp_lexer_consume_token (lexer: parser->lexer); |
28138 | |
28139 | /* Accept = default or = delete in c++0x mode. */ |
28140 | if (token->keyword == RID_DEFAULT |
28141 | || token->keyword == RID_DELETE) |
28142 | { |
28143 | maybe_warn_cpp0x (str: CPP0X_DEFAULTED_DELETED); |
28144 | return token->u.value; |
28145 | } |
28146 | |
28147 | /* c_lex_with_flags marks a single digit '0' with PURE_ZERO. */ |
28148 | if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO)) |
28149 | { |
28150 | cp_parser_error (parser, |
28151 | gmsgid: "invalid pure specifier (only %<= 0%> is allowed)" ); |
28152 | cp_parser_skip_to_end_of_statement (parser); |
28153 | return error_mark_node; |
28154 | } |
28155 | if (PROCESSING_REAL_TEMPLATE_DECL_P ()) |
28156 | { |
28157 | error_at (token->location, "templates may not be %<virtual%>" ); |
28158 | return error_mark_node; |
28159 | } |
28160 | |
28161 | return integer_zero_node; |
28162 | } |
28163 | |
28164 | /* Parse a constant-initializer. |
28165 | |
28166 | constant-initializer: |
28167 | = constant-expression |
28168 | |
28169 | Returns a representation of the constant-expression. */ |
28170 | |
28171 | static tree |
28172 | cp_parser_constant_initializer (cp_parser* parser) |
28173 | { |
28174 | /* Look for the `=' token. */ |
28175 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
28176 | return error_mark_node; |
28177 | |
28178 | /* It is invalid to write: |
28179 | |
28180 | struct S { static const int i = { 7 }; }; |
28181 | |
28182 | */ |
28183 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
28184 | { |
28185 | cp_parser_error (parser, |
28186 | gmsgid: "a brace-enclosed initializer is not allowed here" ); |
28187 | /* Consume the opening brace. */ |
28188 | matching_braces braces; |
28189 | braces.consume_open (parser); |
28190 | /* Skip the initializer. */ |
28191 | cp_parser_skip_to_closing_brace (parser); |
28192 | /* Look for the trailing `}'. */ |
28193 | braces.require_close (parser); |
28194 | |
28195 | return error_mark_node; |
28196 | } |
28197 | |
28198 | return cp_parser_constant_expression (parser); |
28199 | } |
28200 | |
28201 | /* Derived classes [gram.class.derived] */ |
28202 | |
28203 | /* Parse a base-clause. |
28204 | |
28205 | base-clause: |
28206 | : base-specifier-list |
28207 | |
28208 | base-specifier-list: |
28209 | base-specifier ... [opt] |
28210 | base-specifier-list , base-specifier ... [opt] |
28211 | |
28212 | Returns a TREE_LIST representing the base-classes, in the order in |
28213 | which they were declared. The representation of each node is as |
28214 | described by cp_parser_base_specifier. |
28215 | |
28216 | In the case that no bases are specified, this function will return |
28217 | NULL_TREE, not ERROR_MARK_NODE. */ |
28218 | |
28219 | static tree |
28220 | cp_parser_base_clause (cp_parser* parser) |
28221 | { |
28222 | tree bases = NULL_TREE; |
28223 | |
28224 | /* Look for the `:' that begins the list. */ |
28225 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
28226 | |
28227 | /* Scan the base-specifier-list. */ |
28228 | while (true) |
28229 | { |
28230 | cp_token *token; |
28231 | tree base; |
28232 | bool pack_expansion_p = false; |
28233 | |
28234 | /* Look for the base-specifier. */ |
28235 | base = cp_parser_base_specifier (parser); |
28236 | /* Look for the (optional) ellipsis. */ |
28237 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
28238 | { |
28239 | /* Consume the `...'. */ |
28240 | cp_lexer_consume_token (lexer: parser->lexer); |
28241 | |
28242 | pack_expansion_p = true; |
28243 | } |
28244 | |
28245 | /* Add BASE to the front of the list. */ |
28246 | if (base && base != error_mark_node) |
28247 | { |
28248 | if (pack_expansion_p) |
28249 | /* Make this a pack expansion type. */ |
28250 | TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base)); |
28251 | |
28252 | if (!check_for_bare_parameter_packs (TREE_VALUE (base))) |
28253 | { |
28254 | TREE_CHAIN (base) = bases; |
28255 | bases = base; |
28256 | } |
28257 | } |
28258 | /* Peek at the next token. */ |
28259 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28260 | /* If it's not a comma, then the list is complete. */ |
28261 | if (token->type != CPP_COMMA) |
28262 | break; |
28263 | /* Consume the `,'. */ |
28264 | cp_lexer_consume_token (lexer: parser->lexer); |
28265 | } |
28266 | |
28267 | /* PARSER->SCOPE may still be non-NULL at this point, if the last |
28268 | base class had a qualified name. However, the next name that |
28269 | appears is certainly not qualified. */ |
28270 | parser->scope = NULL_TREE; |
28271 | parser->qualifying_scope = NULL_TREE; |
28272 | parser->object_scope = NULL_TREE; |
28273 | |
28274 | return nreverse (bases); |
28275 | } |
28276 | |
28277 | /* Parse a base-specifier. |
28278 | |
28279 | base-specifier: |
28280 | :: [opt] nested-name-specifier [opt] class-name |
28281 | virtual access-specifier [opt] :: [opt] nested-name-specifier |
28282 | [opt] class-name |
28283 | access-specifier virtual [opt] :: [opt] nested-name-specifier |
28284 | [opt] class-name |
28285 | |
28286 | Returns a TREE_LIST. The TREE_PURPOSE will be one of |
28287 | ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_[VIRTUAL]_NODE to |
28288 | indicate the specifiers provided. The TREE_VALUE will be a TYPE |
28289 | (or the ERROR_MARK_NODE) indicating the type that was specified. */ |
28290 | |
28291 | static tree |
28292 | cp_parser_base_specifier (cp_parser* parser) |
28293 | { |
28294 | cp_token *token; |
28295 | bool done = false; |
28296 | bool virtual_p = false; |
28297 | bool duplicate_virtual_error_issued_p = false; |
28298 | bool duplicate_access_error_issued_p = false; |
28299 | bool class_scope_p, template_p; |
28300 | tree access = access_default_node; |
28301 | tree type; |
28302 | |
28303 | /* Process the optional `virtual' and `access-specifier'. */ |
28304 | while (!done) |
28305 | { |
28306 | /* Peek at the next token. */ |
28307 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28308 | /* Process `virtual'. */ |
28309 | switch (token->keyword) |
28310 | { |
28311 | case RID_VIRTUAL: |
28312 | /* If `virtual' appears more than once, issue an error. */ |
28313 | if (virtual_p && !duplicate_virtual_error_issued_p) |
28314 | { |
28315 | cp_parser_error (parser, |
28316 | gmsgid: "%<virtual%> specified more than once in base-specifier" ); |
28317 | duplicate_virtual_error_issued_p = true; |
28318 | } |
28319 | |
28320 | virtual_p = true; |
28321 | |
28322 | /* Consume the `virtual' token. */ |
28323 | cp_lexer_consume_token (lexer: parser->lexer); |
28324 | |
28325 | break; |
28326 | |
28327 | case RID_PUBLIC: |
28328 | case RID_PROTECTED: |
28329 | case RID_PRIVATE: |
28330 | /* If more than one access specifier appears, issue an |
28331 | error. */ |
28332 | if (access != access_default_node |
28333 | && !duplicate_access_error_issued_p) |
28334 | { |
28335 | cp_parser_error (parser, |
28336 | gmsgid: "more than one access specifier in base-specifier" ); |
28337 | duplicate_access_error_issued_p = true; |
28338 | } |
28339 | |
28340 | access = ridpointers[(int) token->keyword]; |
28341 | |
28342 | /* Consume the access-specifier. */ |
28343 | cp_lexer_consume_token (lexer: parser->lexer); |
28344 | |
28345 | break; |
28346 | |
28347 | default: |
28348 | done = true; |
28349 | break; |
28350 | } |
28351 | } |
28352 | /* It is not uncommon to see programs mechanically, erroneously, use |
28353 | the 'typename' keyword to denote (dependent) qualified types |
28354 | as base classes. */ |
28355 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
28356 | { |
28357 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28358 | if (!processing_template_decl) |
28359 | error_at (token->location, |
28360 | "keyword %<typename%> not allowed outside of templates" ); |
28361 | else |
28362 | error_at (token->location, |
28363 | "keyword %<typename%> not allowed in this context " |
28364 | "(the base class is implicitly a type)" ); |
28365 | cp_lexer_consume_token (lexer: parser->lexer); |
28366 | } |
28367 | |
28368 | /* Look for the optional `::' operator. */ |
28369 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
28370 | /* Look for the nested-name-specifier. The simplest way to |
28371 | implement: |
28372 | |
28373 | [temp.res] |
28374 | |
28375 | The keyword `typename' is not permitted in a base-specifier or |
28376 | mem-initializer; in these contexts a qualified name that |
28377 | depends on a template-parameter is implicitly assumed to be a |
28378 | type name. |
28379 | |
28380 | is to pretend that we have seen the `typename' keyword at this |
28381 | point. */ |
28382 | cp_parser_nested_name_specifier_opt (parser, |
28383 | /*typename_keyword_p=*/true, |
28384 | /*check_dependency_p=*/true, |
28385 | /*type_p=*/true, |
28386 | /*is_declaration=*/true); |
28387 | /* If the base class is given by a qualified name, assume that names |
28388 | we see are type names or templates, as appropriate. */ |
28389 | class_scope_p = (parser->scope && TYPE_P (parser->scope)); |
28390 | template_p = class_scope_p && cp_parser_optional_template_keyword (parser); |
28391 | |
28392 | if (!parser->scope |
28393 | && cp_lexer_next_token_is_decltype (lexer: parser->lexer)) |
28394 | /* DR 950 allows decltype as a base-specifier. */ |
28395 | type = cp_parser_decltype (parser); |
28396 | else |
28397 | { |
28398 | /* Otherwise, look for the class-name. */ |
28399 | type = cp_parser_class_name (parser, |
28400 | typename_keyword_p: class_scope_p, |
28401 | template_keyword_p: template_p, |
28402 | tag_type: typename_type, |
28403 | /*check_dependency_p=*/true, |
28404 | /*class_head_p=*/false, |
28405 | /*is_declaration=*/true); |
28406 | type = TREE_TYPE (type); |
28407 | } |
28408 | |
28409 | if (type == error_mark_node) |
28410 | return error_mark_node; |
28411 | |
28412 | return finish_base_specifier (type, access, virtual_p); |
28413 | } |
28414 | |
28415 | /* Exception handling [gram.exception] */ |
28416 | |
28417 | /* Save the tokens that make up the noexcept-specifier for a member-function. |
28418 | Returns a DEFERRED_PARSE. */ |
28419 | |
28420 | static tree |
28421 | cp_parser_save_noexcept (cp_parser *parser) |
28422 | { |
28423 | cp_token *first = parser->lexer->next_token; |
28424 | /* We want everything up to, including, the final ')'. */ |
28425 | cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0); |
28426 | cp_token *last = parser->lexer->next_token; |
28427 | |
28428 | /* As with default arguments and NSDMIs, make use of DEFERRED_PARSE |
28429 | to carry the information we will need. */ |
28430 | tree expr = make_node (DEFERRED_PARSE); |
28431 | /* Save away the noexcept-specifier; we will process it when the |
28432 | class is complete. */ |
28433 | DEFPARSE_TOKENS (expr) = cp_token_cache_new (first, last); |
28434 | DEFPARSE_INSTANTIATIONS (expr) = nullptr; |
28435 | expr = build_tree_list (expr, NULL_TREE); |
28436 | return expr; |
28437 | } |
28438 | |
28439 | /* Used for late processing of noexcept-specifiers of member-functions. |
28440 | DEFAULT_ARG is the unparsed operand of a noexcept-specifier which |
28441 | we saved for later; parse it now. DECL is the declaration of the |
28442 | member function. */ |
28443 | |
28444 | static tree |
28445 | cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg) |
28446 | { |
28447 | /* Make sure we've gotten something that hasn't been parsed yet. */ |
28448 | gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE); |
28449 | |
28450 | push_unparsed_function_queues (parser); |
28451 | |
28452 | /* Push the saved tokens for the noexcept-specifier onto the parser's |
28453 | lexer stack. */ |
28454 | cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg); |
28455 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
28456 | |
28457 | /* Parse the cached noexcept-specifier. */ |
28458 | tree parsed_arg |
28459 | = cp_parser_noexcept_specification_opt (parser, |
28460 | CP_PARSER_FLAGS_NONE, |
28461 | /*require_constexpr=*/true, |
28462 | /*consumed_expr=*/NULL, |
28463 | /*return_cond=*/false); |
28464 | |
28465 | /* Revert to the main lexer. */ |
28466 | cp_parser_pop_lexer (parser); |
28467 | |
28468 | /* Restore the queue. */ |
28469 | pop_unparsed_function_queues (parser); |
28470 | |
28471 | /* And we're done. */ |
28472 | return parsed_arg; |
28473 | } |
28474 | |
28475 | /* Perform late checking of overriding function with respect to their |
28476 | noexcept-specifiers. FNDECL is the member function that potentially |
28477 | overrides some virtual function with the same signature. */ |
28478 | |
28479 | static void |
28480 | noexcept_override_late_checks (tree fndecl) |
28481 | { |
28482 | tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl)); |
28483 | tree base_binfo; |
28484 | |
28485 | if (DECL_STATIC_FUNCTION_P (fndecl)) |
28486 | return; |
28487 | |
28488 | for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) |
28489 | { |
28490 | tree basetype = BINFO_TYPE (base_binfo); |
28491 | |
28492 | if (!TYPE_POLYMORPHIC_P (basetype)) |
28493 | continue; |
28494 | |
28495 | tree fn = look_for_overrides_here (basetype, fndecl); |
28496 | if (fn) |
28497 | maybe_check_overriding_exception_spec (fndecl, fn); |
28498 | } |
28499 | } |
28500 | |
28501 | /* Parse an (optional) noexcept-specification. |
28502 | |
28503 | noexcept-specification: |
28504 | noexcept ( constant-expression ) [opt] |
28505 | |
28506 | If no noexcept-specification is present, returns NULL_TREE. |
28507 | Otherwise, if REQUIRE_CONSTEXPR is false, then either parse and return any |
28508 | expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if |
28509 | there are no parentheses. CONSUMED_EXPR will be set accordingly. |
28510 | Otherwise, returns a noexcept specification unless RETURN_COND is true, |
28511 | in which case a boolean condition is returned instead. The parser flags |
28512 | FLAGS is used to control parsing. QUALS are qualifiers indicating whether |
28513 | the (member) function is `const'. */ |
28514 | |
28515 | static tree |
28516 | cp_parser_noexcept_specification_opt (cp_parser* parser, |
28517 | cp_parser_flags flags, |
28518 | bool require_constexpr, |
28519 | bool* consumed_expr, |
28520 | bool return_cond) |
28521 | { |
28522 | cp_token *token; |
28523 | const char *saved_message; |
28524 | |
28525 | /* Peek at the next token. */ |
28526 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28527 | |
28528 | /* Is it a noexcept-specification? */ |
28529 | if (cp_parser_is_keyword (token, keyword: RID_NOEXCEPT)) |
28530 | { |
28531 | tree expr; |
28532 | |
28533 | /* [class.mem]/6 says that a noexcept-specifer (within the |
28534 | member-specification of the class) is a complete-class context of |
28535 | a class. So, if the noexcept-specifier has the optional expression, |
28536 | just save the tokens, and reparse this after we're done with the |
28537 | class. */ |
28538 | |
28539 | if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) |
28540 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN) |
28541 | /* No need to delay parsing for a number literal or true/false. */ |
28542 | && !((cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NUMBER) |
28543 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_KEYWORD)) |
28544 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_PAREN)) |
28545 | && at_class_scope_p () |
28546 | && TYPE_BEING_DEFINED (current_class_type) |
28547 | && !LAMBDA_TYPE_P (current_class_type)) |
28548 | return cp_parser_save_noexcept (parser); |
28549 | |
28550 | cp_lexer_consume_token (lexer: parser->lexer); |
28551 | |
28552 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
28553 | { |
28554 | matching_parens parens; |
28555 | parens.consume_open (parser); |
28556 | |
28557 | if (require_constexpr) |
28558 | { |
28559 | /* Types may not be defined in an exception-specification. */ |
28560 | saved_message = parser->type_definition_forbidden_message; |
28561 | parser->type_definition_forbidden_message |
28562 | = G_("types may not be defined in an exception-specification" ); |
28563 | |
28564 | bool non_constant_p; |
28565 | expr |
28566 | = cp_parser_constant_expression (parser, |
28567 | /*allow_non_constant=*/allow_non_constant_p: true, |
28568 | non_constant_p: &non_constant_p); |
28569 | if (non_constant_p |
28570 | && !require_potential_rvalue_constant_expression (expr)) |
28571 | { |
28572 | expr = NULL_TREE; |
28573 | return_cond = true; |
28574 | } |
28575 | |
28576 | /* Restore the saved message. */ |
28577 | parser->type_definition_forbidden_message = saved_message; |
28578 | } |
28579 | else |
28580 | { |
28581 | expr = cp_parser_expression (parser); |
28582 | *consumed_expr = true; |
28583 | } |
28584 | |
28585 | parens.require_close (parser); |
28586 | } |
28587 | else |
28588 | { |
28589 | expr = boolean_true_node; |
28590 | if (!require_constexpr) |
28591 | *consumed_expr = false; |
28592 | } |
28593 | |
28594 | /* We cannot build a noexcept-spec right away because this will check |
28595 | that expr is a constexpr. */ |
28596 | if (!return_cond) |
28597 | return build_noexcept_spec (expr, tf_warning_or_error); |
28598 | else |
28599 | return expr; |
28600 | } |
28601 | else |
28602 | return NULL_TREE; |
28603 | } |
28604 | |
28605 | /* Parse an (optional) exception-specification. |
28606 | |
28607 | exception-specification: |
28608 | throw ( type-id-list [opt] ) |
28609 | |
28610 | Returns a TREE_LIST representing the exception-specification. The |
28611 | TREE_VALUE of each node is a type. The parser flags FLAGS is used to |
28612 | control parsing. QUALS are qualifiers indicating whether the (member) |
28613 | function is `const'. */ |
28614 | |
28615 | static tree |
28616 | cp_parser_exception_specification_opt (cp_parser* parser, |
28617 | cp_parser_flags flags) |
28618 | { |
28619 | cp_token *token; |
28620 | tree type_id_list; |
28621 | const char *saved_message; |
28622 | |
28623 | /* Peek at the next token. */ |
28624 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28625 | |
28626 | /* Is it a noexcept-specification? */ |
28627 | type_id_list |
28628 | = cp_parser_noexcept_specification_opt (parser, flags, |
28629 | /*require_constexpr=*/true, |
28630 | /*consumed_expr=*/NULL, |
28631 | /*return_cond=*/false); |
28632 | if (type_id_list != NULL_TREE) |
28633 | return type_id_list; |
28634 | |
28635 | /* If it's not `throw', then there's no exception-specification. */ |
28636 | if (!cp_parser_is_keyword (token, keyword: RID_THROW)) |
28637 | return NULL_TREE; |
28638 | |
28639 | location_t loc = token->location; |
28640 | |
28641 | /* Consume the `throw'. */ |
28642 | cp_lexer_consume_token (lexer: parser->lexer); |
28643 | |
28644 | /* Look for the `('. */ |
28645 | matching_parens parens; |
28646 | parens.require_open (parser); |
28647 | |
28648 | /* Peek at the next token. */ |
28649 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28650 | /* If it's not a `)', then there is a type-id-list. */ |
28651 | if (token->type != CPP_CLOSE_PAREN) |
28652 | { |
28653 | /* Types may not be defined in an exception-specification. */ |
28654 | saved_message = parser->type_definition_forbidden_message; |
28655 | parser->type_definition_forbidden_message |
28656 | = G_("types may not be defined in an exception-specification" ); |
28657 | /* Parse the type-id-list. */ |
28658 | type_id_list = cp_parser_type_id_list (parser); |
28659 | /* Restore the saved message. */ |
28660 | parser->type_definition_forbidden_message = saved_message; |
28661 | |
28662 | if (cxx_dialect >= cxx17) |
28663 | { |
28664 | error_at (loc, "ISO C++17 does not allow dynamic exception " |
28665 | "specifications" ); |
28666 | type_id_list = NULL_TREE; |
28667 | } |
28668 | else if (cxx_dialect >= cxx11) |
28669 | warning_at (loc, OPT_Wdeprecated, |
28670 | "dynamic exception specifications are deprecated in " |
28671 | "C++11" ); |
28672 | } |
28673 | /* In C++17, throw() is equivalent to noexcept (true). throw() |
28674 | is deprecated in C++11 and above as well, but is still widely used, |
28675 | so don't warn about it yet. */ |
28676 | else if (cxx_dialect >= cxx17) |
28677 | type_id_list = noexcept_true_spec; |
28678 | else |
28679 | type_id_list = empty_except_spec; |
28680 | |
28681 | /* Look for the `)'. */ |
28682 | parens.require_close (parser); |
28683 | |
28684 | return type_id_list; |
28685 | } |
28686 | |
28687 | /* Parse an (optional) type-id-list. |
28688 | |
28689 | type-id-list: |
28690 | type-id ... [opt] |
28691 | type-id-list , type-id ... [opt] |
28692 | |
28693 | Returns a TREE_LIST. The TREE_VALUE of each node is a TYPE, |
28694 | in the order that the types were presented. */ |
28695 | |
28696 | static tree |
28697 | cp_parser_type_id_list (cp_parser* parser) |
28698 | { |
28699 | tree types = NULL_TREE; |
28700 | |
28701 | while (true) |
28702 | { |
28703 | cp_token *token; |
28704 | tree type; |
28705 | |
28706 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28707 | |
28708 | /* Get the next type-id. */ |
28709 | type = cp_parser_type_id (parser); |
28710 | /* Check for invalid 'auto'. */ |
28711 | if (flag_concepts && type_uses_auto (type)) |
28712 | { |
28713 | error_at (token->location, |
28714 | "invalid use of %<auto%> in exception-specification" ); |
28715 | type = error_mark_node; |
28716 | } |
28717 | /* Parse the optional ellipsis. */ |
28718 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
28719 | { |
28720 | /* Consume the `...'. */ |
28721 | cp_lexer_consume_token (lexer: parser->lexer); |
28722 | |
28723 | /* Turn the type into a pack expansion expression. */ |
28724 | type = make_pack_expansion (type); |
28725 | } |
28726 | /* Add it to the list. */ |
28727 | types = add_exception_specifier (types, type, /*complain=*/1); |
28728 | /* Peek at the next token. */ |
28729 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28730 | /* If it is not a `,', we are done. */ |
28731 | if (token->type != CPP_COMMA) |
28732 | break; |
28733 | /* Consume the `,'. */ |
28734 | cp_lexer_consume_token (lexer: parser->lexer); |
28735 | } |
28736 | |
28737 | return nreverse (types); |
28738 | } |
28739 | |
28740 | /* Parse a try-block. |
28741 | |
28742 | try-block: |
28743 | try compound-statement handler-seq */ |
28744 | |
28745 | static tree |
28746 | cp_parser_try_block (cp_parser* parser) |
28747 | { |
28748 | tree try_block; |
28749 | |
28750 | cp_parser_require_keyword (parser, RID_TRY, RT_TRY); |
28751 | if (parser->in_function_body |
28752 | && DECL_DECLARED_CONSTEXPR_P (current_function_decl) |
28753 | && cxx_dialect < cxx20) |
28754 | pedwarn (input_location, OPT_Wc__20_extensions, |
28755 | "%<try%> in %<constexpr%> function only " |
28756 | "available with %<-std=c++20%> or %<-std=gnu++20%>" ); |
28757 | |
28758 | try_block = begin_try_block (); |
28759 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_TRY_BLOCK, function_body: false); |
28760 | finish_try_block (try_block); |
28761 | cp_parser_handler_seq (parser); |
28762 | finish_handler_sequence (try_block); |
28763 | |
28764 | return try_block; |
28765 | } |
28766 | |
28767 | /* Parse a function-try-block. |
28768 | |
28769 | function-try-block: |
28770 | try ctor-initializer [opt] function-body handler-seq */ |
28771 | |
28772 | static void |
28773 | cp_parser_function_try_block (cp_parser* parser) |
28774 | { |
28775 | tree compound_stmt; |
28776 | tree try_block; |
28777 | |
28778 | /* Look for the `try' keyword. */ |
28779 | if (!cp_parser_require_keyword (parser, RID_TRY, RT_TRY)) |
28780 | return; |
28781 | /* Let the rest of the front end know where we are. */ |
28782 | try_block = begin_function_try_block (&compound_stmt); |
28783 | /* Parse the function-body. */ |
28784 | cp_parser_ctor_initializer_opt_and_function_body |
28785 | (parser, /*in_function_try_block=*/true); |
28786 | /* We're done with the `try' part. */ |
28787 | finish_function_try_block (try_block); |
28788 | /* Parse the handlers. */ |
28789 | cp_parser_handler_seq (parser); |
28790 | /* We're done with the handlers. */ |
28791 | finish_function_handler_sequence (try_block, compound_stmt); |
28792 | } |
28793 | |
28794 | /* Parse a handler-seq. |
28795 | |
28796 | handler-seq: |
28797 | handler handler-seq [opt] */ |
28798 | |
28799 | static void |
28800 | cp_parser_handler_seq (cp_parser* parser) |
28801 | { |
28802 | while (true) |
28803 | { |
28804 | cp_token *token; |
28805 | |
28806 | /* Parse the handler. */ |
28807 | cp_parser_handler (parser); |
28808 | /* Peek at the next token. */ |
28809 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28810 | /* If it's not `catch' then there are no more handlers. */ |
28811 | if (!cp_parser_is_keyword (token, keyword: RID_CATCH)) |
28812 | break; |
28813 | } |
28814 | } |
28815 | |
28816 | /* Parse a handler. |
28817 | |
28818 | handler: |
28819 | catch ( exception-declaration ) compound-statement */ |
28820 | |
28821 | static void |
28822 | cp_parser_handler (cp_parser* parser) |
28823 | { |
28824 | tree handler; |
28825 | tree declaration; |
28826 | |
28827 | cp_parser_require_keyword (parser, RID_CATCH, RT_CATCH); |
28828 | handler = begin_handler (); |
28829 | matching_parens parens; |
28830 | parens.require_open (parser); |
28831 | declaration = cp_parser_exception_declaration (parser); |
28832 | finish_handler_parms (declaration, handler); |
28833 | parens.require_close (parser); |
28834 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
28835 | finish_handler (handler); |
28836 | } |
28837 | |
28838 | /* Parse an exception-declaration. |
28839 | |
28840 | exception-declaration: |
28841 | type-specifier-seq declarator |
28842 | type-specifier-seq abstract-declarator |
28843 | type-specifier-seq |
28844 | ... |
28845 | |
28846 | Returns a VAR_DECL for the declaration, or NULL_TREE if the |
28847 | ellipsis variant is used. */ |
28848 | |
28849 | static tree |
28850 | cp_parser_exception_declaration (cp_parser* parser) |
28851 | { |
28852 | cp_decl_specifier_seq type_specifiers; |
28853 | cp_declarator *declarator; |
28854 | const char *saved_message; |
28855 | |
28856 | /* If it's an ellipsis, it's easy to handle. */ |
28857 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
28858 | { |
28859 | /* Consume the `...' token. */ |
28860 | cp_lexer_consume_token (lexer: parser->lexer); |
28861 | return NULL_TREE; |
28862 | } |
28863 | |
28864 | /* Types may not be defined in exception-declarations. */ |
28865 | saved_message = parser->type_definition_forbidden_message; |
28866 | parser->type_definition_forbidden_message |
28867 | = G_("types may not be defined in exception-declarations" ); |
28868 | |
28869 | /* Parse the type-specifier-seq. */ |
28870 | cp_parser_type_specifier_seq (parser, flags: CP_PARSER_FLAGS_NONE, |
28871 | /*is_declaration=*/true, |
28872 | /*is_trailing_return=*/false, |
28873 | type_specifier_seq: &type_specifiers); |
28874 | /* If it's a `)', then there is no declarator. */ |
28875 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
28876 | declarator = NULL; |
28877 | else |
28878 | declarator = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_EITHER, |
28879 | flags: CP_PARSER_FLAGS_NONE, |
28880 | /*ctor_dtor_or_conv_p=*/NULL, |
28881 | /*parenthesized_p=*/NULL, |
28882 | /*member_p=*/false, |
28883 | /*friend_p=*/false, |
28884 | /*static_p=*/false); |
28885 | |
28886 | /* Restore the saved message. */ |
28887 | parser->type_definition_forbidden_message = saved_message; |
28888 | |
28889 | if (!type_specifiers.any_specifiers_p) |
28890 | return error_mark_node; |
28891 | |
28892 | return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL); |
28893 | } |
28894 | |
28895 | /* Parse a throw-expression. |
28896 | |
28897 | throw-expression: |
28898 | throw assignment-expression [opt] |
28899 | |
28900 | Returns a THROW_EXPR representing the throw-expression. */ |
28901 | |
28902 | static tree |
28903 | cp_parser_throw_expression (cp_parser* parser) |
28904 | { |
28905 | tree expression; |
28906 | cp_token* token; |
28907 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
28908 | |
28909 | cp_parser_require_keyword (parser, RID_THROW, RT_THROW); |
28910 | token = cp_lexer_peek_token (lexer: parser->lexer); |
28911 | /* Figure out whether or not there is an assignment-expression |
28912 | following the "throw" keyword. */ |
28913 | if (token->type == CPP_COMMA |
28914 | || token->type == CPP_SEMICOLON |
28915 | || token->type == CPP_CLOSE_PAREN |
28916 | || token->type == CPP_CLOSE_SQUARE |
28917 | || token->type == CPP_CLOSE_BRACE |
28918 | || token->type == CPP_COLON) |
28919 | expression = NULL_TREE; |
28920 | else |
28921 | expression = cp_parser_assignment_expression (parser); |
28922 | |
28923 | /* Construct a location e.g.: |
28924 | throw x |
28925 | ^~~~~~~ |
28926 | with caret == start at the start of the "throw" token, and |
28927 | the end at the end of the final token we consumed. */ |
28928 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
28929 | lexer: parser->lexer); |
28930 | expression = build_throw (combined_loc, expression); |
28931 | |
28932 | return expression; |
28933 | } |
28934 | |
28935 | /* Parse a yield-expression. |
28936 | |
28937 | yield-expression: |
28938 | co_yield assignment-expression |
28939 | co_yield braced-init-list |
28940 | |
28941 | Returns a CO_YIELD_EXPR representing the yield-expression. */ |
28942 | |
28943 | static tree |
28944 | cp_parser_yield_expression (cp_parser* parser) |
28945 | { |
28946 | tree expr; |
28947 | |
28948 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
28949 | location_t kw_loc = token->location; /* Save for later. */ |
28950 | |
28951 | cp_parser_require_keyword (parser, RID_CO_YIELD, RT_CO_YIELD); |
28952 | |
28953 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
28954 | { |
28955 | cp_lexer_set_source_position (lexer: parser->lexer); |
28956 | /* ??? : probably a moot point? */ |
28957 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
28958 | expr = cp_parser_braced_list (parser); |
28959 | } |
28960 | else |
28961 | expr = cp_parser_assignment_expression (parser); |
28962 | |
28963 | if (expr == error_mark_node) |
28964 | return expr; |
28965 | |
28966 | return finish_co_yield_expr (kw_loc, expr); |
28967 | } |
28968 | |
28969 | /* GNU Extensions */ |
28970 | |
28971 | /* Parse an (optional) asm-specification. |
28972 | |
28973 | asm-specification: |
28974 | asm ( string-literal ) |
28975 | |
28976 | If the asm-specification is present, returns a STRING_CST |
28977 | corresponding to the string-literal. Otherwise, returns |
28978 | NULL_TREE. */ |
28979 | |
28980 | static tree |
28981 | cp_parser_asm_specification_opt (cp_parser* parser) |
28982 | { |
28983 | /* Peek at the next token. */ |
28984 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
28985 | /* If the next token isn't the `asm' keyword, then there's no |
28986 | asm-specification. */ |
28987 | if (!cp_parser_is_keyword (token, keyword: RID_ASM)) |
28988 | return NULL_TREE; |
28989 | |
28990 | /* Consume the `asm' token. */ |
28991 | cp_lexer_consume_token (lexer: parser->lexer); |
28992 | /* Look for the `('. */ |
28993 | matching_parens parens; |
28994 | parens.require_open (parser); |
28995 | |
28996 | /* Look for the string-literal. */ |
28997 | tree asm_specification = cp_parser_string_literal (parser, |
28998 | /*translate=*/false, |
28999 | /*wide_ok=*/false); |
29000 | |
29001 | /* Look for the `)'. */ |
29002 | parens.require_close (parser); |
29003 | |
29004 | return asm_specification; |
29005 | } |
29006 | |
29007 | /* Parse an asm-operand-list. |
29008 | |
29009 | asm-operand-list: |
29010 | asm-operand |
29011 | asm-operand-list , asm-operand |
29012 | |
29013 | asm-operand: |
29014 | string-literal ( expression ) |
29015 | [ string-literal ] string-literal ( expression ) |
29016 | |
29017 | Returns a TREE_LIST representing the operands. The TREE_VALUE of |
29018 | each node is the expression. The TREE_PURPOSE is itself a |
29019 | TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed |
29020 | string-literal (or NULL_TREE if not present) and whose TREE_VALUE |
29021 | is a STRING_CST for the string literal before the parenthesis. Returns |
29022 | ERROR_MARK_NODE if any of the operands are invalid. */ |
29023 | |
29024 | static tree |
29025 | cp_parser_asm_operand_list (cp_parser* parser) |
29026 | { |
29027 | tree asm_operands = NULL_TREE; |
29028 | bool invalid_operands = false; |
29029 | |
29030 | while (true) |
29031 | { |
29032 | tree name; |
29033 | |
29034 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
29035 | { |
29036 | /* Consume the `[' token. */ |
29037 | cp_lexer_consume_token (lexer: parser->lexer); |
29038 | /* Read the operand name. */ |
29039 | name = cp_parser_identifier (parser); |
29040 | if (name != error_mark_node) |
29041 | name = build_string (IDENTIFIER_LENGTH (name), |
29042 | IDENTIFIER_POINTER (name)); |
29043 | /* Look for the closing `]'. */ |
29044 | cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); |
29045 | } |
29046 | else |
29047 | name = NULL_TREE; |
29048 | /* Look for the string-literal. */ |
29049 | tree string_literal = cp_parser_string_literal (parser, |
29050 | /*translate=*/false, |
29051 | /*wide_ok=*/false); |
29052 | |
29053 | /* Look for the `('. */ |
29054 | matching_parens parens; |
29055 | parens.require_open (parser); |
29056 | /* Parse the expression. */ |
29057 | tree expression = cp_parser_expression (parser); |
29058 | /* Look for the `)'. */ |
29059 | parens.require_close (parser); |
29060 | |
29061 | if (name == error_mark_node |
29062 | || string_literal == error_mark_node |
29063 | || expression == error_mark_node) |
29064 | invalid_operands = true; |
29065 | |
29066 | /* Add this operand to the list. */ |
29067 | asm_operands = tree_cons (build_tree_list (name, string_literal), |
29068 | expression, |
29069 | asm_operands); |
29070 | /* If the next token is not a `,', there are no more |
29071 | operands. */ |
29072 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29073 | break; |
29074 | /* Consume the `,'. */ |
29075 | cp_lexer_consume_token (lexer: parser->lexer); |
29076 | } |
29077 | |
29078 | return invalid_operands ? error_mark_node : nreverse (asm_operands); |
29079 | } |
29080 | |
29081 | /* Parse an asm-clobber-list. |
29082 | |
29083 | asm-clobber-list: |
29084 | string-literal |
29085 | asm-clobber-list , string-literal |
29086 | |
29087 | Returns a TREE_LIST, indicating the clobbers in the order that they |
29088 | appeared. The TREE_VALUE of each node is a STRING_CST. */ |
29089 | |
29090 | static tree |
29091 | cp_parser_asm_clobber_list (cp_parser* parser) |
29092 | { |
29093 | tree clobbers = NULL_TREE; |
29094 | |
29095 | while (true) |
29096 | { |
29097 | /* Look for the string literal. */ |
29098 | tree string_literal = cp_parser_string_literal (parser, |
29099 | /*translate=*/false, |
29100 | /*wide_ok=*/false); |
29101 | /* Add it to the list. */ |
29102 | clobbers = tree_cons (NULL_TREE, string_literal, clobbers); |
29103 | /* If the next token is not a `,', then the list is |
29104 | complete. */ |
29105 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29106 | break; |
29107 | /* Consume the `,' token. */ |
29108 | cp_lexer_consume_token (lexer: parser->lexer); |
29109 | } |
29110 | |
29111 | return clobbers; |
29112 | } |
29113 | |
29114 | /* Parse an asm-label-list. |
29115 | |
29116 | asm-label-list: |
29117 | identifier |
29118 | asm-label-list , identifier |
29119 | |
29120 | Returns a TREE_LIST, indicating the labels in the order that they |
29121 | appeared. The TREE_VALUE of each node is a label. */ |
29122 | |
29123 | static tree |
29124 | cp_parser_asm_label_list (cp_parser* parser) |
29125 | { |
29126 | tree labels = NULL_TREE; |
29127 | |
29128 | while (true) |
29129 | { |
29130 | tree identifier, label, name; |
29131 | |
29132 | /* Look for the identifier. */ |
29133 | identifier = cp_parser_identifier (parser); |
29134 | if (!error_operand_p (t: identifier)) |
29135 | { |
29136 | label = lookup_label (identifier); |
29137 | if (TREE_CODE (label) == LABEL_DECL) |
29138 | { |
29139 | TREE_USED (label) = 1; |
29140 | check_goto (label); |
29141 | name = build_string (IDENTIFIER_LENGTH (identifier), |
29142 | IDENTIFIER_POINTER (identifier)); |
29143 | labels = tree_cons (name, label, labels); |
29144 | } |
29145 | } |
29146 | /* If the next token is not a `,', then the list is |
29147 | complete. */ |
29148 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29149 | break; |
29150 | /* Consume the `,' token. */ |
29151 | cp_lexer_consume_token (lexer: parser->lexer); |
29152 | } |
29153 | |
29154 | return nreverse (labels); |
29155 | } |
29156 | |
29157 | /* Return TRUE iff the next tokens in the stream are possibly the |
29158 | beginning of a GNU extension attribute. */ |
29159 | |
29160 | static bool |
29161 | cp_next_tokens_can_be_gnu_attribute_p (cp_parser *parser) |
29162 | { |
29163 | return cp_nth_tokens_can_be_gnu_attribute_p (parser, 1); |
29164 | } |
29165 | |
29166 | /* Return TRUE iff the next tokens in the stream are possibly the |
29167 | beginning of a standard C++-11 attribute specifier. */ |
29168 | |
29169 | static bool |
29170 | cp_next_tokens_can_be_std_attribute_p (cp_parser *parser) |
29171 | { |
29172 | return cp_nth_tokens_can_be_std_attribute_p (parser, 1); |
29173 | } |
29174 | |
29175 | /* Return TRUE iff the next Nth tokens in the stream are possibly the |
29176 | beginning of a standard C++-11 attribute specifier. */ |
29177 | |
29178 | static bool |
29179 | cp_nth_tokens_can_be_std_attribute_p (cp_parser *parser, size_t n) |
29180 | { |
29181 | cp_token *token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
29182 | |
29183 | return (cxx_dialect >= cxx11 |
29184 | && ((token->type == CPP_KEYWORD && token->keyword == RID_ALIGNAS) |
29185 | || (token->type == CPP_OPEN_SQUARE |
29186 | && (token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n + 1)) |
29187 | && token->type == CPP_OPEN_SQUARE))); |
29188 | } |
29189 | |
29190 | /* Return TRUE iff the next Nth tokens in the stream are possibly the |
29191 | beginning of a GNU extension attribute. */ |
29192 | |
29193 | static bool |
29194 | cp_nth_tokens_can_be_gnu_attribute_p (cp_parser *parser, size_t n) |
29195 | { |
29196 | cp_token *token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
29197 | |
29198 | return token->type == CPP_KEYWORD && token->keyword == RID_ATTRIBUTE; |
29199 | } |
29200 | |
29201 | /* Return true iff the next tokens can be the beginning of either a |
29202 | GNU attribute list, or a standard C++11 attribute sequence. */ |
29203 | |
29204 | static bool |
29205 | cp_next_tokens_can_be_attribute_p (cp_parser *parser) |
29206 | { |
29207 | return (cp_next_tokens_can_be_gnu_attribute_p (parser) |
29208 | || cp_next_tokens_can_be_std_attribute_p (parser)); |
29209 | } |
29210 | |
29211 | /* Return true iff the next Nth tokens can be the beginning of either |
29212 | a GNU attribute list, or a standard C++11 attribute sequence. */ |
29213 | |
29214 | static bool |
29215 | cp_nth_tokens_can_be_attribute_p (cp_parser *parser, size_t n) |
29216 | { |
29217 | return (cp_nth_tokens_can_be_gnu_attribute_p (parser, n) |
29218 | || cp_nth_tokens_can_be_std_attribute_p (parser, n)); |
29219 | } |
29220 | |
29221 | /* Parse either a standard C++-11 attribute-specifier-seq, or a series |
29222 | of GNU attributes, or return NULL. */ |
29223 | |
29224 | static tree |
29225 | cp_parser_attributes_opt (cp_parser *parser) |
29226 | { |
29227 | tree attrs = NULL_TREE; |
29228 | while (true) |
29229 | { |
29230 | if (cp_next_tokens_can_be_gnu_attribute_p (parser)) |
29231 | attrs = attr_chainon (attrs, attr: cp_parser_gnu_attributes_opt (parser)); |
29232 | else if (cp_next_tokens_can_be_std_attribute_p (parser)) |
29233 | attrs = attr_chainon (attrs, attr: cp_parser_std_attribute_spec_seq (parser)); |
29234 | else |
29235 | break; |
29236 | } |
29237 | return attrs; |
29238 | } |
29239 | |
29240 | /* Parse an (optional) series of attributes. |
29241 | |
29242 | attributes: |
29243 | attributes attribute |
29244 | |
29245 | attribute: |
29246 | __attribute__ (( attribute-list [opt] )) |
29247 | |
29248 | The return value is as for cp_parser_gnu_attribute_list. */ |
29249 | |
29250 | static tree |
29251 | cp_parser_gnu_attributes_opt (cp_parser* parser) |
29252 | { |
29253 | tree attributes = NULL_TREE; |
29254 | |
29255 | auto cleanup = make_temp_override |
29256 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
29257 | |
29258 | while (true) |
29259 | { |
29260 | cp_token *token; |
29261 | tree attribute_list; |
29262 | bool ok = true; |
29263 | |
29264 | /* Peek at the next token. */ |
29265 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29266 | /* If it's not `__attribute__', then we're done. */ |
29267 | if (token->keyword != RID_ATTRIBUTE) |
29268 | break; |
29269 | |
29270 | /* Consume the `__attribute__' keyword. */ |
29271 | cp_lexer_consume_token (lexer: parser->lexer); |
29272 | /* Look for the two `(' tokens. */ |
29273 | matching_parens outer_parens; |
29274 | if (!outer_parens.require_open (parser)) |
29275 | ok = false; |
29276 | matching_parens inner_parens; |
29277 | if (!inner_parens.require_open (parser)) |
29278 | ok = false; |
29279 | |
29280 | /* Peek at the next token. */ |
29281 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29282 | if (token->type != CPP_CLOSE_PAREN) |
29283 | /* Parse the attribute-list. */ |
29284 | attribute_list = cp_parser_gnu_attribute_list (parser); |
29285 | else |
29286 | /* If the next token is a `)', then there is no attribute |
29287 | list. */ |
29288 | attribute_list = NULL; |
29289 | |
29290 | /* Look for the two `)' tokens. */ |
29291 | if (!inner_parens.require_close (parser)) |
29292 | ok = false; |
29293 | if (!outer_parens.require_close (parser)) |
29294 | ok = false; |
29295 | if (!ok) |
29296 | cp_parser_skip_to_end_of_statement (parser); |
29297 | |
29298 | /* Add these new attributes to the list. */ |
29299 | attributes = attr_chainon (attrs: attributes, attr: attribute_list); |
29300 | } |
29301 | |
29302 | return attributes; |
29303 | } |
29304 | |
29305 | /* Parse a GNU attribute-list. |
29306 | |
29307 | attribute-list: |
29308 | attribute |
29309 | attribute-list , attribute |
29310 | |
29311 | attribute: |
29312 | identifier |
29313 | identifier ( identifier ) |
29314 | identifier ( identifier , expression-list ) |
29315 | identifier ( expression-list ) |
29316 | |
29317 | Returns a TREE_LIST, or NULL_TREE on error. Each node corresponds |
29318 | to an attribute. The TREE_PURPOSE of each node is the identifier |
29319 | indicating which attribute is in use. The TREE_VALUE represents |
29320 | the arguments, if any. */ |
29321 | |
29322 | static tree |
29323 | cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) |
29324 | { |
29325 | tree attribute_list = NULL_TREE; |
29326 | bool save_translate_strings_p = parser->translate_strings_p; |
29327 | |
29328 | /* Don't create wrapper nodes within attributes: the |
29329 | handlers don't know how to handle them. */ |
29330 | auto_suppress_location_wrappers sentinel; |
29331 | |
29332 | parser->translate_strings_p = false; |
29333 | while (true) |
29334 | { |
29335 | cp_token *token; |
29336 | tree identifier; |
29337 | tree attribute; |
29338 | |
29339 | /* Look for the identifier. We also allow keywords here; for |
29340 | example `__attribute__ ((const))' is legal. */ |
29341 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29342 | if (token->type == CPP_NAME |
29343 | || token->type == CPP_KEYWORD) |
29344 | { |
29345 | tree arguments = NULL_TREE; |
29346 | |
29347 | /* Consume the token, but save it since we need it for the |
29348 | SIMD enabled function parsing. */ |
29349 | cp_token *id_token = cp_lexer_consume_token (lexer: parser->lexer); |
29350 | |
29351 | /* Save away the identifier that indicates which attribute |
29352 | this is. */ |
29353 | identifier = (token->type == CPP_KEYWORD) |
29354 | /* For keywords, use the canonical spelling, not the |
29355 | parsed identifier. */ |
29356 | ? ridpointers[(int) token->keyword] |
29357 | : id_token->u.value; |
29358 | |
29359 | identifier = canonicalize_attr_name (attr_name: identifier); |
29360 | attribute = build_tree_list (identifier, NULL_TREE); |
29361 | |
29362 | /* Peek at the next token. */ |
29363 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29364 | /* If it's an `(', then parse the attribute arguments. */ |
29365 | if (token->type == CPP_OPEN_PAREN) |
29366 | { |
29367 | vec<tree, va_gc> *vec; |
29368 | int attr_flag = (attribute_takes_identifier_p (identifier) |
29369 | ? id_attr : normal_attr); |
29370 | if (is_attribute_p (attr_name: "assume" , ident: identifier)) |
29371 | attr_flag = assume_attr; |
29372 | vec = cp_parser_parenthesized_expression_list |
29373 | (parser, is_attribute_list: attr_flag, /*cast_p=*/false, |
29374 | /*allow_expansion_p=*/false, |
29375 | /*non_constant_p=*/NULL); |
29376 | if (vec == NULL) |
29377 | arguments = error_mark_node; |
29378 | else |
29379 | { |
29380 | arguments = build_tree_list_vec (vec); |
29381 | release_tree_vector (vec); |
29382 | } |
29383 | /* Save the arguments away. */ |
29384 | TREE_VALUE (attribute) = arguments; |
29385 | } |
29386 | |
29387 | if (arguments != error_mark_node) |
29388 | { |
29389 | /* Add this attribute to the list. */ |
29390 | TREE_CHAIN (attribute) = attribute_list; |
29391 | attribute_list = attribute; |
29392 | } |
29393 | |
29394 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29395 | } |
29396 | /* Unless EXACTLY_ONE is set look for more attributes. |
29397 | If the next token isn't a `,', we're done. */ |
29398 | if (exactly_one || token->type != CPP_COMMA) |
29399 | break; |
29400 | |
29401 | /* Consume the comma and keep going. */ |
29402 | cp_lexer_consume_token (lexer: parser->lexer); |
29403 | } |
29404 | parser->translate_strings_p = save_translate_strings_p; |
29405 | |
29406 | /* We built up the list in reverse order. */ |
29407 | return nreverse (attribute_list); |
29408 | } |
29409 | |
29410 | /* Parse arguments of omp::directive attribute. |
29411 | |
29412 | ( directive-name ,[opt] clause-list[opt] ) |
29413 | |
29414 | For directive just remember the first/last tokens for subsequent |
29415 | parsing. */ |
29416 | |
29417 | static void |
29418 | cp_parser_omp_directive_args (cp_parser *parser, tree attribute, bool decl_p) |
29419 | { |
29420 | cp_token *first = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
29421 | if (first->type == CPP_CLOSE_PAREN) |
29422 | { |
29423 | cp_lexer_consume_token (lexer: parser->lexer); |
29424 | error_at (first->location, "expected OpenMP directive name" ); |
29425 | cp_lexer_consume_token (lexer: parser->lexer); |
29426 | TREE_VALUE (attribute) = NULL_TREE; |
29427 | return; |
29428 | } |
29429 | size_t n = cp_parser_skip_balanced_tokens (parser, 1); |
29430 | if (n == 1) |
29431 | { |
29432 | cp_lexer_consume_token (lexer: parser->lexer); |
29433 | error_at (first->location, "expected attribute argument as balanced " |
29434 | "token sequence" ); |
29435 | TREE_VALUE (attribute) = NULL_TREE; |
29436 | return; |
29437 | } |
29438 | for (n = n - 2; n; --n) |
29439 | cp_lexer_consume_token (lexer: parser->lexer); |
29440 | cp_token *last = cp_lexer_peek_token (lexer: parser->lexer); |
29441 | cp_lexer_consume_token (lexer: parser->lexer); |
29442 | tree arg = make_node (DEFERRED_PARSE); |
29443 | DEFPARSE_TOKENS (arg) = cp_token_cache_new (first, last); |
29444 | DEFPARSE_INSTANTIATIONS (arg) = nullptr; |
29445 | if (decl_p) |
29446 | TREE_PUBLIC (arg) = 1; |
29447 | TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute)); |
29448 | } |
29449 | |
29450 | /* Parse arguments of omp::sequence attribute. |
29451 | |
29452 | ( omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... ) */ |
29453 | |
29454 | static void |
29455 | cp_parser_omp_sequence_args (cp_parser *parser, tree attribute) |
29456 | { |
29457 | matching_parens parens; |
29458 | parens.consume_open (parser); |
29459 | do |
29460 | { |
29461 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29462 | if (token->type == CPP_NAME |
29463 | && token->u.value == omp_identifier |
29464 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_SCOPE)) |
29465 | { |
29466 | cp_lexer_consume_token (lexer: parser->lexer); |
29467 | cp_lexer_consume_token (lexer: parser->lexer); |
29468 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29469 | } |
29470 | bool directive = false; |
29471 | const char *p; |
29472 | if (token->type != CPP_NAME) |
29473 | p = "" ; |
29474 | else |
29475 | p = IDENTIFIER_POINTER (token->u.value); |
29476 | if (strcmp (s1: p, s2: "directive" ) == 0) |
29477 | directive = true; |
29478 | else if (strcmp (s1: p, s2: "sequence" ) != 0) |
29479 | { |
29480 | error_at (token->location, "expected %<directive%> or %<sequence%>" ); |
29481 | cp_parser_skip_to_closing_parenthesis (parser, |
29482 | /*recovering=*/true, |
29483 | /*or_comma=*/true, |
29484 | /*consume_paren=*/false); |
29485 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29486 | break; |
29487 | cp_lexer_consume_token (lexer: parser->lexer); |
29488 | } |
29489 | cp_lexer_consume_token (lexer: parser->lexer); |
29490 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
29491 | cp_parser_required_error (parser, RT_OPEN_PAREN, false, |
29492 | UNKNOWN_LOCATION); |
29493 | else if (directive) |
29494 | cp_parser_omp_directive_args (parser, attribute, decl_p: false); |
29495 | else |
29496 | cp_parser_omp_sequence_args (parser, attribute); |
29497 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
29498 | break; |
29499 | cp_lexer_consume_token (lexer: parser->lexer); |
29500 | } |
29501 | while (1); |
29502 | if (!parens.require_close (parser)) |
29503 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, |
29504 | /*consume_paren=*/true); |
29505 | } |
29506 | |
29507 | /* Parse a standard C++11 attribute. |
29508 | |
29509 | The returned representation is a TREE_LIST which TREE_PURPOSE is |
29510 | the scoped name of the attribute, and the TREE_VALUE is its |
29511 | arguments list. |
29512 | |
29513 | Note that the scoped name of the attribute is itself a TREE_LIST |
29514 | which TREE_PURPOSE is the namespace of the attribute, and |
29515 | TREE_VALUE its name. This is unlike a GNU attribute -- as parsed |
29516 | by cp_parser_gnu_attribute_list -- that doesn't have any namespace |
29517 | and which TREE_PURPOSE is directly the attribute name. |
29518 | |
29519 | Clients of the attribute code should use get_attribute_namespace |
29520 | and get_attribute_name to get the actual namespace and name of |
29521 | attributes, regardless of their being GNU or C++11 attributes. |
29522 | |
29523 | attribute: |
29524 | attribute-token attribute-argument-clause [opt] |
29525 | |
29526 | attribute-token: |
29527 | identifier |
29528 | attribute-scoped-token |
29529 | |
29530 | attribute-scoped-token: |
29531 | attribute-namespace :: identifier |
29532 | |
29533 | attribute-namespace: |
29534 | identifier |
29535 | |
29536 | attribute-argument-clause: |
29537 | ( balanced-token-seq ) |
29538 | |
29539 | balanced-token-seq: |
29540 | balanced-token [opt] |
29541 | balanced-token-seq balanced-token |
29542 | |
29543 | balanced-token: |
29544 | ( balanced-token-seq ) |
29545 | [ balanced-token-seq ] |
29546 | { balanced-token-seq }. */ |
29547 | |
29548 | static tree |
29549 | cp_parser_std_attribute (cp_parser *parser, tree attr_ns) |
29550 | { |
29551 | tree attribute, attr_id = NULL_TREE, arguments; |
29552 | cp_token *token; |
29553 | |
29554 | auto cleanup = make_temp_override |
29555 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
29556 | |
29557 | /* First, parse name of the attribute, a.k.a attribute-token. */ |
29558 | |
29559 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29560 | if (token->type == CPP_NAME) |
29561 | attr_id = token->u.value; |
29562 | else if (token->type == CPP_KEYWORD) |
29563 | attr_id = ridpointers[(int) token->keyword]; |
29564 | else if (token->flags & NAMED_OP) |
29565 | attr_id = get_identifier (cpp_type2name (token->type, token->flags)); |
29566 | |
29567 | if (attr_id == NULL_TREE) |
29568 | return NULL_TREE; |
29569 | |
29570 | cp_lexer_consume_token (lexer: parser->lexer); |
29571 | |
29572 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29573 | if (token->type == CPP_SCOPE) |
29574 | { |
29575 | /* We are seeing a scoped attribute token. */ |
29576 | |
29577 | cp_lexer_consume_token (lexer: parser->lexer); |
29578 | if (attr_ns) |
29579 | error_at (token->location, "attribute using prefix used together " |
29580 | "with scoped attribute token" ); |
29581 | attr_ns = attr_id; |
29582 | |
29583 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29584 | if (token->type == CPP_NAME) |
29585 | attr_id = token->u.value; |
29586 | else if (token->type == CPP_KEYWORD) |
29587 | attr_id = ridpointers[(int) token->keyword]; |
29588 | else if (token->flags & NAMED_OP) |
29589 | attr_id = get_identifier (cpp_type2name (token->type, token->flags)); |
29590 | else |
29591 | { |
29592 | error_at (token->location, |
29593 | "expected an identifier for the attribute name" ); |
29594 | return error_mark_node; |
29595 | } |
29596 | cp_lexer_consume_token (lexer: parser->lexer); |
29597 | |
29598 | attr_ns = canonicalize_attr_name (attr_name: attr_ns); |
29599 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
29600 | attribute = build_tree_list (build_tree_list (attr_ns, attr_id), |
29601 | NULL_TREE); |
29602 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29603 | } |
29604 | else if (attr_ns) |
29605 | { |
29606 | attr_ns = canonicalize_attr_name (attr_name: attr_ns); |
29607 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
29608 | attribute = build_tree_list (build_tree_list (attr_ns, attr_id), |
29609 | NULL_TREE); |
29610 | } |
29611 | else |
29612 | { |
29613 | attr_id = canonicalize_attr_name (attr_name: attr_id); |
29614 | attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), |
29615 | NULL_TREE); |
29616 | |
29617 | /* We used to treat C++11 noreturn attribute as equivalent to GNU's, |
29618 | but no longer: we have to be able to tell [[noreturn]] and |
29619 | __attribute__((noreturn)) apart. */ |
29620 | /* C++14 deprecated attribute is equivalent to GNU's. */ |
29621 | if (is_attribute_p (attr_name: "deprecated" , ident: attr_id)) |
29622 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
29623 | /* C++17 fallthrough attribute is equivalent to GNU's. */ |
29624 | else if (is_attribute_p (attr_name: "fallthrough" , ident: attr_id)) |
29625 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
29626 | /* C++23 assume attribute is equivalent to GNU's. */ |
29627 | else if (is_attribute_p (attr_name: "assume" , ident: attr_id)) |
29628 | TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; |
29629 | /* Transactional Memory TS optimize_for_synchronized attribute is |
29630 | equivalent to GNU transaction_callable. */ |
29631 | else if (is_attribute_p (attr_name: "optimize_for_synchronized" , ident: attr_id)) |
29632 | TREE_PURPOSE (attribute) |
29633 | = get_identifier ("transaction_callable" ); |
29634 | /* Transactional Memory attributes are GNU attributes. */ |
29635 | else if (tm_attr_to_mask (attr_id)) |
29636 | TREE_PURPOSE (attribute) = attr_id; |
29637 | } |
29638 | |
29639 | /* Now parse the optional argument clause of the attribute. */ |
29640 | |
29641 | if (token->type != CPP_OPEN_PAREN) |
29642 | { |
29643 | if ((flag_openmp || flag_openmp_simd) |
29644 | && attr_ns == omp_identifier |
29645 | && (is_attribute_p (attr_name: "directive" , ident: attr_id) |
29646 | || is_attribute_p (attr_name: "sequence" , ident: attr_id) |
29647 | || is_attribute_p (attr_name: "decl" , ident: attr_id))) |
29648 | { |
29649 | error_at (token->location, "%<omp::%E%> attribute requires argument" , |
29650 | attr_id); |
29651 | return NULL_TREE; |
29652 | } |
29653 | return attribute; |
29654 | } |
29655 | |
29656 | { |
29657 | vec<tree, va_gc> *vec; |
29658 | int attr_flag = normal_attr; |
29659 | |
29660 | /* Maybe we don't expect to see any arguments for this attribute. */ |
29661 | const attribute_spec *as |
29662 | = lookup_attribute_spec (TREE_PURPOSE (attribute)); |
29663 | if (as && as->max_length == 0) |
29664 | { |
29665 | error_at (token->location, "%qE attribute does not take any arguments" , |
29666 | attr_id); |
29667 | cp_parser_skip_to_closing_parenthesis (parser, |
29668 | /*recovering=*/true, |
29669 | /*or_comma=*/false, |
29670 | /*consume_paren=*/true); |
29671 | return error_mark_node; |
29672 | } |
29673 | |
29674 | if (is_attribute_p (attr_name: "assume" , ident: attr_id) |
29675 | && (attr_ns == NULL_TREE || attr_ns == gnu_identifier)) |
29676 | /* The assume attribute needs special handling of the argument. */ |
29677 | attr_flag = assume_attr; |
29678 | else if (attr_ns == gnu_identifier |
29679 | && attribute_takes_identifier_p (attr_id)) |
29680 | /* A GNU attribute that takes an identifier in parameter. */ |
29681 | attr_flag = id_attr; |
29682 | else if (attr_ns == NULL_TREE |
29683 | && cxx_dialect >= cxx26 |
29684 | && (is_attribute_p (attr_name: "deprecated" , ident: attr_id) |
29685 | || is_attribute_p (attr_name: "nodiscard" , ident: attr_id))) |
29686 | attr_flag = uneval_string_attr; |
29687 | |
29688 | /* If this is a fake attribute created to handle -Wno-attributes, |
29689 | we must skip parsing the arguments. */ |
29690 | if (as == NULL || attribute_ignored_p (as)) |
29691 | { |
29692 | if ((flag_openmp || flag_openmp_simd) && attr_ns == omp_identifier) |
29693 | { |
29694 | if (is_attribute_p (attr_name: "directive" , ident: attr_id)) |
29695 | { |
29696 | cp_parser_omp_directive_args (parser, attribute, decl_p: false); |
29697 | return attribute; |
29698 | } |
29699 | else if (is_attribute_p (attr_name: "decl" , ident: attr_id)) |
29700 | { |
29701 | TREE_VALUE (TREE_PURPOSE (attribute)) |
29702 | = get_identifier ("directive" ); |
29703 | cp_parser_omp_directive_args (parser, attribute, decl_p: true); |
29704 | return attribute; |
29705 | } |
29706 | else if (is_attribute_p (attr_name: "sequence" , ident: attr_id)) |
29707 | { |
29708 | TREE_VALUE (TREE_PURPOSE (attribute)) |
29709 | = get_identifier ("directive" ); |
29710 | cp_parser_omp_sequence_args (parser, attribute); |
29711 | TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute)); |
29712 | return attribute; |
29713 | } |
29714 | } |
29715 | |
29716 | /* For unknown attributes, just skip balanced tokens instead of |
29717 | trying to parse the arguments. Set TREE_VALUE (attribute) to |
29718 | error_mark_node to distinguish skipped arguments from attributes |
29719 | with no arguments. */ |
29720 | for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n) |
29721 | cp_lexer_consume_token (lexer: parser->lexer); |
29722 | TREE_VALUE (attribute) = error_mark_node; |
29723 | return attribute; |
29724 | } |
29725 | |
29726 | vec = cp_parser_parenthesized_expression_list |
29727 | (parser, is_attribute_list: attr_flag, /*cast_p=*/false, |
29728 | /*allow_expansion_p=*/true, |
29729 | /*non_constant_p=*/NULL); |
29730 | if (vec == NULL) |
29731 | arguments = error_mark_node; |
29732 | else |
29733 | { |
29734 | if (vec->is_empty ()) |
29735 | /* e.g. [[attr()]]. */ |
29736 | error_at (token->location, "parentheses must be omitted if " |
29737 | "%qE attribute argument list is empty" , |
29738 | attr_id); |
29739 | arguments = build_tree_list_vec (vec); |
29740 | release_tree_vector (vec); |
29741 | } |
29742 | |
29743 | if (arguments == error_mark_node) |
29744 | attribute = error_mark_node; |
29745 | else |
29746 | TREE_VALUE (attribute) = arguments; |
29747 | } |
29748 | |
29749 | return attribute; |
29750 | } |
29751 | |
29752 | /* Warn if the attribute ATTRIBUTE appears more than once in the |
29753 | attribute-list ATTRIBUTES. This used to be enforced for certain |
29754 | attributes, but the restriction was removed in P2156. |
29755 | LOC is the location of ATTRIBUTE. Returns true if ATTRIBUTE was not |
29756 | found in ATTRIBUTES. */ |
29757 | |
29758 | static bool |
29759 | cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute) |
29760 | { |
29761 | static auto alist = { "noreturn" , "deprecated" , "nodiscard" , "maybe_unused" , |
29762 | "likely" , "unlikely" , "fallthrough" , |
29763 | "no_unique_address" , "carries_dependency" }; |
29764 | if (attributes) |
29765 | for (const auto &a : alist) |
29766 | if (is_attribute_p (attr_name: a, ident: get_attribute_name (attribute)) |
29767 | && is_attribute_namespace_p (attr_ns: "" , attr: attribute) |
29768 | && lookup_attribute (attr_ns: "" , attr_name: a, list: attributes)) |
29769 | { |
29770 | if (!from_macro_expansion_at (loc)) |
29771 | warning_at (loc, OPT_Wattributes, "attribute %qs specified " |
29772 | "multiple times" , a); |
29773 | return false; |
29774 | } |
29775 | return true; |
29776 | } |
29777 | |
29778 | /* Parse a list of standard C++-11 attributes. |
29779 | |
29780 | attribute-list: |
29781 | attribute [opt] |
29782 | attribute-list , attribute[opt] |
29783 | attribute ... |
29784 | attribute-list , attribute ... |
29785 | */ |
29786 | |
29787 | static tree |
29788 | cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns) |
29789 | { |
29790 | tree attributes = NULL_TREE, attribute = NULL_TREE; |
29791 | cp_token *token = NULL; |
29792 | |
29793 | while (true) |
29794 | { |
29795 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
29796 | attribute = cp_parser_std_attribute (parser, attr_ns); |
29797 | if (attribute == error_mark_node) |
29798 | break; |
29799 | if (attribute != NULL_TREE) |
29800 | { |
29801 | if (cp_parser_check_std_attribute (loc, attributes, attribute)) |
29802 | { |
29803 | TREE_CHAIN (attribute) = attributes; |
29804 | attributes = attribute; |
29805 | } |
29806 | } |
29807 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29808 | if (token->type == CPP_ELLIPSIS) |
29809 | { |
29810 | cp_lexer_consume_token (lexer: parser->lexer); |
29811 | if (attribute == NULL_TREE) |
29812 | error_at (token->location, |
29813 | "expected attribute before %<...%>" ); |
29814 | else if (TREE_VALUE (attribute) == NULL_TREE) |
29815 | { |
29816 | error_at (token->location, "attribute with no arguments " |
29817 | "contains no parameter packs" ); |
29818 | return error_mark_node; |
29819 | } |
29820 | else if (TREE_VALUE (attribute) != error_mark_node) |
29821 | { |
29822 | tree pack = make_pack_expansion (TREE_VALUE (attribute)); |
29823 | if (pack == error_mark_node) |
29824 | return error_mark_node; |
29825 | TREE_VALUE (attribute) = pack; |
29826 | } |
29827 | token = cp_lexer_peek_token (lexer: parser->lexer); |
29828 | } |
29829 | if (token->type != CPP_COMMA) |
29830 | break; |
29831 | cp_lexer_consume_token (lexer: parser->lexer); |
29832 | } |
29833 | attributes = nreverse (attributes); |
29834 | return attributes; |
29835 | } |
29836 | |
29837 | /* Optionally parse a C++20 contract role. A NULL return means that no |
29838 | contract role was specified. |
29839 | |
29840 | contract-role: |
29841 | % default |
29842 | % identifier |
29843 | |
29844 | If the identifier does not name a known contract role, it will |
29845 | be assumed to be default. Returns the identifier for the role |
29846 | token. */ |
29847 | |
29848 | static tree |
29849 | cp_parser_contract_role (cp_parser *parser) |
29850 | { |
29851 | gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_MOD)); |
29852 | cp_lexer_consume_token (lexer: parser->lexer); |
29853 | |
29854 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29855 | tree role_id = NULL_TREE; |
29856 | if (token->type == CPP_NAME) |
29857 | role_id = token->u.value; |
29858 | else if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT) |
29859 | role_id = get_identifier ("default" ); |
29860 | else |
29861 | { |
29862 | error_at (token->location, "expected contract-role" ); |
29863 | return error_mark_node; |
29864 | } |
29865 | cp_lexer_consume_token (lexer: parser->lexer); |
29866 | |
29867 | /* FIXME: Warn about invalid/unknown roles? */ |
29868 | return role_id; |
29869 | } |
29870 | |
29871 | /* Parse an optional contract mode. |
29872 | |
29873 | contract-mode: |
29874 | contract-semantic |
29875 | [contract-level] [contract-role] |
29876 | |
29877 | contract-semantic: |
29878 | check_never_continue |
29879 | check_maybe_continue |
29880 | check_always_continue |
29881 | |
29882 | contract-level: |
29883 | default |
29884 | audit |
29885 | axiom |
29886 | |
29887 | contract-role: |
29888 | default |
29889 | identifier |
29890 | |
29891 | This grammar is taken from P1332R0. During parsing, this sets options |
29892 | on the MODE object to determine the configuration of the contract. |
29893 | |
29894 | Returns a tree containing the identifiers used in the configuration. |
29895 | This is either an IDENTIFIER with the literal semantic or a TREE_LIST |
29896 | whose TREE_VALUE is the contract-level and whose TREE_PURPOSE is the |
29897 | contract-role, if any. NULL_TREE is returned if no information is |
29898 | given (i.e., all defaults selected). */ |
29899 | |
29900 | static tree |
29901 | cp_parser_contract_mode_opt (cp_parser *parser, |
29902 | bool postcondition_p) |
29903 | { |
29904 | /* The mode is empty; the level and role are default. */ |
29905 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
29906 | return NULL_TREE; |
29907 | |
29908 | /* There is only a role; the level is default. */ |
29909 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
29910 | { |
29911 | tree role_id = cp_parser_contract_role (parser); |
29912 | return build_tree_list (role_id, get_identifier ("default" )); |
29913 | } |
29914 | |
29915 | /* Otherwise, match semantic or level. */ |
29916 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
29917 | contract_level level = CONTRACT_INVALID; |
29918 | contract_semantic semantic = CCS_INVALID; |
29919 | tree config_id; |
29920 | if (token->type == CPP_NAME) |
29921 | { |
29922 | config_id = token->u.value; |
29923 | |
29924 | /* Either a named level, a concrete semantic, or an identifier |
29925 | for a postcondition. */ |
29926 | const char *ident = IDENTIFIER_POINTER (token->u.value); |
29927 | level = map_contract_level (ident); |
29928 | semantic = map_contract_semantic (ident); |
29929 | |
29930 | /* The identifier is the return value for a postcondition. */ |
29931 | if (level == CONTRACT_INVALID && semantic == CCS_INVALID |
29932 | && postcondition_p) |
29933 | return NULL_TREE; |
29934 | } |
29935 | else if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT) |
29936 | { |
29937 | config_id = get_identifier ("default" ); |
29938 | level = CONTRACT_DEFAULT; |
29939 | } |
29940 | else |
29941 | { |
29942 | /* We got some other token other than a ':'. */ |
29943 | error_at (token->location, "expected contract semantic or level" ); |
29944 | return NULL_TREE; |
29945 | } |
29946 | |
29947 | /* Consume the literal semantic or level token. */ |
29948 | cp_lexer_consume_token (lexer: parser->lexer); |
29949 | |
29950 | if (semantic == CCS_INVALID && level == CONTRACT_INVALID) |
29951 | { |
29952 | error_at (token->location, |
29953 | "expected contract level: " |
29954 | "%<default%>, %<audit%>, or %<axiom%>" ); |
29955 | return NULL_TREE; |
29956 | } |
29957 | |
29958 | /* We matched an explicit semantic. */ |
29959 | if (semantic != CCS_INVALID) |
29960 | { |
29961 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
29962 | { |
29963 | error ("invalid use of contract role for explicit semantic" ); |
29964 | cp_lexer_consume_token (lexer: parser->lexer); |
29965 | cp_lexer_consume_token (lexer: parser->lexer); |
29966 | } |
29967 | return config_id; |
29968 | } |
29969 | |
29970 | /* We matched a level, there may be a role; otherwise this is default. */ |
29971 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MOD)) |
29972 | { |
29973 | tree role_id = cp_parser_contract_role (parser); |
29974 | return build_tree_list (role_id, config_id); |
29975 | } |
29976 | |
29977 | return build_tree_list (NULL_TREE, config_id); |
29978 | } |
29979 | |
29980 | static tree |
29981 | find_error (tree *tp, int *, void *) |
29982 | { |
29983 | if (*tp == error_mark_node) |
29984 | return *tp; |
29985 | return NULL_TREE; |
29986 | } |
29987 | |
29988 | static bool |
29989 | contains_error_p (tree t) |
29990 | { |
29991 | return walk_tree (&t, find_error, NULL, NULL); |
29992 | } |
29993 | |
29994 | /* Parse a standard C++20 contract attribute specifier. |
29995 | |
29996 | contract-attribute-specifier: |
29997 | [ [ assert contract-level [opt] : conditional-expression ] ] |
29998 | [ [ pre contract-level [opt] : conditional-expression ] ] |
29999 | [ [ post contract-level [opt] identifier [opt] : conditional-expression ] ] |
30000 | |
30001 | For free functions, we cannot determine the type of the postcondition |
30002 | identifier because the we haven't called grokdeclarator yet. In those |
30003 | cases we parse the postcondition as if the identifier was declared as |
30004 | 'auto <identifier>'. We then instantiate the postcondition once the |
30005 | return type is known. |
30006 | |
30007 | For member functions, contracts are in the complete-class context, so the |
30008 | parse is deferred. We also have the return type avaialable (unless it's |
30009 | deduced), so we don't need to parse the postcondition in terms of a |
30010 | placeholder. */ |
30011 | |
30012 | static tree |
30013 | cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute) |
30014 | { |
30015 | gcc_assert (contract_attribute_p (attribute)); |
30016 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
30017 | location_t loc = token->location; |
30018 | |
30019 | bool assertion_p = is_attribute_p (attr_name: "assert" , ident: attribute); |
30020 | bool postcondition_p = is_attribute_p (attr_name: "post" , ident: attribute); |
30021 | |
30022 | /* Parse the optional mode. */ |
30023 | tree mode = cp_parser_contract_mode_opt (parser, postcondition_p); |
30024 | |
30025 | /* Check for postcondition identifiers. */ |
30026 | cp_expr identifier; |
30027 | if (postcondition_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
30028 | identifier = cp_parser_identifier (parser); |
30029 | if (identifier == error_mark_node) |
30030 | return error_mark_node; |
30031 | |
30032 | cp_parser_require (parser, CPP_COLON, RT_COLON); |
30033 | |
30034 | /* Defer the parsing of pre/post contracts inside class definitions. */ |
30035 | tree contract; |
30036 | if (!assertion_p && |
30037 | current_class_type && |
30038 | TYPE_BEING_DEFINED (current_class_type)) |
30039 | { |
30040 | /* Skip until we reach an unenclose ']'. If we ran into an unnested ']' |
30041 | that doesn't close the attribute, return an error and let the attribute |
30042 | handling code emit an error for missing ']]'. */ |
30043 | cp_token *first = cp_lexer_peek_token (lexer: parser->lexer); |
30044 | cp_parser_skip_to_closing_parenthesis_1 (parser, |
30045 | /*recovering=*/false, |
30046 | or_ttype: CPP_CLOSE_SQUARE, |
30047 | /*consume_paren=*/false); |
30048 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_CLOSE_SQUARE |
30049 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type != CPP_CLOSE_SQUARE) |
30050 | return error_mark_node; |
30051 | cp_token *last = cp_lexer_peek_token (lexer: parser->lexer); |
30052 | |
30053 | /* Build a deferred-parse node. */ |
30054 | tree condition = make_node (DEFERRED_PARSE); |
30055 | DEFPARSE_TOKENS (condition) = cp_token_cache_new (first, last); |
30056 | DEFPARSE_INSTANTIATIONS (condition) = NULL; |
30057 | |
30058 | /* And its corresponding contract. */ |
30059 | contract = grok_contract (attribute, mode, identifier, condition, loc); |
30060 | } |
30061 | else |
30062 | { |
30063 | /* Enable location wrappers when parsing contracts. */ |
30064 | auto suppression = make_temp_override (var&: suppress_location_wrappers, overrider: 0); |
30065 | |
30066 | /* Build a fake variable for the result identifier. */ |
30067 | tree result = NULL_TREE; |
30068 | if (identifier) |
30069 | { |
30070 | begin_scope (sk_block, NULL_TREE); |
30071 | result = make_postcondition_variable (identifier); |
30072 | ++processing_template_decl; |
30073 | } |
30074 | |
30075 | /* Parse the condition, ensuring that parameters or the return variable |
30076 | aren't flagged for use outside the body of a function. */ |
30077 | ++processing_contract_condition; |
30078 | cp_expr condition = cp_parser_conditional_expression (parser); |
30079 | --processing_contract_condition; |
30080 | |
30081 | /* Try to recover from errors by scanning up to the end of the |
30082 | attribute. Sometimes we get partially parsed expressions, so |
30083 | we need to search the condition for errors. */ |
30084 | if (contains_error_p (t: condition)) |
30085 | cp_parser_skip_up_to_closing_square_bracket (parser); |
30086 | |
30087 | /* Build the contract. */ |
30088 | contract = grok_contract (attribute, mode, result, condition, loc); |
30089 | |
30090 | /* Leave our temporary scope for the postcondition result. */ |
30091 | if (result) |
30092 | { |
30093 | --processing_template_decl; |
30094 | pop_bindings_and_leave_scope (); |
30095 | } |
30096 | } |
30097 | |
30098 | if (!flag_contracts) |
30099 | { |
30100 | error_at (loc, "contracts are only available with %<-fcontracts%>" ); |
30101 | return error_mark_node; |
30102 | } |
30103 | |
30104 | return finish_contract_attribute (attribute, contract); |
30105 | } |
30106 | |
30107 | /* Parse a contract condition for a deferred contract. */ |
30108 | |
30109 | void cp_parser_late_contract_condition (cp_parser *parser, |
30110 | tree fn, |
30111 | tree attribute) |
30112 | { |
30113 | tree contract = TREE_VALUE (TREE_VALUE (attribute)); |
30114 | |
30115 | /* Make sure we've gotten something that hasn't been parsed yet or that |
30116 | we're not parsing an invalid contract. */ |
30117 | tree condition = CONTRACT_CONDITION (contract); |
30118 | if (TREE_CODE (condition) != DEFERRED_PARSE) |
30119 | return; |
30120 | |
30121 | tree identifier = NULL_TREE; |
30122 | if (TREE_CODE (contract) == POSTCONDITION_STMT) |
30123 | identifier = POSTCONDITION_IDENTIFIER (contract); |
30124 | |
30125 | /* Build a fake variable for the result identifier. */ |
30126 | tree result = NULL_TREE; |
30127 | if (identifier) |
30128 | { |
30129 | /* TODO: Can we guarantee that the identifier has a location? */ |
30130 | location_t loc = cp_expr_location (t_: contract); |
30131 | tree type = TREE_TYPE (TREE_TYPE (fn)); |
30132 | if (!check_postcondition_result (fn, type, loc)) |
30133 | { |
30134 | invalidate_contract (contract); |
30135 | return; |
30136 | } |
30137 | |
30138 | begin_scope (sk_block, NULL_TREE); |
30139 | result = make_postcondition_variable (identifier, type); |
30140 | ++processing_template_decl; |
30141 | } |
30142 | |
30143 | /* 'this' is not allowed in preconditions of constructors or in postconditions |
30144 | of destructors. Note that the previous value of this variable is |
30145 | established by the calling function, so we need to save it here. */ |
30146 | tree saved_ccr = current_class_ref; |
30147 | tree saved_ccp = current_class_ptr; |
30148 | if ((DECL_CONSTRUCTOR_P (fn) && PRECONDITION_P (contract)) || |
30149 | (DECL_DESTRUCTOR_P (fn) && POSTCONDITION_P (contract))) |
30150 | { |
30151 | current_class_ref = current_class_ptr = NULL_TREE; |
30152 | parser->local_variables_forbidden_p |= THIS_FORBIDDEN; |
30153 | } |
30154 | |
30155 | push_unparsed_function_queues (parser); |
30156 | |
30157 | /* Push the saved tokens onto the parser's lexer stack. */ |
30158 | cp_token_cache *tokens = DEFPARSE_TOKENS (condition); |
30159 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
30160 | |
30161 | /* Parse the condition, ensuring that parameters or the return variable |
30162 | aren't flagged for use outside the body of a function. */ |
30163 | ++processing_contract_condition; |
30164 | condition = cp_parser_conditional_expression (parser); |
30165 | --processing_contract_condition; |
30166 | |
30167 | /* Revert to the main lexer. */ |
30168 | cp_parser_pop_lexer (parser); |
30169 | |
30170 | /* Restore the queue. */ |
30171 | pop_unparsed_function_queues (parser); |
30172 | |
30173 | current_class_ref = saved_ccr; |
30174 | current_class_ptr = saved_ccp; |
30175 | |
30176 | /* Commit to changes. */ |
30177 | update_late_contract (contract, result, condition); |
30178 | |
30179 | /* Leave our temporary scope for the postcondition result. */ |
30180 | if (result) |
30181 | { |
30182 | --processing_template_decl; |
30183 | pop_bindings_and_leave_scope (); |
30184 | } |
30185 | } |
30186 | |
30187 | /* Parse a standard C++-11 attribute specifier. |
30188 | |
30189 | attribute-specifier: |
30190 | [ [ attribute-using-prefix [opt] attribute-list ] ] |
30191 | contract-attribute-specifier |
30192 | alignment-specifier |
30193 | |
30194 | attribute-using-prefix: |
30195 | using attribute-namespace : |
30196 | |
30197 | alignment-specifier: |
30198 | alignas ( type-id ... [opt] ) |
30199 | alignas ( alignment-expression ... [opt] ). |
30200 | |
30201 | Extensions for contracts: |
30202 | |
30203 | contract-attribute-specifier: |
30204 | [ [ assert : contract-mode [opt] : conditional-expression ] ] |
30205 | [ [ pre : contract-mode [opt] : conditional-expression ] ] |
30206 | [ [ post : contract-mode [opt] identifier [opt] : |
30207 | conditional-expression ] ] */ |
30208 | |
30209 | static tree |
30210 | cp_parser_std_attribute_spec (cp_parser *parser) |
30211 | { |
30212 | tree attributes = NULL_TREE; |
30213 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30214 | |
30215 | if (token->type == CPP_OPEN_SQUARE |
30216 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_OPEN_SQUARE) |
30217 | { |
30218 | tree attr_ns = NULL_TREE; |
30219 | tree attr_name = NULL_TREE; |
30220 | |
30221 | cp_lexer_consume_token (lexer: parser->lexer); |
30222 | cp_lexer_consume_token (lexer: parser->lexer); |
30223 | |
30224 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30225 | if (token->type == CPP_NAME) |
30226 | { |
30227 | attr_name = token->u.value; |
30228 | attr_name = canonicalize_attr_name (attr_name); |
30229 | } |
30230 | |
30231 | /* Handle contract-attribute-specs specially. */ |
30232 | if (attr_name && contract_attribute_p (id: attr_name)) |
30233 | { |
30234 | tree attrs = cp_parser_contract_attribute_spec (parser, attribute: attr_name); |
30235 | if (attrs != error_mark_node) |
30236 | attributes = attrs; |
30237 | goto finish_attrs; |
30238 | } |
30239 | |
30240 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
30241 | { |
30242 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
30243 | if (token->type == CPP_NAME) |
30244 | attr_ns = token->u.value; |
30245 | else if (token->type == CPP_KEYWORD) |
30246 | attr_ns = ridpointers[(int) token->keyword]; |
30247 | else if (token->flags & NAMED_OP) |
30248 | attr_ns = get_identifier (cpp_type2name (token->type, |
30249 | token->flags)); |
30250 | if (attr_ns |
30251 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_COLON)) |
30252 | { |
30253 | if (cxx_dialect < cxx17) |
30254 | pedwarn (input_location, OPT_Wc__17_extensions, |
30255 | "attribute using prefix only available " |
30256 | "with %<-std=c++17%> or %<-std=gnu++17%>" ); |
30257 | |
30258 | cp_lexer_consume_token (lexer: parser->lexer); |
30259 | cp_lexer_consume_token (lexer: parser->lexer); |
30260 | cp_lexer_consume_token (lexer: parser->lexer); |
30261 | } |
30262 | else |
30263 | attr_ns = NULL_TREE; |
30264 | } |
30265 | |
30266 | attributes = cp_parser_std_attribute_list (parser, attr_ns); |
30267 | |
30268 | finish_attrs: |
30269 | if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) |
30270 | || !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) |
30271 | cp_parser_skip_to_end_of_statement (parser); |
30272 | else |
30273 | /* Warn about parsing c++11 attribute in non-c++11 mode, only |
30274 | when we are sure that we have actually parsed them. */ |
30275 | maybe_warn_cpp0x (str: CPP0X_ATTRIBUTES); |
30276 | } |
30277 | else |
30278 | { |
30279 | tree alignas_expr; |
30280 | |
30281 | /* Look for an alignment-specifier. */ |
30282 | |
30283 | token = cp_lexer_peek_token (lexer: parser->lexer); |
30284 | |
30285 | if (token->type != CPP_KEYWORD |
30286 | || token->keyword != RID_ALIGNAS) |
30287 | return NULL_TREE; |
30288 | |
30289 | cp_lexer_consume_token (lexer: parser->lexer); |
30290 | maybe_warn_cpp0x (str: CPP0X_ATTRIBUTES); |
30291 | |
30292 | matching_parens parens; |
30293 | if (!parens.require_open (parser)) |
30294 | return error_mark_node; |
30295 | |
30296 | cp_parser_parse_tentatively (parser); |
30297 | alignas_expr = cp_parser_type_id (parser); |
30298 | |
30299 | if (!cp_parser_parse_definitely (parser)) |
30300 | { |
30301 | alignas_expr = cp_parser_assignment_expression (parser); |
30302 | if (alignas_expr == error_mark_node) |
30303 | cp_parser_skip_to_end_of_statement (parser); |
30304 | if (alignas_expr == NULL_TREE |
30305 | || alignas_expr == error_mark_node) |
30306 | return alignas_expr; |
30307 | } |
30308 | |
30309 | alignas_expr = cxx_alignas_expr (alignas_expr); |
30310 | alignas_expr = build_tree_list (NULL_TREE, alignas_expr); |
30311 | |
30312 | /* Handle alignas (pack...). */ |
30313 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
30314 | { |
30315 | cp_lexer_consume_token (lexer: parser->lexer); |
30316 | alignas_expr = make_pack_expansion (alignas_expr); |
30317 | } |
30318 | |
30319 | /* Something went wrong, so don't build the attribute. */ |
30320 | if (alignas_expr == error_mark_node) |
30321 | return error_mark_node; |
30322 | |
30323 | /* Missing ')' means the code cannot possibly be valid; go ahead |
30324 | and commit to make sure we issue a hard error. */ |
30325 | if (cp_parser_uncommitted_to_tentative_parse_p (parser) |
30326 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
30327 | cp_parser_commit_to_tentative_parse (parser); |
30328 | |
30329 | if (!parens.require_close (parser)) |
30330 | return error_mark_node; |
30331 | |
30332 | /* Build the C++-11 representation of an 'aligned' |
30333 | attribute. */ |
30334 | attributes |
30335 | = build_tree_list (build_tree_list (gnu_identifier, |
30336 | aligned_identifier), alignas_expr); |
30337 | } |
30338 | |
30339 | return attributes; |
30340 | } |
30341 | |
30342 | /* Parse a standard C++-11 attribute-specifier-seq. |
30343 | |
30344 | attribute-specifier-seq: |
30345 | attribute-specifier-seq [opt] attribute-specifier */ |
30346 | |
30347 | static tree |
30348 | cp_parser_std_attribute_spec_seq (cp_parser *parser) |
30349 | { |
30350 | tree attr_specs = NULL_TREE; |
30351 | tree attr_last = NULL_TREE; |
30352 | |
30353 | /* Don't create wrapper nodes within attributes: the |
30354 | handlers don't know how to handle them. */ |
30355 | auto_suppress_location_wrappers sentinel; |
30356 | |
30357 | while (true) |
30358 | { |
30359 | tree attr_spec = cp_parser_std_attribute_spec (parser); |
30360 | if (attr_spec == NULL_TREE) |
30361 | break; |
30362 | if (attr_spec == error_mark_node) |
30363 | return error_mark_node; |
30364 | |
30365 | if (attr_last) |
30366 | TREE_CHAIN (attr_last) = attr_spec; |
30367 | else |
30368 | attr_specs = attr_last = attr_spec; |
30369 | attr_last = tree_last (attr_last); |
30370 | } |
30371 | |
30372 | return attr_specs; |
30373 | } |
30374 | |
30375 | /* Skip a balanced-token starting at Nth token (with 1 as the next token), |
30376 | return index of the first token after balanced-token, or N on failure. */ |
30377 | |
30378 | static size_t |
30379 | cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n) |
30380 | { |
30381 | size_t orig_n = n; |
30382 | int nparens = 0, nbraces = 0, nsquares = 0; |
30383 | do |
30384 | switch (cp_lexer_peek_nth_token (lexer: parser->lexer, n: n++)->type) |
30385 | { |
30386 | case CPP_PRAGMA_EOL: |
30387 | if (!parser->lexer->in_pragma) |
30388 | break; |
30389 | /* FALLTHRU */ |
30390 | case CPP_EOF: |
30391 | /* Ran out of tokens. */ |
30392 | return orig_n; |
30393 | case CPP_OPEN_PAREN: |
30394 | ++nparens; |
30395 | break; |
30396 | case CPP_OPEN_BRACE: |
30397 | ++nbraces; |
30398 | break; |
30399 | case CPP_OPEN_SQUARE: |
30400 | ++nsquares; |
30401 | break; |
30402 | case CPP_CLOSE_PAREN: |
30403 | --nparens; |
30404 | break; |
30405 | case CPP_CLOSE_BRACE: |
30406 | --nbraces; |
30407 | break; |
30408 | case CPP_CLOSE_SQUARE: |
30409 | --nsquares; |
30410 | break; |
30411 | default: |
30412 | break; |
30413 | } |
30414 | while (nparens || nbraces || nsquares); |
30415 | return n; |
30416 | } |
30417 | |
30418 | /* Skip GNU attribute tokens starting at Nth token (with 1 as the next token), |
30419 | return index of the first token after the GNU attribute tokens, or N on |
30420 | failure. */ |
30421 | |
30422 | static size_t |
30423 | cp_parser_skip_gnu_attributes_opt (cp_parser *parser, size_t n) |
30424 | { |
30425 | while (true) |
30426 | { |
30427 | if (!cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n, keyword: RID_ATTRIBUTE) |
30428 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_PAREN) |
30429 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 2, type: CPP_OPEN_PAREN)) |
30430 | break; |
30431 | |
30432 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 2); |
30433 | if (n2 == n + 2) |
30434 | break; |
30435 | if (!cp_lexer_nth_token_is (lexer: parser->lexer, n: n2, type: CPP_CLOSE_PAREN)) |
30436 | break; |
30437 | n = n2 + 1; |
30438 | } |
30439 | return n; |
30440 | } |
30441 | |
30442 | /* Skip standard C++11 attribute tokens starting at Nth token (with 1 as the |
30443 | next token), return index of the first token after the standard C++11 |
30444 | attribute tokens, or N on failure. */ |
30445 | |
30446 | static size_t |
30447 | cp_parser_skip_std_attribute_spec_seq (cp_parser *parser, size_t n) |
30448 | { |
30449 | while (true) |
30450 | { |
30451 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_OPEN_SQUARE) |
30452 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_SQUARE)) |
30453 | { |
30454 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 1); |
30455 | if (n2 == n + 1) |
30456 | break; |
30457 | if (!cp_lexer_nth_token_is (lexer: parser->lexer, n: n2, type: CPP_CLOSE_SQUARE)) |
30458 | break; |
30459 | n = n2 + 1; |
30460 | } |
30461 | else if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n, keyword: RID_ALIGNAS) |
30462 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: n + 1, type: CPP_OPEN_PAREN)) |
30463 | { |
30464 | size_t n2 = cp_parser_skip_balanced_tokens (parser, n: n + 1); |
30465 | if (n2 == n + 1) |
30466 | break; |
30467 | n = n2; |
30468 | } |
30469 | else |
30470 | break; |
30471 | } |
30472 | return n; |
30473 | } |
30474 | |
30475 | /* Skip standard C++11 or GNU attribute tokens starting at Nth token (with 1 |
30476 | as the next token), return index of the first token after the attribute |
30477 | tokens, or N on failure. */ |
30478 | |
30479 | static size_t |
30480 | cp_parser_skip_attributes_opt (cp_parser *parser, size_t n) |
30481 | { |
30482 | if (cp_nth_tokens_can_be_gnu_attribute_p (parser, n)) |
30483 | return cp_parser_skip_gnu_attributes_opt (parser, n); |
30484 | return cp_parser_skip_std_attribute_spec_seq (parser, n); |
30485 | } |
30486 | |
30487 | /* Parse an optional `__extension__' keyword. Returns TRUE if it is |
30488 | present, and FALSE otherwise. *SAVED_PEDANTIC is set to the |
30489 | current value of the PEDANTIC flag, regardless of whether or not |
30490 | the `__extension__' keyword is present. The caller is responsible |
30491 | for restoring the value of the PEDANTIC flag. */ |
30492 | |
30493 | static bool |
30494 | cp_parser_extension_opt (cp_parser* parser, int* saved_pedantic) |
30495 | { |
30496 | /* Save the old value of the PEDANTIC flag. */ |
30497 | *saved_pedantic = pedantic; |
30498 | |
30499 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_EXTENSION)) |
30500 | { |
30501 | /* Consume the `__extension__' token. */ |
30502 | cp_lexer_consume_token (lexer: parser->lexer); |
30503 | /* We're not being pedantic while the `__extension__' keyword is |
30504 | in effect. */ |
30505 | pedantic = 0; |
30506 | |
30507 | return true; |
30508 | } |
30509 | |
30510 | return false; |
30511 | } |
30512 | |
30513 | /* Parse a label declaration. |
30514 | |
30515 | label-declaration: |
30516 | __label__ label-declarator-seq ; |
30517 | |
30518 | label-declarator-seq: |
30519 | identifier , label-declarator-seq |
30520 | identifier */ |
30521 | |
30522 | static void |
30523 | cp_parser_label_declaration (cp_parser* parser) |
30524 | { |
30525 | /* Look for the `__label__' keyword. */ |
30526 | cp_parser_require_keyword (parser, RID_LABEL, RT_LABEL); |
30527 | |
30528 | while (true) |
30529 | { |
30530 | tree identifier; |
30531 | |
30532 | /* Look for an identifier. */ |
30533 | identifier = cp_parser_identifier (parser); |
30534 | /* If we failed, stop. */ |
30535 | if (identifier == error_mark_node) |
30536 | break; |
30537 | /* Declare it as a label. */ |
30538 | finish_label_decl (identifier); |
30539 | /* If the next token is a `;', stop. */ |
30540 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
30541 | break; |
30542 | /* Look for the `,' separating the label declarations. */ |
30543 | cp_parser_require (parser, CPP_COMMA, RT_COMMA); |
30544 | } |
30545 | |
30546 | /* Look for the final `;'. */ |
30547 | cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); |
30548 | } |
30549 | |
30550 | // -------------------------------------------------------------------------- // |
30551 | // Concept definitions |
30552 | |
30553 | static tree |
30554 | cp_parser_concept_definition (cp_parser *parser) |
30555 | { |
30556 | /* A concept definition is an unevaluated context. */ |
30557 | cp_unevaluated u; |
30558 | |
30559 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT)); |
30560 | cp_lexer_consume_token (lexer: parser->lexer); |
30561 | |
30562 | cp_expr id = cp_parser_identifier (parser); |
30563 | if (id == error_mark_node) |
30564 | { |
30565 | cp_parser_skip_to_end_of_statement (parser); |
30566 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
30567 | return NULL_TREE; |
30568 | } |
30569 | |
30570 | tree attrs = cp_parser_attributes_opt (parser); |
30571 | |
30572 | if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) |
30573 | { |
30574 | cp_parser_skip_to_end_of_statement (parser); |
30575 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
30576 | return error_mark_node; |
30577 | } |
30578 | |
30579 | processing_constraint_expression_sentinel parsing_constraint; |
30580 | tree init = cp_parser_constraint_expression (parser); |
30581 | if (init == error_mark_node) |
30582 | cp_parser_skip_to_end_of_statement (parser); |
30583 | |
30584 | /* Consume the trailing ';'. Diagnose the problem if it isn't there, |
30585 | but continue as if it were. */ |
30586 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
30587 | |
30588 | return finish_concept_definition (id, init, attrs); |
30589 | } |
30590 | |
30591 | // -------------------------------------------------------------------------- // |
30592 | // Requires Clause |
30593 | |
30594 | /* Diagnose an expression that should appear in ()'s within a requires-clause |
30595 | and suggest where to place those parentheses. */ |
30596 | |
30597 | static void |
30598 | cp_parser_diagnose_ungrouped_constraint_plain (location_t loc) |
30599 | { |
30600 | error_at (loc, "expression must be enclosed in parentheses" ); |
30601 | } |
30602 | |
30603 | static void |
30604 | cp_parser_diagnose_ungrouped_constraint_rich (location_t loc) |
30605 | { |
30606 | gcc_rich_location richloc (loc); |
30607 | richloc.add_fixit_insert_before (new_content: "(" ); |
30608 | richloc.add_fixit_insert_after (new_content: ")" ); |
30609 | error_at (&richloc, "expression must be enclosed in parentheses" ); |
30610 | } |
30611 | |
30612 | /* Characterizes the likely kind of expression intended by a mis-written |
30613 | primary constraint. */ |
30614 | enum primary_constraint_error |
30615 | { |
30616 | pce_ok, |
30617 | pce_maybe_operator, |
30618 | pce_maybe_postfix |
30619 | }; |
30620 | |
30621 | /* Returns true if the token(s) following a primary-expression in a |
30622 | constraint-logical-* expression would require parentheses. */ |
30623 | |
30624 | static primary_constraint_error |
30625 | cp_parser_constraint_requires_parens (cp_parser *parser, bool lambda_p) |
30626 | { |
30627 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30628 | switch (token->type) |
30629 | { |
30630 | default: |
30631 | return pce_ok; |
30632 | |
30633 | case CPP_EQ: |
30634 | { |
30635 | /* An equal sign may be part of the definition of a function, |
30636 | and not an assignment operator, when parsing the expression |
30637 | for a trailing requires-clause. For example: |
30638 | |
30639 | template<typename T> |
30640 | struct S { |
30641 | S() requires C<T> = default; |
30642 | }; |
30643 | |
30644 | Don't try to reparse this a binary operator. */ |
30645 | if (cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_DELETE) |
30646 | || cp_lexer_nth_token_is_keyword (lexer: parser->lexer, n: 2, keyword: RID_DEFAULT)) |
30647 | return pce_ok; |
30648 | |
30649 | gcc_fallthrough (); |
30650 | } |
30651 | |
30652 | /* Arithmetic operators. */ |
30653 | case CPP_PLUS: |
30654 | case CPP_MINUS: |
30655 | case CPP_MULT: |
30656 | case CPP_DIV: |
30657 | case CPP_MOD: |
30658 | /* Bitwise operators. */ |
30659 | case CPP_AND: |
30660 | case CPP_OR: |
30661 | case CPP_XOR: |
30662 | case CPP_RSHIFT: |
30663 | case CPP_LSHIFT: |
30664 | /* Relational operators. */ |
30665 | case CPP_EQ_EQ: |
30666 | case CPP_NOT_EQ: |
30667 | case CPP_LESS: |
30668 | case CPP_GREATER: |
30669 | case CPP_LESS_EQ: |
30670 | case CPP_GREATER_EQ: |
30671 | case CPP_SPACESHIP: |
30672 | /* Pointer-to-member. */ |
30673 | case CPP_DOT_STAR: |
30674 | case CPP_DEREF_STAR: |
30675 | /* Assignment operators. */ |
30676 | case CPP_PLUS_EQ: |
30677 | case CPP_MINUS_EQ: |
30678 | case CPP_MULT_EQ: |
30679 | case CPP_DIV_EQ: |
30680 | case CPP_MOD_EQ: |
30681 | case CPP_AND_EQ: |
30682 | case CPP_OR_EQ: |
30683 | case CPP_XOR_EQ: |
30684 | case CPP_RSHIFT_EQ: |
30685 | case CPP_LSHIFT_EQ: |
30686 | /* Conditional operator */ |
30687 | case CPP_QUERY: |
30688 | /* Unenclosed binary or conditional operator. */ |
30689 | return pce_maybe_operator; |
30690 | |
30691 | case CPP_OPEN_PAREN: |
30692 | { |
30693 | /* A primary constraint that precedes the parameter-list of a |
30694 | lambda expression is followed by an open paren. |
30695 | |
30696 | []<typename T> requires C (T a, T b) { ... } |
30697 | |
30698 | Don't try to re-parse this as a postfix expression. */ |
30699 | if (lambda_p) |
30700 | return pce_ok; |
30701 | |
30702 | gcc_fallthrough (); |
30703 | } |
30704 | case CPP_OPEN_SQUARE: |
30705 | { |
30706 | /* A primary-constraint-expression followed by a '[[' is not a |
30707 | postfix expression. */ |
30708 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_SQUARE)) |
30709 | return pce_ok; |
30710 | |
30711 | gcc_fallthrough (); |
30712 | } |
30713 | case CPP_PLUS_PLUS: |
30714 | case CPP_MINUS_MINUS: |
30715 | case CPP_DOT: |
30716 | /* Unenclosed postfix operator. */ |
30717 | return pce_maybe_postfix; |
30718 | |
30719 | case CPP_DEREF: |
30720 | /* A primary constraint that precedes the lambda-declarator of a |
30721 | lambda expression is followed by trailing return type. |
30722 | |
30723 | []<typename T> requires C -> void {} |
30724 | |
30725 | Don't try to re-parse this as a postfix expression in |
30726 | C++23 and later. In C++20 ( needs to come in between but we |
30727 | allow it to be omitted with pedwarn. */ |
30728 | if (lambda_p) |
30729 | return pce_ok; |
30730 | /* Unenclosed postfix operator. */ |
30731 | return pce_maybe_postfix; |
30732 | } |
30733 | } |
30734 | |
30735 | /* Returns true if the next token begins a unary expression, preceded by |
30736 | an operator or keyword. */ |
30737 | |
30738 | static bool |
30739 | cp_parser_unary_constraint_requires_parens (cp_parser *parser) |
30740 | { |
30741 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
30742 | switch (token->type) |
30743 | { |
30744 | case CPP_NOT: |
30745 | case CPP_PLUS: |
30746 | case CPP_MINUS: |
30747 | case CPP_MULT: |
30748 | case CPP_COMPL: |
30749 | case CPP_PLUS_PLUS: |
30750 | case CPP_MINUS_MINUS: |
30751 | return true; |
30752 | |
30753 | case CPP_KEYWORD: |
30754 | { |
30755 | switch (token->keyword) |
30756 | { |
30757 | case RID_STATCAST: |
30758 | case RID_DYNCAST: |
30759 | case RID_REINTCAST: |
30760 | case RID_CONSTCAST: |
30761 | case RID_TYPEID: |
30762 | case RID_SIZEOF: |
30763 | case RID_ALIGNOF: |
30764 | case RID_NOEXCEPT: |
30765 | case RID_NEW: |
30766 | case RID_DELETE: |
30767 | case RID_THROW: |
30768 | return true; |
30769 | |
30770 | default: |
30771 | break; |
30772 | } |
30773 | } |
30774 | |
30775 | default: |
30776 | break; |
30777 | } |
30778 | |
30779 | return false; |
30780 | } |
30781 | |
30782 | /* Parse a primary expression within a constraint. */ |
30783 | |
30784 | static cp_expr |
30785 | cp_parser_constraint_primary_expression (cp_parser *parser, bool lambda_p) |
30786 | { |
30787 | /* If this looks like a unary expression, parse it as such, but diagnose |
30788 | it as ill-formed; it requires parens. */ |
30789 | if (cp_parser_unary_constraint_requires_parens (parser)) |
30790 | { |
30791 | cp_expr e = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
30792 | cp_parser_diagnose_ungrouped_constraint_rich (loc: e.get_location()); |
30793 | return e; |
30794 | } |
30795 | |
30796 | cp_lexer_save_tokens (lexer: parser->lexer); |
30797 | cp_id_kind idk; |
30798 | location_t loc = input_location; |
30799 | cp_expr expr = cp_parser_primary_expression (parser, |
30800 | /*address_p=*/false, |
30801 | /*cast_p=*/false, |
30802 | /*template_arg_p=*/false, |
30803 | idk: &idk); |
30804 | expr.maybe_add_location_wrapper (); |
30805 | |
30806 | primary_constraint_error pce = pce_ok; |
30807 | if (expr != error_mark_node) |
30808 | { |
30809 | /* The primary-expression could be part of an unenclosed non-logical |
30810 | compound expression. */ |
30811 | pce = cp_parser_constraint_requires_parens (parser, lambda_p); |
30812 | } |
30813 | if (pce == pce_ok) |
30814 | { |
30815 | cp_lexer_commit_tokens (lexer: parser->lexer); |
30816 | return finish_constraint_primary_expr (expr); |
30817 | } |
30818 | |
30819 | /* Retry the parse at a lower precedence. If that succeeds, diagnose the |
30820 | error, but return the expression as if it were valid. */ |
30821 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
30822 | cp_parser_parse_tentatively (parser); |
30823 | if (pce == pce_maybe_operator) |
30824 | expr = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
30825 | else |
30826 | expr = cp_parser_simple_cast_expression (parser); |
30827 | if (cp_parser_parse_definitely (parser)) |
30828 | { |
30829 | cp_parser_diagnose_ungrouped_constraint_rich (loc: expr.get_location()); |
30830 | return expr; |
30831 | } |
30832 | |
30833 | /* Otherwise, something has gone very wrong, and we can't generate a more |
30834 | meaningful diagnostic or recover. */ |
30835 | cp_parser_diagnose_ungrouped_constraint_plain (loc); |
30836 | return error_mark_node; |
30837 | } |
30838 | |
30839 | /* Parse a constraint-logical-and-expression. |
30840 | |
30841 | constraint-logical-and-expression: |
30842 | primary-expression |
30843 | constraint-logical-and-expression '&&' primary-expression */ |
30844 | |
30845 | static cp_expr |
30846 | cp_parser_constraint_logical_and_expression (cp_parser *parser, bool lambda_p) |
30847 | { |
30848 | cp_expr lhs = cp_parser_constraint_primary_expression (parser, lambda_p); |
30849 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_AND_AND)) |
30850 | { |
30851 | cp_token *op = cp_lexer_consume_token (lexer: parser->lexer); |
30852 | tree rhs = cp_parser_constraint_primary_expression (parser, lambda_p); |
30853 | lhs = finish_constraint_and_expr (op->location, lhs, rhs); |
30854 | } |
30855 | return lhs; |
30856 | } |
30857 | |
30858 | /* Parse a constraint-logical-or-expression. |
30859 | |
30860 | constraint-logical-or-expression: |
30861 | constraint-logical-and-expression |
30862 | constraint-logical-or-expression '||' constraint-logical-and-expression */ |
30863 | |
30864 | static cp_expr |
30865 | cp_parser_constraint_logical_or_expression (cp_parser *parser, bool lambda_p) |
30866 | { |
30867 | cp_expr lhs = cp_parser_constraint_logical_and_expression (parser, lambda_p); |
30868 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OR_OR)) |
30869 | { |
30870 | cp_token *op = cp_lexer_consume_token (lexer: parser->lexer); |
30871 | cp_expr rhs = cp_parser_constraint_logical_and_expression (parser, lambda_p); |
30872 | lhs = finish_constraint_or_expr (op->location, lhs, rhs); |
30873 | } |
30874 | return lhs; |
30875 | } |
30876 | |
30877 | /* Parse the expression after a requires-clause. This has a different grammar |
30878 | than that in the concepts TS. */ |
30879 | |
30880 | static tree |
30881 | cp_parser_requires_clause_expression (cp_parser *parser, bool lambda_p) |
30882 | { |
30883 | processing_constraint_expression_sentinel parsing_constraint; |
30884 | ++processing_template_decl; |
30885 | cp_expr expr = cp_parser_constraint_logical_or_expression (parser, lambda_p); |
30886 | --processing_template_decl; |
30887 | if (check_for_bare_parameter_packs (expr)) |
30888 | expr = error_mark_node; |
30889 | return expr; |
30890 | } |
30891 | |
30892 | /* Parse a expression after a requires clause. |
30893 | |
30894 | constraint-expression: |
30895 | logical-or-expression |
30896 | |
30897 | The required logical-or-expression must be a constant expression. Note |
30898 | that we don't check that the expression is constepxr here. We defer until |
30899 | we analyze constraints and then, we only check atomic constraints. */ |
30900 | |
30901 | static tree |
30902 | cp_parser_constraint_expression (cp_parser *parser) |
30903 | { |
30904 | processing_constraint_expression_sentinel parsing_constraint; |
30905 | ++processing_template_decl; |
30906 | cp_expr expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
30907 | prec: PREC_NOT_OPERATOR, NULL); |
30908 | --processing_template_decl; |
30909 | if (check_for_bare_parameter_packs (expr)) |
30910 | expr = error_mark_node; |
30911 | expr.maybe_add_location_wrapper (); |
30912 | return expr; |
30913 | } |
30914 | |
30915 | /* Optionally parse a requires clause: |
30916 | |
30917 | requires-clause: |
30918 | `requires` constraint-logical-or-expression. |
30919 | [ConceptsTS] |
30920 | `requires constraint-expression. |
30921 | |
30922 | LAMBDA_P is true when the requires-clause is parsed before the |
30923 | parameter-list of a lambda-declarator. */ |
30924 | |
30925 | static tree |
30926 | cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p) |
30927 | { |
30928 | /* A requires clause is an unevaluated context. */ |
30929 | cp_unevaluated u; |
30930 | |
30931 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
30932 | if (tok->keyword != RID_REQUIRES) |
30933 | { |
30934 | if (!flag_concepts && tok->type == CPP_NAME |
30935 | && tok->u.value == ridpointers[RID_REQUIRES]) |
30936 | { |
30937 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
30938 | "%<requires%> only available with " |
30939 | "%<-std=c++20%> or %<-fconcepts%>" ); |
30940 | /* Parse and discard the requires-clause. */ |
30941 | cp_lexer_consume_token (lexer: parser->lexer); |
30942 | cp_parser_constraint_expression (parser); |
30943 | } |
30944 | return NULL_TREE; |
30945 | } |
30946 | |
30947 | cp_token *tok2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
30948 | if (tok2->type == CPP_OPEN_BRACE) |
30949 | { |
30950 | /* An opening brace following the start of a requires-clause is |
30951 | ill-formed; the user likely forgot the second `requires' that |
30952 | would start a requires-expression. */ |
30953 | gcc_rich_location richloc (tok2->location); |
30954 | richloc.add_fixit_insert_after (where: tok->location, new_content: " requires" ); |
30955 | error_at (&richloc, "missing additional %<requires%> to start " |
30956 | "a requires-expression" ); |
30957 | /* Don't consume the `requires', so that it's reused as the start of a |
30958 | requires-expression. */ |
30959 | } |
30960 | else |
30961 | cp_lexer_consume_token (lexer: parser->lexer); |
30962 | |
30963 | if (!flag_concepts_ts) |
30964 | return cp_parser_requires_clause_expression (parser, lambda_p); |
30965 | else |
30966 | return cp_parser_constraint_expression (parser); |
30967 | } |
30968 | |
30969 | /*--------------------------------------------------------------------------- |
30970 | Requires expressions |
30971 | ---------------------------------------------------------------------------*/ |
30972 | |
30973 | /* Parse a requires expression |
30974 | |
30975 | requirement-expression: |
30976 | 'requires' requirement-parameter-list [opt] requirement-body */ |
30977 | |
30978 | static tree |
30979 | cp_parser_requires_expression (cp_parser *parser) |
30980 | { |
30981 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES)); |
30982 | location_t loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
30983 | |
30984 | /* Avoid committing to outer tentative parse. */ |
30985 | tentative_firewall firewall (parser); |
30986 | |
30987 | /* This is definitely a requires-expression. */ |
30988 | cp_parser_commit_to_tentative_parse (parser); |
30989 | |
30990 | tree parms, reqs; |
30991 | { |
30992 | /* Local parameters are delared as variables within the scope |
30993 | of the expression. They are not visible past the end of |
30994 | the expression. Expressions within the requires-expression |
30995 | are unevaluated. */ |
30996 | struct scope_sentinel |
30997 | { |
30998 | scope_sentinel () |
30999 | { |
31000 | ++cp_unevaluated_operand; |
31001 | begin_scope (sk_function_parms, NULL_TREE); |
31002 | current_binding_level->requires_expression = true; |
31003 | } |
31004 | |
31005 | ~scope_sentinel () |
31006 | { |
31007 | pop_bindings_and_leave_scope (); |
31008 | --cp_unevaluated_operand; |
31009 | } |
31010 | } s; |
31011 | |
31012 | /* Parse the optional parameter list. */ |
31013 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
31014 | { |
31015 | parms = cp_parser_requirement_parameter_list (parser); |
31016 | if (parms == error_mark_node) |
31017 | return error_mark_node; |
31018 | } |
31019 | else |
31020 | parms = NULL_TREE; |
31021 | |
31022 | /* Parse the requirement body. */ |
31023 | ++processing_template_decl; |
31024 | reqs = cp_parser_requirement_body (parser); |
31025 | --processing_template_decl; |
31026 | if (reqs == error_mark_node) |
31027 | return error_mark_node; |
31028 | } |
31029 | |
31030 | /* This needs to happen after pop_bindings_and_leave_scope, as it reverses |
31031 | the parm chain. */ |
31032 | grokparms (parms, &parms); |
31033 | loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
31034 | tree expr = finish_requires_expr (loc, parms, reqs); |
31035 | if (!processing_template_decl) |
31036 | { |
31037 | /* Perform semantic processing now to diagnose any invalid types and |
31038 | expressions. */ |
31039 | int saved_errorcount = errorcount; |
31040 | tsubst_requires_expr (expr, NULL_TREE, tf_warning_or_error, NULL_TREE); |
31041 | if (errorcount > saved_errorcount) |
31042 | return error_mark_node; |
31043 | } |
31044 | return expr; |
31045 | } |
31046 | |
31047 | /* Parse a parameterized requirement. |
31048 | |
31049 | requirement-parameter-list: |
31050 | '(' parameter-declaration-clause ')' */ |
31051 | |
31052 | static tree |
31053 | cp_parser_requirement_parameter_list (cp_parser *parser) |
31054 | { |
31055 | matching_parens parens; |
31056 | if (!parens.require_open (parser)) |
31057 | return error_mark_node; |
31058 | |
31059 | tree parms = (cp_parser_parameter_declaration_clause |
31060 | (parser, flags: CP_PARSER_FLAGS_TYPENAME_OPTIONAL)); |
31061 | |
31062 | if (!parens.require_close (parser)) |
31063 | return error_mark_node; |
31064 | |
31065 | /* Modify the declared parameters by removing their context |
31066 | so they don't refer to the enclosing scope and explicitly |
31067 | indicating that they are constraint variables. */ |
31068 | for (tree parm = parms; parm; parm = TREE_CHAIN (parm)) |
31069 | { |
31070 | if (parm == void_list_node || parm == explicit_void_list_node) |
31071 | break; |
31072 | tree decl = TREE_VALUE (parm); |
31073 | if (decl != error_mark_node) |
31074 | { |
31075 | DECL_CONTEXT (decl) = NULL_TREE; |
31076 | CONSTRAINT_VAR_P (decl) = true; |
31077 | } |
31078 | } |
31079 | |
31080 | return parms; |
31081 | } |
31082 | |
31083 | /* Parse the body of a requirement. |
31084 | |
31085 | requirement-body: |
31086 | '{' requirement-list '}' */ |
31087 | static tree |
31088 | cp_parser_requirement_body (cp_parser *parser) |
31089 | { |
31090 | matching_braces braces; |
31091 | if (!braces.require_open (parser)) |
31092 | return error_mark_node; |
31093 | |
31094 | tree reqs = cp_parser_requirement_seq (parser); |
31095 | |
31096 | if (!braces.require_close (parser)) |
31097 | return error_mark_node; |
31098 | |
31099 | return reqs; |
31100 | } |
31101 | |
31102 | /* Parse a sequence of requirements. |
31103 | |
31104 | requirement-seq: |
31105 | requirement |
31106 | requirement-seq requirement */ |
31107 | |
31108 | static tree |
31109 | cp_parser_requirement_seq (cp_parser *parser) |
31110 | { |
31111 | tree result = NULL_TREE; |
31112 | do |
31113 | { |
31114 | tree req = cp_parser_requirement (parser); |
31115 | if (req != error_mark_node) |
31116 | result = tree_cons (NULL_TREE, req, result); |
31117 | } |
31118 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_BRACE) |
31119 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EOF)); |
31120 | |
31121 | /* If there are no valid requirements, this is not a valid expression. */ |
31122 | if (!result) |
31123 | return error_mark_node; |
31124 | |
31125 | /* Reverse the order of requirements so they are analyzed in order. */ |
31126 | return nreverse (result); |
31127 | } |
31128 | |
31129 | /* Parse a syntactic requirement or type requirement. |
31130 | |
31131 | requirement: |
31132 | simple-requirement |
31133 | compound-requirement |
31134 | type-requirement |
31135 | nested-requirement */ |
31136 | |
31137 | static tree |
31138 | cp_parser_requirement (cp_parser *parser) |
31139 | { |
31140 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
31141 | return cp_parser_compound_requirement (parser); |
31142 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TYPENAME)) |
31143 | { |
31144 | /* It's probably a type-requirement. */ |
31145 | cp_parser_parse_tentatively (parser); |
31146 | tree req = cp_parser_type_requirement (parser); |
31147 | if (cp_parser_parse_definitely (parser)) |
31148 | return req; |
31149 | /* No, maybe it's something like typename T::type(); */ |
31150 | cp_parser_parse_tentatively (parser); |
31151 | req = cp_parser_simple_requirement (parser); |
31152 | if (cp_parser_parse_definitely (parser)) |
31153 | return req; |
31154 | /* Non-tentative for the error. */ |
31155 | return cp_parser_type_requirement (parser); |
31156 | } |
31157 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_REQUIRES)) |
31158 | return cp_parser_nested_requirement (parser); |
31159 | else |
31160 | return cp_parser_simple_requirement (parser); |
31161 | } |
31162 | |
31163 | /* Parse a simple requirement. |
31164 | |
31165 | simple-requirement: |
31166 | expression ';' */ |
31167 | |
31168 | static tree |
31169 | cp_parser_simple_requirement (cp_parser *parser) |
31170 | { |
31171 | location_t start = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31172 | cp_expr expr = cp_parser_expression (parser, NULL, cast_p: false, decltype_p: false); |
31173 | if (expr == error_mark_node) |
31174 | cp_parser_skip_to_end_of_statement (parser); |
31175 | |
31176 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31177 | |
31178 | if (!expr || expr == error_mark_node) |
31179 | return error_mark_node; |
31180 | |
31181 | /* Sometimes we don't get locations, so use the cached token location |
31182 | as a reasonable approximation. */ |
31183 | if (expr.get_location() == UNKNOWN_LOCATION) |
31184 | expr.set_location (start); |
31185 | |
31186 | for (tree t = expr; ; ) |
31187 | { |
31188 | if (TREE_CODE (t) == TRUTH_ANDIF_EXPR |
31189 | || TREE_CODE (t) == TRUTH_ORIF_EXPR) |
31190 | { |
31191 | t = TREE_OPERAND (t, 0); |
31192 | continue; |
31193 | } |
31194 | if (concept_check_p (t)) |
31195 | { |
31196 | gcc_rich_location richloc (get_start (loc: start)); |
31197 | richloc.add_fixit_insert_before (where: start, new_content: "requires " ); |
31198 | warning_at (&richloc, OPT_Wmissing_requires, "testing " |
31199 | "if a concept-id is a valid expression; add " |
31200 | "%<requires%> to check satisfaction" ); |
31201 | } |
31202 | break; |
31203 | } |
31204 | |
31205 | return finish_simple_requirement (expr.get_location (), expr); |
31206 | } |
31207 | |
31208 | /* Parse a type requirement |
31209 | |
31210 | type-requirement |
31211 | nested-name-specifier [opt] required-type-name ';' |
31212 | |
31213 | required-type-name: |
31214 | type-name |
31215 | 'template' [opt] simple-template-id */ |
31216 | |
31217 | static tree |
31218 | cp_parser_type_requirement (cp_parser *parser) |
31219 | { |
31220 | cp_token *start_tok = cp_lexer_consume_token (lexer: parser->lexer); |
31221 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31222 | |
31223 | // Save the scope before parsing name specifiers. |
31224 | tree saved_scope = parser->scope; |
31225 | tree saved_object_scope = parser->object_scope; |
31226 | tree saved_qualifying_scope = parser->qualifying_scope; |
31227 | cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); |
31228 | cp_parser_nested_name_specifier_opt (parser, |
31229 | /*typename_keyword_p=*/true, |
31230 | /*check_dependency_p=*/true, |
31231 | /*type_p=*/true, |
31232 | /*is_declaration=*/false); |
31233 | |
31234 | tree type; |
31235 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
31236 | { |
31237 | cp_lexer_consume_token (lexer: parser->lexer); |
31238 | type = cp_parser_template_id (parser, |
31239 | /*template_keyword_p=*/true, |
31240 | /*check_dependency_p=*/true, |
31241 | /*tag_type=*/none_type, |
31242 | /*is_declaration=*/false); |
31243 | type = make_typename_type (parser->scope, type, typename_type, |
31244 | /*complain=*/tf_error); |
31245 | } |
31246 | else |
31247 | type = cp_parser_type_name (parser, /*typename_keyword_p=*/true); |
31248 | |
31249 | if (TREE_CODE (type) == TYPE_DECL) |
31250 | type = TREE_TYPE (type); |
31251 | |
31252 | parser->scope = saved_scope; |
31253 | parser->object_scope = saved_object_scope; |
31254 | parser->qualifying_scope = saved_qualifying_scope; |
31255 | |
31256 | if (type == error_mark_node) |
31257 | cp_parser_skip_to_end_of_statement (parser); |
31258 | |
31259 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31260 | |
31261 | if (type == error_mark_node) |
31262 | return error_mark_node; |
31263 | |
31264 | loc = make_location (caret: loc, start: start_tok->location, lexer: parser->lexer); |
31265 | return finish_type_requirement (loc, type); |
31266 | } |
31267 | |
31268 | /* Parse a compound requirement |
31269 | |
31270 | compound-requirement: |
31271 | '{' expression '}' 'noexcept' [opt] trailing-return-type [opt] ';' */ |
31272 | |
31273 | static tree |
31274 | cp_parser_compound_requirement (cp_parser *parser) |
31275 | { |
31276 | /* Parse an expression enclosed in '{ }'s. */ |
31277 | matching_braces braces; |
31278 | if (!braces.require_open (parser)) |
31279 | return error_mark_node; |
31280 | |
31281 | cp_token *expr_token = cp_lexer_peek_token (lexer: parser->lexer); |
31282 | |
31283 | tree expr = cp_parser_expression (parser, NULL, cast_p: false, decltype_p: false); |
31284 | if (expr == error_mark_node) |
31285 | cp_parser_skip_to_closing_brace (parser); |
31286 | |
31287 | if (!braces.require_close (parser)) |
31288 | { |
31289 | cp_parser_skip_to_end_of_statement (parser); |
31290 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31291 | return error_mark_node; |
31292 | } |
31293 | |
31294 | /* If the expression was invalid, skip the remainder of the requirement. */ |
31295 | if (!expr || expr == error_mark_node) |
31296 | { |
31297 | cp_parser_skip_to_end_of_statement (parser); |
31298 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31299 | return error_mark_node; |
31300 | } |
31301 | |
31302 | /* Parse the optional noexcept. */ |
31303 | bool noexcept_p = false; |
31304 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_NOEXCEPT)) |
31305 | { |
31306 | cp_lexer_consume_token (lexer: parser->lexer); |
31307 | noexcept_p = true; |
31308 | } |
31309 | |
31310 | /* Parse the optional trailing return type. */ |
31311 | tree type = NULL_TREE; |
31312 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF)) |
31313 | { |
31314 | cp_lexer_consume_token (lexer: parser->lexer); |
31315 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
31316 | |
31317 | bool saved_result_type_constraint_p = parser->in_result_type_constraint_p; |
31318 | parser->in_result_type_constraint_p = true; |
31319 | /* C++20 allows either a type-id or a type-constraint. Parsing |
31320 | a type-id will subsume the parsing for a type-constraint but |
31321 | allow for more syntactic forms (e.g., const C<T>*). */ |
31322 | type = cp_parser_trailing_type_id (parser); |
31323 | parser->in_result_type_constraint_p = saved_result_type_constraint_p; |
31324 | if (type == error_mark_node) |
31325 | return error_mark_node; |
31326 | |
31327 | location_t type_loc = make_location (caret: tok->location, start: tok->location, |
31328 | lexer: parser->lexer); |
31329 | |
31330 | /* Check that we haven't written something like 'const C<T>*'. */ |
31331 | if (type_uses_auto (type)) |
31332 | { |
31333 | if (!is_auto (type)) |
31334 | { |
31335 | error_at (type_loc, |
31336 | "result type is not a plain type-constraint" ); |
31337 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31338 | return error_mark_node; |
31339 | } |
31340 | } |
31341 | else if (!flag_concepts_ts) |
31342 | /* P1452R2 removed the trailing-return-type option. */ |
31343 | error_at (type_loc, |
31344 | "return-type-requirement is not a type-constraint" ); |
31345 | } |
31346 | |
31347 | location_t loc = make_location (caret: expr_token->location, |
31348 | start: braces.open_location (), |
31349 | lexer: parser->lexer); |
31350 | |
31351 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31352 | |
31353 | if (expr == error_mark_node || type == error_mark_node) |
31354 | return error_mark_node; |
31355 | |
31356 | return finish_compound_requirement (loc, expr, type, noexcept_p); |
31357 | } |
31358 | |
31359 | /* Parse a nested requirement. This is the same as a requires clause. |
31360 | |
31361 | nested-requirement: |
31362 | requires-clause */ |
31363 | |
31364 | static tree |
31365 | cp_parser_nested_requirement (cp_parser *parser) |
31366 | { |
31367 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES)); |
31368 | cp_token *tok = cp_lexer_consume_token (lexer: parser->lexer); |
31369 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
31370 | tree req = cp_parser_constraint_expression (parser); |
31371 | if (req == error_mark_node) |
31372 | cp_parser_skip_to_end_of_statement (parser); |
31373 | loc = make_location (caret: loc, start: tok->location, lexer: parser->lexer); |
31374 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
31375 | if (req == error_mark_node) |
31376 | return error_mark_node; |
31377 | return finish_nested_requirement (loc, req); |
31378 | } |
31379 | |
31380 | /* Support Functions */ |
31381 | |
31382 | /* Return the appropriate prefer_type argument for lookup_name based on |
31383 | tag_type. */ |
31384 | |
31385 | static inline LOOK_want |
31386 | prefer_type_arg (tag_types tag_type) |
31387 | { |
31388 | switch (tag_type) |
31389 | { |
31390 | case none_type: return LOOK_want::NORMAL; // No preference. |
31391 | case scope_type: return LOOK_want::TYPE_NAMESPACE; // Type or namespace. |
31392 | default: return LOOK_want::TYPE; // Type only. |
31393 | } |
31394 | } |
31395 | |
31396 | /* Looks up NAME in the current scope, as given by PARSER->SCOPE. |
31397 | NAME should have one of the representations used for an |
31398 | id-expression. If NAME is the ERROR_MARK_NODE, the ERROR_MARK_NODE |
31399 | is returned. If PARSER->SCOPE is a dependent type, then a |
31400 | SCOPE_REF is returned. |
31401 | |
31402 | If NAME is a TEMPLATE_ID_EXPR, then it will be immediately |
31403 | returned; the name was already resolved when the TEMPLATE_ID_EXPR |
31404 | was formed. Abstractly, such entities should not be passed to this |
31405 | function, because they do not need to be looked up, but it is |
31406 | simpler to check for this special case here, rather than at the |
31407 | call-sites. |
31408 | |
31409 | In cases not explicitly covered above, this function returns a |
31410 | DECL, OVERLOAD, or baselink representing the result of the lookup. |
31411 | If there was no entity with the indicated NAME, the ERROR_MARK_NODE |
31412 | is returned. |
31413 | |
31414 | If TAG_TYPE is not NONE_TYPE, it indicates an explicit type keyword |
31415 | (e.g., "struct") that was used. In that case bindings that do not |
31416 | refer to types are ignored. |
31417 | |
31418 | If IS_TEMPLATE is TRUE, bindings that do not refer to templates are |
31419 | ignored. If IS_TEMPLATE IS 2, the 'template' keyword was specified. |
31420 | |
31421 | If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces |
31422 | are ignored. |
31423 | |
31424 | If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent |
31425 | types. |
31426 | |
31427 | If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a |
31428 | TREE_LIST of candidates if name-lookup results in an ambiguity, and |
31429 | NULL_TREE otherwise. */ |
31430 | |
31431 | static cp_expr |
31432 | cp_parser_lookup_name (cp_parser *parser, tree name, |
31433 | enum tag_types tag_type, |
31434 | int is_template, |
31435 | bool is_namespace, |
31436 | bool check_dependency, |
31437 | tree *ambiguous_decls, |
31438 | location_t name_location) |
31439 | { |
31440 | tree decl; |
31441 | tree object_type = parser->context->object_type; |
31442 | |
31443 | /* Assume that the lookup will be unambiguous. */ |
31444 | if (ambiguous_decls) |
31445 | *ambiguous_decls = NULL_TREE; |
31446 | |
31447 | /* Now that we have looked up the name, the OBJECT_TYPE (if any) is |
31448 | no longer valid. Note that if we are parsing tentatively, and |
31449 | the parse fails, OBJECT_TYPE will be automatically restored. */ |
31450 | parser->context->object_type = NULL_TREE; |
31451 | |
31452 | if (name == error_mark_node) |
31453 | return error_mark_node; |
31454 | |
31455 | /* A template-id has already been resolved; there is no lookup to |
31456 | do. */ |
31457 | if (TREE_CODE (name) == TEMPLATE_ID_EXPR) |
31458 | return name; |
31459 | if (BASELINK_P (name)) |
31460 | { |
31461 | gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) |
31462 | == TEMPLATE_ID_EXPR); |
31463 | return name; |
31464 | } |
31465 | |
31466 | /* A BIT_NOT_EXPR is used to represent a destructor. By this point, |
31467 | it should already have been checked to make sure that the name |
31468 | used matches the type being destroyed. */ |
31469 | if (TREE_CODE (name) == BIT_NOT_EXPR) |
31470 | { |
31471 | tree type; |
31472 | |
31473 | /* Figure out to which type this destructor applies. */ |
31474 | if (parser->scope) |
31475 | type = parser->scope; |
31476 | else if (object_type) |
31477 | type = object_type; |
31478 | else |
31479 | type = current_class_type; |
31480 | /* If that's not a class type, there is no destructor. */ |
31481 | if (!type || !CLASS_TYPE_P (type)) |
31482 | return error_mark_node; |
31483 | |
31484 | /* In a non-static member function, check implicit this->. */ |
31485 | if (current_class_ref) |
31486 | return lookup_destructor (current_class_ref, parser->scope, name, |
31487 | tf_warning_or_error); |
31488 | |
31489 | if (CLASSTYPE_LAZY_DESTRUCTOR (type)) |
31490 | lazily_declare_fn (sfk_destructor, type); |
31491 | |
31492 | if (tree dtor = CLASSTYPE_DESTRUCTOR (type)) |
31493 | return dtor; |
31494 | |
31495 | return error_mark_node; |
31496 | } |
31497 | |
31498 | /* By this point, the NAME should be an ordinary identifier. If |
31499 | the id-expression was a qualified name, the qualifying scope is |
31500 | stored in PARSER->SCOPE at this point. */ |
31501 | gcc_assert (identifier_p (name)); |
31502 | |
31503 | /* Perform the lookup. */ |
31504 | if (parser->scope) |
31505 | { |
31506 | bool dependent_p; |
31507 | |
31508 | if (parser->scope == error_mark_node) |
31509 | return error_mark_node; |
31510 | |
31511 | /* If the SCOPE is dependent, the lookup must be deferred until |
31512 | the template is instantiated -- unless we are explicitly |
31513 | looking up names in uninstantiated templates. Even then, we |
31514 | cannot look up the name if the scope is not a class type; it |
31515 | might, for example, be a template type parameter. */ |
31516 | dependent_p = (TYPE_P (parser->scope) |
31517 | && dependent_scope_p (parser->scope)); |
31518 | if ((check_dependency || !CLASS_TYPE_P (parser->scope)) |
31519 | && dependent_p) |
31520 | /* Defer lookup. */ |
31521 | decl = error_mark_node; |
31522 | else |
31523 | { |
31524 | tree pushed_scope = NULL_TREE; |
31525 | |
31526 | /* If PARSER->SCOPE is a dependent type, then it must be a |
31527 | class type, and we must not be checking dependencies; |
31528 | otherwise, we would have processed this lookup above. So |
31529 | that PARSER->SCOPE is not considered a dependent base by |
31530 | lookup_member, we must enter the scope here. */ |
31531 | if (dependent_p) |
31532 | pushed_scope = push_scope (parser->scope); |
31533 | |
31534 | /* If the PARSER->SCOPE is a template specialization, it |
31535 | may be instantiated during name lookup. In that case, |
31536 | errors may be issued. Even if we rollback the current |
31537 | tentative parse, those errors are valid. */ |
31538 | decl = lookup_qualified_name (scope: parser->scope, name, |
31539 | prefer_type_arg (tag_type), |
31540 | /*complain=*/true); |
31541 | |
31542 | /* 3.4.3.1: In a lookup in which the constructor is an acceptable |
31543 | lookup result and the nested-name-specifier nominates a class C: |
31544 | * if the name specified after the nested-name-specifier, when |
31545 | looked up in C, is the injected-class-name of C (Clause 9), or |
31546 | * if the name specified after the nested-name-specifier is the |
31547 | same as the identifier or the simple-template-id's template- |
31548 | name in the last component of the nested-name-specifier, |
31549 | the name is instead considered to name the constructor of |
31550 | class C. [ Note: for example, the constructor is not an |
31551 | acceptable lookup result in an elaborated-type-specifier so |
31552 | the constructor would not be used in place of the |
31553 | injected-class-name. --end note ] Such a constructor name |
31554 | shall be used only in the declarator-id of a declaration that |
31555 | names a constructor or in a using-declaration. */ |
31556 | if (tag_type == none_type |
31557 | && DECL_SELF_REFERENCE_P (decl) |
31558 | && same_type_p (DECL_CONTEXT (decl), parser->scope)) |
31559 | decl = lookup_qualified_name (scope: parser->scope, ctor_identifier, |
31560 | prefer_type_arg (tag_type), |
31561 | /*complain=*/true); |
31562 | |
31563 | if (pushed_scope) |
31564 | pop_scope (pushed_scope); |
31565 | } |
31566 | |
31567 | /* If the scope is a dependent type and either we deferred lookup or |
31568 | we did lookup but didn't find the name, rememeber the name. */ |
31569 | if (decl == error_mark_node && TYPE_P (parser->scope) |
31570 | && dependent_type_p (parser->scope)) |
31571 | { |
31572 | if (tag_type) |
31573 | { |
31574 | tree type; |
31575 | |
31576 | /* The resolution to Core Issue 180 says that `struct |
31577 | A::B' should be considered a type-name, even if `A' |
31578 | is dependent. */ |
31579 | type = make_typename_type (parser->scope, name, tag_type, |
31580 | /*complain=*/tf_error); |
31581 | if (type != error_mark_node) |
31582 | decl = TYPE_NAME (type); |
31583 | } |
31584 | else if (is_template |
31585 | && (cp_parser_next_token_ends_template_argument_p (parser) |
31586 | || cp_lexer_next_token_is (lexer: parser->lexer, |
31587 | type: CPP_CLOSE_PAREN))) |
31588 | decl = make_unbound_class_template (parser->scope, |
31589 | name, NULL_TREE, |
31590 | /*complain=*/tf_error); |
31591 | else |
31592 | decl = build_qualified_name (/*type=*/NULL_TREE, |
31593 | parser->scope, name, |
31594 | is_template); |
31595 | } |
31596 | parser->qualifying_scope = parser->scope; |
31597 | parser->object_scope = NULL_TREE; |
31598 | } |
31599 | else if (object_type) |
31600 | { |
31601 | bool dep = dependent_scope_p (object_type); |
31602 | |
31603 | /* Look up the name in the scope of the OBJECT_TYPE, unless the |
31604 | OBJECT_TYPE is not a class. */ |
31605 | if (!dep && CLASS_TYPE_P (object_type)) |
31606 | /* If the OBJECT_TYPE is a template specialization, it may |
31607 | be instantiated during name lookup. In that case, errors |
31608 | may be issued. Even if we rollback the current tentative |
31609 | parse, those errors are valid. */ |
31610 | decl = lookup_member (object_type, |
31611 | name, |
31612 | /*protect=*/0, |
31613 | /*prefer_type=*/tag_type != none_type, |
31614 | tf_warning_or_error); |
31615 | else |
31616 | decl = NULL_TREE; |
31617 | |
31618 | /* If we didn't find a member and have dependent bases, the member lookup |
31619 | is now dependent. */ |
31620 | if (!dep && !decl && any_dependent_bases_p (object_type)) |
31621 | dep = true; |
31622 | |
31623 | if (dep && is_template == 2) |
31624 | /* The template keyword specifies a dependent template. */; |
31625 | else if (!decl) |
31626 | /* Look it up in the enclosing context. DR 141: When looking for a |
31627 | template-name after -> or ., only consider class templates. */ |
31628 | decl = lookup_name (name, want: is_namespace ? LOOK_want::NAMESPACE |
31629 | /* DR 141: When looking in the |
31630 | current enclosing context for a |
31631 | template-name after -> or ., only |
31632 | consider class templates. */ |
31633 | : is_template ? LOOK_want::TYPE |
31634 | : prefer_type_arg (tag_type)); |
31635 | |
31636 | /* If we did unqualified lookup of a dependent member-qualified name and |
31637 | found something, do we want to use it? P1787 clarified that we need |
31638 | to look in the object scope first even if it's dependent, but for now |
31639 | let's still use it in some cases. |
31640 | FIXME remember unqualified lookup result to use if member lookup fails |
31641 | at instantiation time. */ |
31642 | if (decl && dep && is_template) |
31643 | { |
31644 | saved_token_sentinel toks (parser->lexer, STS_ROLLBACK); |
31645 | /* Only use the unqualified class template lookup if we're actually |
31646 | looking at a template arg list. */ |
31647 | if (!cp_parser_skip_entire_template_parameter_list (parser)) |
31648 | decl = NULL_TREE; |
31649 | } |
31650 | |
31651 | /* If we know we're looking for a type (e.g. A in p->A::x), |
31652 | mock up a typename. */ |
31653 | if (!decl && dep && tag_type != none_type) |
31654 | { |
31655 | tree type = build_typename_type (object_type, name, name, |
31656 | typename_type); |
31657 | decl = TYPE_NAME (type); |
31658 | } |
31659 | |
31660 | parser->object_scope = object_type; |
31661 | parser->qualifying_scope = NULL_TREE; |
31662 | } |
31663 | else |
31664 | { |
31665 | decl = lookup_name (name, want: is_namespace ? LOOK_want::NAMESPACE |
31666 | : prefer_type_arg (tag_type)); |
31667 | parser->qualifying_scope = NULL_TREE; |
31668 | parser->object_scope = NULL_TREE; |
31669 | } |
31670 | |
31671 | /* If the lookup failed, let our caller know. */ |
31672 | if (!decl || decl == error_mark_node) |
31673 | return error_mark_node; |
31674 | |
31675 | /* If we have resolved the name of a member declaration, check to |
31676 | see if the declaration is accessible. When the name resolves to |
31677 | set of overloaded functions, accessibility is checked when |
31678 | overload resolution is done. If we have a TREE_LIST, then the lookup |
31679 | is either ambiguous or it found multiple injected-class-names, the |
31680 | accessibility of which is trivially satisfied. |
31681 | |
31682 | During an explicit instantiation, access is not checked at all, |
31683 | as per [temp.explicit]. */ |
31684 | if (DECL_P (decl)) |
31685 | check_accessibility_of_qualified_id (decl, object_type, parser->scope, |
31686 | tf_warning_or_error); |
31687 | |
31688 | /* Pull out the template from an injected-class-name (or multiple). */ |
31689 | if (is_template) |
31690 | decl = maybe_get_template_decl_from_type_decl (decl); |
31691 | |
31692 | /* If it's a TREE_LIST, the result of the lookup was ambiguous. */ |
31693 | if (TREE_CODE (decl) == TREE_LIST) |
31694 | { |
31695 | if (ambiguous_decls) |
31696 | *ambiguous_decls = decl; |
31697 | /* The error message we have to print is too complicated for |
31698 | cp_parser_error, so we incorporate its actions directly. */ |
31699 | if (!cp_parser_simulate_error (parser)) |
31700 | { |
31701 | error_at (name_location, "reference to %qD is ambiguous" , |
31702 | name); |
31703 | print_candidates (decl); |
31704 | } |
31705 | return error_mark_node; |
31706 | } |
31707 | |
31708 | gcc_assert (DECL_P (decl) |
31709 | || TREE_CODE (decl) == OVERLOAD |
31710 | || TREE_CODE (decl) == SCOPE_REF |
31711 | || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE |
31712 | || BASELINK_P (decl)); |
31713 | |
31714 | maybe_record_typedef_use (decl); |
31715 | |
31716 | return cp_expr (decl, name_location); |
31717 | } |
31718 | |
31719 | /* Like cp_parser_lookup_name, but for use in the typical case where |
31720 | CHECK_ACCESS is TRUE, IS_TYPE is FALSE, IS_TEMPLATE is FALSE, |
31721 | IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE. */ |
31722 | |
31723 | static tree |
31724 | cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location) |
31725 | { |
31726 | return cp_parser_lookup_name (parser, name, |
31727 | tag_type: none_type, |
31728 | /*is_template=*/false, |
31729 | /*is_namespace=*/false, |
31730 | /*check_dependency=*/true, |
31731 | /*ambiguous_decls=*/NULL, |
31732 | name_location: location); |
31733 | } |
31734 | |
31735 | /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in |
31736 | the current context, return the TYPE_DECL. If TAG_NAME_P is |
31737 | true, the DECL indicates the class being defined in a class-head, |
31738 | or declared in an elaborated-type-specifier. |
31739 | |
31740 | Otherwise, return DECL. */ |
31741 | |
31742 | static tree |
31743 | cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) |
31744 | { |
31745 | /* If the TEMPLATE_DECL is being declared as part of a class-head, |
31746 | the translation from TEMPLATE_DECL to TYPE_DECL occurs: |
31747 | |
31748 | struct A { |
31749 | template <typename T> struct B; |
31750 | }; |
31751 | |
31752 | template <typename T> struct A::B {}; |
31753 | |
31754 | Similarly, in an elaborated-type-specifier: |
31755 | |
31756 | namespace N { struct X{}; } |
31757 | |
31758 | struct A { |
31759 | template <typename T> friend struct N::X; |
31760 | }; |
31761 | |
31762 | However, if the DECL refers to a class type, and we are in |
31763 | the scope of the class, then the name lookup automatically |
31764 | finds the TYPE_DECL created by build_self_reference rather |
31765 | than a TEMPLATE_DECL. For example, in: |
31766 | |
31767 | template <class T> struct S { |
31768 | S s; |
31769 | }; |
31770 | |
31771 | there is no need to handle such case. */ |
31772 | |
31773 | if (DECL_CLASS_TEMPLATE_P (decl) && tag_name_p) |
31774 | return DECL_TEMPLATE_RESULT (decl); |
31775 | |
31776 | return decl; |
31777 | } |
31778 | |
31779 | /* If too many, or too few, template-parameter lists apply to the |
31780 | declarator, issue an error message. Returns TRUE if all went well, |
31781 | and FALSE otherwise. */ |
31782 | |
31783 | static bool |
31784 | cp_parser_check_declarator_template_parameters (cp_parser* parser, |
31785 | cp_declarator *declarator, |
31786 | location_t declarator_location) |
31787 | { |
31788 | switch (declarator->kind) |
31789 | { |
31790 | case cdk_id: |
31791 | { |
31792 | unsigned num_templates = 0; |
31793 | tree scope = declarator->u.id.qualifying_scope; |
31794 | bool template_id_p = false; |
31795 | |
31796 | if (scope) |
31797 | num_templates = num_template_headers_for_class (scope); |
31798 | else if (TREE_CODE (declarator->u.id.unqualified_name) |
31799 | == TEMPLATE_ID_EXPR) |
31800 | { |
31801 | /* If the DECLARATOR has the form `X<y>' then it uses one |
31802 | additional level of template parameters. */ |
31803 | ++num_templates; |
31804 | template_id_p = true; |
31805 | } |
31806 | |
31807 | return cp_parser_check_template_parameters |
31808 | (parser, num_templates, template_id_p, declarator_location, |
31809 | declarator); |
31810 | } |
31811 | |
31812 | case cdk_function: |
31813 | case cdk_array: |
31814 | case cdk_pointer: |
31815 | case cdk_reference: |
31816 | case cdk_ptrmem: |
31817 | return (cp_parser_check_declarator_template_parameters |
31818 | (parser, declarator: declarator->declarator, declarator_location)); |
31819 | |
31820 | case cdk_decomp: |
31821 | case cdk_error: |
31822 | return true; |
31823 | |
31824 | default: |
31825 | gcc_unreachable (); |
31826 | } |
31827 | return false; |
31828 | } |
31829 | |
31830 | /* NUM_TEMPLATES were used in the current declaration. If that is |
31831 | invalid, return FALSE and issue an error messages. Otherwise, |
31832 | return TRUE. If DECLARATOR is non-NULL, then we are checking a |
31833 | declarator and we can print more accurate diagnostics. */ |
31834 | |
31835 | static bool |
31836 | cp_parser_check_template_parameters (cp_parser* parser, |
31837 | unsigned num_templates, |
31838 | bool template_id_p, |
31839 | location_t location, |
31840 | cp_declarator *declarator) |
31841 | { |
31842 | /* If there are the same number of template classes and parameter |
31843 | lists, that's OK. */ |
31844 | if (parser->num_template_parameter_lists == num_templates) |
31845 | return true; |
31846 | /* If there are more, but only one more, and the name ends in an identifier, |
31847 | then we are declaring a primary template. That's OK too. */ |
31848 | if (!template_id_p |
31849 | && parser->num_template_parameter_lists == num_templates + 1) |
31850 | return true; |
31851 | |
31852 | if (cp_parser_simulate_error (parser)) |
31853 | return false; |
31854 | |
31855 | /* If there are more template classes than parameter lists, we have |
31856 | something like: |
31857 | |
31858 | template <class T> void S<T>::R<T>::f (); */ |
31859 | if (parser->num_template_parameter_lists < num_templates) |
31860 | { |
31861 | if (declarator && !current_function_decl) |
31862 | error_at (location, "specializing member %<%T::%E%> " |
31863 | "requires %<template<>%> syntax" , |
31864 | declarator->u.id.qualifying_scope, |
31865 | declarator->u.id.unqualified_name); |
31866 | else if (declarator) |
31867 | error_at (location, "invalid declaration of %<%T::%E%>" , |
31868 | declarator->u.id.qualifying_scope, |
31869 | declarator->u.id.unqualified_name); |
31870 | else |
31871 | error_at (location, "too few template-parameter-lists" ); |
31872 | return false; |
31873 | } |
31874 | /* Otherwise, there are too many template parameter lists. We have |
31875 | something like: |
31876 | |
31877 | template <class T> template <class U> void S::f(); */ |
31878 | error_at (location, "too many template-parameter-lists" ); |
31879 | return false; |
31880 | } |
31881 | |
31882 | /* Parse an optional `::' token indicating that the following name is |
31883 | from the global namespace. If so, PARSER->SCOPE is set to the |
31884 | GLOBAL_NAMESPACE. Otherwise, PARSER->SCOPE is set to NULL_TREE, |
31885 | unless CURRENT_SCOPE_VALID_P is TRUE, in which case it is left alone. |
31886 | Returns the new value of PARSER->SCOPE, if the `::' token is |
31887 | present, and NULL_TREE otherwise. */ |
31888 | |
31889 | static tree |
31890 | cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p) |
31891 | { |
31892 | cp_token *token; |
31893 | |
31894 | /* Peek at the next token. */ |
31895 | token = cp_lexer_peek_token (lexer: parser->lexer); |
31896 | /* If we're looking at a `::' token then we're starting from the |
31897 | global namespace, not our current location. */ |
31898 | if (token->type == CPP_SCOPE) |
31899 | { |
31900 | /* Consume the `::' token. */ |
31901 | cp_lexer_consume_token (lexer: parser->lexer); |
31902 | /* Set the SCOPE so that we know where to start the lookup. */ |
31903 | parser->scope = global_namespace; |
31904 | parser->qualifying_scope = global_namespace; |
31905 | parser->object_scope = NULL_TREE; |
31906 | |
31907 | return parser->scope; |
31908 | } |
31909 | else if (!current_scope_valid_p) |
31910 | { |
31911 | parser->scope = NULL_TREE; |
31912 | parser->qualifying_scope = NULL_TREE; |
31913 | parser->object_scope = NULL_TREE; |
31914 | } |
31915 | |
31916 | return NULL_TREE; |
31917 | } |
31918 | |
31919 | /* Returns TRUE if the upcoming token sequence is the start of a |
31920 | constructor declarator or C++17 deduction guide. If FRIEND_P is true, the |
31921 | declarator is preceded by the `friend' specifier. The parser flags FLAGS |
31922 | is used to control type-specifier parsing. */ |
31923 | |
31924 | static bool |
31925 | cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, |
31926 | bool friend_p) |
31927 | { |
31928 | bool constructor_p; |
31929 | bool outside_class_specifier_p; |
31930 | tree nested_name_specifier; |
31931 | cp_token *next_token; |
31932 | |
31933 | /* The common case is that this is not a constructor declarator, so |
31934 | try to avoid doing lots of work if at all possible. It's not |
31935 | valid declare a constructor at function scope. */ |
31936 | if (parser->in_function_body) |
31937 | return false; |
31938 | /* And only certain tokens can begin a constructor declarator. */ |
31939 | next_token = cp_lexer_peek_token (lexer: parser->lexer); |
31940 | if (next_token->type != CPP_NAME |
31941 | && next_token->type != CPP_SCOPE |
31942 | && next_token->type != CPP_NESTED_NAME_SPECIFIER |
31943 | /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the |
31944 | declarator-id of a constructor or destructor. */ |
31945 | && (next_token->type != CPP_TEMPLATE_ID || cxx_dialect >= cxx20)) |
31946 | return false; |
31947 | |
31948 | /* Parse tentatively; we are going to roll back all of the tokens |
31949 | consumed here. */ |
31950 | cp_parser_parse_tentatively (parser); |
31951 | /* Assume that we are looking at a constructor declarator. */ |
31952 | constructor_p = true; |
31953 | |
31954 | /* Look for the optional `::' operator. */ |
31955 | cp_parser_global_scope_opt (parser, |
31956 | /*current_scope_valid_p=*/false); |
31957 | /* Look for the nested-name-specifier. */ |
31958 | nested_name_specifier |
31959 | = (cp_parser_nested_name_specifier_opt (parser, |
31960 | /*typename_keyword_p=*/false, |
31961 | /*check_dependency_p=*/false, |
31962 | /*type_p=*/false, |
31963 | /*is_declaration=*/false)); |
31964 | |
31965 | /* Resolve the TYPENAME_TYPE, because the call above didn't do it. */ |
31966 | if (nested_name_specifier |
31967 | && TREE_CODE (nested_name_specifier) == TYPENAME_TYPE) |
31968 | { |
31969 | tree s = resolve_typename_type (nested_name_specifier, |
31970 | /*only_current_p=*/false); |
31971 | if (TREE_CODE (s) != TYPENAME_TYPE) |
31972 | nested_name_specifier = s; |
31973 | } |
31974 | |
31975 | outside_class_specifier_p = (!at_class_scope_p () |
31976 | || !TYPE_BEING_DEFINED (current_class_type) |
31977 | || friend_p); |
31978 | |
31979 | /* Outside of a class-specifier, there must be a |
31980 | nested-name-specifier. Except in C++17 mode, where we |
31981 | might be declaring a guiding declaration. */ |
31982 | if (!nested_name_specifier && outside_class_specifier_p |
31983 | && cxx_dialect < cxx17) |
31984 | constructor_p = false; |
31985 | else if (nested_name_specifier == error_mark_node) |
31986 | constructor_p = false; |
31987 | |
31988 | /* If we have a class scope, this is easy; DR 147 says that S::S always |
31989 | names the constructor, and no other qualified name could. */ |
31990 | if (constructor_p && nested_name_specifier |
31991 | && CLASS_TYPE_P (nested_name_specifier)) |
31992 | { |
31993 | tree id = cp_parser_unqualified_id (parser, |
31994 | /*template_keyword_p=*/false, |
31995 | /*check_dependency_p=*/false, |
31996 | /*declarator_p=*/true, |
31997 | /*optional_p=*/false); |
31998 | if (is_overloaded_fn (id)) |
31999 | id = DECL_NAME (get_first_fn (id)); |
32000 | if (!constructor_name_p (id, nested_name_specifier)) |
32001 | constructor_p = false; |
32002 | } |
32003 | /* If we still think that this might be a constructor-declarator, |
32004 | look for a class-name. */ |
32005 | else if (constructor_p) |
32006 | { |
32007 | /* If we have: |
32008 | |
32009 | template <typename T> struct S { |
32010 | S(); |
32011 | }; |
32012 | |
32013 | we must recognize that the nested `S' names a class. */ |
32014 | if (cxx_dialect >= cxx17) |
32015 | cp_parser_parse_tentatively (parser); |
32016 | |
32017 | tree type_decl; |
32018 | type_decl = cp_parser_class_name (parser, |
32019 | /*typename_keyword_p=*/false, |
32020 | /*template_keyword_p=*/false, |
32021 | tag_type: none_type, |
32022 | /*check_dependency_p=*/false, |
32023 | /*class_head_p=*/false, |
32024 | /*is_declaration=*/false); |
32025 | |
32026 | if (cxx_dialect >= cxx17 |
32027 | && !cp_parser_parse_definitely (parser)) |
32028 | { |
32029 | type_decl = NULL_TREE; |
32030 | tree tmpl = cp_parser_template_name (parser, |
32031 | /*template_keyword*/template_keyword_p: false, |
32032 | /*check_dependency_p*/false, |
32033 | /*is_declaration*/false, |
32034 | tag_type: none_type, |
32035 | /*is_identifier*/NULL); |
32036 | if (DECL_CLASS_TEMPLATE_P (tmpl) |
32037 | || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)) |
32038 | /* It's a deduction guide, return true. */; |
32039 | else |
32040 | cp_parser_simulate_error (parser); |
32041 | } |
32042 | |
32043 | /* If there was no class-name, then this is not a constructor. |
32044 | Otherwise, if we are in a class-specifier and we aren't |
32045 | handling a friend declaration, check that its type matches |
32046 | current_class_type (c++/38313). Note: error_mark_node |
32047 | is left alone for error recovery purposes. */ |
32048 | constructor_p = (!cp_parser_error_occurred (parser) |
32049 | && (outside_class_specifier_p |
32050 | || type_decl == NULL_TREE |
32051 | || type_decl == error_mark_node |
32052 | || same_type_p (current_class_type, |
32053 | TREE_TYPE (type_decl)))); |
32054 | |
32055 | /* If we're still considering a constructor, we have to see a `(', |
32056 | to begin the parameter-declaration-clause, followed by either a |
32057 | `)', an `...', or a decl-specifier. We need to check for a |
32058 | type-specifier to avoid being fooled into thinking that: |
32059 | |
32060 | S (f) (int); |
32061 | |
32062 | is a constructor. (It is actually a function named `f' that |
32063 | takes one parameter (of type `int') and returns a value of type |
32064 | `S'. */ |
32065 | if (constructor_p |
32066 | && !cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) |
32067 | constructor_p = false; |
32068 | |
32069 | if (constructor_p |
32070 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
32071 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_ELLIPSIS) |
32072 | /* A parameter declaration begins with a decl-specifier, |
32073 | which is either the "attribute" keyword, a storage class |
32074 | specifier, or (usually) a type-specifier. */ |
32075 | && !cp_lexer_next_token_is_decl_specifier_keyword (lexer: parser->lexer) |
32076 | /* GNU attributes can actually appear both at the start of |
32077 | a parameter and parenthesized declarator. |
32078 | S (__attribute__((unused)) int); |
32079 | is a constructor, but |
32080 | S (__attribute__((unused)) foo) (int); |
32081 | is a function declaration. [[attribute]] can appear in the |
32082 | first form too, but not in the second form. */ |
32083 | && !cp_next_tokens_can_be_std_attribute_p (parser)) |
32084 | { |
32085 | tree type; |
32086 | tree pushed_scope = NULL_TREE; |
32087 | unsigned saved_num_template_parameter_lists; |
32088 | |
32089 | if (cp_parser_allow_gnu_extensions_p (parser) |
32090 | && cp_next_tokens_can_be_gnu_attribute_p (parser)) |
32091 | { |
32092 | unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, n: 1); |
32093 | while (--n) |
32094 | cp_lexer_consume_token (lexer: parser->lexer); |
32095 | } |
32096 | |
32097 | /* Names appearing in the type-specifier should be looked up |
32098 | in the scope of the class. */ |
32099 | if (current_class_type) |
32100 | type = NULL_TREE; |
32101 | else if (type_decl) |
32102 | { |
32103 | type = TREE_TYPE (type_decl); |
32104 | if (TREE_CODE (type) == TYPENAME_TYPE) |
32105 | { |
32106 | type = resolve_typename_type (type, |
32107 | /*only_current_p=*/false); |
32108 | if (TREE_CODE (type) == TYPENAME_TYPE) |
32109 | { |
32110 | cp_parser_abort_tentative_parse (parser); |
32111 | return false; |
32112 | } |
32113 | } |
32114 | pushed_scope = push_scope (type); |
32115 | } |
32116 | |
32117 | /* Inside the constructor parameter list, surrounding |
32118 | template-parameter-lists do not apply. */ |
32119 | saved_num_template_parameter_lists |
32120 | = parser->num_template_parameter_lists; |
32121 | parser->num_template_parameter_lists = 0; |
32122 | |
32123 | /* Look for the type-specifier. It's not optional, but its typename |
32124 | might be. Unless this is a friend declaration; we don't want to |
32125 | treat |
32126 | |
32127 | friend S (T::fn)(int); |
32128 | |
32129 | as a constructor, but with P0634, we might assume a type when |
32130 | looking for the type-specifier. It is actually a function named |
32131 | `T::fn' that takes one parameter (of type `int') and returns a |
32132 | value of type `S'. Constructors can be friends, but they must |
32133 | use a qualified name. |
32134 | |
32135 | Parse with an empty set of declaration specifiers since we're |
32136 | trying to match a decl-specifier-seq of the first parameter. |
32137 | This must be non-null so that cp_parser_simple_type_specifier |
32138 | will recognize a constrained placeholder type such as: |
32139 | 'C<int> auto' where C is a type concept. */ |
32140 | cp_decl_specifier_seq ctor_specs; |
32141 | clear_decl_specs (decl_specs: &ctor_specs); |
32142 | cp_parser_type_specifier (parser, |
32143 | flags: (friend_p ? CP_PARSER_FLAGS_NONE |
32144 | : (flags & ~CP_PARSER_FLAGS_OPTIONAL)), |
32145 | /*decl_specs=*/&ctor_specs, |
32146 | /*is_declarator=*/is_declaration: true, |
32147 | /*declares_class_or_enum=*/NULL, |
32148 | /*is_cv_qualifier=*/NULL); |
32149 | |
32150 | parser->num_template_parameter_lists |
32151 | = saved_num_template_parameter_lists; |
32152 | |
32153 | /* Leave the scope of the class. */ |
32154 | if (pushed_scope) |
32155 | pop_scope (pushed_scope); |
32156 | |
32157 | constructor_p = !cp_parser_error_occurred (parser); |
32158 | } |
32159 | } |
32160 | |
32161 | /* We did not really want to consume any tokens. */ |
32162 | cp_parser_abort_tentative_parse (parser); |
32163 | |
32164 | return constructor_p; |
32165 | } |
32166 | |
32167 | /* Parse the definition of the function given by the DECL_SPECIFIERS, |
32168 | ATTRIBUTES, and DECLARATOR. The access checks have been deferred; |
32169 | they must be performed once we are in the scope of the function. |
32170 | |
32171 | Returns the function defined. */ |
32172 | |
32173 | static tree |
32174 | cp_parser_function_definition_from_specifiers_and_declarator |
32175 | (cp_parser* parser, |
32176 | cp_decl_specifier_seq *decl_specifiers, |
32177 | tree attributes, |
32178 | const cp_declarator *declarator) |
32179 | { |
32180 | tree fn; |
32181 | bool success_p; |
32182 | |
32183 | /* Begin the function-definition. */ |
32184 | success_p = start_function (decl_specifiers, declarator, attributes); |
32185 | |
32186 | /* The things we're about to see are not directly qualified by any |
32187 | template headers we've seen thus far. */ |
32188 | reset_specialization (); |
32189 | |
32190 | /* If there were names looked up in the decl-specifier-seq that we |
32191 | did not check, check them now. We must wait until we are in the |
32192 | scope of the function to perform the checks, since the function |
32193 | might be a friend. */ |
32194 | perform_deferred_access_checks (tf_warning_or_error); |
32195 | |
32196 | if (success_p) |
32197 | { |
32198 | cp_finalize_omp_declare_simd (parser, fndecl: current_function_decl); |
32199 | parser->omp_declare_simd = NULL; |
32200 | cp_finalize_oacc_routine (parser, current_function_decl, true); |
32201 | parser->oacc_routine = NULL; |
32202 | } |
32203 | |
32204 | if (!success_p) |
32205 | { |
32206 | /* Skip the entire function. */ |
32207 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32208 | fn = error_mark_node; |
32209 | } |
32210 | else if (DECL_INITIAL (current_function_decl) != error_mark_node) |
32211 | { |
32212 | /* Seen already, skip it. An error message has already been output. */ |
32213 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32214 | fn = current_function_decl; |
32215 | current_function_decl = NULL_TREE; |
32216 | /* If this is a function from a class, pop the nested class. */ |
32217 | if (current_class_name) |
32218 | pop_nested_class (); |
32219 | } |
32220 | else |
32221 | { |
32222 | auto_timevar tv (DECL_DECLARED_INLINE_P (current_function_decl) |
32223 | ? TV_PARSE_INLINE : TV_PARSE_FUNC); |
32224 | fn = cp_parser_function_definition_after_declarator (parser, |
32225 | /*inline_p=*/false); |
32226 | } |
32227 | |
32228 | return fn; |
32229 | } |
32230 | |
32231 | /* Parse the part of a function-definition that follows the |
32232 | declarator. INLINE_P is TRUE iff this function is an inline |
32233 | function defined within a class-specifier. |
32234 | |
32235 | Returns the function defined. */ |
32236 | |
32237 | static tree |
32238 | cp_parser_function_definition_after_declarator (cp_parser* parser, |
32239 | bool inline_p) |
32240 | { |
32241 | tree fn; |
32242 | bool saved_in_unbraced_linkage_specification_p; |
32243 | bool saved_in_function_body; |
32244 | unsigned saved_num_template_parameter_lists; |
32245 | cp_token *token; |
32246 | bool fully_implicit_function_template_p |
32247 | = parser->fully_implicit_function_template_p; |
32248 | parser->fully_implicit_function_template_p = false; |
32249 | tree implicit_template_parms |
32250 | = parser->implicit_template_parms; |
32251 | parser->implicit_template_parms = 0; |
32252 | cp_binding_level* implicit_template_scope |
32253 | = parser->implicit_template_scope; |
32254 | parser->implicit_template_scope = 0; |
32255 | |
32256 | saved_in_function_body = parser->in_function_body; |
32257 | parser->in_function_body = true; |
32258 | /* If the next token is `return', then the code may be trying to |
32259 | make use of the "named return value" extension that G++ used to |
32260 | support. */ |
32261 | token = cp_lexer_peek_token (lexer: parser->lexer); |
32262 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_RETURN)) |
32263 | { |
32264 | /* Consume the `return' keyword. */ |
32265 | cp_lexer_consume_token (lexer: parser->lexer); |
32266 | /* Look for the identifier that indicates what value is to be |
32267 | returned. */ |
32268 | cp_parser_identifier (parser); |
32269 | /* Issue an error message. */ |
32270 | error_at (token->location, |
32271 | "named return values are no longer supported" ); |
32272 | /* Skip tokens until we reach the start of the function body. */ |
32273 | while (true) |
32274 | { |
32275 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32276 | if (token->type == CPP_OPEN_BRACE |
32277 | || token->type == CPP_EOF |
32278 | || token->type == CPP_PRAGMA_EOL) |
32279 | break; |
32280 | cp_lexer_consume_token (lexer: parser->lexer); |
32281 | } |
32282 | } |
32283 | /* The `extern' in `extern "C" void f () { ... }' does not apply to |
32284 | anything declared inside `f'. */ |
32285 | saved_in_unbraced_linkage_specification_p |
32286 | = parser->in_unbraced_linkage_specification_p; |
32287 | parser->in_unbraced_linkage_specification_p = false; |
32288 | /* Inside the function, surrounding template-parameter-lists do not |
32289 | apply. */ |
32290 | saved_num_template_parameter_lists |
32291 | = parser->num_template_parameter_lists; |
32292 | parser->num_template_parameter_lists = 0; |
32293 | |
32294 | /* If the next token is `try', `__transaction_atomic', or |
32295 | `__transaction_relaxed`, then we are looking at either function-try-block |
32296 | or function-transaction-block. Note that all of these include the |
32297 | function-body. */ |
32298 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRANSACTION_ATOMIC)) |
32299 | cp_parser_function_transaction (parser, RID_TRANSACTION_ATOMIC); |
32300 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
32301 | keyword: RID_TRANSACTION_RELAXED)) |
32302 | cp_parser_function_transaction (parser, RID_TRANSACTION_RELAXED); |
32303 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
32304 | cp_parser_function_try_block (parser); |
32305 | else |
32306 | cp_parser_ctor_initializer_opt_and_function_body |
32307 | (parser, /*in_function_try_block=*/false); |
32308 | |
32309 | /* Finish the function. */ |
32310 | fn = finish_function (inline_p); |
32311 | |
32312 | if (modules_p () |
32313 | && !inline_p |
32314 | && TYPE_P (DECL_CONTEXT (fn)) |
32315 | && (DECL_DECLARED_INLINE_P (fn) |
32316 | || processing_template_decl)) |
32317 | set_defining_module (fn); |
32318 | |
32319 | /* Generate code for it, if necessary. */ |
32320 | expand_or_defer_fn (fn); |
32321 | |
32322 | /* Restore the saved values. */ |
32323 | parser->in_unbraced_linkage_specification_p |
32324 | = saved_in_unbraced_linkage_specification_p; |
32325 | parser->num_template_parameter_lists |
32326 | = saved_num_template_parameter_lists; |
32327 | parser->in_function_body = saved_in_function_body; |
32328 | |
32329 | parser->fully_implicit_function_template_p |
32330 | = fully_implicit_function_template_p; |
32331 | parser->implicit_template_parms |
32332 | = implicit_template_parms; |
32333 | parser->implicit_template_scope |
32334 | = implicit_template_scope; |
32335 | |
32336 | if (parser->fully_implicit_function_template_p) |
32337 | finish_fully_implicit_template (parser, /*member_decl_opt=*/0); |
32338 | |
32339 | return fn; |
32340 | } |
32341 | |
32342 | /* Parse a template-declaration body (following argument list). */ |
32343 | |
32344 | static void |
32345 | cp_parser_template_declaration_after_parameters (cp_parser* parser, |
32346 | tree parameter_list, |
32347 | bool member_p) |
32348 | { |
32349 | tree decl = NULL_TREE; |
32350 | bool friend_p = false; |
32351 | |
32352 | /* We just processed one more parameter list. */ |
32353 | ++parser->num_template_parameter_lists; |
32354 | |
32355 | /* Get the deferred access checks from the parameter list. These |
32356 | will be checked once we know what is being declared, as for a |
32357 | member template the checks must be performed in the scope of the |
32358 | class containing the member. */ |
32359 | vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks (); |
32360 | |
32361 | /* Tentatively parse for a new template parameter list, which can either be |
32362 | the template keyword or a template introduction. */ |
32363 | if (cp_parser_template_declaration_after_export (parser, member_p)) |
32364 | /* OK */; |
32365 | else if (cxx_dialect >= cxx11 |
32366 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_USING)) |
32367 | decl = cp_parser_alias_declaration (parser); |
32368 | else if (flag_concepts |
32369 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CONCEPT) |
32370 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
32371 | /* -fconcept-ts 'concept bool' syntax is handled below, in |
32372 | cp_parser_single_declaration. */ |
32373 | decl = cp_parser_concept_definition (parser); |
32374 | else |
32375 | { |
32376 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32377 | decl = cp_parser_single_declaration (parser, |
32378 | checks, |
32379 | member_p, |
32380 | /*explicit_specialization_p=*/false, |
32381 | &friend_p); |
32382 | |
32383 | /* If this is a member template declaration, let the front |
32384 | end know. */ |
32385 | if (member_p && !friend_p && decl) |
32386 | { |
32387 | if (TREE_CODE (decl) == TYPE_DECL) |
32388 | cp_parser_check_access_in_redeclaration (type: decl, location: token->location); |
32389 | |
32390 | decl = finish_member_template_decl (decl); |
32391 | } |
32392 | else if (friend_p && decl |
32393 | && DECL_DECLARES_TYPE_P (decl)) |
32394 | make_friend_class (current_class_type, TREE_TYPE (decl), |
32395 | /*complain=*/true); |
32396 | } |
32397 | /* We are done with the current parameter list. */ |
32398 | --parser->num_template_parameter_lists; |
32399 | |
32400 | pop_deferring_access_checks (); |
32401 | |
32402 | /* Finish up. */ |
32403 | finish_template_decl (parameter_list); |
32404 | |
32405 | /* Check the template arguments for a literal operator template. */ |
32406 | if (decl |
32407 | && DECL_DECLARES_FUNCTION_P (decl) |
32408 | && UDLIT_OPER_P (DECL_NAME (decl))) |
32409 | { |
32410 | bool ok = true; |
32411 | if (parameter_list == NULL_TREE) |
32412 | ok = false; |
32413 | else |
32414 | { |
32415 | int num_parms = TREE_VEC_LENGTH (parameter_list); |
32416 | if (num_parms == 1) |
32417 | { |
32418 | tree parm_list = TREE_VEC_ELT (parameter_list, 0); |
32419 | tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); |
32420 | if (TREE_CODE (parm) != PARM_DECL) |
32421 | ok = false; |
32422 | else if (MAYBE_CLASS_TYPE_P (TREE_TYPE (parm)) |
32423 | && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32424 | /* OK, C++20 string literal operator template. We don't need |
32425 | to warn in lower dialects here because we will have already |
32426 | warned about the template parameter. */; |
32427 | else if (TREE_TYPE (parm) != char_type_node |
32428 | || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32429 | ok = false; |
32430 | } |
32431 | else if (num_parms == 2 && cxx_dialect >= cxx14) |
32432 | { |
32433 | tree parm_type = TREE_VEC_ELT (parameter_list, 0); |
32434 | tree type = INNERMOST_TEMPLATE_PARMS (parm_type); |
32435 | tree parm_list = TREE_VEC_ELT (parameter_list, 1); |
32436 | tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); |
32437 | if (TREE_CODE (parm) != PARM_DECL |
32438 | || TREE_TYPE (parm) != TREE_TYPE (type) |
32439 | || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) |
32440 | ok = false; |
32441 | else |
32442 | /* http://cplusplus.github.io/EWG/ewg-active.html#66 */ |
32443 | pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, |
32444 | "ISO C++ did not adopt string literal operator templa" |
32445 | "tes taking an argument pack of characters" ); |
32446 | } |
32447 | else |
32448 | ok = false; |
32449 | } |
32450 | if (!ok) |
32451 | { |
32452 | if (cxx_dialect > cxx17) |
32453 | error_at (DECL_SOURCE_LOCATION (decl), "literal operator " |
32454 | "template %qD has invalid parameter list; expected " |
32455 | "non-type template parameter pack %<<char...>%> or " |
32456 | "single non-type parameter of class type" , |
32457 | decl); |
32458 | else |
32459 | error_at (DECL_SOURCE_LOCATION (decl), "literal operator " |
32460 | "template %qD has invalid parameter list; expected " |
32461 | "non-type template parameter pack %<<char...>%>" , |
32462 | decl); |
32463 | } |
32464 | } |
32465 | |
32466 | /* Register member declarations. */ |
32467 | if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)) |
32468 | finish_member_declaration (decl); |
32469 | /* If DECL is a function template, we must return to parse it later. |
32470 | (Even though there is no definition, there might be default |
32471 | arguments that need handling.) */ |
32472 | if (member_p && decl |
32473 | && DECL_DECLARES_FUNCTION_P (decl)) |
32474 | vec_safe_push (unparsed_funs_with_definitions, obj: decl); |
32475 | } |
32476 | |
32477 | /* Parse a template introduction header for a template-declaration. Returns |
32478 | false if tentative parse fails. */ |
32479 | |
32480 | static bool |
32481 | cp_parser_template_introduction (cp_parser* parser, bool member_p) |
32482 | { |
32483 | cp_parser_parse_tentatively (parser); |
32484 | |
32485 | tree saved_scope = parser->scope; |
32486 | tree saved_object_scope = parser->object_scope; |
32487 | tree saved_qualifying_scope = parser->qualifying_scope; |
32488 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
32489 | |
32490 | cp_token *start_token = cp_lexer_peek_token (lexer: parser->lexer); |
32491 | |
32492 | /* In classes don't parse valid unnamed bitfields as invalid |
32493 | template introductions. */ |
32494 | if (member_p) |
32495 | parser->colon_corrects_to_scope_p = false; |
32496 | |
32497 | /* Look for the optional `::' operator. */ |
32498 | cp_parser_global_scope_opt (parser, |
32499 | /*current_scope_valid_p=*/false); |
32500 | /* Look for the nested-name-specifier. */ |
32501 | cp_parser_nested_name_specifier_opt (parser, |
32502 | /*typename_keyword_p=*/false, |
32503 | /*check_dependency_p=*/true, |
32504 | /*type_p=*/false, |
32505 | /*is_declaration=*/false); |
32506 | |
32507 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
32508 | tree concept_name = cp_parser_identifier (parser); |
32509 | |
32510 | /* Look up the concept for which we will be matching |
32511 | template parameters. */ |
32512 | tree tmpl_decl = cp_parser_lookup_name_simple (parser, name: concept_name, |
32513 | location: token->location); |
32514 | parser->scope = saved_scope; |
32515 | parser->object_scope = saved_object_scope; |
32516 | parser->qualifying_scope = saved_qualifying_scope; |
32517 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
32518 | |
32519 | if (concept_name == error_mark_node |
32520 | || (seen_error () && !concept_definition_p (t: tmpl_decl))) |
32521 | cp_parser_simulate_error (parser); |
32522 | |
32523 | /* Look for opening brace for introduction. */ |
32524 | matching_braces braces; |
32525 | braces.require_open (parser); |
32526 | location_t open_loc = input_location; |
32527 | |
32528 | if (!cp_parser_parse_definitely (parser)) |
32529 | return false; |
32530 | |
32531 | push_deferring_access_checks (dk_deferred); |
32532 | |
32533 | /* Build vector of placeholder parameters and grab |
32534 | matching identifiers. */ |
32535 | tree introduction_list = cp_parser_introduction_list (parser); |
32536 | |
32537 | /* Look for closing brace for introduction. */ |
32538 | if (!braces.require_close (parser)) |
32539 | return true; |
32540 | |
32541 | /* The introduction-list shall not be empty. */ |
32542 | int nargs = TREE_VEC_LENGTH (introduction_list); |
32543 | if (nargs == 0) |
32544 | { |
32545 | /* In cp_parser_introduction_list we have already issued an error. */ |
32546 | return true; |
32547 | } |
32548 | |
32549 | if (tmpl_decl == error_mark_node) |
32550 | { |
32551 | cp_parser_name_lookup_error (parser, name: concept_name, decl: tmpl_decl, desired: NLE_NULL, |
32552 | location: token->location); |
32553 | return true; |
32554 | } |
32555 | |
32556 | /* Build and associate the constraint. */ |
32557 | location_t introduction_loc = make_location (caret: open_loc, |
32558 | start: start_token->location, |
32559 | lexer: parser->lexer); |
32560 | tree parms = finish_template_introduction (tmpl_decl, |
32561 | introduction_list, |
32562 | loc: introduction_loc); |
32563 | if (parms && parms != error_mark_node) |
32564 | { |
32565 | if (!flag_concepts_ts) |
32566 | pedwarn (introduction_loc, 0, "template-introductions" |
32567 | " are not part of C++20 concepts; use %qs to enable" , |
32568 | "-fconcepts-ts" ); |
32569 | |
32570 | cp_parser_template_declaration_after_parameters (parser, parameter_list: parms, |
32571 | member_p); |
32572 | return true; |
32573 | } |
32574 | |
32575 | if (parms == NULL_TREE) |
32576 | error_at (token->location, "no matching concept for template-introduction" ); |
32577 | |
32578 | return true; |
32579 | } |
32580 | |
32581 | /* Parse a normal template-declaration following the template keyword. */ |
32582 | |
32583 | static void |
32584 | cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p) |
32585 | { |
32586 | tree parameter_list; |
32587 | bool need_lang_pop; |
32588 | location_t location = input_location; |
32589 | |
32590 | /* Look for the `<' token. */ |
32591 | if (!cp_parser_require (parser, CPP_LESS, RT_LESS)) |
32592 | return; |
32593 | if (at_class_scope_p () && current_function_decl) |
32594 | { |
32595 | /* 14.5.2.2 [temp.mem] |
32596 | |
32597 | A local class shall not have member templates. */ |
32598 | error_at (location, |
32599 | "invalid declaration of member template in local class" ); |
32600 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32601 | return; |
32602 | } |
32603 | /* [temp] |
32604 | |
32605 | A template ... shall not have C linkage. */ |
32606 | if (current_lang_name == lang_name_c) |
32607 | { |
32608 | error_at (location, "template with C linkage" ); |
32609 | maybe_show_extern_c_location (); |
32610 | /* Give it C++ linkage to avoid confusing other parts of the |
32611 | front end. */ |
32612 | push_lang_context (lang_name_cplusplus); |
32613 | need_lang_pop = true; |
32614 | } |
32615 | else |
32616 | need_lang_pop = false; |
32617 | |
32618 | /* We cannot perform access checks on the template parameter |
32619 | declarations until we know what is being declared, just as we |
32620 | cannot check the decl-specifier list. */ |
32621 | push_deferring_access_checks (dk_deferred); |
32622 | |
32623 | /* If the next token is `>', then we have an invalid |
32624 | specialization. Rather than complain about an invalid template |
32625 | parameter, issue an error message here. */ |
32626 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER)) |
32627 | { |
32628 | cp_parser_error (parser, gmsgid: "invalid explicit specialization" ); |
32629 | begin_specialization (); |
32630 | parameter_list = NULL_TREE; |
32631 | } |
32632 | else |
32633 | { |
32634 | /* Parse the template parameters. */ |
32635 | parameter_list = cp_parser_template_parameter_list (parser); |
32636 | } |
32637 | |
32638 | /* Look for the `>'. */ |
32639 | cp_parser_require_end_of_template_parameter_list (parser); |
32640 | |
32641 | /* Manage template requirements */ |
32642 | if (flag_concepts) |
32643 | { |
32644 | tree reqs = get_shorthand_constraints (current_template_parms); |
32645 | if (tree treqs = cp_parser_requires_clause_opt (parser, lambda_p: false)) |
32646 | reqs = combine_constraint_expressions (reqs, treqs); |
32647 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
32648 | } |
32649 | |
32650 | cp_parser_template_declaration_after_parameters (parser, parameter_list, |
32651 | member_p); |
32652 | |
32653 | /* For the erroneous case of a template with C linkage, we pushed an |
32654 | implicit C++ linkage scope; exit that scope now. */ |
32655 | if (need_lang_pop) |
32656 | pop_lang_context (); |
32657 | } |
32658 | |
32659 | /* Parse a template-declaration, assuming that the `export' (and |
32660 | `extern') keywords, if present, has already been scanned. MEMBER_P |
32661 | is as for cp_parser_template_declaration. */ |
32662 | |
32663 | static bool |
32664 | cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) |
32665 | { |
32666 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
32667 | { |
32668 | cp_lexer_consume_token (lexer: parser->lexer); |
32669 | cp_parser_explicit_template_declaration (parser, member_p); |
32670 | return true; |
32671 | } |
32672 | else if (flag_concepts) |
32673 | return cp_parser_template_introduction (parser, member_p); |
32674 | |
32675 | return false; |
32676 | } |
32677 | |
32678 | /* Perform the deferred access checks from a template-parameter-list. |
32679 | CHECKS is a TREE_LIST of access checks, as returned by |
32680 | get_deferred_access_checks. */ |
32681 | |
32682 | static void |
32683 | cp_parser_perform_template_parameter_access_checks (vec<deferred_access_check, va_gc> *checks) |
32684 | { |
32685 | ++processing_template_parmlist; |
32686 | perform_access_checks (checks, tf_warning_or_error); |
32687 | --processing_template_parmlist; |
32688 | } |
32689 | |
32690 | /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or |
32691 | `function-definition' sequence that follows a template header. |
32692 | If MEMBER_P is true, this declaration appears in a class scope. |
32693 | |
32694 | Returns the DECL for the declared entity. If FRIEND_P is non-NULL, |
32695 | *FRIEND_P is set to TRUE iff the declaration is a friend. */ |
32696 | |
32697 | static tree |
32698 | cp_parser_single_declaration (cp_parser* parser, |
32699 | vec<deferred_access_check, va_gc> *checks, |
32700 | bool member_p, |
32701 | bool explicit_specialization_p, |
32702 | bool* friend_p) |
32703 | { |
32704 | int declares_class_or_enum; |
32705 | tree decl = NULL_TREE; |
32706 | cp_decl_specifier_seq decl_specifiers; |
32707 | bool function_definition_p = false; |
32708 | cp_token *decl_spec_token_start; |
32709 | |
32710 | /* This function is only used when processing a template |
32711 | declaration. */ |
32712 | gcc_assert (innermost_scope_kind () == sk_template_parms |
32713 | || innermost_scope_kind () == sk_template_spec); |
32714 | |
32715 | /* Defer access checks until we know what is being declared. */ |
32716 | push_deferring_access_checks (dk_deferred); |
32717 | |
32718 | /* Try the `decl-specifier-seq [opt] init-declarator [opt]' |
32719 | alternative. */ |
32720 | decl_spec_token_start = cp_lexer_peek_token (lexer: parser->lexer); |
32721 | cp_parser_decl_specifier_seq (parser, |
32722 | flags: (CP_PARSER_FLAGS_OPTIONAL |
32723 | | CP_PARSER_FLAGS_TYPENAME_OPTIONAL), |
32724 | decl_specs: &decl_specifiers, |
32725 | declares_class_or_enum: &declares_class_or_enum); |
32726 | |
32727 | cp_omp_declare_simd_data odsd; |
32728 | if (decl_specifiers.attributes && (flag_openmp || flag_openmp_simd)) |
32729 | cp_parser_handle_directive_omp_attributes (parser, |
32730 | pattrs: &decl_specifiers.attributes, |
32731 | data: &odsd, start: true); |
32732 | |
32733 | if (friend_p) |
32734 | *friend_p = cp_parser_friend_p (&decl_specifiers); |
32735 | |
32736 | /* There are no template typedefs. */ |
32737 | if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) |
32738 | { |
32739 | error_at (decl_spec_token_start->location, |
32740 | "template declaration of %<typedef%>" ); |
32741 | decl = error_mark_node; |
32742 | } |
32743 | |
32744 | /* Gather up the access checks that occurred the |
32745 | decl-specifier-seq. */ |
32746 | stop_deferring_access_checks (); |
32747 | |
32748 | /* Check for the declaration of a template class. */ |
32749 | if (declares_class_or_enum) |
32750 | { |
32751 | if (cp_parser_declares_only_class_p (parser) |
32752 | || (declares_class_or_enum & 2)) |
32753 | { |
32754 | decl = shadow_tag (&decl_specifiers); |
32755 | |
32756 | /* In this case: |
32757 | |
32758 | struct C { |
32759 | friend template <typename T> struct A<T>::B; |
32760 | }; |
32761 | |
32762 | A<T>::B will be represented by a TYPENAME_TYPE, and |
32763 | therefore not recognized by shadow_tag. */ |
32764 | if (friend_p && *friend_p |
32765 | && !decl |
32766 | && decl_specifiers.type |
32767 | && TYPE_P (decl_specifiers.type)) |
32768 | decl = decl_specifiers.type; |
32769 | |
32770 | if (decl && decl != error_mark_node) |
32771 | decl = TYPE_NAME (decl); |
32772 | else |
32773 | decl = error_mark_node; |
32774 | |
32775 | /* If this is a declaration, but not a definition, associate |
32776 | any constraints with the type declaration. Constraints |
32777 | are associated with definitions in cp_parser_class_specifier. */ |
32778 | if (declares_class_or_enum == 1) |
32779 | associate_classtype_constraints (TREE_TYPE (decl)); |
32780 | |
32781 | /* Perform access checks for template parameters. */ |
32782 | cp_parser_perform_template_parameter_access_checks (checks); |
32783 | |
32784 | /* Give a helpful diagnostic for |
32785 | template <class T> struct A { } a; |
32786 | if we aren't already recovering from an error. */ |
32787 | if (!cp_parser_declares_only_class_p (parser) |
32788 | && !seen_error ()) |
32789 | { |
32790 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
32791 | "a class template declaration must not declare " |
32792 | "anything else" ); |
32793 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32794 | goto out; |
32795 | } |
32796 | } |
32797 | } |
32798 | |
32799 | /* Complain about missing 'typename' or other invalid type names. */ |
32800 | if (!decl_specifiers.any_type_specifiers_p |
32801 | && cp_parser_parse_and_diagnose_invalid_type_name (parser)) |
32802 | { |
32803 | /* cp_parser_parse_and_diagnose_invalid_type_name calls |
32804 | cp_parser_skip_to_end_of_block_or_statement, so don't try to parse |
32805 | the rest of this declaration. */ |
32806 | decl = error_mark_node; |
32807 | goto out; |
32808 | } |
32809 | |
32810 | /* If it's not a template class, try for a template function. If |
32811 | the next token is a `;', then this declaration does not declare |
32812 | anything. But, if there were errors in the decl-specifiers, then |
32813 | the error might well have come from an attempted class-specifier. |
32814 | In that case, there's no need to warn about a missing declarator. */ |
32815 | if (!decl |
32816 | && (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON) |
32817 | || decl_specifiers.type != error_mark_node)) |
32818 | { |
32819 | int flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; |
32820 | /* We don't delay parsing for friends, though CWG 2510 may change |
32821 | that. */ |
32822 | if (member_p && !(friend_p && *friend_p)) |
32823 | flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; |
32824 | decl = cp_parser_init_declarator (parser, |
32825 | flags, |
32826 | decl_specifiers: &decl_specifiers, |
32827 | checks, |
32828 | /*function_definition_allowed_p=*/true, |
32829 | member_p, |
32830 | declares_class_or_enum, |
32831 | function_definition_p: &function_definition_p, |
32832 | NULL, NULL, NULL); |
32833 | |
32834 | /* 7.1.1-1 [dcl.stc] |
32835 | |
32836 | A storage-class-specifier shall not be specified in an explicit |
32837 | specialization... */ |
32838 | if (decl |
32839 | && explicit_specialization_p |
32840 | && decl_specifiers.storage_class != sc_none) |
32841 | { |
32842 | error_at (decl_spec_token_start->location, |
32843 | "explicit template specialization cannot have a storage class" ); |
32844 | decl = error_mark_node; |
32845 | } |
32846 | |
32847 | if (decl && VAR_P (decl)) |
32848 | check_template_variable (decl); |
32849 | } |
32850 | |
32851 | /* Look for a trailing `;' after the declaration. */ |
32852 | if (!function_definition_p |
32853 | && (decl == error_mark_node |
32854 | || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))) |
32855 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32856 | |
32857 | out: |
32858 | pop_deferring_access_checks (); |
32859 | |
32860 | /* Clear any current qualification; whatever comes next is the start |
32861 | of something new. */ |
32862 | parser->scope = NULL_TREE; |
32863 | parser->qualifying_scope = NULL_TREE; |
32864 | parser->object_scope = NULL_TREE; |
32865 | |
32866 | cp_finalize_omp_declare_simd (parser, data: &odsd); |
32867 | |
32868 | return decl; |
32869 | } |
32870 | |
32871 | /* Parse a cast-expression that is not the operand of a unary "&". */ |
32872 | |
32873 | static cp_expr |
32874 | cp_parser_simple_cast_expression (cp_parser *parser) |
32875 | { |
32876 | return cp_parser_cast_expression (parser, /*address_p=*/false, |
32877 | /*cast_p=*/false, /*decltype*/decltype_p: false, NULL); |
32878 | } |
32879 | |
32880 | /* Parse a functional cast to TYPE. Returns an expression |
32881 | representing the cast. */ |
32882 | |
32883 | static cp_expr |
32884 | cp_parser_functional_cast (cp_parser* parser, tree type) |
32885 | { |
32886 | vec<tree, va_gc> *vec; |
32887 | tree expression_list; |
32888 | cp_expr cast; |
32889 | |
32890 | location_t start_loc = input_location; |
32891 | |
32892 | if (!type) |
32893 | type = error_mark_node; |
32894 | |
32895 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
32896 | { |
32897 | cp_lexer_set_source_position (lexer: parser->lexer); |
32898 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
32899 | expression_list = cp_parser_braced_list (parser); |
32900 | CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; |
32901 | if (TREE_CODE (type) == TYPE_DECL) |
32902 | type = TREE_TYPE (type); |
32903 | |
32904 | cast = finish_compound_literal (type, expression_list, |
32905 | tf_warning_or_error, fcl_functional); |
32906 | /* Create a location of the form: |
32907 | type_name{i, f} |
32908 | ^~~~~~~~~~~~~~~ |
32909 | with caret == start at the start of the type name, |
32910 | finishing at the closing brace. */ |
32911 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
32912 | lexer: parser->lexer); |
32913 | cast.set_location (combined_loc); |
32914 | return cast; |
32915 | } |
32916 | |
32917 | |
32918 | vec = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
32919 | /*cast_p=*/true, |
32920 | /*allow_expansion_p=*/true, |
32921 | /*non_constant_p=*/NULL); |
32922 | if (vec == NULL) |
32923 | expression_list = error_mark_node; |
32924 | else |
32925 | { |
32926 | expression_list = build_tree_list_vec (vec); |
32927 | release_tree_vector (vec); |
32928 | } |
32929 | |
32930 | /* Create a location of the form: |
32931 | float(i) |
32932 | ^~~~~~~~ |
32933 | with caret == start at the start of the type name, |
32934 | finishing at the closing paren. */ |
32935 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, |
32936 | lexer: parser->lexer); |
32937 | cast = build_functional_cast (combined_loc, type, expression_list, |
32938 | tf_warning_or_error); |
32939 | |
32940 | /* [expr.const]/1: In an integral constant expression "only type |
32941 | conversions to integral or enumeration type can be used". */ |
32942 | if (TREE_CODE (type) == TYPE_DECL) |
32943 | type = TREE_TYPE (type); |
32944 | if (cast != error_mark_node |
32945 | && !cast_valid_in_integral_constant_expression_p (type) |
32946 | && cp_parser_non_integral_constant_expression (parser, |
32947 | thing: NIC_CONSTRUCTOR)) |
32948 | return error_mark_node; |
32949 | |
32950 | return cast; |
32951 | } |
32952 | |
32953 | /* Save the tokens that make up the body of a member function defined |
32954 | in a class-specifier. The DECL_SPECIFIERS and DECLARATOR have |
32955 | already been parsed. The ATTRIBUTES are any GNU "__attribute__" |
32956 | specifiers applied to the declaration. Returns the FUNCTION_DECL |
32957 | for the member function. */ |
32958 | |
32959 | static tree |
32960 | cp_parser_save_member_function_body (cp_parser* parser, |
32961 | cp_decl_specifier_seq *decl_specifiers, |
32962 | cp_declarator *declarator, |
32963 | tree attributes) |
32964 | { |
32965 | cp_token *first; |
32966 | cp_token *last; |
32967 | tree fn; |
32968 | bool function_try_block = false; |
32969 | |
32970 | /* Create the FUNCTION_DECL. */ |
32971 | fn = grokmethod (decl_specifiers, declarator, attributes); |
32972 | cp_finalize_omp_declare_simd (parser, fndecl: fn); |
32973 | cp_finalize_oacc_routine (parser, fn, true); |
32974 | /* If something went badly wrong, bail out now. */ |
32975 | if (fn == error_mark_node) |
32976 | { |
32977 | /* If there's a function-body, skip it. */ |
32978 | if (cp_parser_token_starts_function_definition_p |
32979 | (cp_lexer_peek_token (lexer: parser->lexer))) |
32980 | cp_parser_skip_to_end_of_block_or_statement (parser); |
32981 | return error_mark_node; |
32982 | } |
32983 | |
32984 | /* Remember it, if there are default args to post process. */ |
32985 | cp_parser_save_default_args (parser, fn); |
32986 | |
32987 | /* Save away the tokens that make up the body of the |
32988 | function. */ |
32989 | first = parser->lexer->next_token; |
32990 | |
32991 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRANSACTION_RELAXED)) |
32992 | cp_lexer_consume_token (lexer: parser->lexer); |
32993 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, |
32994 | keyword: RID_TRANSACTION_ATOMIC)) |
32995 | { |
32996 | cp_lexer_consume_token (lexer: parser->lexer); |
32997 | /* Match cp_parser_txn_attribute_opt [[ identifier ]]. */ |
32998 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE) |
32999 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_SQUARE) |
33000 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NAME) |
33001 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_KEYWORD)) |
33002 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_SQUARE) |
33003 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 5, type: CPP_CLOSE_SQUARE)) |
33004 | { |
33005 | cp_lexer_consume_token (lexer: parser->lexer); |
33006 | cp_lexer_consume_token (lexer: parser->lexer); |
33007 | cp_lexer_consume_token (lexer: parser->lexer); |
33008 | cp_lexer_consume_token (lexer: parser->lexer); |
33009 | cp_lexer_consume_token (lexer: parser->lexer); |
33010 | } |
33011 | else |
33012 | while (cp_next_tokens_can_be_gnu_attribute_p (parser) |
33013 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
33014 | { |
33015 | cp_lexer_consume_token (lexer: parser->lexer); |
33016 | if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) |
33017 | break; |
33018 | } |
33019 | } |
33020 | |
33021 | /* Handle function try blocks. */ |
33022 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
33023 | { |
33024 | cp_lexer_consume_token (lexer: parser->lexer); |
33025 | function_try_block = true; |
33026 | } |
33027 | /* We can have braced-init-list mem-initializers before the fn body. */ |
33028 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
33029 | { |
33030 | cp_lexer_consume_token (lexer: parser->lexer); |
33031 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
33032 | { |
33033 | /* cache_group will stop after an un-nested { } pair, too. */ |
33034 | if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) |
33035 | break; |
33036 | |
33037 | /* variadic mem-inits have ... after the ')'. */ |
33038 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
33039 | cp_lexer_consume_token (lexer: parser->lexer); |
33040 | } |
33041 | } |
33042 | cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); |
33043 | /* Handle function try blocks. */ |
33044 | if (function_try_block) |
33045 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_CATCH)) |
33046 | cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); |
33047 | last = parser->lexer->next_token; |
33048 | |
33049 | /* Save away the inline definition; we will process it when the |
33050 | class is complete. */ |
33051 | DECL_PENDING_INLINE_INFO (fn) = cp_token_cache_new (first, last); |
33052 | DECL_PENDING_INLINE_P (fn) = 1; |
33053 | |
33054 | /* We need to know that this was defined in the class, so that |
33055 | friend templates are handled correctly. */ |
33056 | DECL_INITIALIZED_IN_CLASS_P (fn) = 1; |
33057 | |
33058 | /* Add FN to the queue of functions to be parsed later. */ |
33059 | vec_safe_push (unparsed_funs_with_definitions, obj: fn); |
33060 | |
33061 | return fn; |
33062 | } |
33063 | |
33064 | /* Save the tokens that make up the in-class initializer for a non-static |
33065 | data member. Returns a DEFERRED_PARSE. */ |
33066 | |
33067 | static tree |
33068 | cp_parser_save_nsdmi (cp_parser* parser) |
33069 | { |
33070 | return cp_parser_cache_defarg (parser, /*nsdmi=*/true); |
33071 | } |
33072 | |
33073 | /* Parse a template-argument-list, as well as the trailing ">" (but |
33074 | not the opening "<"). See cp_parser_template_argument_list for the |
33075 | return value. */ |
33076 | |
33077 | static tree |
33078 | cp_parser_enclosed_template_argument_list (cp_parser* parser) |
33079 | { |
33080 | tree arguments; |
33081 | tree saved_scope; |
33082 | tree saved_qualifying_scope; |
33083 | tree saved_object_scope; |
33084 | bool saved_greater_than_is_operator_p; |
33085 | |
33086 | /* [temp.names] |
33087 | |
33088 | When parsing a template-id, the first non-nested `>' is taken as |
33089 | the end of the template-argument-list rather than a greater-than |
33090 | operator. */ |
33091 | saved_greater_than_is_operator_p |
33092 | = parser->greater_than_is_operator_p; |
33093 | parser->greater_than_is_operator_p = false; |
33094 | /* Parsing the argument list may modify SCOPE, so we save it |
33095 | here. */ |
33096 | saved_scope = parser->scope; |
33097 | saved_qualifying_scope = parser->qualifying_scope; |
33098 | saved_object_scope = parser->object_scope; |
33099 | /* We need to evaluate the template arguments, even though this |
33100 | template-id may be nested within a "sizeof". */ |
33101 | cp_evaluated ev; |
33102 | /* Parse the template-argument-list itself. */ |
33103 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER) |
33104 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT) |
33105 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ) |
33106 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT_EQ)) |
33107 | { |
33108 | arguments = make_tree_vec (0); |
33109 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (arguments, 0); |
33110 | } |
33111 | else |
33112 | arguments = cp_parser_template_argument_list (parser); |
33113 | /* Look for the `>' that ends the template-argument-list. If we find |
33114 | a '>>' instead, it's probably just a typo. */ |
33115 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT)) |
33116 | { |
33117 | if (cxx_dialect != cxx98) |
33118 | { |
33119 | /* In C++0x, a `>>' in a template argument list or cast |
33120 | expression is considered to be two separate `>' |
33121 | tokens. So, change the current token to a `>', but don't |
33122 | consume it: it will be consumed later when the outer |
33123 | template argument list (or cast expression) is parsed. |
33124 | Note that this replacement of `>' for `>>' is necessary |
33125 | even if we are parsing tentatively: in the tentative |
33126 | case, after calling |
33127 | cp_parser_enclosed_template_argument_list we will always |
33128 | throw away all of the template arguments and the first |
33129 | closing `>', either because the template argument list |
33130 | was erroneous or because we are replacing those tokens |
33131 | with a CPP_TEMPLATE_ID token. The second `>' (which will |
33132 | not have been thrown away) is needed either to close an |
33133 | outer template argument list or to complete a new-style |
33134 | cast. */ |
33135 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33136 | token->type = CPP_GREATER; |
33137 | } |
33138 | else if (!saved_greater_than_is_operator_p) |
33139 | { |
33140 | /* If we're in a nested template argument list, the '>>' has |
33141 | to be a typo for '> >'. We emit the error message, but we |
33142 | continue parsing and we push a '>' as next token, so that |
33143 | the argument list will be parsed correctly. Note that the |
33144 | global source location is still on the token before the |
33145 | '>>', so we need to say explicitly where we want it. */ |
33146 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33147 | gcc_rich_location richloc (token->location); |
33148 | richloc.add_fixit_replace (new_content: "> >" ); |
33149 | error_at (&richloc, "%<>>%> should be %<> >%> " |
33150 | "within a nested template argument list" ); |
33151 | |
33152 | token->type = CPP_GREATER; |
33153 | } |
33154 | else |
33155 | { |
33156 | /* If this is not a nested template argument list, the '>>' |
33157 | is a typo for '>'. Emit an error message and continue. |
33158 | Same deal about the token location, but here we can get it |
33159 | right by consuming the '>>' before issuing the diagnostic. */ |
33160 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
33161 | error_at (token->location, |
33162 | "spurious %<>>%>, use %<>%> to terminate " |
33163 | "a template argument list" ); |
33164 | } |
33165 | } |
33166 | /* Similarly for >>= and >=. */ |
33167 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_GREATER_EQ) |
33168 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_RSHIFT_EQ)) |
33169 | { |
33170 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
33171 | gcc_rich_location richloc (token->location); |
33172 | enum cpp_ttype new_type; |
33173 | const char *replacement; |
33174 | if (token->type == CPP_GREATER_EQ) |
33175 | { |
33176 | replacement = "> =" ; |
33177 | new_type = CPP_EQ; |
33178 | } |
33179 | else if (!saved_greater_than_is_operator_p) |
33180 | { |
33181 | if (cxx_dialect != cxx98) |
33182 | replacement = ">> =" ; |
33183 | else |
33184 | replacement = "> > =" ; |
33185 | new_type = CPP_GREATER; |
33186 | } |
33187 | else |
33188 | { |
33189 | replacement = "> >=" ; |
33190 | new_type = CPP_GREATER_EQ; |
33191 | } |
33192 | richloc.add_fixit_replace (new_content: replacement); |
33193 | error_at (&richloc, "%qs should be %qs to terminate a template " |
33194 | "argument list" , |
33195 | cpp_type2name (token->type, flags: token->flags), replacement); |
33196 | token->type = new_type; |
33197 | } |
33198 | else |
33199 | cp_parser_require_end_of_template_parameter_list (parser); |
33200 | /* The `>' token might be a greater-than operator again now. */ |
33201 | parser->greater_than_is_operator_p |
33202 | = saved_greater_than_is_operator_p; |
33203 | /* Restore the SAVED_SCOPE. */ |
33204 | parser->scope = saved_scope; |
33205 | parser->qualifying_scope = saved_qualifying_scope; |
33206 | parser->object_scope = saved_object_scope; |
33207 | |
33208 | return arguments; |
33209 | } |
33210 | |
33211 | /* MEMBER_FUNCTION is a member function, or a friend. If default |
33212 | arguments, or the body of the function have not yet been parsed, |
33213 | parse them now. */ |
33214 | |
33215 | static void |
33216 | cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) |
33217 | { |
33218 | auto_timevar tv (TV_PARSE_INMETH); |
33219 | |
33220 | /* If this member is a template, get the underlying |
33221 | FUNCTION_DECL. */ |
33222 | if (DECL_FUNCTION_TEMPLATE_P (member_function)) |
33223 | member_function = DECL_TEMPLATE_RESULT (member_function); |
33224 | |
33225 | /* There should not be any class definitions in progress at this |
33226 | point; the bodies of members are only parsed outside of all class |
33227 | definitions. */ |
33228 | gcc_assert (parser->num_classes_being_defined == 0); |
33229 | /* While we're parsing the member functions we might encounter more |
33230 | classes. We want to handle them right away, but we don't want |
33231 | them getting mixed up with functions that are currently in the |
33232 | queue. */ |
33233 | push_unparsed_function_queues (parser); |
33234 | |
33235 | /* Make sure that any template parameters are in scope. */ |
33236 | maybe_begin_member_template_processing (member_function); |
33237 | |
33238 | /* If the body of the function has not yet been parsed, parse it |
33239 | now. Except if the tokens have been purged (PR c++/39751). */ |
33240 | if (DECL_PENDING_INLINE_P (member_function) |
33241 | && !DECL_PENDING_INLINE_INFO (member_function)->first->purged_p) |
33242 | { |
33243 | tree function_scope; |
33244 | cp_token_cache *tokens; |
33245 | |
33246 | /* The function is no longer pending; we are processing it. */ |
33247 | tokens = DECL_PENDING_INLINE_INFO (member_function); |
33248 | DECL_PENDING_INLINE_INFO (member_function) = NULL; |
33249 | DECL_PENDING_INLINE_P (member_function) = 0; |
33250 | |
33251 | /* If this is a local class, enter the scope of the containing |
33252 | function. */ |
33253 | function_scope = current_function_decl; |
33254 | if (function_scope) |
33255 | push_function_context (); |
33256 | |
33257 | /* Push the body of the function onto the lexer stack. */ |
33258 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
33259 | |
33260 | /* Let the front end know that we going to be defining this |
33261 | function. */ |
33262 | start_preparsed_function (member_function, NULL_TREE, |
33263 | SF_PRE_PARSED | SF_INCLASS_INLINE); |
33264 | |
33265 | /* #pragma omp declare reduction needs special parsing. */ |
33266 | if (DECL_OMP_DECLARE_REDUCTION_P (member_function)) |
33267 | { |
33268 | parser->lexer->in_pragma = true; |
33269 | cp_parser_omp_declare_reduction_exprs (member_function, parser); |
33270 | finish_function (/*inline_p=*/true); |
33271 | cp_check_omp_declare_reduction (member_function); |
33272 | } |
33273 | else |
33274 | /* Now, parse the body of the function. */ |
33275 | cp_parser_function_definition_after_declarator (parser, |
33276 | /*inline_p=*/true); |
33277 | |
33278 | /* Leave the scope of the containing function. */ |
33279 | if (function_scope) |
33280 | pop_function_context (); |
33281 | cp_parser_pop_lexer (parser); |
33282 | } |
33283 | |
33284 | /* Remove any template parameters from the symbol table. */ |
33285 | maybe_end_member_template_processing (); |
33286 | |
33287 | /* Restore the queue. */ |
33288 | pop_unparsed_function_queues (parser); |
33289 | } |
33290 | |
33291 | /* If DECL contains any default args, remember it on the unparsed |
33292 | functions queue. */ |
33293 | |
33294 | static void |
33295 | cp_parser_save_default_args (cp_parser* parser, tree decl) |
33296 | { |
33297 | tree probe; |
33298 | |
33299 | for (probe = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
33300 | probe; |
33301 | probe = TREE_CHAIN (probe)) |
33302 | if (TREE_PURPOSE (probe)) |
33303 | { |
33304 | cp_default_arg_entry entry = {current_class_type, .decl: decl}; |
33305 | vec_safe_push (unparsed_funs_with_default_args, obj: entry); |
33306 | break; |
33307 | } |
33308 | |
33309 | /* Remember if there is a noexcept-specifier to post process. */ |
33310 | tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)); |
33311 | if (UNPARSED_NOEXCEPT_SPEC_P (spec)) |
33312 | vec_safe_push (unparsed_noexcepts, obj: decl); |
33313 | |
33314 | /* Contracts are deferred. */ |
33315 | for (tree attr = DECL_ATTRIBUTES (decl); attr; attr = TREE_CHAIN (attr)) |
33316 | if (cxx_contract_attribute_p (attr)) |
33317 | { |
33318 | vec_safe_push (unparsed_contracts, obj: decl); |
33319 | break; |
33320 | } |
33321 | } |
33322 | |
33323 | /* DEFAULT_ARG contains the saved tokens for the initializer of DECL, |
33324 | which is either a FIELD_DECL or PARM_DECL. Parse it and return |
33325 | the result. For a PARM_DECL, PARMTYPE is the corresponding type |
33326 | from the parameter-type-list. */ |
33327 | |
33328 | static tree |
33329 | cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, |
33330 | tree default_arg, tree parmtype) |
33331 | { |
33332 | cp_token_cache *tokens; |
33333 | tree parsed_arg; |
33334 | |
33335 | if (default_arg == error_mark_node) |
33336 | return error_mark_node; |
33337 | |
33338 | /* Push the saved tokens for the default argument onto the parser's |
33339 | lexer stack. */ |
33340 | tokens = DEFPARSE_TOKENS (default_arg); |
33341 | cp_parser_push_lexer_for_tokens (parser, cache: tokens); |
33342 | |
33343 | start_lambda_scope (decl); |
33344 | |
33345 | /* Parse the default argument. */ |
33346 | parsed_arg = cp_parser_initializer (parser); |
33347 | if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)) |
33348 | maybe_warn_cpp0x (str: CPP0X_INITIALIZER_LISTS); |
33349 | |
33350 | finish_lambda_scope (); |
33351 | |
33352 | if (parsed_arg == error_mark_node) |
33353 | cp_parser_skip_to_end_of_statement (parser); |
33354 | |
33355 | if (!processing_template_decl) |
33356 | { |
33357 | /* In a non-template class, check conversions now. In a template, |
33358 | we'll wait and instantiate these as needed. */ |
33359 | if (TREE_CODE (decl) == PARM_DECL) |
33360 | parsed_arg = check_default_argument (parmtype, parsed_arg, |
33361 | tf_warning_or_error); |
33362 | else if (maybe_reject_flexarray_init (decl, parsed_arg)) |
33363 | parsed_arg = error_mark_node; |
33364 | else |
33365 | parsed_arg = digest_nsdmi_init (decl, parsed_arg, tf_warning_or_error); |
33366 | } |
33367 | |
33368 | /* If the token stream has not been completely used up, then |
33369 | there was extra junk after the end of the default |
33370 | argument. */ |
33371 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EOF)) |
33372 | { |
33373 | if (TREE_CODE (decl) == PARM_DECL) |
33374 | cp_parser_error (parser, gmsgid: "expected %<,%>" ); |
33375 | else |
33376 | cp_parser_error (parser, gmsgid: "expected %<;%>" ); |
33377 | } |
33378 | |
33379 | /* Revert to the main lexer. */ |
33380 | cp_parser_pop_lexer (parser); |
33381 | |
33382 | return parsed_arg; |
33383 | } |
33384 | |
33385 | /* FIELD is a non-static data member with an initializer which we saved for |
33386 | later; parse it now. */ |
33387 | |
33388 | static void |
33389 | cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field) |
33390 | { |
33391 | tree def; |
33392 | |
33393 | maybe_begin_member_template_processing (field); |
33394 | |
33395 | push_unparsed_function_queues (parser); |
33396 | def = cp_parser_late_parse_one_default_arg (parser, decl: field, |
33397 | DECL_INITIAL (field), |
33398 | NULL_TREE); |
33399 | pop_unparsed_function_queues (parser); |
33400 | |
33401 | maybe_end_member_template_processing (); |
33402 | |
33403 | DECL_INITIAL (field) = def; |
33404 | } |
33405 | |
33406 | /* FN is a FUNCTION_DECL which may contains a parameter with an |
33407 | unparsed DEFERRED_PARSE. Parse the default args now. This function |
33408 | assumes that the current scope is the scope in which the default |
33409 | argument should be processed. */ |
33410 | |
33411 | static void |
33412 | cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) |
33413 | { |
33414 | unsigned char saved_local_variables_forbidden_p; |
33415 | |
33416 | /* While we're parsing the default args, we might (due to the |
33417 | statement expression extension) encounter more classes. We want |
33418 | to handle them right away, but we don't want them getting mixed |
33419 | up with default args that are currently in the queue. */ |
33420 | push_unparsed_function_queues (parser); |
33421 | |
33422 | /* Local variable names (and the `this' keyword) may not appear |
33423 | in a default argument. */ |
33424 | saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; |
33425 | parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN; |
33426 | |
33427 | push_defarg_context (fn); |
33428 | |
33429 | begin_scope (sk_function_parms, fn); |
33430 | |
33431 | /* Gather the PARM_DECLs into a vec so we can keep track of them when |
33432 | pushdecl clears DECL_CHAIN. */ |
33433 | releasing_vec parms; |
33434 | for (tree parmdecl = DECL_ARGUMENTS (fn); parmdecl; |
33435 | parmdecl = DECL_CHAIN (parmdecl)) |
33436 | vec_safe_push (r&: parms, t: parmdecl); |
33437 | |
33438 | tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); |
33439 | for (int i = 0; |
33440 | parm && parm != void_list_node; |
33441 | parm = TREE_CHAIN (parm), |
33442 | ++i) |
33443 | { |
33444 | tree default_arg = TREE_PURPOSE (parm); |
33445 | tree parsed_arg; |
33446 | |
33447 | tree parmdecl = parms[i]; |
33448 | pushdecl (parmdecl); |
33449 | |
33450 | if (!default_arg) |
33451 | continue; |
33452 | |
33453 | if (TREE_CODE (default_arg) != DEFERRED_PARSE) |
33454 | /* This can happen for a friend declaration for a function |
33455 | already declared with default arguments. */ |
33456 | continue; |
33457 | |
33458 | parsed_arg |
33459 | = cp_parser_late_parse_one_default_arg (parser, decl: parmdecl, |
33460 | default_arg, |
33461 | TREE_VALUE (parm)); |
33462 | TREE_PURPOSE (parm) = parsed_arg; |
33463 | |
33464 | /* Update any instantiations we've already created. */ |
33465 | for (tree copy : DEFPARSE_INSTANTIATIONS (default_arg)) |
33466 | TREE_PURPOSE (copy) = parsed_arg; |
33467 | } |
33468 | |
33469 | pop_bindings_and_leave_scope (); |
33470 | |
33471 | /* Restore DECL_CHAINs after clobbering by pushdecl. */ |
33472 | parm = NULL_TREE; |
33473 | for (int i = parms->length () - 1; i >= 0; --i) |
33474 | { |
33475 | DECL_CHAIN (parms[i]) = parm; |
33476 | parm = parms[i]; |
33477 | } |
33478 | |
33479 | pop_defarg_context (); |
33480 | |
33481 | /* Make sure no default arg is missing. */ |
33482 | check_default_args (fn); |
33483 | |
33484 | /* Restore the state of local_variables_forbidden_p. */ |
33485 | parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; |
33486 | |
33487 | /* Restore the queue. */ |
33488 | pop_unparsed_function_queues (parser); |
33489 | } |
33490 | |
33491 | /* Subroutine of cp_parser_sizeof_operand, for handling C++11 |
33492 | |
33493 | sizeof ... ( identifier ) |
33494 | |
33495 | where the 'sizeof' token has already been consumed. */ |
33496 | |
33497 | static tree |
33498 | cp_parser_sizeof_pack (cp_parser *parser) |
33499 | { |
33500 | /* Consume the `...'. */ |
33501 | cp_lexer_consume_token (lexer: parser->lexer); |
33502 | maybe_warn_variadic_templates (); |
33503 | |
33504 | matching_parens parens; |
33505 | bool paren = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN); |
33506 | if (paren) |
33507 | parens.consume_open (parser); |
33508 | else |
33509 | permerror (cp_lexer_peek_token (lexer: parser->lexer)->location, |
33510 | "%<sizeof...%> argument must be surrounded by parentheses" ); |
33511 | |
33512 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
33513 | tree name = cp_parser_identifier (parser); |
33514 | if (name == error_mark_node) |
33515 | return error_mark_node; |
33516 | /* The name is not qualified. */ |
33517 | parser->scope = NULL_TREE; |
33518 | parser->qualifying_scope = NULL_TREE; |
33519 | parser->object_scope = NULL_TREE; |
33520 | tree expr = cp_parser_lookup_name_simple (parser, name, location: token->location); |
33521 | if (expr == error_mark_node) |
33522 | cp_parser_name_lookup_error (parser, name, decl: expr, desired: NLE_NULL, |
33523 | location: token->location); |
33524 | if (TREE_CODE (expr) == TYPE_DECL || TREE_CODE (expr) == TEMPLATE_DECL) |
33525 | expr = TREE_TYPE (expr); |
33526 | else if (TREE_CODE (expr) == CONST_DECL) |
33527 | expr = DECL_INITIAL (expr); |
33528 | expr = make_pack_expansion (expr); |
33529 | if (expr != error_mark_node) |
33530 | PACK_EXPANSION_SIZEOF_P (expr) = true; |
33531 | |
33532 | if (paren) |
33533 | parens.require_close (parser); |
33534 | |
33535 | return expr; |
33536 | } |
33537 | |
33538 | /* Parse the operand of `sizeof' (or a similar operator). Returns |
33539 | either a TYPE or an expression, depending on the form of the |
33540 | input. The KEYWORD indicates which kind of expression we have |
33541 | encountered. */ |
33542 | |
33543 | static tree |
33544 | cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) |
33545 | { |
33546 | tree expr = NULL_TREE; |
33547 | const char *saved_message; |
33548 | const char *saved_message_arg; |
33549 | bool saved_integral_constant_expression_p; |
33550 | bool saved_non_integral_constant_expression_p; |
33551 | |
33552 | /* If it's a `...', then we are computing the length of a parameter |
33553 | pack. */ |
33554 | if (keyword == RID_SIZEOF |
33555 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
33556 | return cp_parser_sizeof_pack (parser); |
33557 | |
33558 | /* Types cannot be defined in a `sizeof' expression. Save away the |
33559 | old message. */ |
33560 | saved_message = parser->type_definition_forbidden_message; |
33561 | saved_message_arg = parser->type_definition_forbidden_message_arg; |
33562 | parser->type_definition_forbidden_message |
33563 | = G_("types may not be defined in %qs expressions" ); |
33564 | parser->type_definition_forbidden_message_arg |
33565 | = IDENTIFIER_POINTER (ridpointers[keyword]); |
33566 | |
33567 | /* The restrictions on constant-expressions do not apply inside |
33568 | sizeof expressions. */ |
33569 | saved_integral_constant_expression_p |
33570 | = parser->integral_constant_expression_p; |
33571 | saved_non_integral_constant_expression_p |
33572 | = parser->non_integral_constant_expression_p; |
33573 | parser->integral_constant_expression_p = false; |
33574 | |
33575 | auto cleanup = make_temp_override |
33576 | (var&: parser->auto_is_implicit_function_template_parm_p, overrider: false); |
33577 | |
33578 | /* Do not actually evaluate the expression. */ |
33579 | ++cp_unevaluated_operand; |
33580 | ++c_inhibit_evaluation_warnings; |
33581 | /* If it's a `(', then we might be looking at the type-id |
33582 | construction. */ |
33583 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
33584 | { |
33585 | tree type = NULL_TREE; |
33586 | |
33587 | tentative_firewall firewall (parser); |
33588 | |
33589 | /* We can't be sure yet whether we're looking at a type-id or an |
33590 | expression. */ |
33591 | cp_parser_parse_tentatively (parser); |
33592 | |
33593 | matching_parens parens; |
33594 | parens.consume_open (parser); |
33595 | |
33596 | /* Note: as a GNU Extension, compound literals are considered |
33597 | postfix-expressions as they are in C99, so they are valid |
33598 | arguments to sizeof. See comment in cp_parser_cast_expression |
33599 | for details. */ |
33600 | if (cp_parser_compound_literal_p (parser)) |
33601 | cp_parser_simulate_error (parser); |
33602 | else |
33603 | { |
33604 | bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; |
33605 | parser->in_type_id_in_expr_p = true; |
33606 | /* Look for the type-id. */ |
33607 | type = cp_parser_type_id (parser); |
33608 | /* Look for the closing `)'. */ |
33609 | parens.require_close (parser); |
33610 | parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; |
33611 | } |
33612 | |
33613 | /* If all went well, then we're done. */ |
33614 | if (cp_parser_parse_definitely (parser)) |
33615 | expr = type; |
33616 | else |
33617 | { |
33618 | /* Commit to the tentative_firewall so we get syntax errors. */ |
33619 | cp_parser_commit_to_tentative_parse (parser); |
33620 | |
33621 | expr = cp_parser_unary_expression (parser); |
33622 | } |
33623 | } |
33624 | else |
33625 | expr = cp_parser_unary_expression (parser); |
33626 | |
33627 | /* Go back to evaluating expressions. */ |
33628 | --cp_unevaluated_operand; |
33629 | --c_inhibit_evaluation_warnings; |
33630 | |
33631 | /* And restore the old one. */ |
33632 | parser->type_definition_forbidden_message = saved_message; |
33633 | parser->type_definition_forbidden_message_arg = saved_message_arg; |
33634 | parser->integral_constant_expression_p |
33635 | = saved_integral_constant_expression_p; |
33636 | parser->non_integral_constant_expression_p |
33637 | = saved_non_integral_constant_expression_p; |
33638 | |
33639 | return expr; |
33640 | } |
33641 | |
33642 | /* If the current declaration has no declarator, return true. */ |
33643 | |
33644 | static bool |
33645 | cp_parser_declares_only_class_p (cp_parser *parser) |
33646 | { |
33647 | /* If the next token is a `;' or a `,' then there is no |
33648 | declarator. */ |
33649 | return (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
33650 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)); |
33651 | } |
33652 | |
33653 | /* Update the DECL_SPECS to reflect the storage class indicated by |
33654 | KEYWORD. */ |
33655 | |
33656 | static void |
33657 | cp_parser_set_storage_class (cp_parser *parser, |
33658 | cp_decl_specifier_seq *decl_specs, |
33659 | enum rid keyword, |
33660 | cp_token *token) |
33661 | { |
33662 | cp_storage_class storage_class; |
33663 | |
33664 | switch (keyword) |
33665 | { |
33666 | case RID_AUTO: |
33667 | storage_class = sc_auto; |
33668 | break; |
33669 | case RID_REGISTER: |
33670 | storage_class = sc_register; |
33671 | break; |
33672 | case RID_STATIC: |
33673 | storage_class = sc_static; |
33674 | break; |
33675 | case RID_EXTERN: |
33676 | storage_class = sc_extern; |
33677 | break; |
33678 | case RID_MUTABLE: |
33679 | storage_class = sc_mutable; |
33680 | break; |
33681 | default: |
33682 | gcc_unreachable (); |
33683 | } |
33684 | |
33685 | if (parser->in_unbraced_linkage_specification_p) |
33686 | { |
33687 | error_at (token->location, "invalid use of %qD in linkage specification" , |
33688 | ridpointers[keyword]); |
33689 | return; |
33690 | } |
33691 | else if (decl_specs->storage_class != sc_none) |
33692 | { |
33693 | if (decl_specs->conflicting_specifiers_p) |
33694 | return; |
33695 | gcc_rich_location richloc (token->location); |
33696 | richloc.add_location_if_nearby (loc: decl_specs->locations[ds_storage_class]); |
33697 | if (decl_specs->storage_class == storage_class) |
33698 | error_at (&richloc, "duplicate %qD specifier" , ridpointers[keyword]); |
33699 | else |
33700 | error_at (&richloc, |
33701 | "%qD specifier conflicts with %qs" , |
33702 | ridpointers[keyword], |
33703 | cp_storage_class_name[decl_specs->storage_class]); |
33704 | decl_specs->conflicting_specifiers_p = true; |
33705 | return; |
33706 | } |
33707 | |
33708 | if ((keyword == RID_EXTERN || keyword == RID_STATIC) |
33709 | && decl_spec_seq_has_spec_p (decl_specs, ds_thread) |
33710 | && decl_specs->gnu_thread_keyword_p) |
33711 | { |
33712 | pedwarn (decl_specs->locations[ds_thread], 0, |
33713 | "%<__thread%> before %qD" , ridpointers[keyword]); |
33714 | } |
33715 | |
33716 | decl_specs->storage_class = storage_class; |
33717 | set_and_check_decl_spec_loc (decl_specs, ds: ds_storage_class, token); |
33718 | |
33719 | /* A storage class specifier cannot be applied alongside a typedef |
33720 | specifier. If there is a typedef specifier present then set |
33721 | conflicting_specifiers_p which will trigger an error later |
33722 | on in grokdeclarator. */ |
33723 | if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) |
33724 | && !decl_specs->conflicting_specifiers_p) |
33725 | { |
33726 | gcc_rich_location richloc (token->location); |
33727 | richloc.add_location_if_nearby (loc: decl_specs->locations[ds_typedef]); |
33728 | error_at (&richloc, |
33729 | "%qD specifier conflicts with %<typedef%>" , |
33730 | ridpointers[keyword]); |
33731 | decl_specs->conflicting_specifiers_p = true; |
33732 | } |
33733 | } |
33734 | |
33735 | /* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P |
33736 | is true, the type is a class or enum definition. */ |
33737 | |
33738 | static void |
33739 | cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, |
33740 | tree type_spec, |
33741 | cp_token *token, |
33742 | bool type_definition_p) |
33743 | { |
33744 | decl_specs->any_specifiers_p = true; |
33745 | |
33746 | /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or |
33747 | wchar_t (with, for example, in "typedef int wchar_t;") we remember that |
33748 | this is what happened. In system headers, we ignore these |
33749 | declarations so that G++ can work with system headers that are not |
33750 | C++-safe. */ |
33751 | if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) |
33752 | && !type_definition_p |
33753 | && TYPE_P (type_spec) |
33754 | && (type_spec == boolean_type_node |
33755 | || type_spec == char8_type_node |
33756 | || type_spec == char16_type_node |
33757 | || type_spec == char32_type_node |
33758 | || extended_float_type_p (type: type_spec) |
33759 | || type_spec == wchar_type_node) |
33760 | && (decl_specs->type |
33761 | || decl_spec_seq_has_spec_p (decl_specs, ds_long) |
33762 | || decl_spec_seq_has_spec_p (decl_specs, ds_short) |
33763 | || decl_spec_seq_has_spec_p (decl_specs, ds_unsigned) |
33764 | || decl_spec_seq_has_spec_p (decl_specs, ds_signed))) |
33765 | { |
33766 | decl_specs->redefined_builtin_type = type_spec; |
33767 | set_and_check_decl_spec_loc (decl_specs, |
33768 | ds: ds_redefined_builtin_type_spec, |
33769 | token); |
33770 | if (!decl_specs->type) |
33771 | { |
33772 | decl_specs->type = type_spec; |
33773 | decl_specs->type_definition_p = false; |
33774 | set_and_check_decl_spec_loc (decl_specs,ds: ds_type_spec, token); |
33775 | } |
33776 | } |
33777 | else if (decl_specs->type) |
33778 | decl_specs->multiple_types_p = true; |
33779 | else |
33780 | { |
33781 | decl_specs->type = type_spec; |
33782 | decl_specs->type_definition_p = type_definition_p; |
33783 | decl_specs->redefined_builtin_type = NULL_TREE; |
33784 | set_and_check_decl_spec_loc (decl_specs, ds: ds_type_spec, token); |
33785 | } |
33786 | } |
33787 | |
33788 | /* True iff TOKEN is the GNU keyword __thread. */ |
33789 | |
33790 | static bool |
33791 | token_is__thread (cp_token *token) |
33792 | { |
33793 | gcc_assert (token->keyword == RID_THREAD); |
33794 | return id_equal (id: token->u.value, str: "__thread" ); |
33795 | } |
33796 | |
33797 | /* Set the location for a declarator specifier and check if it is |
33798 | duplicated. |
33799 | |
33800 | DECL_SPECS is the sequence of declarator specifiers onto which to |
33801 | set the location. |
33802 | |
33803 | DS is the single declarator specifier to set which location is to |
33804 | be set onto the existing sequence of declarators. |
33805 | |
33806 | LOCATION is the location for the declarator specifier to |
33807 | consider. */ |
33808 | |
33809 | static void |
33810 | set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs, |
33811 | cp_decl_spec ds, cp_token *token) |
33812 | { |
33813 | gcc_assert (ds < ds_last); |
33814 | |
33815 | if (decl_specs == NULL) |
33816 | return; |
33817 | |
33818 | location_t location = token->location; |
33819 | |
33820 | if (decl_specs->locations[ds] == 0) |
33821 | { |
33822 | decl_specs->locations[ds] = location; |
33823 | if (ds == ds_thread) |
33824 | decl_specs->gnu_thread_keyword_p = token_is__thread (token); |
33825 | } |
33826 | else |
33827 | { |
33828 | if (ds == ds_long) |
33829 | { |
33830 | if (decl_specs->locations[ds_long_long] != 0) |
33831 | error_at (location, |
33832 | "%<long long long%> is too long for GCC" ); |
33833 | else |
33834 | { |
33835 | decl_specs->locations[ds_long_long] = location; |
33836 | pedwarn_cxx98 (location, |
33837 | OPT_Wlong_long, |
33838 | "ISO C++ 1998 does not support %<long long%>" ); |
33839 | } |
33840 | } |
33841 | else if (ds == ds_thread) |
33842 | { |
33843 | bool gnu = token_is__thread (token); |
33844 | gcc_rich_location richloc (location); |
33845 | if (gnu != decl_specs->gnu_thread_keyword_p) |
33846 | { |
33847 | richloc.add_range (loc: decl_specs->locations[ds_thread]); |
33848 | error_at (&richloc, |
33849 | "both %<__thread%> and %<thread_local%> specified" ); |
33850 | } |
33851 | else |
33852 | { |
33853 | richloc.add_fixit_remove (); |
33854 | error_at (&richloc, "duplicate %qD" , token->u.value); |
33855 | } |
33856 | } |
33857 | else |
33858 | { |
33859 | static const char *const decl_spec_names[] = { |
33860 | "signed" , |
33861 | "unsigned" , |
33862 | "short" , |
33863 | "long" , |
33864 | "const" , |
33865 | "volatile" , |
33866 | "restrict" , |
33867 | "inline" , |
33868 | "virtual" , |
33869 | "explicit" , |
33870 | "friend" , |
33871 | "typedef" , |
33872 | "using" , |
33873 | "constexpr" , |
33874 | "__complex" , |
33875 | "constinit" , |
33876 | "consteval" |
33877 | }; |
33878 | gcc_rich_location richloc (location); |
33879 | richloc.add_fixit_remove (); |
33880 | error_at (&richloc, "duplicate %qs" , decl_spec_names[ds]); |
33881 | } |
33882 | } |
33883 | } |
33884 | |
33885 | /* Return true iff the declarator specifier DS is present in the |
33886 | sequence of declarator specifiers DECL_SPECS. */ |
33887 | |
33888 | bool |
33889 | decl_spec_seq_has_spec_p (const cp_decl_specifier_seq * decl_specs, |
33890 | cp_decl_spec ds) |
33891 | { |
33892 | gcc_assert (ds < ds_last); |
33893 | |
33894 | if (decl_specs == NULL) |
33895 | return false; |
33896 | |
33897 | return decl_specs->locations[ds] != 0; |
33898 | } |
33899 | |
33900 | /* DECL_SPECIFIERS is the representation of a decl-specifier-seq. |
33901 | Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */ |
33902 | |
33903 | static bool |
33904 | cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers) |
33905 | { |
33906 | return decl_spec_seq_has_spec_p (decl_specs: decl_specifiers, ds: ds_friend); |
33907 | } |
33908 | |
33909 | /* Issue an error message indicating that TOKEN_DESC was expected. |
33910 | If KEYWORD is true, it indicated this function is called by |
33911 | cp_parser_require_keword and the required token can only be |
33912 | a indicated keyword. |
33913 | |
33914 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it |
33915 | within any error as the location of an "opening" token matching |
33916 | the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is |
33917 | RT_CLOSE_PAREN). */ |
33918 | |
33919 | static void |
33920 | cp_parser_required_error (cp_parser *parser, |
33921 | required_token token_desc, |
33922 | bool keyword, |
33923 | location_t matching_location) |
33924 | { |
33925 | if (cp_parser_simulate_error (parser)) |
33926 | return; |
33927 | |
33928 | const char *gmsgid = NULL; |
33929 | switch (token_desc) |
33930 | { |
33931 | case RT_NEW: |
33932 | gmsgid = G_("expected %<new%>" ); |
33933 | break; |
33934 | case RT_DELETE: |
33935 | gmsgid = G_("expected %<delete%>" ); |
33936 | break; |
33937 | case RT_RETURN: |
33938 | gmsgid = G_("expected %<return%>" ); |
33939 | break; |
33940 | case RT_WHILE: |
33941 | gmsgid = G_("expected %<while%>" ); |
33942 | break; |
33943 | case RT_EXTERN: |
33944 | gmsgid = G_("expected %<extern%>" ); |
33945 | break; |
33946 | case RT_STATIC_ASSERT: |
33947 | gmsgid = G_("expected %<static_assert%>" ); |
33948 | break; |
33949 | case RT_DECLTYPE: |
33950 | gmsgid = G_("expected %<decltype%>" ); |
33951 | break; |
33952 | case RT_OPERATOR: |
33953 | gmsgid = G_("expected %<operator%>" ); |
33954 | break; |
33955 | case RT_CLASS: |
33956 | gmsgid = G_("expected %<class%>" ); |
33957 | break; |
33958 | case RT_TEMPLATE: |
33959 | gmsgid = G_("expected %<template%>" ); |
33960 | break; |
33961 | case RT_NAMESPACE: |
33962 | gmsgid = G_("expected %<namespace%>" ); |
33963 | break; |
33964 | case RT_USING: |
33965 | gmsgid = G_("expected %<using%>" ); |
33966 | break; |
33967 | case RT_ASM: |
33968 | gmsgid = G_("expected %<asm%>" ); |
33969 | break; |
33970 | case RT_TRY: |
33971 | gmsgid = G_("expected %<try%>" ); |
33972 | break; |
33973 | case RT_CATCH: |
33974 | gmsgid = G_("expected %<catch%>" ); |
33975 | break; |
33976 | case RT_THROW: |
33977 | gmsgid = G_("expected %<throw%>" ); |
33978 | break; |
33979 | case RT_AUTO: |
33980 | gmsgid = G_("expected %<auto%>" ); |
33981 | break; |
33982 | case RT_LABEL: |
33983 | gmsgid = G_("expected %<__label__%>" ); |
33984 | break; |
33985 | case RT_AT_TRY: |
33986 | gmsgid = G_("expected %<@try%>" ); |
33987 | break; |
33988 | case RT_AT_SYNCHRONIZED: |
33989 | gmsgid = G_("expected %<@synchronized%>" ); |
33990 | break; |
33991 | case RT_AT_THROW: |
33992 | gmsgid = G_("expected %<@throw%>" ); |
33993 | break; |
33994 | case RT_TRANSACTION_ATOMIC: |
33995 | gmsgid = G_("expected %<__transaction_atomic%>" ); |
33996 | break; |
33997 | case RT_TRANSACTION_RELAXED: |
33998 | gmsgid = G_("expected %<__transaction_relaxed%>" ); |
33999 | break; |
34000 | case RT_CO_YIELD: |
34001 | gmsgid = G_("expected %<co_yield%>" ); |
34002 | break; |
34003 | default: |
34004 | break; |
34005 | } |
34006 | |
34007 | if (!gmsgid && !keyword) |
34008 | { |
34009 | switch (token_desc) |
34010 | { |
34011 | case RT_SEMICOLON: |
34012 | gmsgid = G_("expected %<;%>" ); |
34013 | break; |
34014 | case RT_OPEN_PAREN: |
34015 | gmsgid = G_("expected %<(%>" ); |
34016 | break; |
34017 | case RT_CLOSE_BRACE: |
34018 | gmsgid = G_("expected %<}%>" ); |
34019 | break; |
34020 | case RT_OPEN_BRACE: |
34021 | gmsgid = G_("expected %<{%>" ); |
34022 | break; |
34023 | case RT_CLOSE_SQUARE: |
34024 | gmsgid = G_("expected %<]%>" ); |
34025 | break; |
34026 | case RT_OPEN_SQUARE: |
34027 | gmsgid = G_("expected %<[%>" ); |
34028 | break; |
34029 | case RT_COMMA: |
34030 | gmsgid = G_("expected %<,%>" ); |
34031 | break; |
34032 | case RT_SCOPE: |
34033 | gmsgid = G_("expected %<::%>" ); |
34034 | break; |
34035 | case RT_LESS: |
34036 | gmsgid = G_("expected %<<%>" ); |
34037 | break; |
34038 | case RT_GREATER: |
34039 | gmsgid = G_("expected %<>%>" ); |
34040 | break; |
34041 | case RT_EQ: |
34042 | gmsgid = G_("expected %<=%>" ); |
34043 | break; |
34044 | case RT_ELLIPSIS: |
34045 | gmsgid = G_("expected %<...%>" ); |
34046 | break; |
34047 | case RT_MULT: |
34048 | gmsgid = G_("expected %<*%>" ); |
34049 | break; |
34050 | case RT_COMPL: |
34051 | gmsgid = G_("expected %<~%>" ); |
34052 | break; |
34053 | case RT_COLON: |
34054 | gmsgid = G_("expected %<:%>" ); |
34055 | break; |
34056 | case RT_COLON_SCOPE: |
34057 | gmsgid = G_("expected %<:%> or %<::%>" ); |
34058 | break; |
34059 | case RT_CLOSE_PAREN: |
34060 | gmsgid = G_("expected %<)%>" ); |
34061 | break; |
34062 | case RT_COMMA_CLOSE_PAREN: |
34063 | gmsgid = G_("expected %<,%> or %<)%>" ); |
34064 | break; |
34065 | case RT_PRAGMA_EOL: |
34066 | gmsgid = G_("expected end of line" ); |
34067 | break; |
34068 | case RT_NAME: |
34069 | gmsgid = G_("expected identifier" ); |
34070 | break; |
34071 | case RT_SELECT: |
34072 | gmsgid = G_("expected selection-statement" ); |
34073 | break; |
34074 | case RT_ITERATION: |
34075 | gmsgid = G_("expected iteration-statement" ); |
34076 | break; |
34077 | case RT_JUMP: |
34078 | gmsgid = G_("expected jump-statement" ); |
34079 | break; |
34080 | case RT_CLASS_KEY: |
34081 | gmsgid = G_("expected class-key" ); |
34082 | break; |
34083 | case RT_CLASS_TYPENAME_TEMPLATE: |
34084 | gmsgid = G_("expected %<class%>, %<typename%>, or %<template%>" ); |
34085 | break; |
34086 | default: |
34087 | gcc_unreachable (); |
34088 | } |
34089 | } |
34090 | |
34091 | if (gmsgid) |
34092 | cp_parser_error_1 (parser, gmsgid, missing_token_desc: token_desc, matching_location); |
34093 | } |
34094 | |
34095 | |
34096 | /* If the next token is of the indicated TYPE, consume it. Otherwise, |
34097 | issue an error message indicating that TOKEN_DESC was expected. |
34098 | |
34099 | Returns the token consumed, if the token had the appropriate type. |
34100 | Otherwise, returns NULL. |
34101 | |
34102 | If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it |
34103 | within any error as the location of an "opening" token matching |
34104 | the close token TYPE (e.g. the location of the '(' when TOKEN_DESC is |
34105 | RT_CLOSE_PAREN). */ |
34106 | |
34107 | static cp_token * |
34108 | cp_parser_require (cp_parser* parser, |
34109 | enum cpp_ttype type, |
34110 | required_token token_desc, |
34111 | location_t matching_location) |
34112 | { |
34113 | if (cp_lexer_next_token_is (lexer: parser->lexer, type)) |
34114 | return cp_lexer_consume_token (lexer: parser->lexer); |
34115 | else |
34116 | { |
34117 | /* Output the MESSAGE -- unless we're parsing tentatively. */ |
34118 | if (!cp_parser_simulate_error (parser)) |
34119 | cp_parser_required_error (parser, token_desc, /*keyword=*/false, |
34120 | matching_location); |
34121 | return NULL; |
34122 | } |
34123 | } |
34124 | |
34125 | /* Skip an entire parameter list from start to finish. The next token must |
34126 | be the initial "<" of the parameter list. Returns true on success and |
34127 | false otherwise. */ |
34128 | |
34129 | static bool |
34130 | cp_parser_skip_entire_template_parameter_list (cp_parser* parser) |
34131 | { |
34132 | /* Consume the "<" because cp_parser_skip_to_end_of_template_parameter_list |
34133 | requires it. */ |
34134 | cp_lexer_consume_token (lexer: parser->lexer); |
34135 | return cp_parser_skip_to_end_of_template_parameter_list (parser); |
34136 | } |
34137 | |
34138 | /* Ensure we are at the end of a template parameter list. If we are, return. |
34139 | If we are not, something has gone wrong, in which case issue an error and |
34140 | skip to end of the parameter list. */ |
34141 | |
34142 | static void |
34143 | cp_parser_require_end_of_template_parameter_list (cp_parser* parser) |
34144 | { |
34145 | /* Are we ready, yet? If not, issue error message. */ |
34146 | if (cp_parser_require (parser, type: CPP_GREATER, token_desc: RT_GREATER)) |
34147 | return; |
34148 | |
34149 | cp_parser_skip_to_end_of_template_parameter_list (parser); |
34150 | } |
34151 | |
34152 | /* You should only call this function from inside a template parameter list |
34153 | (i.e. the current token should at least be the initial "<" of the |
34154 | parameter list). If you are skipping the entire list, it may be better to |
34155 | use cp_parser_skip_entire_template_parameter_list. |
34156 | |
34157 | Tokens are skipped until the final ">" is found, or if we see |
34158 | '{', '}', ';', or if we find an unbalanced ')' or ']'. |
34159 | |
34160 | Returns true if we successfully reached the end, and false if |
34161 | something unexpected happened (e.g. end of file). */ |
34162 | |
34163 | static bool |
34164 | cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser) |
34165 | { |
34166 | /* Current level of '< ... >'. */ |
34167 | unsigned level = 0; |
34168 | /* Ignore '<' and '>' nested inside '( ... )' or '[ ... ]'. */ |
34169 | unsigned nesting_depth = 0; |
34170 | |
34171 | /* Skip tokens until the desired token is found. */ |
34172 | while (true) |
34173 | { |
34174 | /* Peek at the next token. */ |
34175 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
34176 | { |
34177 | case CPP_LESS: |
34178 | if (!nesting_depth) |
34179 | ++level; |
34180 | break; |
34181 | |
34182 | case CPP_RSHIFT: |
34183 | if (cxx_dialect == cxx98) |
34184 | /* C++0x views the `>>' operator as two `>' tokens, but |
34185 | C++98 does not. */ |
34186 | break; |
34187 | else if (!nesting_depth && level-- == 0) |
34188 | { |
34189 | /* We've hit a `>>' where the first `>' closes the |
34190 | template argument list, and the second `>' is |
34191 | spurious. Just consume the `>>' and stop; we've |
34192 | already produced at least one error. */ |
34193 | cp_lexer_consume_token (lexer: parser->lexer); |
34194 | return false; |
34195 | } |
34196 | /* Fall through for C++0x, so we handle the second `>' in |
34197 | the `>>'. */ |
34198 | gcc_fallthrough (); |
34199 | |
34200 | case CPP_GREATER: |
34201 | if (!nesting_depth && level-- == 0) |
34202 | { |
34203 | /* We've reached the token we want, consume it and stop. */ |
34204 | cp_lexer_consume_token (lexer: parser->lexer); |
34205 | return true; |
34206 | } |
34207 | break; |
34208 | |
34209 | case CPP_OPEN_PAREN: |
34210 | case CPP_OPEN_SQUARE: |
34211 | ++nesting_depth; |
34212 | break; |
34213 | |
34214 | case CPP_CLOSE_PAREN: |
34215 | case CPP_CLOSE_SQUARE: |
34216 | if (nesting_depth-- == 0) |
34217 | return false; |
34218 | break; |
34219 | |
34220 | case CPP_EOF: |
34221 | case CPP_PRAGMA_EOL: |
34222 | case CPP_SEMICOLON: |
34223 | case CPP_OPEN_BRACE: |
34224 | case CPP_CLOSE_BRACE: |
34225 | /* The '>' was probably forgotten, don't look further. */ |
34226 | return false; |
34227 | |
34228 | default: |
34229 | break; |
34230 | } |
34231 | |
34232 | /* Consume this token. */ |
34233 | cp_lexer_consume_token (lexer: parser->lexer); |
34234 | } |
34235 | } |
34236 | |
34237 | /* If the next token is the indicated keyword, consume it. Otherwise, |
34238 | issue an error message indicating that TOKEN_DESC was expected. |
34239 | |
34240 | Returns the token consumed, if the token had the appropriate type. |
34241 | Otherwise, returns NULL. */ |
34242 | |
34243 | static cp_token * |
34244 | cp_parser_require_keyword (cp_parser* parser, |
34245 | enum rid keyword, |
34246 | required_token token_desc) |
34247 | { |
34248 | cp_token *token = cp_parser_require (parser, type: CPP_KEYWORD, token_desc); |
34249 | |
34250 | if (token && token->keyword != keyword) |
34251 | { |
34252 | cp_parser_required_error (parser, token_desc, /*keyword=*/true, |
34253 | UNKNOWN_LOCATION); |
34254 | return NULL; |
34255 | } |
34256 | |
34257 | return token; |
34258 | } |
34259 | |
34260 | /* Returns TRUE iff TOKEN is a token that can begin the body of a |
34261 | function-definition. */ |
34262 | |
34263 | static bool |
34264 | cp_parser_token_starts_function_definition_p (cp_token* token) |
34265 | { |
34266 | return (/* An ordinary function-body begins with an `{'. */ |
34267 | token->type == CPP_OPEN_BRACE |
34268 | /* A ctor-initializer begins with a `:'. */ |
34269 | || token->type == CPP_COLON |
34270 | /* A function-try-block begins with `try'. */ |
34271 | || token->keyword == RID_TRY |
34272 | /* A function-transaction-block begins with `__transaction_atomic' |
34273 | or `__transaction_relaxed'. */ |
34274 | || token->keyword == RID_TRANSACTION_ATOMIC |
34275 | || token->keyword == RID_TRANSACTION_RELAXED |
34276 | /* The named return value extension begins with `return'. */ |
34277 | || token->keyword == RID_RETURN); |
34278 | } |
34279 | |
34280 | /* Returns TRUE iff the next token is the ":" or "{" beginning a class |
34281 | definition. */ |
34282 | |
34283 | static bool |
34284 | cp_parser_next_token_starts_class_definition_p (cp_parser *parser) |
34285 | { |
34286 | cp_token *token; |
34287 | |
34288 | token = cp_lexer_peek_token (lexer: parser->lexer); |
34289 | return (token->type == CPP_OPEN_BRACE |
34290 | || (token->type == CPP_COLON |
34291 | && !parser->colon_doesnt_start_class_def_p)); |
34292 | } |
34293 | |
34294 | /* Returns TRUE iff the next token is the "," or ">" (or `>>', in |
34295 | C++0x) ending a template-argument. */ |
34296 | |
34297 | static bool |
34298 | cp_parser_next_token_ends_template_argument_p (cp_parser *parser) |
34299 | { |
34300 | cp_token *token; |
34301 | |
34302 | token = cp_lexer_peek_token (lexer: parser->lexer); |
34303 | return (token->type == CPP_COMMA |
34304 | || token->type == CPP_GREATER |
34305 | || token->type == CPP_ELLIPSIS |
34306 | || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT) |
34307 | /* For better diagnostics, treat >>= like that too, that |
34308 | shouldn't appear non-nested in template arguments. */ |
34309 | || token->type == CPP_RSHIFT_EQ); |
34310 | } |
34311 | |
34312 | /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the |
34313 | (n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */ |
34314 | |
34315 | static bool |
34316 | cp_parser_nth_token_starts_template_argument_list_p (cp_parser * parser, |
34317 | size_t n) |
34318 | { |
34319 | cp_token *token; |
34320 | |
34321 | token = cp_lexer_peek_nth_token (lexer: parser->lexer, n); |
34322 | if (token->type == CPP_LESS) |
34323 | return true; |
34324 | /* Check for the sequence `<::' in the original code. It would be lexed as |
34325 | `[:', where `[' is a digraph, and there is no whitespace before |
34326 | `:'. */ |
34327 | if (token->type == CPP_OPEN_SQUARE && token->flags & DIGRAPH) |
34328 | { |
34329 | cp_token *token2; |
34330 | token2 = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n+1); |
34331 | if (token2->type == CPP_COLON && !(token2->flags & PREV_WHITE)) |
34332 | return true; |
34333 | } |
34334 | return false; |
34335 | } |
34336 | |
34337 | /* Returns the kind of tag indicated by TOKEN, if it is a class-key, |
34338 | or none_type otherwise. */ |
34339 | |
34340 | static enum tag_types |
34341 | cp_parser_token_is_class_key (cp_token* token) |
34342 | { |
34343 | switch (token->keyword) |
34344 | { |
34345 | case RID_CLASS: |
34346 | return class_type; |
34347 | case RID_STRUCT: |
34348 | return record_type; |
34349 | case RID_UNION: |
34350 | return union_type; |
34351 | |
34352 | default: |
34353 | return none_type; |
34354 | } |
34355 | } |
34356 | |
34357 | /* Returns the kind of tag indicated by TOKEN, if it is a type-parameter-key, |
34358 | or none_type otherwise or if the token is null. */ |
34359 | |
34360 | static enum tag_types |
34361 | cp_parser_token_is_type_parameter_key (cp_token* token) |
34362 | { |
34363 | if (!token) |
34364 | return none_type; |
34365 | |
34366 | switch (token->keyword) |
34367 | { |
34368 | case RID_CLASS: |
34369 | return class_type; |
34370 | case RID_TYPENAME: |
34371 | return typename_type; |
34372 | |
34373 | default: |
34374 | return none_type; |
34375 | } |
34376 | } |
34377 | |
34378 | /* Diagnose redundant enum-keys. */ |
34379 | |
34380 | static void |
34381 | cp_parser_maybe_warn_enum_key (cp_parser *parser, location_t key_loc, |
34382 | tree type, rid scoped_key) |
34383 | { |
34384 | if (!warn_redundant_tags) |
34385 | return; |
34386 | |
34387 | tree type_decl = TYPE_MAIN_DECL (type); |
34388 | tree name = DECL_NAME (type_decl); |
34389 | /* Look up the NAME to see if it unambiguously refers to the TYPE. */ |
34390 | push_deferring_access_checks (dk_no_check); |
34391 | tree decl = cp_parser_lookup_name_simple (parser, name, location: input_location); |
34392 | pop_deferring_access_checks (); |
34393 | |
34394 | /* The enum-key is redundant for uses of the TYPE that are not |
34395 | declarations and for which name lookup returns just the type |
34396 | itself. */ |
34397 | if (decl != type_decl) |
34398 | return; |
34399 | |
34400 | if (scoped_key != RID_CLASS |
34401 | && scoped_key != RID_STRUCT |
34402 | && current_lang_name != lang_name_cplusplus |
34403 | && current_namespace == global_namespace) |
34404 | { |
34405 | /* Avoid issuing the diagnostic for apparently redundant (unscoped) |
34406 | enum tag in shared C/C++ code in files (such as headers) included |
34407 | in the main source file. */ |
34408 | const line_map_ordinary *map = NULL; |
34409 | linemap_resolve_location (line_table, loc: key_loc, |
34410 | lrk: LRK_MACRO_DEFINITION_LOCATION, |
34411 | loc_map: &map); |
34412 | if (!MAIN_FILE_P (ord_map: map)) |
34413 | return; |
34414 | } |
34415 | |
34416 | gcc_rich_location richloc (key_loc); |
34417 | richloc.add_fixit_remove (where: key_loc); |
34418 | warning_at (&richloc, OPT_Wredundant_tags, |
34419 | "redundant enum-key %<enum%s%> in reference to %q#T" , |
34420 | (scoped_key == RID_CLASS ? " class" |
34421 | : scoped_key == RID_STRUCT ? " struct" : "" ), type); |
34422 | } |
34423 | |
34424 | /* Describes the set of declarations of a struct, class, or class template |
34425 | or its specializations. Used for -Wmismatched-tags. */ |
34426 | |
34427 | class class_decl_loc_t |
34428 | { |
34429 | public: |
34430 | |
34431 | class_decl_loc_t () |
34432 | : locvec (), idxdef (), def_class_key () |
34433 | { |
34434 | locvec.create (nelems: 4); |
34435 | } |
34436 | |
34437 | /* Constructs an object for a single declaration of a class with |
34438 | CLASS_KEY at the current location in the current function (or |
34439 | at another scope). KEY_REDUNDANT is true if the class-key may |
34440 | be omitted in the current context without an ambiguity with |
34441 | another symbol with the same name. |
34442 | DEF_P is true for a class declaration that is a definition. |
34443 | CURLOC is the associated location. */ |
34444 | class_decl_loc_t (tag_types class_key, bool key_redundant, bool def_p, |
34445 | location_t curloc = input_location) |
34446 | : locvec (), idxdef (def_p ? 0 : UINT_MAX), def_class_key (class_key) |
34447 | { |
34448 | locvec.create (nelems: 4); |
34449 | class_key_loc_t ckl (current_function_decl, curloc, class_key, |
34450 | key_redundant); |
34451 | locvec.quick_push (obj: ckl); |
34452 | } |
34453 | |
34454 | /* Copy, assign, and destroy the object. Necessary because LOCVEC |
34455 | isn't safely copyable and assignable and doesn't release storage |
34456 | on its own. */ |
34457 | class_decl_loc_t (const class_decl_loc_t &rhs) |
34458 | : locvec (rhs.locvec.copy ()), idxdef (rhs.idxdef), |
34459 | def_class_key (rhs.def_class_key) |
34460 | { } |
34461 | |
34462 | class_decl_loc_t& operator= (const class_decl_loc_t &rhs) |
34463 | { |
34464 | if (this == &rhs) |
34465 | return *this; |
34466 | locvec.release (); |
34467 | locvec = rhs.locvec.copy (); |
34468 | idxdef = rhs.idxdef; |
34469 | def_class_key = rhs.def_class_key; |
34470 | return *this; |
34471 | } |
34472 | |
34473 | ~class_decl_loc_t () |
34474 | { |
34475 | locvec.release (); |
34476 | } |
34477 | |
34478 | /* Issues -Wmismatched-tags for a single class. */ |
34479 | void diag_mismatched_tags (tree); |
34480 | |
34481 | /* Issues -Wmismatched-tags for all classes. */ |
34482 | static void diag_mismatched_tags (); |
34483 | |
34484 | /* Adds TYPE_DECL to the collection of class decls and diagnoses |
34485 | redundant tags (if -Wredundant-tags is enabled). */ |
34486 | static void add (cp_parser *, location_t, tag_types, tree, bool, bool); |
34487 | |
34488 | /* Either adds this decl to the collection of class decls |
34489 | or diagnoses it, whichever is appropriate. */ |
34490 | void add_or_diag_mismatched_tag (tree, tag_types, bool, bool); |
34491 | |
34492 | private: |
34493 | |
34494 | tree function (unsigned i) const |
34495 | { |
34496 | return locvec[i].func; |
34497 | } |
34498 | |
34499 | location_t location (unsigned i) const |
34500 | { |
34501 | return locvec[i].loc; |
34502 | } |
34503 | |
34504 | bool key_redundant (unsigned i) const |
34505 | { |
34506 | return locvec[i].key_redundant; |
34507 | } |
34508 | |
34509 | tag_types class_key (unsigned i) const |
34510 | { |
34511 | return locvec[i].class_key; |
34512 | } |
34513 | |
34514 | /* True if a definition for the class has been seen. */ |
34515 | bool def_p () const |
34516 | { |
34517 | return idxdef < locvec.length (); |
34518 | } |
34519 | |
34520 | /* The location of a single mention of a class type with the given |
34521 | class-key. */ |
34522 | struct class_key_loc_t |
34523 | { |
34524 | class_key_loc_t (tree func, location_t loc, tag_types key, bool redundant) |
34525 | : func (func), loc (loc), class_key (key), key_redundant (redundant) |
34526 | { } |
34527 | |
34528 | /* The function the type is mentioned in. */ |
34529 | tree func; |
34530 | /* The exact location. */ |
34531 | location_t loc; |
34532 | /* The class-key used in the mention of the type. */ |
34533 | tag_types class_key; |
34534 | /* True when the class-key could be omitted at this location |
34535 | without an ambiguity with another symbol of the same name. */ |
34536 | bool key_redundant; |
34537 | }; |
34538 | /* Avoid using auto_vec here since it's not safe to copy due to pr90904. */ |
34539 | vec <class_key_loc_t> locvec; |
34540 | /* LOCVEC index of the definition or UINT_MAX if none exists. */ |
34541 | unsigned idxdef; |
34542 | /* The class-key the class was last declared with or none_type when |
34543 | it has been declared with a mismatched key. */ |
34544 | tag_types def_class_key; |
34545 | |
34546 | /* A mapping between a TYPE_DECL for a class and the class_decl_loc_t |
34547 | description above. */ |
34548 | typedef hash_map<tree_decl_hash, class_decl_loc_t> class_to_loc_map_t; |
34549 | static class_to_loc_map_t class2loc; |
34550 | }; |
34551 | |
34552 | class_decl_loc_t::class_to_loc_map_t class_decl_loc_t::class2loc; |
34553 | |
34554 | /* Issue an error message if the CLASS_KEY does not match the TYPE. |
34555 | DEF_P is expected to be set for a definition of class TYPE. DECL_P |
34556 | is set for a declaration of class TYPE and clear for a reference to |
34557 | it that is not a declaration of it. */ |
34558 | |
34559 | static void |
34560 | cp_parser_check_class_key (cp_parser *parser, location_t key_loc, |
34561 | tag_types class_key, tree type, bool def_p, |
34562 | bool decl_p) |
34563 | { |
34564 | if (type == error_mark_node) |
34565 | return; |
34566 | |
34567 | bool seen_as_union = TREE_CODE (type) == UNION_TYPE; |
34568 | if (seen_as_union != (class_key == union_type)) |
34569 | { |
34570 | if (permerror (input_location, "%qs tag used in naming %q#T" , |
34571 | class_key == union_type ? "union" |
34572 | : class_key == record_type ? "struct" : "class" , |
34573 | type)) |
34574 | inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), |
34575 | "%q#T was previously declared here" , type); |
34576 | return; |
34577 | } |
34578 | |
34579 | if (!warn_mismatched_tags && !warn_redundant_tags) |
34580 | return; |
34581 | |
34582 | /* Only consider the true class-keys below and ignore typename_type, |
34583 | etc. that are not C++ class-keys. */ |
34584 | if (class_key != class_type |
34585 | && class_key != record_type |
34586 | && class_key != union_type) |
34587 | return; |
34588 | |
34589 | class_decl_loc_t::add (parser, key_loc, class_key, type, def_p, decl_p); |
34590 | } |
34591 | |
34592 | /* Returns the template or specialization of one to which the RECORD_TYPE |
34593 | TYPE corresponds. */ |
34594 | |
34595 | static tree |
34596 | specialization_of (tree type) |
34597 | { |
34598 | tree ret = type; |
34599 | |
34600 | /* Determine the template or its partial specialization to which TYPE |
34601 | corresponds. */ |
34602 | if (tree ti = most_specialized_partial_spec (type, tf_none)) |
34603 | if (ti != error_mark_node) |
34604 | ret = TREE_TYPE (TI_TEMPLATE (ti)); |
34605 | |
34606 | if (ret == type) |
34607 | ret = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (type); |
34608 | |
34609 | return TYPE_MAIN_DECL (ret); |
34610 | } |
34611 | |
34612 | |
34613 | /* Adds the class TYPE to the collection of class decls and diagnoses |
34614 | redundant tags (if -Wredundant-tags is enabled). |
34615 | DEF_P is expected to be set for a definition of class TYPE. DECL_P |
34616 | is set for a (likely, based on syntactic context) declaration of class |
34617 | TYPE and clear for a reference to it that is not a declaration of it. */ |
34618 | |
34619 | void |
34620 | class_decl_loc_t::add (cp_parser *parser, location_t key_loc, |
34621 | tag_types class_key, tree type, bool def_p, bool decl_p) |
34622 | { |
34623 | tree type_decl = TYPE_MAIN_DECL (type); |
34624 | tree name = DECL_NAME (type_decl); |
34625 | /* Look up the NAME to see if it unambiguously refers to the TYPE |
34626 | and set KEY_REDUNDANT if so. */ |
34627 | push_deferring_access_checks (dk_no_check); |
34628 | tree decl = cp_parser_lookup_name_simple (parser, name, location: input_location); |
34629 | pop_deferring_access_checks (); |
34630 | |
34631 | /* The class-key is redundant for uses of the CLASS_TYPE that are |
34632 | neither definitions of it nor declarations, and for which name |
34633 | lookup returns just the type itself. */ |
34634 | bool key_redundant = (!def_p && !decl_p |
34635 | && (decl == type_decl |
34636 | || TREE_CODE (decl) == TEMPLATE_DECL |
34637 | || (CLASS_TYPE_P (type) |
34638 | && TYPE_BEING_DEFINED (type)))); |
34639 | |
34640 | if (key_redundant |
34641 | && class_key != class_type |
34642 | && current_lang_name != lang_name_cplusplus |
34643 | && current_namespace == global_namespace) |
34644 | { |
34645 | /* Avoid issuing the diagnostic for apparently redundant struct |
34646 | and union class-keys in shared C/C++ code in files (such as |
34647 | headers) included in the main source file. */ |
34648 | const line_map_ordinary *map = NULL; |
34649 | linemap_resolve_location (line_table, loc: key_loc, |
34650 | lrk: LRK_MACRO_DEFINITION_LOCATION, |
34651 | loc_map: &map); |
34652 | if (!MAIN_FILE_P (ord_map: map)) |
34653 | key_redundant = false; |
34654 | } |
34655 | |
34656 | /* Set if a declaration of TYPE has previously been seen or if it must |
34657 | exist in a precompiled header. */ |
34658 | bool exist; |
34659 | class_decl_loc_t *rdl = &class2loc.get_or_insert (k: type_decl, existed: &exist); |
34660 | if (!exist) |
34661 | { |
34662 | tree type = TREE_TYPE (type_decl); |
34663 | if (def_p || !COMPLETE_TYPE_P (type)) |
34664 | { |
34665 | /* TYPE_DECL is the first declaration or definition of the type |
34666 | (outside precompiled headers -- see below). Just create |
34667 | a new entry for it and return unless it's a declaration |
34668 | involving a template that may need to be diagnosed by |
34669 | -Wredundant-tags. */ |
34670 | *rdl = class_decl_loc_t (class_key, false, def_p); |
34671 | if (TREE_CODE (decl) != TEMPLATE_DECL) |
34672 | return; |
34673 | } |
34674 | else |
34675 | { |
34676 | /* TYPE was previously defined in some unknown precompiled header. |
34677 | Simply add a record of its definition at an unknown location and |
34678 | proceed below to add a reference to it at the current location. |
34679 | (Declarations in precompiled headers that are not definitions |
34680 | are ignored.) */ |
34681 | tag_types def_key |
34682 | = CLASSTYPE_DECLARED_CLASS (type) ? class_type : record_type; |
34683 | location_t def_loc = DECL_SOURCE_LOCATION (type_decl); |
34684 | *rdl = class_decl_loc_t (def_key, false, true, def_loc); |
34685 | exist = true; |
34686 | } |
34687 | } |
34688 | |
34689 | /* A prior declaration of TYPE_DECL has been seen. */ |
34690 | |
34691 | if (key_redundant) |
34692 | { |
34693 | gcc_rich_location richloc (key_loc); |
34694 | richloc.add_fixit_remove (where: key_loc); |
34695 | warning_at (&richloc, OPT_Wredundant_tags, |
34696 | "redundant class-key %qs in reference to %q#T" , |
34697 | class_key == union_type ? "union" |
34698 | : class_key == record_type ? "struct" : "class" , |
34699 | type); |
34700 | } |
34701 | |
34702 | if (!exist) |
34703 | /* Do nothing if this is the first declaration of the type. */ |
34704 | return; |
34705 | |
34706 | if (rdl->idxdef != UINT_MAX && rdl->def_class_key == class_key) |
34707 | /* Do nothing if the class-key in this declaration matches |
34708 | the definition. */ |
34709 | return; |
34710 | |
34711 | rdl->add_or_diag_mismatched_tag (type_decl, class_key, key_redundant, |
34712 | def_p); |
34713 | } |
34714 | |
34715 | /* Either adds this DECL corresponding to the TYPE_DECL to the collection |
34716 | of class decls or diagnoses it, whichever is appropriate. */ |
34717 | |
34718 | void |
34719 | class_decl_loc_t::add_or_diag_mismatched_tag (tree type_decl, |
34720 | tag_types class_key, |
34721 | bool redundant, |
34722 | bool def_p) |
34723 | { |
34724 | /* Reset the CLASS_KEY associated with this type on mismatch. |
34725 | This is an optimization that lets the diagnostic code skip |
34726 | over classes that use the same class-key in all declarations. */ |
34727 | if (def_class_key != class_key) |
34728 | def_class_key = none_type; |
34729 | |
34730 | /* Set IDXDEF to the index of the vector corresponding to |
34731 | the definition. */ |
34732 | if (def_p) |
34733 | idxdef = locvec.length (); |
34734 | |
34735 | /* Append a record of this declaration to the vector. */ |
34736 | class_key_loc_t ckl (current_function_decl, input_location, class_key, |
34737 | redundant); |
34738 | locvec.safe_push (obj: ckl); |
34739 | |
34740 | if (idxdef == UINT_MAX) |
34741 | return; |
34742 | |
34743 | /* As a space optimization diagnose declarations of a class |
34744 | whose definition has been seen and purge the LOCVEC of |
34745 | all entries except the definition. */ |
34746 | diag_mismatched_tags (type_decl); |
34747 | if (idxdef) |
34748 | { |
34749 | class_decl_loc_t::class_key_loc_t ent = locvec[idxdef]; |
34750 | locvec.release (); |
34751 | locvec.reserve (nelems: 2); |
34752 | locvec.safe_push (obj: ent); |
34753 | idxdef = 0; |
34754 | } |
34755 | else |
34756 | /* Pop the entry pushed above for this declaration. */ |
34757 | locvec.pop (); |
34758 | } |
34759 | |
34760 | /* Issues -Wmismatched-tags for a single class. */ |
34761 | |
34762 | void |
34763 | class_decl_loc_t::diag_mismatched_tags (tree type_decl) |
34764 | { |
34765 | if (!warn_mismatched_tags) |
34766 | return; |
34767 | |
34768 | /* Number of uses of the class. */ |
34769 | const unsigned ndecls = locvec.length (); |
34770 | |
34771 | /* The class (or template) declaration guiding the decisions about |
34772 | the diagnostic. For ordinary classes it's the same as THIS. For |
34773 | uses of instantiations of templates other than their declarations |
34774 | it points to the record for the declaration of the corresponding |
34775 | primary template or partial specialization. */ |
34776 | class_decl_loc_t *cdlguide = this; |
34777 | |
34778 | tree type = TREE_TYPE (type_decl); |
34779 | if (CLASS_TYPE_P (type) && CLASSTYPE_IMPLICIT_INSTANTIATION (type)) |
34780 | { |
34781 | /* For implicit instantiations of a primary template look up |
34782 | the primary or partial specialization and use it as |
34783 | the expected class-key rather than using the class-key of |
34784 | the first reference to the instantiation. The primary must |
34785 | be (and inevitably is) at index zero. */ |
34786 | tree spec = specialization_of (type); |
34787 | cdlguide = class2loc.get (k: spec); |
34788 | /* It's possible that we didn't find SPEC. Consider: |
34789 | |
34790 | template<typename T> struct A { |
34791 | template<typename U> struct W { }; |
34792 | }; |
34793 | struct A<int>::W<int> w; // #1 |
34794 | |
34795 | where while parsing A and #1 we've stashed |
34796 | A<T> |
34797 | A<T>::W<U> |
34798 | A<int>::W<int> |
34799 | into CLASS2LOC. If TYPE is A<int>::W<int>, specialization_of |
34800 | will yield A<int>::W<U> which may be in CLASS2LOC if we had |
34801 | an A<int> class specialization, but otherwise won't be in it. |
34802 | So try to look up A<T>::W<U>. */ |
34803 | if (!cdlguide) |
34804 | { |
34805 | spec = DECL_TEMPLATE_RESULT (most_general_template (spec)); |
34806 | cdlguide = class2loc.get (k: spec); |
34807 | } |
34808 | /* Now we really should have found something. */ |
34809 | gcc_assert (cdlguide != NULL); |
34810 | } |
34811 | /* Skip declarations that consistently use the same class-key. */ |
34812 | else if (def_class_key != none_type) |
34813 | return; |
34814 | |
34815 | /* Set if a definition for the class has been seen. */ |
34816 | const bool def_p = cdlguide->def_p (); |
34817 | |
34818 | /* The index of the declaration whose class-key this declaration |
34819 | is expected to match. It's either the class-key of the class |
34820 | definition if one exists or the first declaration otherwise. */ |
34821 | const unsigned idxguide = def_p ? cdlguide->idxdef : 0; |
34822 | |
34823 | /* The class-key the class is expected to be declared with: it's |
34824 | either the key used in its definition or the first declaration |
34825 | if no definition has been provided. |
34826 | For implicit instantiations of a primary template it's |
34827 | the class-key used to declare the primary with. The primary |
34828 | must be at index zero. */ |
34829 | const tag_types xpect_key = cdlguide->class_key (i: idxguide); |
34830 | |
34831 | unsigned idx = 0; |
34832 | /* Advance IDX to the first declaration that either is not |
34833 | a definition or that doesn't match the first declaration |
34834 | if no definition is provided. */ |
34835 | while (class_key (i: idx) == xpect_key) |
34836 | if (++idx == ndecls) |
34837 | return; |
34838 | |
34839 | /* Save the current function before changing it below. */ |
34840 | tree save_func = current_function_decl; |
34841 | /* Set the function declaration to print in diagnostic context. */ |
34842 | current_function_decl = function (i: idx); |
34843 | |
34844 | const char *xmatchkstr = xpect_key == record_type ? "class" : "struct" ; |
34845 | const char *xpectkstr = xpect_key == record_type ? "struct" : "class" ; |
34846 | |
34847 | location_t loc = location (i: idx); |
34848 | bool key_redundant_p = key_redundant (i: idx); |
34849 | auto_diagnostic_group d; |
34850 | /* Issue a warning for the first mismatched declaration. |
34851 | Avoid using "%#qT" since the class-key for the same type will |
34852 | be the same regardless of which one was used in the declaraion. */ |
34853 | if (warning_at (loc, OPT_Wmismatched_tags, |
34854 | "%qT declared with a mismatched class-key %qs" , |
34855 | type_decl, xmatchkstr)) |
34856 | { |
34857 | /* Suggest how to avoid the warning for each instance since |
34858 | the guidance may be different depending on context. */ |
34859 | inform (loc, |
34860 | (key_redundant_p |
34861 | ? G_("remove the class-key or replace it with %qs" ) |
34862 | : G_("replace the class-key with %qs" )), |
34863 | xpectkstr); |
34864 | |
34865 | /* Also point to the first declaration or definition that guided |
34866 | the decision to issue the warning above. */ |
34867 | inform (cdlguide->location (i: idxguide), |
34868 | (def_p |
34869 | ? G_("%qT defined as %qs here" ) |
34870 | : G_("%qT first declared as %qs here" )), |
34871 | type_decl, xpectkstr); |
34872 | } |
34873 | |
34874 | /* Issue warnings for the remaining inconsistent declarations. */ |
34875 | for (unsigned i = idx + 1; i != ndecls; ++i) |
34876 | { |
34877 | tag_types clskey = class_key (i); |
34878 | /* Skip over the declarations that match either the definition |
34879 | if one was provided or the first declaration. */ |
34880 | if (clskey == xpect_key) |
34881 | continue; |
34882 | |
34883 | loc = location (i); |
34884 | key_redundant_p = key_redundant (i); |
34885 | /* Set the function declaration to print in diagnostic context. */ |
34886 | current_function_decl = function (i); |
34887 | if (warning_at (loc, OPT_Wmismatched_tags, |
34888 | "%qT declared with a mismatched class-key %qs" , |
34889 | type_decl, xmatchkstr)) |
34890 | /* Suggest how to avoid the warning for each instance since |
34891 | the guidance may be different depending on context. */ |
34892 | inform (loc, |
34893 | (key_redundant_p |
34894 | ? G_("remove the class-key or replace it with %qs" ) |
34895 | : G_("replace the class-key with %qs" )), |
34896 | xpectkstr); |
34897 | } |
34898 | |
34899 | /* Restore the current function in case it was replaced above. */ |
34900 | current_function_decl = save_func; |
34901 | } |
34902 | |
34903 | /* Issues -Wmismatched-tags for all classes. Called at the end |
34904 | of processing a translation unit, after declarations of all class |
34905 | types and their uses have been recorded. */ |
34906 | |
34907 | void |
34908 | class_decl_loc_t::diag_mismatched_tags () |
34909 | { |
34910 | /* CLASS2LOC should be empty if both -Wmismatched-tags and |
34911 | -Wredundant-tags are disabled. */ |
34912 | gcc_assert (warn_mismatched_tags |
34913 | || warn_redundant_tags |
34914 | || class2loc.is_empty ()); |
34915 | |
34916 | /* Save the current function before changing on return. It should |
34917 | be null at this point. */ |
34918 | temp_override<tree> cleanup (current_function_decl); |
34919 | |
34920 | if (warn_mismatched_tags) |
34921 | { |
34922 | /* Iterate over the collected class/struct/template declarations. */ |
34923 | typedef class_to_loc_map_t::iterator iter_t; |
34924 | for (iter_t it = class2loc.begin (); it != class2loc.end (); ++it) |
34925 | { |
34926 | tree type_decl = (*it).first; |
34927 | class_decl_loc_t &recloc = (*it).second; |
34928 | recloc.diag_mismatched_tags (type_decl); |
34929 | } |
34930 | } |
34931 | |
34932 | class2loc.empty (); |
34933 | } |
34934 | |
34935 | /* Issue an error message if DECL is redeclared with different |
34936 | access than its original declaration [class.access.spec/3]. |
34937 | This applies to nested classes, nested class templates and |
34938 | enumerations [class.mem/1]. */ |
34939 | |
34940 | static void |
34941 | cp_parser_check_access_in_redeclaration (tree decl, location_t location) |
34942 | { |
34943 | if (!decl |
34944 | || (!CLASS_TYPE_P (TREE_TYPE (decl)) |
34945 | && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)) |
34946 | return; |
34947 | |
34948 | if ((TREE_PRIVATE (decl) |
34949 | != (current_access_specifier == access_private_node)) |
34950 | || (TREE_PROTECTED (decl) |
34951 | != (current_access_specifier == access_protected_node))) |
34952 | error_at (location, "%qD redeclared with different access" , decl); |
34953 | } |
34954 | |
34955 | /* Look for the `template' keyword, as a syntactic disambiguator. |
34956 | Return TRUE iff it is present, in which case it will be |
34957 | consumed. */ |
34958 | |
34959 | static bool |
34960 | cp_parser_optional_template_keyword (cp_parser *parser) |
34961 | { |
34962 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TEMPLATE)) |
34963 | { |
34964 | /* In C++98 the `template' keyword can only be used within templates; |
34965 | outside templates the parser can always figure out what is a |
34966 | template and what is not. In C++11, per the resolution of DR 468, |
34967 | `template' is allowed in cases where it is not strictly necessary. */ |
34968 | if (!processing_template_decl |
34969 | && pedantic && cxx_dialect == cxx98) |
34970 | { |
34971 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
34972 | pedwarn (token->location, OPT_Wpedantic, |
34973 | "in C++98 %<template%> (as a disambiguator) is only " |
34974 | "allowed within templates" ); |
34975 | /* If this part of the token stream is rescanned, the same |
34976 | error message would be generated. So, we purge the token |
34977 | from the stream. */ |
34978 | cp_lexer_purge_token (lexer: parser->lexer); |
34979 | return false; |
34980 | } |
34981 | else |
34982 | { |
34983 | /* Consume the `template' keyword. */ |
34984 | cp_lexer_consume_token (lexer: parser->lexer); |
34985 | return true; |
34986 | } |
34987 | } |
34988 | return false; |
34989 | } |
34990 | |
34991 | /* The next token is a CPP_NESTED_NAME_SPECIFIER. Consume the token, |
34992 | set PARSER->SCOPE, and perform other related actions. */ |
34993 | |
34994 | static void |
34995 | cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser) |
34996 | { |
34997 | struct tree_check *check_value; |
34998 | |
34999 | /* Get the stored value. */ |
35000 | check_value = cp_lexer_consume_token (lexer: parser->lexer)->u.tree_check_value; |
35001 | /* Set the scope from the stored value. */ |
35002 | parser->scope = saved_checks_value (check_value); |
35003 | parser->qualifying_scope = check_value->qualifying_scope; |
35004 | parser->object_scope = parser->context->object_type; |
35005 | parser->context->object_type = NULL_TREE; |
35006 | } |
35007 | |
35008 | /* Consume tokens up through a non-nested END token. Returns TRUE if we |
35009 | encounter the end of a block before what we were looking for. */ |
35010 | |
35011 | static bool |
35012 | cp_parser_cache_group (cp_parser *parser, |
35013 | enum cpp_ttype end, |
35014 | unsigned depth) |
35015 | { |
35016 | while (true) |
35017 | { |
35018 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
35019 | |
35020 | /* Abort a parenthesized expression if we encounter a semicolon. */ |
35021 | if ((end == CPP_CLOSE_PAREN || depth == 0) |
35022 | && token->type == CPP_SEMICOLON) |
35023 | return true; |
35024 | /* If we've reached the end of the file, stop. */ |
35025 | if (token->type == CPP_EOF |
35026 | || (end != CPP_PRAGMA_EOL |
35027 | && token->type == CPP_PRAGMA_EOL)) |
35028 | return true; |
35029 | if (token->type == CPP_CLOSE_BRACE && depth == 0) |
35030 | /* We've hit the end of an enclosing block, so there's been some |
35031 | kind of syntax error. */ |
35032 | return true; |
35033 | |
35034 | /* Consume the token. */ |
35035 | cp_lexer_consume_token (lexer: parser->lexer); |
35036 | /* See if it starts a new group. */ |
35037 | if (token->type == CPP_OPEN_BRACE) |
35038 | { |
35039 | cp_parser_cache_group (parser, end: CPP_CLOSE_BRACE, depth: depth + 1); |
35040 | /* In theory this should probably check end == '}', but |
35041 | cp_parser_save_member_function_body needs it to exit |
35042 | after either '}' or ')' when called with ')'. */ |
35043 | if (depth == 0) |
35044 | return false; |
35045 | } |
35046 | else if (token->type == CPP_OPEN_PAREN) |
35047 | { |
35048 | cp_parser_cache_group (parser, end: CPP_CLOSE_PAREN, depth: depth + 1); |
35049 | if (depth == 0 && end == CPP_CLOSE_PAREN) |
35050 | return false; |
35051 | } |
35052 | else if (token->type == CPP_PRAGMA) |
35053 | cp_parser_cache_group (parser, end: CPP_PRAGMA_EOL, depth: depth + 1); |
35054 | else if (token->type == end) |
35055 | return false; |
35056 | } |
35057 | } |
35058 | |
35059 | /* Like above, for caching a default argument or NSDMI. Both of these are |
35060 | terminated by a non-nested comma, but it can be unclear whether or not a |
35061 | comma is nested in a template argument list unless we do more parsing. |
35062 | In order to handle this ambiguity, when we encounter a ',' after a '<' |
35063 | we try to parse what follows as a parameter-declaration-list (in the |
35064 | case of a default argument) or a member-declarator (in the case of an |
35065 | NSDMI). If that succeeds, then we stop caching. */ |
35066 | |
35067 | static tree |
35068 | cp_parser_cache_defarg (cp_parser *parser, bool nsdmi) |
35069 | { |
35070 | unsigned depth = 0; |
35071 | int maybe_template_id = 0; |
35072 | cp_token *first_token; |
35073 | cp_token *token; |
35074 | tree default_argument; |
35075 | |
35076 | /* Add tokens until we have processed the entire default |
35077 | argument. We add the range [first_token, token). */ |
35078 | first_token = cp_lexer_peek_token (lexer: parser->lexer); |
35079 | if (first_token->type == CPP_OPEN_BRACE) |
35080 | { |
35081 | /* For list-initialization, this is straightforward. */ |
35082 | cp_parser_cache_group (parser, end: CPP_CLOSE_BRACE, /*depth=*/0); |
35083 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35084 | } |
35085 | else while (true) |
35086 | { |
35087 | bool done = false; |
35088 | |
35089 | /* Peek at the next token. */ |
35090 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35091 | /* What we do depends on what token we have. */ |
35092 | switch (token->type) |
35093 | { |
35094 | /* In valid code, a default argument must be |
35095 | immediately followed by a `,' `)', or `...'. */ |
35096 | case CPP_COMMA: |
35097 | if (depth == 0 && maybe_template_id) |
35098 | { |
35099 | /* If we've seen a '<', we might be in a |
35100 | template-argument-list. Until Core issue 325 is |
35101 | resolved, we don't know how this situation ought |
35102 | to be handled, so try to DTRT. We check whether |
35103 | what comes after the comma is a valid parameter |
35104 | declaration list. If it is, then the comma ends |
35105 | the default argument; otherwise the default |
35106 | argument continues. */ |
35107 | bool error = false; |
35108 | cp_token *peek; |
35109 | |
35110 | /* Set ITALP so cp_parser_parameter_declaration_list |
35111 | doesn't decide to commit to this parse. */ |
35112 | bool saved_italp = parser->in_template_argument_list_p; |
35113 | parser->in_template_argument_list_p = true; |
35114 | |
35115 | cp_parser_parse_tentatively (parser); |
35116 | |
35117 | if (nsdmi) |
35118 | { |
35119 | /* Parse declarators until we reach a non-comma or |
35120 | somthing that cannot be an initializer. |
35121 | Just checking whether we're looking at a single |
35122 | declarator is insufficient. Consider: |
35123 | int var = tuple<T,U>::x; |
35124 | The template parameter 'U' looks exactly like a |
35125 | declarator. */ |
35126 | do |
35127 | { |
35128 | int ctor_dtor_or_conv_p; |
35129 | cp_lexer_consume_token (lexer: parser->lexer); |
35130 | cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
35131 | flags: CP_PARSER_FLAGS_NONE, |
35132 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
35133 | /*parenthesized_p=*/NULL, |
35134 | /*member_p=*/true, |
35135 | /*friend_p=*/false, |
35136 | /*static_p=*/false); |
35137 | peek = cp_lexer_peek_token (lexer: parser->lexer); |
35138 | if (cp_parser_error_occurred (parser)) |
35139 | break; |
35140 | } |
35141 | while (peek->type == CPP_COMMA); |
35142 | /* If we met an '=' or ';' then the original comma |
35143 | was the end of the NSDMI. Otherwise assume |
35144 | we're still in the NSDMI. */ |
35145 | error = (peek->type != CPP_EQ |
35146 | && peek->type != CPP_SEMICOLON); |
35147 | } |
35148 | else |
35149 | { |
35150 | cp_lexer_consume_token (lexer: parser->lexer); |
35151 | begin_scope (sk_function_parms, NULL_TREE); |
35152 | tree t = cp_parser_parameter_declaration_list |
35153 | (parser, flags: CP_PARSER_FLAGS_NONE, |
35154 | /*pending_decls*/nullptr); |
35155 | if (t == error_mark_node) |
35156 | error = true; |
35157 | pop_bindings_and_leave_scope (); |
35158 | } |
35159 | if (!cp_parser_error_occurred (parser) && !error) |
35160 | done = true; |
35161 | cp_parser_abort_tentative_parse (parser); |
35162 | |
35163 | parser->in_template_argument_list_p = saved_italp; |
35164 | break; |
35165 | } |
35166 | /* FALLTHRU */ |
35167 | case CPP_CLOSE_PAREN: |
35168 | case CPP_ELLIPSIS: |
35169 | /* If we run into a non-nested `;', `}', or `]', |
35170 | then the code is invalid -- but the default |
35171 | argument is certainly over. */ |
35172 | case CPP_SEMICOLON: |
35173 | case CPP_CLOSE_BRACE: |
35174 | case CPP_CLOSE_SQUARE: |
35175 | if (depth == 0 |
35176 | /* Handle correctly int n = sizeof ... ( p ); */ |
35177 | && token->type != CPP_ELLIPSIS) |
35178 | done = true; |
35179 | /* Update DEPTH, if necessary. */ |
35180 | else if (token->type == CPP_CLOSE_PAREN |
35181 | || token->type == CPP_CLOSE_BRACE |
35182 | || token->type == CPP_CLOSE_SQUARE) |
35183 | --depth; |
35184 | break; |
35185 | |
35186 | case CPP_OPEN_PAREN: |
35187 | case CPP_OPEN_SQUARE: |
35188 | case CPP_OPEN_BRACE: |
35189 | ++depth; |
35190 | break; |
35191 | |
35192 | case CPP_LESS: |
35193 | if (depth == 0) |
35194 | /* This might be the comparison operator, or it might |
35195 | start a template argument list. */ |
35196 | ++maybe_template_id; |
35197 | break; |
35198 | |
35199 | case CPP_RSHIFT: |
35200 | if (cxx_dialect == cxx98) |
35201 | break; |
35202 | /* Fall through for C++0x, which treats the `>>' |
35203 | operator like two `>' tokens in certain |
35204 | cases. */ |
35205 | gcc_fallthrough (); |
35206 | |
35207 | case CPP_GREATER: |
35208 | if (depth == 0) |
35209 | { |
35210 | /* This might be an operator, or it might close a |
35211 | template argument list. But if a previous '<' |
35212 | started a template argument list, this will have |
35213 | closed it, so we can't be in one anymore. */ |
35214 | maybe_template_id -= 1 + (token->type == CPP_RSHIFT); |
35215 | if (maybe_template_id < 0) |
35216 | maybe_template_id = 0; |
35217 | } |
35218 | break; |
35219 | |
35220 | /* If we run out of tokens, issue an error message. */ |
35221 | case CPP_EOF: |
35222 | case CPP_PRAGMA_EOL: |
35223 | error_at (token->location, "file ends in default argument" ); |
35224 | return error_mark_node; |
35225 | |
35226 | case CPP_NAME: |
35227 | case CPP_SCOPE: |
35228 | /* In these cases, we should look for template-ids. |
35229 | For example, if the default argument is |
35230 | `X<int, double>()', we need to do name lookup to |
35231 | figure out whether or not `X' is a template; if |
35232 | so, the `,' does not end the default argument. |
35233 | |
35234 | That is not yet done. */ |
35235 | break; |
35236 | |
35237 | default: |
35238 | break; |
35239 | } |
35240 | |
35241 | /* If we've reached the end, stop. */ |
35242 | if (done) |
35243 | break; |
35244 | |
35245 | /* Add the token to the token block. */ |
35246 | token = cp_lexer_consume_token (lexer: parser->lexer); |
35247 | } |
35248 | |
35249 | /* Create a DEFERRED_PARSE to represent the unparsed default |
35250 | argument. */ |
35251 | default_argument = make_node (DEFERRED_PARSE); |
35252 | DEFPARSE_TOKENS (default_argument) |
35253 | = cp_token_cache_new (first: first_token, last: token); |
35254 | DEFPARSE_INSTANTIATIONS (default_argument) = NULL; |
35255 | |
35256 | return default_argument; |
35257 | } |
35258 | |
35259 | /* A location to use for diagnostics about an unparsed DEFERRED_PARSE. */ |
35260 | |
35261 | location_t |
35262 | defparse_location (tree default_argument) |
35263 | { |
35264 | cp_token_cache *tokens = DEFPARSE_TOKENS (default_argument); |
35265 | location_t start = tokens->first->location; |
35266 | location_t end = tokens->last->location; |
35267 | return make_location (caret: start, start, finish: end); |
35268 | } |
35269 | |
35270 | /* Begin parsing tentatively. We always save tokens while parsing |
35271 | tentatively so that if the tentative parsing fails we can restore the |
35272 | tokens. */ |
35273 | |
35274 | static void |
35275 | cp_parser_parse_tentatively (cp_parser* parser) |
35276 | { |
35277 | /* Enter a new parsing context. */ |
35278 | parser->context = cp_parser_context_new (next: parser->context); |
35279 | /* Begin saving tokens. */ |
35280 | cp_lexer_save_tokens (lexer: parser->lexer); |
35281 | /* In order to avoid repetitive access control error messages, |
35282 | access checks are queued up until we are no longer parsing |
35283 | tentatively. */ |
35284 | push_deferring_access_checks (dk_deferred); |
35285 | } |
35286 | |
35287 | /* Commit to the currently active tentative parse. */ |
35288 | |
35289 | static void |
35290 | cp_parser_commit_to_tentative_parse (cp_parser* parser) |
35291 | { |
35292 | cp_parser_context *context; |
35293 | cp_lexer *lexer; |
35294 | |
35295 | /* Mark all of the levels as committed. */ |
35296 | lexer = parser->lexer; |
35297 | for (context = parser->context; context->next; context = context->next) |
35298 | { |
35299 | if (context->status == CP_PARSER_STATUS_KIND_COMMITTED) |
35300 | break; |
35301 | context->status = CP_PARSER_STATUS_KIND_COMMITTED; |
35302 | while (!cp_lexer_saving_tokens (lexer)) |
35303 | lexer = lexer->next; |
35304 | cp_lexer_commit_tokens (lexer); |
35305 | } |
35306 | } |
35307 | |
35308 | /* Commit to the topmost currently active tentative parse. |
35309 | |
35310 | Note that this function shouldn't be called when there are |
35311 | irreversible side-effects while in a tentative state. For |
35312 | example, we shouldn't create a permanent entry in the symbol |
35313 | table, or issue an error message that might not apply if the |
35314 | tentative parse is aborted. */ |
35315 | |
35316 | static void |
35317 | cp_parser_commit_to_topmost_tentative_parse (cp_parser* parser) |
35318 | { |
35319 | cp_parser_context *context = parser->context; |
35320 | cp_lexer *lexer = parser->lexer; |
35321 | |
35322 | if (context) |
35323 | { |
35324 | if (context->status == CP_PARSER_STATUS_KIND_COMMITTED) |
35325 | return; |
35326 | context->status = CP_PARSER_STATUS_KIND_COMMITTED; |
35327 | |
35328 | while (!cp_lexer_saving_tokens (lexer)) |
35329 | lexer = lexer->next; |
35330 | cp_lexer_commit_tokens (lexer); |
35331 | } |
35332 | } |
35333 | |
35334 | /* Abort the currently active tentative parse. All consumed tokens |
35335 | will be rolled back, and no diagnostics will be issued. */ |
35336 | |
35337 | static void |
35338 | cp_parser_abort_tentative_parse (cp_parser* parser) |
35339 | { |
35340 | gcc_assert (parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED |
35341 | || errorcount > 0); |
35342 | cp_parser_simulate_error (parser); |
35343 | /* Now, pretend that we want to see if the construct was |
35344 | successfully parsed. */ |
35345 | cp_parser_parse_definitely (parser); |
35346 | } |
35347 | |
35348 | /* Stop parsing tentatively. If a parse error has occurred, restore the |
35349 | token stream. Otherwise, commit to the tokens we have consumed. |
35350 | Returns true if no error occurred; false otherwise. */ |
35351 | |
35352 | static bool |
35353 | cp_parser_parse_definitely (cp_parser* parser) |
35354 | { |
35355 | bool error_occurred; |
35356 | cp_parser_context *context; |
35357 | |
35358 | /* Remember whether or not an error occurred, since we are about to |
35359 | destroy that information. */ |
35360 | error_occurred = cp_parser_error_occurred (parser); |
35361 | /* Remove the topmost context from the stack. */ |
35362 | context = parser->context; |
35363 | parser->context = context->next; |
35364 | /* If no parse errors occurred, commit to the tentative parse. */ |
35365 | if (!error_occurred) |
35366 | { |
35367 | /* Commit to the tokens read tentatively, unless that was |
35368 | already done. */ |
35369 | if (context->status != CP_PARSER_STATUS_KIND_COMMITTED) |
35370 | cp_lexer_commit_tokens (lexer: parser->lexer); |
35371 | |
35372 | pop_to_parent_deferring_access_checks (); |
35373 | } |
35374 | /* Otherwise, if errors occurred, roll back our state so that things |
35375 | are just as they were before we began the tentative parse. */ |
35376 | else |
35377 | { |
35378 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
35379 | pop_deferring_access_checks (); |
35380 | } |
35381 | /* Add the context to the front of the free list. */ |
35382 | context->next = cp_parser_context_free_list; |
35383 | cp_parser_context_free_list = context; |
35384 | |
35385 | return !error_occurred; |
35386 | } |
35387 | |
35388 | /* Returns true if we are parsing tentatively and are not committed to |
35389 | this tentative parse. */ |
35390 | |
35391 | static bool |
35392 | cp_parser_uncommitted_to_tentative_parse_p (cp_parser* parser) |
35393 | { |
35394 | return (cp_parser_parsing_tentatively (parser) |
35395 | && parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED); |
35396 | } |
35397 | |
35398 | /* Returns nonzero iff an error has occurred during the most recent |
35399 | tentative parse. */ |
35400 | |
35401 | static bool |
35402 | cp_parser_error_occurred (cp_parser* parser) |
35403 | { |
35404 | return (cp_parser_parsing_tentatively (parser) |
35405 | && parser->context->status == CP_PARSER_STATUS_KIND_ERROR); |
35406 | } |
35407 | |
35408 | /* Returns nonzero if GNU extensions are allowed. */ |
35409 | |
35410 | static bool |
35411 | cp_parser_allow_gnu_extensions_p (cp_parser* parser) |
35412 | { |
35413 | return parser->allow_gnu_extensions_p; |
35414 | } |
35415 | |
35416 | /* Objective-C++ Productions */ |
35417 | |
35418 | |
35419 | /* Parse an Objective-C expression, which feeds into a primary-expression |
35420 | above. |
35421 | |
35422 | objc-expression: |
35423 | objc-message-expression |
35424 | objc-string-literal |
35425 | objc-encode-expression |
35426 | objc-protocol-expression |
35427 | objc-selector-expression |
35428 | |
35429 | Returns a tree representation of the expression. */ |
35430 | |
35431 | static cp_expr |
35432 | cp_parser_objc_expression (cp_parser* parser) |
35433 | { |
35434 | /* Try to figure out what kind of declaration is present. */ |
35435 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
35436 | |
35437 | switch (kwd->type) |
35438 | { |
35439 | case CPP_OPEN_SQUARE: |
35440 | return cp_parser_objc_message_expression (parser); |
35441 | |
35442 | case CPP_OBJC_STRING: |
35443 | kwd = cp_lexer_consume_token (lexer: parser->lexer); |
35444 | return objc_build_string_object (kwd->u.value); |
35445 | |
35446 | case CPP_KEYWORD: |
35447 | switch (kwd->keyword) |
35448 | { |
35449 | case RID_AT_ENCODE: |
35450 | return cp_parser_objc_encode_expression (parser); |
35451 | |
35452 | case RID_AT_PROTOCOL: |
35453 | return cp_parser_objc_protocol_expression (parser); |
35454 | |
35455 | case RID_AT_SELECTOR: |
35456 | return cp_parser_objc_selector_expression (parser); |
35457 | |
35458 | default: |
35459 | break; |
35460 | } |
35461 | /* FALLTHRU */ |
35462 | default: |
35463 | error_at (kwd->location, |
35464 | "misplaced %<@%D%> Objective-C++ construct" , |
35465 | kwd->u.value); |
35466 | cp_parser_skip_to_end_of_block_or_statement (parser); |
35467 | } |
35468 | |
35469 | return error_mark_node; |
35470 | } |
35471 | |
35472 | /* Parse an Objective-C message expression. |
35473 | |
35474 | objc-message-expression: |
35475 | [ objc-message-receiver objc-message-args ] |
35476 | |
35477 | Returns a representation of an Objective-C message. */ |
35478 | |
35479 | static tree |
35480 | cp_parser_objc_message_expression (cp_parser* parser) |
35481 | { |
35482 | tree receiver, messageargs; |
35483 | |
35484 | parser->objective_c_message_context_p = true; |
35485 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35486 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '['. */ |
35487 | receiver = cp_parser_objc_message_receiver (parser); |
35488 | messageargs = cp_parser_objc_message_args (parser); |
35489 | location_t end_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35490 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
35491 | |
35492 | tree result = objc_build_message_expr (receiver, messageargs); |
35493 | |
35494 | /* Construct a location e.g. |
35495 | [self func1:5] |
35496 | ^~~~~~~~~~~~~~ |
35497 | ranging from the '[' to the ']', with the caret at the start. */ |
35498 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, finish: end_loc); |
35499 | protected_set_expr_location (result, combined_loc); |
35500 | |
35501 | parser->objective_c_message_context_p = false; |
35502 | return result; |
35503 | } |
35504 | |
35505 | /* Parse an objc-message-receiver. |
35506 | |
35507 | objc-message-receiver: |
35508 | expression |
35509 | simple-type-specifier |
35510 | |
35511 | Returns a representation of the type or expression. */ |
35512 | |
35513 | static tree |
35514 | cp_parser_objc_message_receiver (cp_parser* parser) |
35515 | { |
35516 | tree rcv; |
35517 | |
35518 | /* An Objective-C message receiver may be either (1) a type |
35519 | or (2) an expression. */ |
35520 | cp_parser_parse_tentatively (parser); |
35521 | rcv = cp_parser_expression (parser); |
35522 | |
35523 | /* If that worked out, fine. */ |
35524 | if (cp_parser_parse_definitely (parser)) |
35525 | return rcv; |
35526 | |
35527 | cp_parser_parse_tentatively (parser); |
35528 | rcv = cp_parser_simple_type_specifier (parser, |
35529 | /*decl_specs=*/NULL, |
35530 | flags: CP_PARSER_FLAGS_NONE); |
35531 | |
35532 | if (cp_parser_parse_definitely (parser)) |
35533 | return objc_get_class_reference (rcv); |
35534 | |
35535 | cp_parser_error (parser, gmsgid: "objective-c++ message receiver expected" ); |
35536 | return error_mark_node; |
35537 | } |
35538 | |
35539 | /* Parse the arguments and selectors comprising an Objective-C message. |
35540 | |
35541 | objc-message-args: |
35542 | objc-selector |
35543 | objc-selector-args |
35544 | objc-selector-args , objc-comma-args |
35545 | |
35546 | objc-selector-args: |
35547 | objc-selector [opt] : assignment-expression |
35548 | objc-selector-args objc-selector [opt] : assignment-expression |
35549 | |
35550 | objc-comma-args: |
35551 | assignment-expression |
35552 | objc-comma-args , assignment-expression |
35553 | |
35554 | Returns a TREE_LIST, with TREE_PURPOSE containing a list of |
35555 | selector arguments and TREE_VALUE containing a list of comma |
35556 | arguments. */ |
35557 | |
35558 | static tree |
35559 | cp_parser_objc_message_args (cp_parser* parser) |
35560 | { |
35561 | tree sel_args = NULL_TREE, addl_args = NULL_TREE; |
35562 | bool maybe_unary_selector_p = true; |
35563 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
35564 | |
35565 | while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) |
35566 | { |
35567 | tree selector = NULL_TREE, arg; |
35568 | |
35569 | if (token->type != CPP_COLON) |
35570 | selector = cp_parser_objc_selector (parser); |
35571 | |
35572 | /* Detect if we have a unary selector. */ |
35573 | if (maybe_unary_selector_p |
35574 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
35575 | return build_tree_list (selector, NULL_TREE); |
35576 | |
35577 | maybe_unary_selector_p = false; |
35578 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
35579 | arg = cp_parser_assignment_expression (parser); |
35580 | |
35581 | sel_args |
35582 | = chainon (sel_args, |
35583 | build_tree_list (selector, arg)); |
35584 | |
35585 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35586 | } |
35587 | |
35588 | /* Handle non-selector arguments, if any. */ |
35589 | while (token->type == CPP_COMMA) |
35590 | { |
35591 | tree arg; |
35592 | |
35593 | cp_lexer_consume_token (lexer: parser->lexer); |
35594 | arg = cp_parser_assignment_expression (parser); |
35595 | |
35596 | addl_args |
35597 | = chainon (addl_args, |
35598 | build_tree_list (NULL_TREE, arg)); |
35599 | |
35600 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35601 | } |
35602 | |
35603 | if (sel_args == NULL_TREE && addl_args == NULL_TREE) |
35604 | { |
35605 | cp_parser_error (parser, gmsgid: "objective-c++ message argument(s) are expected" ); |
35606 | return build_tree_list (error_mark_node, error_mark_node); |
35607 | } |
35608 | |
35609 | return build_tree_list (sel_args, addl_args); |
35610 | } |
35611 | |
35612 | /* Parse an Objective-C encode expression. |
35613 | |
35614 | objc-encode-expression: |
35615 | @encode objc-typename |
35616 | |
35617 | Returns an encoded representation of the type argument. */ |
35618 | |
35619 | static cp_expr |
35620 | cp_parser_objc_encode_expression (cp_parser* parser) |
35621 | { |
35622 | tree type; |
35623 | cp_token *token; |
35624 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35625 | |
35626 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@encode'. */ |
35627 | matching_parens parens; |
35628 | parens.require_open (parser); |
35629 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35630 | type = complete_type (cp_parser_type_id (parser)); |
35631 | parens.require_close (parser); |
35632 | |
35633 | if (!type) |
35634 | { |
35635 | error_at (token->location, |
35636 | "%<@encode%> must specify a type as an argument" ); |
35637 | return error_mark_node; |
35638 | } |
35639 | |
35640 | /* This happens if we find @encode(T) (where T is a template |
35641 | typename or something dependent on a template typename) when |
35642 | parsing a template. In that case, we can't compile it |
35643 | immediately, but we rather create an AT_ENCODE_EXPR which will |
35644 | need to be instantiated when the template is used. |
35645 | */ |
35646 | if (dependent_type_p (type)) |
35647 | { |
35648 | tree value = build_min (AT_ENCODE_EXPR, size_type_node, type); |
35649 | TREE_READONLY (value) = 1; |
35650 | return value; |
35651 | } |
35652 | |
35653 | |
35654 | /* Build a location of the form: |
35655 | @encode(int) |
35656 | ^~~~~~~~~~~~ |
35657 | with caret==start at the @ token, finishing at the close paren. */ |
35658 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
35659 | |
35660 | return cp_expr (objc_build_encode_expr (type), combined_loc); |
35661 | } |
35662 | |
35663 | /* Parse an Objective-C @defs expression. */ |
35664 | |
35665 | static tree |
35666 | cp_parser_objc_defs_expression (cp_parser *parser) |
35667 | { |
35668 | tree name; |
35669 | |
35670 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@defs'. */ |
35671 | matching_parens parens; |
35672 | parens.require_open (parser); |
35673 | name = cp_parser_identifier (parser); |
35674 | parens.require_close (parser); |
35675 | |
35676 | return objc_get_class_ivars (name); |
35677 | } |
35678 | |
35679 | /* Parse an Objective-C protocol expression. |
35680 | |
35681 | objc-protocol-expression: |
35682 | @protocol ( identifier ) |
35683 | |
35684 | Returns a representation of the protocol expression. */ |
35685 | |
35686 | static tree |
35687 | cp_parser_objc_protocol_expression (cp_parser* parser) |
35688 | { |
35689 | tree proto; |
35690 | location_t start_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35691 | |
35692 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@protocol'. */ |
35693 | matching_parens parens; |
35694 | parens.require_open (parser); |
35695 | proto = cp_parser_identifier (parser); |
35696 | parens.require_close (parser); |
35697 | |
35698 | /* Build a location of the form: |
35699 | @protocol(prot) |
35700 | ^~~~~~~~~~~~~~~ |
35701 | with caret==start at the @ token, finishing at the close paren. */ |
35702 | location_t combined_loc = make_location (caret: start_loc, start: start_loc, lexer: parser->lexer); |
35703 | tree result = objc_build_protocol_expr (proto); |
35704 | protected_set_expr_location (result, combined_loc); |
35705 | return result; |
35706 | } |
35707 | |
35708 | /* Parse an Objective-C selector expression. |
35709 | |
35710 | objc-selector-expression: |
35711 | @selector ( objc-method-signature ) |
35712 | |
35713 | objc-method-signature: |
35714 | objc-selector |
35715 | objc-selector-seq |
35716 | |
35717 | objc-selector-seq: |
35718 | objc-selector : |
35719 | objc-selector-seq objc-selector : |
35720 | |
35721 | Returns a representation of the method selector. */ |
35722 | |
35723 | static tree |
35724 | cp_parser_objc_selector_expression (cp_parser* parser) |
35725 | { |
35726 | tree sel_seq = NULL_TREE; |
35727 | bool maybe_unary_selector_p = true; |
35728 | cp_token *token; |
35729 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
35730 | |
35731 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@selector'. */ |
35732 | matching_parens parens; |
35733 | parens.require_open (parser); |
35734 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35735 | |
35736 | while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON |
35737 | || token->type == CPP_SCOPE) |
35738 | { |
35739 | tree selector = NULL_TREE; |
35740 | |
35741 | if (token->type != CPP_COLON |
35742 | || token->type == CPP_SCOPE) |
35743 | selector = cp_parser_objc_selector (parser); |
35744 | |
35745 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON) |
35746 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SCOPE)) |
35747 | { |
35748 | /* Detect if we have a unary selector. */ |
35749 | if (maybe_unary_selector_p) |
35750 | { |
35751 | sel_seq = selector; |
35752 | goto finish_selector; |
35753 | } |
35754 | else |
35755 | { |
35756 | cp_parser_error (parser, gmsgid: "expected %<:%>" ); |
35757 | } |
35758 | } |
35759 | maybe_unary_selector_p = false; |
35760 | token = cp_lexer_consume_token (lexer: parser->lexer); |
35761 | |
35762 | if (token->type == CPP_SCOPE) |
35763 | { |
35764 | sel_seq |
35765 | = chainon (sel_seq, |
35766 | build_tree_list (selector, NULL_TREE)); |
35767 | sel_seq |
35768 | = chainon (sel_seq, |
35769 | build_tree_list (NULL_TREE, NULL_TREE)); |
35770 | } |
35771 | else |
35772 | sel_seq |
35773 | = chainon (sel_seq, |
35774 | build_tree_list (selector, NULL_TREE)); |
35775 | |
35776 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35777 | } |
35778 | |
35779 | finish_selector: |
35780 | parens.require_close (parser); |
35781 | |
35782 | |
35783 | /* Build a location of the form: |
35784 | @selector(func) |
35785 | ^~~~~~~~~~~~~~~ |
35786 | with caret==start at the @ token, finishing at the close paren. */ |
35787 | location_t combined_loc = make_location (caret: loc, start: loc, lexer: parser->lexer); |
35788 | tree result = objc_build_selector_expr (combined_loc, sel_seq); |
35789 | /* TODO: objc_build_selector_expr doesn't always honor the location. */ |
35790 | protected_set_expr_location (result, combined_loc); |
35791 | return result; |
35792 | } |
35793 | |
35794 | /* Parse a list of identifiers. |
35795 | |
35796 | objc-identifier-list: |
35797 | identifier |
35798 | objc-identifier-list , identifier |
35799 | |
35800 | Returns a TREE_LIST of identifier nodes. */ |
35801 | |
35802 | static tree |
35803 | cp_parser_objc_identifier_list (cp_parser* parser) |
35804 | { |
35805 | tree identifier; |
35806 | tree list; |
35807 | cp_token *sep; |
35808 | |
35809 | identifier = cp_parser_identifier (parser); |
35810 | if (identifier == error_mark_node) |
35811 | return error_mark_node; |
35812 | |
35813 | list = build_tree_list (NULL_TREE, identifier); |
35814 | sep = cp_lexer_peek_token (lexer: parser->lexer); |
35815 | |
35816 | while (sep->type == CPP_COMMA) |
35817 | { |
35818 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
35819 | identifier = cp_parser_identifier (parser); |
35820 | if (identifier == error_mark_node) |
35821 | return list; |
35822 | |
35823 | list = chainon (list, build_tree_list (NULL_TREE, |
35824 | identifier)); |
35825 | sep = cp_lexer_peek_token (lexer: parser->lexer); |
35826 | } |
35827 | |
35828 | return list; |
35829 | } |
35830 | |
35831 | /* Parse an Objective-C alias declaration. |
35832 | |
35833 | objc-alias-declaration: |
35834 | @compatibility_alias identifier identifier ; |
35835 | |
35836 | This function registers the alias mapping with the Objective-C front end. |
35837 | It returns nothing. */ |
35838 | |
35839 | static void |
35840 | cp_parser_objc_alias_declaration (cp_parser* parser) |
35841 | { |
35842 | tree alias, orig; |
35843 | |
35844 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@compatibility_alias'. */ |
35845 | alias = cp_parser_identifier (parser); |
35846 | orig = cp_parser_identifier (parser); |
35847 | objc_declare_alias (alias, orig); |
35848 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
35849 | } |
35850 | |
35851 | /* Parse an Objective-C class forward-declaration. |
35852 | |
35853 | objc-class-declaration: |
35854 | @class objc-identifier-list ; |
35855 | |
35856 | The function registers the forward declarations with the Objective-C |
35857 | front end. It returns nothing. */ |
35858 | |
35859 | static void |
35860 | cp_parser_objc_class_declaration (cp_parser* parser) |
35861 | { |
35862 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@class'. */ |
35863 | while (true) |
35864 | { |
35865 | tree id; |
35866 | |
35867 | id = cp_parser_identifier (parser); |
35868 | if (id == error_mark_node) |
35869 | break; |
35870 | |
35871 | objc_declare_class (id); |
35872 | |
35873 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
35874 | cp_lexer_consume_token (lexer: parser->lexer); |
35875 | else |
35876 | break; |
35877 | } |
35878 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
35879 | } |
35880 | |
35881 | /* Parse a list of Objective-C protocol references. |
35882 | |
35883 | objc-protocol-refs-opt: |
35884 | objc-protocol-refs [opt] |
35885 | |
35886 | objc-protocol-refs: |
35887 | < objc-identifier-list > |
35888 | |
35889 | Returns a TREE_LIST of identifiers, if any. */ |
35890 | |
35891 | static tree |
35892 | cp_parser_objc_protocol_refs_opt (cp_parser* parser) |
35893 | { |
35894 | tree protorefs = NULL_TREE; |
35895 | |
35896 | if(cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_LESS)) |
35897 | { |
35898 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '<'. */ |
35899 | protorefs = cp_parser_objc_identifier_list (parser); |
35900 | cp_parser_require (parser, type: CPP_GREATER, token_desc: RT_GREATER); |
35901 | } |
35902 | |
35903 | return protorefs; |
35904 | } |
35905 | |
35906 | /* Parse a Objective-C visibility specification. */ |
35907 | |
35908 | static void |
35909 | cp_parser_objc_visibility_spec (cp_parser* parser) |
35910 | { |
35911 | cp_token *vis = cp_lexer_peek_token (lexer: parser->lexer); |
35912 | |
35913 | switch (vis->keyword) |
35914 | { |
35915 | case RID_AT_PRIVATE: |
35916 | objc_set_visibility (OBJC_IVAR_VIS_PRIVATE); |
35917 | break; |
35918 | case RID_AT_PROTECTED: |
35919 | objc_set_visibility (OBJC_IVAR_VIS_PROTECTED); |
35920 | break; |
35921 | case RID_AT_PUBLIC: |
35922 | objc_set_visibility (OBJC_IVAR_VIS_PUBLIC); |
35923 | break; |
35924 | case RID_AT_PACKAGE: |
35925 | objc_set_visibility (OBJC_IVAR_VIS_PACKAGE); |
35926 | break; |
35927 | default: |
35928 | return; |
35929 | } |
35930 | |
35931 | /* Eat '@private'/'@protected'/'@public'. */ |
35932 | cp_lexer_consume_token (lexer: parser->lexer); |
35933 | } |
35934 | |
35935 | /* Parse an Objective-C method type. Return 'true' if it is a class |
35936 | (+) method, and 'false' if it is an instance (-) method. */ |
35937 | |
35938 | static inline bool |
35939 | cp_parser_objc_method_type (cp_parser* parser) |
35940 | { |
35941 | if (cp_lexer_consume_token (lexer: parser->lexer)->type == CPP_PLUS) |
35942 | return true; |
35943 | else |
35944 | return false; |
35945 | } |
35946 | |
35947 | /* Parse an Objective-C protocol qualifier. */ |
35948 | |
35949 | static tree |
35950 | cp_parser_objc_protocol_qualifiers (cp_parser* parser) |
35951 | { |
35952 | tree quals = NULL_TREE, node; |
35953 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
35954 | |
35955 | node = token->u.value; |
35956 | |
35957 | while (node && identifier_p (t: node) |
35958 | && (node == ridpointers [(int) RID_IN] |
35959 | || node == ridpointers [(int) RID_OUT] |
35960 | || node == ridpointers [(int) RID_INOUT] |
35961 | || node == ridpointers [(int) RID_BYCOPY] |
35962 | || node == ridpointers [(int) RID_BYREF] |
35963 | || node == ridpointers [(int) RID_ONEWAY])) |
35964 | { |
35965 | quals = tree_cons (NULL_TREE, node, quals); |
35966 | cp_lexer_consume_token (lexer: parser->lexer); |
35967 | token = cp_lexer_peek_token (lexer: parser->lexer); |
35968 | node = token->u.value; |
35969 | } |
35970 | |
35971 | return quals; |
35972 | } |
35973 | |
35974 | /* Parse an Objective-C typename. */ |
35975 | |
35976 | static tree |
35977 | cp_parser_objc_typename (cp_parser* parser) |
35978 | { |
35979 | tree type_name = NULL_TREE; |
35980 | |
35981 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
35982 | { |
35983 | tree proto_quals, cp_type = NULL_TREE; |
35984 | |
35985 | matching_parens parens; |
35986 | parens.consume_open (parser); /* Eat '('. */ |
35987 | proto_quals = cp_parser_objc_protocol_qualifiers (parser); |
35988 | |
35989 | /* An ObjC type name may consist of just protocol qualifiers, in which |
35990 | case the type shall default to 'id'. */ |
35991 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
35992 | { |
35993 | cp_type = cp_parser_type_id (parser); |
35994 | |
35995 | /* If the type could not be parsed, an error has already |
35996 | been produced. For error recovery, behave as if it had |
35997 | not been specified, which will use the default type |
35998 | 'id'. */ |
35999 | if (cp_type == error_mark_node) |
36000 | { |
36001 | cp_type = NULL_TREE; |
36002 | /* We need to skip to the closing parenthesis as |
36003 | cp_parser_type_id() does not seem to do it for |
36004 | us. */ |
36005 | cp_parser_skip_to_closing_parenthesis (parser, |
36006 | /*recovering=*/true, |
36007 | /*or_comma=*/false, |
36008 | /*consume_paren=*/false); |
36009 | } |
36010 | } |
36011 | |
36012 | parens.require_close (parser); |
36013 | type_name = build_tree_list (proto_quals, cp_type); |
36014 | } |
36015 | |
36016 | return type_name; |
36017 | } |
36018 | |
36019 | /* Check to see if TYPE refers to an Objective-C selector name. */ |
36020 | |
36021 | static bool |
36022 | cp_parser_objc_selector_p (enum cpp_ttype type) |
36023 | { |
36024 | return (type == CPP_NAME || type == CPP_KEYWORD |
36025 | || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND |
36026 | || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT |
36027 | || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ |
36028 | || type == CPP_XOR || type == CPP_XOR_EQ); |
36029 | } |
36030 | |
36031 | /* Parse an Objective-C selector. */ |
36032 | |
36033 | static tree |
36034 | cp_parser_objc_selector (cp_parser* parser) |
36035 | { |
36036 | cp_token *token = cp_lexer_consume_token (lexer: parser->lexer); |
36037 | |
36038 | if (!cp_parser_objc_selector_p (type: token->type)) |
36039 | { |
36040 | error_at (token->location, "invalid Objective-C++ selector name" ); |
36041 | return error_mark_node; |
36042 | } |
36043 | |
36044 | /* C++ operator names are allowed to appear in ObjC selectors. */ |
36045 | switch (token->type) |
36046 | { |
36047 | case CPP_AND_AND: return get_identifier ("and" ); |
36048 | case CPP_AND_EQ: return get_identifier ("and_eq" ); |
36049 | case CPP_AND: return get_identifier ("bitand" ); |
36050 | case CPP_OR: return get_identifier ("bitor" ); |
36051 | case CPP_COMPL: return get_identifier ("compl" ); |
36052 | case CPP_NOT: return get_identifier ("not" ); |
36053 | case CPP_NOT_EQ: return get_identifier ("not_eq" ); |
36054 | case CPP_OR_OR: return get_identifier ("or" ); |
36055 | case CPP_OR_EQ: return get_identifier ("or_eq" ); |
36056 | case CPP_XOR: return get_identifier ("xor" ); |
36057 | case CPP_XOR_EQ: return get_identifier ("xor_eq" ); |
36058 | default: return token->u.value; |
36059 | } |
36060 | } |
36061 | |
36062 | /* Parse an Objective-C params list. */ |
36063 | |
36064 | static tree |
36065 | cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes) |
36066 | { |
36067 | tree params = NULL_TREE; |
36068 | bool maybe_unary_selector_p = true; |
36069 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36070 | |
36071 | while (cp_parser_objc_selector_p (type: token->type) || token->type == CPP_COLON) |
36072 | { |
36073 | tree selector = NULL_TREE, type_name, identifier; |
36074 | tree parm_attr = NULL_TREE; |
36075 | |
36076 | if (token->keyword == RID_ATTRIBUTE) |
36077 | break; |
36078 | |
36079 | if (token->type != CPP_COLON) |
36080 | selector = cp_parser_objc_selector (parser); |
36081 | |
36082 | /* Detect if we have a unary selector. */ |
36083 | if (maybe_unary_selector_p |
36084 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
36085 | { |
36086 | params = selector; /* Might be followed by attributes. */ |
36087 | break; |
36088 | } |
36089 | |
36090 | maybe_unary_selector_p = false; |
36091 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
36092 | { |
36093 | /* Something went quite wrong. There should be a colon |
36094 | here, but there is not. Stop parsing parameters. */ |
36095 | break; |
36096 | } |
36097 | type_name = cp_parser_objc_typename (parser); |
36098 | /* New ObjC allows attributes on parameters too. */ |
36099 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ATTRIBUTE)) |
36100 | parm_attr = cp_parser_attributes_opt (parser); |
36101 | identifier = cp_parser_identifier (parser); |
36102 | |
36103 | params |
36104 | = chainon (params, |
36105 | objc_build_keyword_decl (selector, |
36106 | type_name, |
36107 | identifier, |
36108 | parm_attr)); |
36109 | |
36110 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36111 | } |
36112 | |
36113 | if (params == NULL_TREE) |
36114 | { |
36115 | cp_parser_error (parser, gmsgid: "objective-c++ method declaration is expected" ); |
36116 | return error_mark_node; |
36117 | } |
36118 | |
36119 | /* We allow tail attributes for the method. */ |
36120 | if (token->keyword == RID_ATTRIBUTE) |
36121 | { |
36122 | *attributes = cp_parser_attributes_opt (parser); |
36123 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
36124 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
36125 | return params; |
36126 | cp_parser_error (parser, |
36127 | gmsgid: "method attributes must be specified at the end" ); |
36128 | return error_mark_node; |
36129 | } |
36130 | |
36131 | if (params == NULL_TREE) |
36132 | { |
36133 | cp_parser_error (parser, gmsgid: "objective-c++ method declaration is expected" ); |
36134 | return error_mark_node; |
36135 | } |
36136 | return params; |
36137 | } |
36138 | |
36139 | /* Parse the non-keyword Objective-C params. */ |
36140 | |
36141 | static tree |
36142 | cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, |
36143 | tree* attributes) |
36144 | { |
36145 | tree params = make_node (TREE_LIST); |
36146 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36147 | *ellipsisp = false; /* Initially, assume no ellipsis. */ |
36148 | |
36149 | while (token->type == CPP_COMMA) |
36150 | { |
36151 | cp_parameter_declarator *parmdecl; |
36152 | tree parm; |
36153 | |
36154 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
36155 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36156 | |
36157 | if (token->type == CPP_ELLIPSIS) |
36158 | { |
36159 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '...'. */ |
36160 | *ellipsisp = true; |
36161 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36162 | break; |
36163 | } |
36164 | |
36165 | /* TODO: parse attributes for tail parameters. */ |
36166 | parmdecl = cp_parser_parameter_declaration (parser, flags: CP_PARSER_FLAGS_NONE, |
36167 | template_parm_p: false, NULL); |
36168 | parm = grokdeclarator (parmdecl->declarator, |
36169 | &parmdecl->decl_specifiers, |
36170 | PARM, /*initialized=*/0, |
36171 | /*attrlist=*/NULL); |
36172 | |
36173 | chainon (params, build_tree_list (NULL_TREE, parm)); |
36174 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36175 | } |
36176 | |
36177 | /* We allow tail attributes for the method. */ |
36178 | if (token->keyword == RID_ATTRIBUTE) |
36179 | { |
36180 | if (*attributes == NULL_TREE) |
36181 | { |
36182 | *attributes = cp_parser_attributes_opt (parser); |
36183 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
36184 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
36185 | return params; |
36186 | } |
36187 | else |
36188 | /* We have an error, but parse the attributes, so that we can |
36189 | carry on. */ |
36190 | *attributes = cp_parser_attributes_opt (parser); |
36191 | |
36192 | cp_parser_error (parser, |
36193 | gmsgid: "method attributes must be specified at the end" ); |
36194 | return error_mark_node; |
36195 | } |
36196 | |
36197 | return params; |
36198 | } |
36199 | |
36200 | /* Parse a linkage specification, a pragma, an extra semicolon or a block. */ |
36201 | |
36202 | static void |
36203 | cp_parser_objc_interstitial_code (cp_parser* parser) |
36204 | { |
36205 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36206 | |
36207 | /* If the next token is `extern' and the following token is a string |
36208 | literal, then we have a linkage specification. */ |
36209 | if (token->keyword == RID_EXTERN |
36210 | && cp_parser_is_pure_string_literal |
36211 | (token: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2))) |
36212 | cp_parser_linkage_specification (parser, NULL_TREE); |
36213 | /* Handle #pragma, if any. */ |
36214 | else if (token->type == CPP_PRAGMA) |
36215 | cp_parser_pragma (parser, pragma_objc_icode, NULL); |
36216 | /* Allow stray semicolons. */ |
36217 | else if (token->type == CPP_SEMICOLON) |
36218 | cp_lexer_consume_token (lexer: parser->lexer); |
36219 | /* Mark methods as optional or required, when building protocols. */ |
36220 | else if (token->keyword == RID_AT_OPTIONAL) |
36221 | { |
36222 | cp_lexer_consume_token (lexer: parser->lexer); |
36223 | objc_set_method_opt (true); |
36224 | } |
36225 | else if (token->keyword == RID_AT_REQUIRED) |
36226 | { |
36227 | cp_lexer_consume_token (lexer: parser->lexer); |
36228 | objc_set_method_opt (false); |
36229 | } |
36230 | else if (token->keyword == RID_NAMESPACE) |
36231 | cp_parser_namespace_definition (parser); |
36232 | /* Other stray characters must generate errors. */ |
36233 | else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE) |
36234 | { |
36235 | cp_lexer_consume_token (lexer: parser->lexer); |
36236 | error ("stray %qs between Objective-C++ methods" , |
36237 | token->type == CPP_OPEN_BRACE ? "{" : "}" ); |
36238 | } |
36239 | /* Finally, try to parse a block-declaration, or a function-definition. */ |
36240 | else |
36241 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
36242 | } |
36243 | |
36244 | /* Parse a method signature. */ |
36245 | |
36246 | static tree |
36247 | cp_parser_objc_method_signature (cp_parser* parser, tree* attributes) |
36248 | { |
36249 | tree rettype, kwdparms, optparms; |
36250 | bool ellipsis = false; |
36251 | bool is_class_method; |
36252 | |
36253 | is_class_method = cp_parser_objc_method_type (parser); |
36254 | rettype = cp_parser_objc_typename (parser); |
36255 | *attributes = NULL_TREE; |
36256 | kwdparms = cp_parser_objc_method_keyword_params (parser, attributes); |
36257 | if (kwdparms == error_mark_node) |
36258 | return error_mark_node; |
36259 | optparms = cp_parser_objc_method_tail_params_opt (parser, ellipsisp: &ellipsis, attributes); |
36260 | if (optparms == error_mark_node) |
36261 | return error_mark_node; |
36262 | |
36263 | return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis); |
36264 | } |
36265 | |
36266 | static bool |
36267 | cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser) |
36268 | { |
36269 | tree tattr; |
36270 | cp_lexer_save_tokens (lexer: parser->lexer); |
36271 | tattr = cp_parser_attributes_opt (parser); |
36272 | gcc_assert (tattr) ; |
36273 | |
36274 | /* If the attributes are followed by a method introducer, this is not allowed. |
36275 | Dump the attributes and flag the situation. */ |
36276 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PLUS) |
36277 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MINUS)) |
36278 | return true; |
36279 | |
36280 | /* Otherwise, the attributes introduce some interstitial code, possibly so |
36281 | rewind to allow that check. */ |
36282 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
36283 | return false; |
36284 | } |
36285 | |
36286 | /* Parse an Objective-C method prototype list. */ |
36287 | |
36288 | static void |
36289 | cp_parser_objc_method_prototype_list (cp_parser* parser) |
36290 | { |
36291 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36292 | |
36293 | while (token->keyword != RID_AT_END && token->type != CPP_EOF) |
36294 | { |
36295 | if (token->type == CPP_PLUS || token->type == CPP_MINUS) |
36296 | { |
36297 | tree attributes, sig; |
36298 | bool is_class_method; |
36299 | if (token->type == CPP_PLUS) |
36300 | is_class_method = true; |
36301 | else |
36302 | is_class_method = false; |
36303 | sig = cp_parser_objc_method_signature (parser, attributes: &attributes); |
36304 | if (sig == error_mark_node) |
36305 | { |
36306 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36307 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36308 | continue; |
36309 | } |
36310 | objc_add_method_declaration (is_class_method, sig, attributes); |
36311 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36312 | } |
36313 | else if (token->keyword == RID_AT_PROPERTY) |
36314 | cp_parser_objc_at_property_declaration (parser); |
36315 | else if (token->keyword == RID_ATTRIBUTE |
36316 | && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) |
36317 | warning_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
36318 | OPT_Wattributes, |
36319 | "prefix attributes are ignored for methods" ); |
36320 | else |
36321 | /* Allow for interspersed non-ObjC++ code. */ |
36322 | cp_parser_objc_interstitial_code (parser); |
36323 | |
36324 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36325 | } |
36326 | |
36327 | if (token->type != CPP_EOF) |
36328 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
36329 | else |
36330 | cp_parser_error (parser, gmsgid: "expected %<@end%>" ); |
36331 | |
36332 | objc_finish_interface (); |
36333 | } |
36334 | |
36335 | /* Parse an Objective-C method definition list. */ |
36336 | |
36337 | static void |
36338 | cp_parser_objc_method_definition_list (cp_parser* parser) |
36339 | { |
36340 | for (;;) |
36341 | { |
36342 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36343 | |
36344 | if (token->keyword == RID_AT_END) |
36345 | { |
36346 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
36347 | break; |
36348 | } |
36349 | else if (token->type == CPP_EOF) |
36350 | { |
36351 | cp_parser_error (parser, gmsgid: "expected %<@end%>" ); |
36352 | break; |
36353 | } |
36354 | else if (token->type == CPP_PLUS || token->type == CPP_MINUS) |
36355 | { |
36356 | bool is_class_method = token->type == CPP_PLUS; |
36357 | |
36358 | push_deferring_access_checks (dk_deferred); |
36359 | tree attribute; |
36360 | tree sig = cp_parser_objc_method_signature (parser, attributes: &attribute); |
36361 | if (sig == error_mark_node) |
36362 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36363 | else |
36364 | { |
36365 | objc_start_method_definition (is_class_method, sig, |
36366 | attribute, NULL_TREE); |
36367 | |
36368 | /* For historical reasons, we accept an optional semicolon. */ |
36369 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36370 | cp_lexer_consume_token (lexer: parser->lexer); |
36371 | |
36372 | perform_deferred_access_checks (tf_warning_or_error); |
36373 | stop_deferring_access_checks (); |
36374 | tree meth |
36375 | = cp_parser_function_definition_after_declarator (parser, inline_p: false); |
36376 | pop_deferring_access_checks (); |
36377 | objc_finish_method_definition (meth); |
36378 | } |
36379 | } |
36380 | /* The following case will be removed once @synthesize is |
36381 | completely implemented. */ |
36382 | else if (token->keyword == RID_AT_PROPERTY) |
36383 | cp_parser_objc_at_property_declaration (parser); |
36384 | else if (token->keyword == RID_AT_SYNTHESIZE) |
36385 | cp_parser_objc_at_synthesize_declaration (parser); |
36386 | else if (token->keyword == RID_AT_DYNAMIC) |
36387 | cp_parser_objc_at_dynamic_declaration (parser); |
36388 | else if (token->keyword == RID_ATTRIBUTE |
36389 | && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) |
36390 | warning_at (token->location, OPT_Wattributes, |
36391 | "prefix attributes are ignored for methods" ); |
36392 | else |
36393 | /* Allow for interspersed non-ObjC++ code. */ |
36394 | cp_parser_objc_interstitial_code (parser); |
36395 | } |
36396 | |
36397 | objc_finish_implementation (); |
36398 | } |
36399 | |
36400 | /* Parse Objective-C ivars. */ |
36401 | |
36402 | static void |
36403 | cp_parser_objc_class_ivars (cp_parser* parser) |
36404 | { |
36405 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
36406 | |
36407 | if (token->type != CPP_OPEN_BRACE) |
36408 | return; /* No ivars specified. */ |
36409 | |
36410 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '{'. */ |
36411 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36412 | |
36413 | while (token->type != CPP_CLOSE_BRACE |
36414 | && token->keyword != RID_AT_END && token->type != CPP_EOF) |
36415 | { |
36416 | cp_decl_specifier_seq declspecs; |
36417 | int decl_class_or_enum_p; |
36418 | tree prefix_attributes; |
36419 | |
36420 | cp_parser_objc_visibility_spec (parser); |
36421 | |
36422 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
36423 | break; |
36424 | |
36425 | cp_parser_decl_specifier_seq (parser, |
36426 | flags: CP_PARSER_FLAGS_OPTIONAL, |
36427 | decl_specs: &declspecs, |
36428 | declares_class_or_enum: &decl_class_or_enum_p); |
36429 | |
36430 | /* auto, register, static, extern, mutable. */ |
36431 | if (declspecs.storage_class != sc_none) |
36432 | { |
36433 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36434 | declspecs.storage_class = sc_none; |
36435 | } |
36436 | |
36437 | /* thread_local. */ |
36438 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_thread)) |
36439 | { |
36440 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36441 | declspecs.locations[ds_thread] = 0; |
36442 | } |
36443 | |
36444 | /* typedef. */ |
36445 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_typedef)) |
36446 | { |
36447 | cp_parser_error (parser, gmsgid: "invalid type for instance variable" ); |
36448 | declspecs.locations[ds_typedef] = 0; |
36449 | } |
36450 | |
36451 | prefix_attributes = declspecs.attributes; |
36452 | declspecs.attributes = NULL_TREE; |
36453 | |
36454 | /* Keep going until we hit the `;' at the end of the |
36455 | declaration. */ |
36456 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36457 | { |
36458 | tree width = NULL_TREE, attributes, first_attribute, decl; |
36459 | cp_declarator *declarator = NULL; |
36460 | int ctor_dtor_or_conv_p; |
36461 | |
36462 | /* Check for a (possibly unnamed) bitfield declaration. */ |
36463 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36464 | if (token->type == CPP_COLON) |
36465 | goto eat_colon; |
36466 | |
36467 | if (token->type == CPP_NAME |
36468 | && (cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
36469 | == CPP_COLON)) |
36470 | { |
36471 | /* Get the name of the bitfield. */ |
36472 | declarator = make_id_declarator (NULL_TREE, |
36473 | unqualified_name: cp_parser_identifier (parser), |
36474 | sfk: sfk_none, id_location: token->location); |
36475 | |
36476 | eat_colon: |
36477 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ':'. */ |
36478 | /* Get the width of the bitfield. */ |
36479 | width |
36480 | = cp_parser_constant_expression (parser); |
36481 | } |
36482 | else |
36483 | { |
36484 | /* Parse the declarator. */ |
36485 | declarator |
36486 | = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
36487 | flags: CP_PARSER_FLAGS_NONE, |
36488 | ctor_dtor_or_conv_p: &ctor_dtor_or_conv_p, |
36489 | /*parenthesized_p=*/NULL, |
36490 | /*member_p=*/false, |
36491 | /*friend_p=*/false, |
36492 | /*static_p=*/false); |
36493 | } |
36494 | |
36495 | /* Look for attributes that apply to the ivar. */ |
36496 | attributes = cp_parser_attributes_opt (parser); |
36497 | /* Remember which attributes are prefix attributes and |
36498 | which are not. */ |
36499 | first_attribute = attributes; |
36500 | /* Combine the attributes. */ |
36501 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
36502 | |
36503 | if (width) |
36504 | /* Create the bitfield declaration. */ |
36505 | decl = grokbitfield (declarator, &declspecs, |
36506 | width, NULL_TREE, attributes); |
36507 | else |
36508 | decl = grokfield (declarator, &declspecs, |
36509 | NULL_TREE, /*init_const_expr_p=*/false, |
36510 | NULL_TREE, attributes); |
36511 | |
36512 | /* Add the instance variable. */ |
36513 | if (decl != error_mark_node && decl != NULL_TREE) |
36514 | objc_add_instance_variable (decl); |
36515 | |
36516 | /* Reset PREFIX_ATTRIBUTES. */ |
36517 | if (attributes != error_mark_node) |
36518 | { |
36519 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
36520 | attributes = TREE_CHAIN (attributes); |
36521 | if (attributes) |
36522 | TREE_CHAIN (attributes) = NULL_TREE; |
36523 | } |
36524 | |
36525 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36526 | |
36527 | if (token->type == CPP_COMMA) |
36528 | { |
36529 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
36530 | continue; |
36531 | } |
36532 | break; |
36533 | } |
36534 | |
36535 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36536 | token = cp_lexer_peek_token (lexer: parser->lexer); |
36537 | } |
36538 | |
36539 | if (token->keyword == RID_AT_END) |
36540 | cp_parser_error (parser, gmsgid: "expected %<}%>" ); |
36541 | |
36542 | /* Do not consume the RID_AT_END, so it will be read again as terminating |
36543 | the @interface of @implementation. */ |
36544 | if (token->keyword != RID_AT_END && token->type != CPP_EOF) |
36545 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '}'. */ |
36546 | |
36547 | /* For historical reasons, we accept an optional semicolon. */ |
36548 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36549 | cp_lexer_consume_token (lexer: parser->lexer); |
36550 | } |
36551 | |
36552 | /* Parse an Objective-C protocol declaration. */ |
36553 | |
36554 | static void |
36555 | cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) |
36556 | { |
36557 | tree proto, protorefs; |
36558 | cp_token *tok; |
36559 | |
36560 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@protocol'. */ |
36561 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
36562 | { |
36563 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
36564 | error_at (tok->location, "identifier expected after %<@protocol%>" ); |
36565 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36566 | return; |
36567 | } |
36568 | |
36569 | /* See if we have a forward declaration or a definition. */ |
36570 | tok = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2); |
36571 | |
36572 | /* Try a forward declaration first. */ |
36573 | if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON) |
36574 | { |
36575 | while (true) |
36576 | { |
36577 | tree id; |
36578 | |
36579 | id = cp_parser_identifier (parser); |
36580 | if (id == error_mark_node) |
36581 | break; |
36582 | |
36583 | objc_declare_protocol (id, attributes); |
36584 | |
36585 | if(cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
36586 | cp_lexer_consume_token (lexer: parser->lexer); |
36587 | else |
36588 | break; |
36589 | } |
36590 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36591 | } |
36592 | |
36593 | /* Ok, we got a full-fledged definition (or at least should). */ |
36594 | else |
36595 | { |
36596 | proto = cp_parser_identifier (parser); |
36597 | protorefs = cp_parser_objc_protocol_refs_opt (parser); |
36598 | objc_start_protocol (proto, protorefs, attributes); |
36599 | cp_parser_objc_method_prototype_list (parser); |
36600 | } |
36601 | } |
36602 | |
36603 | /* Parse an Objective-C superclass or category. */ |
36604 | |
36605 | static void |
36606 | cp_parser_objc_superclass_or_category (cp_parser *parser, |
36607 | bool iface_p, |
36608 | tree *super, |
36609 | tree *categ, bool *is_class_extension) |
36610 | { |
36611 | cp_token *next = cp_lexer_peek_token (lexer: parser->lexer); |
36612 | |
36613 | *super = *categ = NULL_TREE; |
36614 | *is_class_extension = false; |
36615 | if (next->type == CPP_COLON) |
36616 | { |
36617 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ':'. */ |
36618 | *super = cp_parser_identifier (parser); |
36619 | } |
36620 | else if (next->type == CPP_OPEN_PAREN) |
36621 | { |
36622 | matching_parens parens; |
36623 | parens.consume_open (parser); /* Eat '('. */ |
36624 | |
36625 | /* If there is no category name, and this is an @interface, we |
36626 | have a class extension. */ |
36627 | if (iface_p && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
36628 | { |
36629 | *categ = NULL_TREE; |
36630 | *is_class_extension = true; |
36631 | } |
36632 | else |
36633 | *categ = cp_parser_identifier (parser); |
36634 | |
36635 | parens.require_close (parser); |
36636 | } |
36637 | } |
36638 | |
36639 | /* Parse an Objective-C class interface. */ |
36640 | |
36641 | static void |
36642 | cp_parser_objc_class_interface (cp_parser* parser, tree attributes) |
36643 | { |
36644 | tree name, super, categ, protos; |
36645 | bool is_class_extension; |
36646 | |
36647 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@interface'. */ |
36648 | location_t nam_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36649 | name = cp_parser_identifier (parser); |
36650 | if (name == error_mark_node) |
36651 | { |
36652 | /* It's hard to recover because even if valid @interface stuff |
36653 | is to follow, we can't compile it (or validate it) if we |
36654 | don't even know which class it refers to. Let's assume this |
36655 | was a stray '@interface' token in the stream and skip it. |
36656 | */ |
36657 | return; |
36658 | } |
36659 | cp_parser_objc_superclass_or_category (parser, iface_p: true, super: &super, categ: &categ, |
36660 | is_class_extension: &is_class_extension); |
36661 | protos = cp_parser_objc_protocol_refs_opt (parser); |
36662 | |
36663 | /* We have either a class or a category on our hands. */ |
36664 | if (categ || is_class_extension) |
36665 | objc_start_category_interface (name, categ, protos, attributes); |
36666 | else |
36667 | { |
36668 | objc_start_class_interface (name, nam_loc, super, protos, attributes); |
36669 | /* Handle instance variable declarations, if any. */ |
36670 | cp_parser_objc_class_ivars (parser); |
36671 | objc_continue_interface (); |
36672 | } |
36673 | |
36674 | cp_parser_objc_method_prototype_list (parser); |
36675 | } |
36676 | |
36677 | /* Parse an Objective-C class implementation. */ |
36678 | |
36679 | static void |
36680 | cp_parser_objc_class_implementation (cp_parser* parser) |
36681 | { |
36682 | tree name, super, categ; |
36683 | bool is_class_extension; |
36684 | |
36685 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@implementation'. */ |
36686 | name = cp_parser_identifier (parser); |
36687 | if (name == error_mark_node) |
36688 | { |
36689 | /* It's hard to recover because even if valid @implementation |
36690 | stuff is to follow, we can't compile it (or validate it) if |
36691 | we don't even know which class it refers to. Let's assume |
36692 | this was a stray '@implementation' token in the stream and |
36693 | skip it. |
36694 | */ |
36695 | return; |
36696 | } |
36697 | cp_parser_objc_superclass_or_category (parser, iface_p: false, super: &super, categ: &categ, |
36698 | is_class_extension: &is_class_extension); |
36699 | |
36700 | /* We have either a class or a category on our hands. */ |
36701 | if (categ) |
36702 | objc_start_category_implementation (name, categ); |
36703 | else |
36704 | { |
36705 | objc_start_class_implementation (name, super); |
36706 | /* Handle instance variable declarations, if any. */ |
36707 | cp_parser_objc_class_ivars (parser); |
36708 | objc_continue_implementation (); |
36709 | } |
36710 | |
36711 | cp_parser_objc_method_definition_list (parser); |
36712 | } |
36713 | |
36714 | /* Consume the @end token and finish off the implementation. */ |
36715 | |
36716 | static void |
36717 | cp_parser_objc_end_implementation (cp_parser* parser) |
36718 | { |
36719 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@end'. */ |
36720 | objc_finish_implementation (); |
36721 | } |
36722 | |
36723 | /* Parse an Objective-C declaration. */ |
36724 | |
36725 | static void |
36726 | cp_parser_objc_declaration (cp_parser* parser, tree attributes) |
36727 | { |
36728 | /* Try to figure out what kind of declaration is present. */ |
36729 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
36730 | |
36731 | if (attributes) |
36732 | switch (kwd->keyword) |
36733 | { |
36734 | case RID_AT_ALIAS: |
36735 | case RID_AT_CLASS: |
36736 | case RID_AT_END: |
36737 | error_at (kwd->location, "attributes may not be specified before" |
36738 | " the %<@%D%> Objective-C++ keyword" , |
36739 | kwd->u.value); |
36740 | attributes = NULL; |
36741 | break; |
36742 | case RID_AT_IMPLEMENTATION: |
36743 | warning_at (kwd->location, OPT_Wattributes, |
36744 | "prefix attributes are ignored before %<@%D%>" , |
36745 | kwd->u.value); |
36746 | attributes = NULL; |
36747 | default: |
36748 | break; |
36749 | } |
36750 | |
36751 | switch (kwd->keyword) |
36752 | { |
36753 | case RID_AT_ALIAS: |
36754 | cp_parser_objc_alias_declaration (parser); |
36755 | break; |
36756 | case RID_AT_CLASS: |
36757 | cp_parser_objc_class_declaration (parser); |
36758 | break; |
36759 | case RID_AT_PROTOCOL: |
36760 | cp_parser_objc_protocol_declaration (parser, attributes); |
36761 | break; |
36762 | case RID_AT_INTERFACE: |
36763 | cp_parser_objc_class_interface (parser, attributes); |
36764 | break; |
36765 | case RID_AT_IMPLEMENTATION: |
36766 | cp_parser_objc_class_implementation (parser); |
36767 | break; |
36768 | case RID_AT_END: |
36769 | cp_parser_objc_end_implementation (parser); |
36770 | break; |
36771 | default: |
36772 | error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct" , |
36773 | kwd->u.value); |
36774 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36775 | } |
36776 | } |
36777 | |
36778 | /* Parse an Objective-C try-catch-finally statement. |
36779 | |
36780 | objc-try-catch-finally-stmt: |
36781 | @try compound-statement objc-catch-clause-seq [opt] |
36782 | objc-finally-clause [opt] |
36783 | |
36784 | objc-catch-clause-seq: |
36785 | objc-catch-clause objc-catch-clause-seq [opt] |
36786 | |
36787 | objc-catch-clause: |
36788 | @catch ( objc-exception-declaration ) compound-statement |
36789 | |
36790 | objc-finally-clause: |
36791 | @finally compound-statement |
36792 | |
36793 | objc-exception-declaration: |
36794 | parameter-declaration |
36795 | '...' |
36796 | |
36797 | where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS. |
36798 | |
36799 | Returns NULL_TREE. |
36800 | |
36801 | PS: This function is identical to c_parser_objc_try_catch_finally_statement |
36802 | for C. Keep them in sync. */ |
36803 | |
36804 | static tree |
36805 | cp_parser_objc_try_catch_finally_statement (cp_parser *parser) |
36806 | { |
36807 | location_t location; |
36808 | tree stmt; |
36809 | |
36810 | cp_parser_require_keyword (parser, keyword: RID_AT_TRY, token_desc: RT_AT_TRY); |
36811 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36812 | objc_maybe_warn_exceptions (location); |
36813 | /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST |
36814 | node, lest it get absorbed into the surrounding block. */ |
36815 | stmt = push_stmt_list (); |
36816 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
36817 | objc_begin_try_stmt (location, pop_stmt_list (stmt)); |
36818 | |
36819 | while (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_CATCH)) |
36820 | { |
36821 | cp_parameter_declarator *parm; |
36822 | tree parameter_declaration = error_mark_node; |
36823 | bool seen_open_paren = false; |
36824 | matching_parens parens; |
36825 | |
36826 | cp_lexer_consume_token (lexer: parser->lexer); |
36827 | if (parens.require_open (parser)) |
36828 | seen_open_paren = true; |
36829 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_ELLIPSIS)) |
36830 | { |
36831 | /* We have "@catch (...)" (where the '...' are literally |
36832 | what is in the code). Skip the '...'. |
36833 | parameter_declaration is set to NULL_TREE, and |
36834 | objc_being_catch_clauses() knows that that means |
36835 | '...'. */ |
36836 | cp_lexer_consume_token (lexer: parser->lexer); |
36837 | parameter_declaration = NULL_TREE; |
36838 | } |
36839 | else |
36840 | { |
36841 | /* We have "@catch (NSException *exception)" or something |
36842 | like that. Parse the parameter declaration. */ |
36843 | parm = cp_parser_parameter_declaration (parser, flags: CP_PARSER_FLAGS_NONE, |
36844 | template_parm_p: false, NULL); |
36845 | if (parm == NULL) |
36846 | parameter_declaration = error_mark_node; |
36847 | else |
36848 | parameter_declaration = grokdeclarator (parm->declarator, |
36849 | &parm->decl_specifiers, |
36850 | PARM, /*initialized=*/0, |
36851 | /*attrlist=*/NULL); |
36852 | } |
36853 | if (seen_open_paren) |
36854 | parens.require_close (parser); |
36855 | else |
36856 | { |
36857 | /* If there was no open parenthesis, we are recovering from |
36858 | an error, and we are trying to figure out what mistake |
36859 | the user has made. */ |
36860 | |
36861 | /* If there is an immediate closing parenthesis, the user |
36862 | probably forgot the opening one (ie, they typed "@catch |
36863 | NSException *e)". Parse the closing parenthesis and keep |
36864 | going. */ |
36865 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
36866 | cp_lexer_consume_token (lexer: parser->lexer); |
36867 | |
36868 | /* If these is no immediate closing parenthesis, the user |
36869 | probably doesn't know that parenthesis are required at |
36870 | all (ie, they typed "@catch NSException *e"). So, just |
36871 | forget about the closing parenthesis and keep going. */ |
36872 | } |
36873 | objc_begin_catch_clause (parameter_declaration); |
36874 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
36875 | objc_finish_catch_clause (); |
36876 | } |
36877 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AT_FINALLY)) |
36878 | { |
36879 | cp_lexer_consume_token (lexer: parser->lexer); |
36880 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36881 | /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST |
36882 | node, lest it get absorbed into the surrounding block. */ |
36883 | stmt = push_stmt_list (); |
36884 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
36885 | objc_build_finally_clause (location, pop_stmt_list (stmt)); |
36886 | } |
36887 | |
36888 | return objc_finish_try_stmt (); |
36889 | } |
36890 | |
36891 | /* Parse an Objective-C synchronized statement. |
36892 | |
36893 | objc-synchronized-stmt: |
36894 | @synchronized ( expression ) compound-statement |
36895 | |
36896 | Returns NULL_TREE. */ |
36897 | |
36898 | static tree |
36899 | cp_parser_objc_synchronized_statement (cp_parser *parser) |
36900 | { |
36901 | location_t location; |
36902 | tree lock, stmt; |
36903 | |
36904 | cp_parser_require_keyword (parser, keyword: RID_AT_SYNCHRONIZED, token_desc: RT_AT_SYNCHRONIZED); |
36905 | |
36906 | location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36907 | objc_maybe_warn_exceptions (location); |
36908 | matching_parens parens; |
36909 | parens.require_open (parser); |
36910 | lock = cp_parser_expression (parser); |
36911 | parens.require_close (parser); |
36912 | |
36913 | /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST |
36914 | node, lest it get absorbed into the surrounding block. */ |
36915 | stmt = push_stmt_list (); |
36916 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
36917 | |
36918 | return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); |
36919 | } |
36920 | |
36921 | /* Parse an Objective-C throw statement. |
36922 | |
36923 | objc-throw-stmt: |
36924 | @throw assignment-expression [opt] ; |
36925 | |
36926 | Returns a constructed '@throw' statement. */ |
36927 | |
36928 | static tree |
36929 | cp_parser_objc_throw_statement (cp_parser *parser) |
36930 | { |
36931 | tree expr = NULL_TREE; |
36932 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
36933 | |
36934 | cp_parser_require_keyword (parser, keyword: RID_AT_THROW, token_desc: RT_AT_THROW); |
36935 | |
36936 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
36937 | expr = cp_parser_expression (parser); |
36938 | |
36939 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
36940 | |
36941 | return objc_build_throw_stmt (loc, expr); |
36942 | } |
36943 | |
36944 | /* Parse an Objective-C statement. */ |
36945 | |
36946 | static tree |
36947 | cp_parser_objc_statement (cp_parser * parser) |
36948 | { |
36949 | /* Try to figure out what kind of declaration is present. */ |
36950 | cp_token *kwd = cp_lexer_peek_token (lexer: parser->lexer); |
36951 | |
36952 | switch (kwd->keyword) |
36953 | { |
36954 | case RID_AT_TRY: |
36955 | return cp_parser_objc_try_catch_finally_statement (parser); |
36956 | case RID_AT_SYNCHRONIZED: |
36957 | return cp_parser_objc_synchronized_statement (parser); |
36958 | case RID_AT_THROW: |
36959 | return cp_parser_objc_throw_statement (parser); |
36960 | default: |
36961 | error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct" , |
36962 | kwd->u.value); |
36963 | cp_parser_skip_to_end_of_block_or_statement (parser); |
36964 | } |
36965 | |
36966 | return error_mark_node; |
36967 | } |
36968 | |
36969 | /* If we are compiling ObjC++ and we see an __attribute__ we neeed to |
36970 | look ahead to see if an objc keyword follows the attributes. This |
36971 | is to detect the use of prefix attributes on ObjC @interface and |
36972 | @protocol. */ |
36973 | |
36974 | static bool |
36975 | cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) |
36976 | { |
36977 | cp_lexer_save_tokens (lexer: parser->lexer); |
36978 | tree addon = cp_parser_attributes_opt (parser); |
36979 | if (addon |
36980 | && OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) |
36981 | { |
36982 | cp_lexer_commit_tokens (lexer: parser->lexer); |
36983 | if (*attrib) |
36984 | TREE_CHAIN (*attrib) = addon; |
36985 | else |
36986 | *attrib = addon; |
36987 | return true; |
36988 | } |
36989 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
36990 | return false; |
36991 | } |
36992 | |
36993 | /* This routine is a minimal replacement for |
36994 | c_parser_struct_declaration () used when parsing the list of |
36995 | types/names or ObjC++ properties. For example, when parsing the |
36996 | code |
36997 | |
36998 | @property (readonly) int a, b, c; |
36999 | |
37000 | this function is responsible for parsing "int a, int b, int c" and |
37001 | returning the declarations as CHAIN of DECLs. |
37002 | |
37003 | TODO: Share this code with cp_parser_objc_class_ivars. It's very |
37004 | similar parsing. */ |
37005 | static tree |
37006 | cp_parser_objc_struct_declaration (cp_parser *parser) |
37007 | { |
37008 | tree decls = NULL_TREE; |
37009 | cp_decl_specifier_seq declspecs; |
37010 | int decl_class_or_enum_p; |
37011 | tree prefix_attributes; |
37012 | |
37013 | cp_parser_decl_specifier_seq (parser, |
37014 | flags: CP_PARSER_FLAGS_NONE, |
37015 | decl_specs: &declspecs, |
37016 | declares_class_or_enum: &decl_class_or_enum_p); |
37017 | |
37018 | if (declspecs.type == error_mark_node) |
37019 | return error_mark_node; |
37020 | |
37021 | /* auto, register, static, extern, mutable. */ |
37022 | if (declspecs.storage_class != sc_none) |
37023 | { |
37024 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37025 | declspecs.storage_class = sc_none; |
37026 | } |
37027 | |
37028 | /* thread_local. */ |
37029 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_thread)) |
37030 | { |
37031 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37032 | declspecs.locations[ds_thread] = 0; |
37033 | } |
37034 | |
37035 | /* typedef. */ |
37036 | if (decl_spec_seq_has_spec_p (decl_specs: &declspecs, ds: ds_typedef)) |
37037 | { |
37038 | cp_parser_error (parser, gmsgid: "invalid type for property" ); |
37039 | declspecs.locations[ds_typedef] = 0; |
37040 | } |
37041 | |
37042 | prefix_attributes = declspecs.attributes; |
37043 | declspecs.attributes = NULL_TREE; |
37044 | |
37045 | /* Keep going until we hit the `;' at the end of the declaration. */ |
37046 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
37047 | { |
37048 | tree attributes, first_attribute, decl; |
37049 | cp_declarator *declarator; |
37050 | cp_token *token; |
37051 | |
37052 | /* Parse the declarator. */ |
37053 | declarator = cp_parser_declarator (parser, dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
37054 | flags: CP_PARSER_FLAGS_NONE, |
37055 | NULL, NULL, member_p: false, friend_p: false, static_p: false); |
37056 | |
37057 | /* Look for attributes that apply to the ivar. */ |
37058 | attributes = cp_parser_attributes_opt (parser); |
37059 | /* Remember which attributes are prefix attributes and |
37060 | which are not. */ |
37061 | first_attribute = attributes; |
37062 | /* Combine the attributes. */ |
37063 | attributes = attr_chainon (attrs: prefix_attributes, attr: attributes); |
37064 | |
37065 | decl = grokfield (declarator, &declspecs, |
37066 | NULL_TREE, /*init_const_expr_p=*/false, |
37067 | NULL_TREE, attributes); |
37068 | |
37069 | if (decl == error_mark_node || decl == NULL_TREE) |
37070 | return error_mark_node; |
37071 | |
37072 | /* Reset PREFIX_ATTRIBUTES. */ |
37073 | if (attributes != error_mark_node) |
37074 | { |
37075 | while (attributes && TREE_CHAIN (attributes) != first_attribute) |
37076 | attributes = TREE_CHAIN (attributes); |
37077 | if (attributes) |
37078 | TREE_CHAIN (attributes) = NULL_TREE; |
37079 | } |
37080 | |
37081 | DECL_CHAIN (decl) = decls; |
37082 | decls = decl; |
37083 | |
37084 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37085 | if (token->type == CPP_COMMA) |
37086 | { |
37087 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat ','. */ |
37088 | continue; |
37089 | } |
37090 | else |
37091 | break; |
37092 | } |
37093 | return decls; |
37094 | } |
37095 | |
37096 | /* Parse an Objective-C @property declaration. The syntax is: |
37097 | |
37098 | objc-property-declaration: |
37099 | '@property' objc-property-attributes[opt] struct-declaration ; |
37100 | |
37101 | objc-property-attributes: |
37102 | '(' objc-property-attribute-list ')' |
37103 | |
37104 | objc-property-attribute-list: |
37105 | objc-property-attribute |
37106 | objc-property-attribute-list, objc-property-attribute |
37107 | |
37108 | objc-property-attribute |
37109 | 'getter' = identifier |
37110 | 'setter' = identifier |
37111 | 'readonly' |
37112 | 'readwrite' |
37113 | 'assign' |
37114 | 'retain' |
37115 | 'copy' |
37116 | 'nonatomic' |
37117 | |
37118 | For example: |
37119 | @property NSString *name; |
37120 | @property (readonly) id object; |
37121 | @property (retain, nonatomic, getter=getTheName) id name; |
37122 | @property int a, b, c; |
37123 | |
37124 | PS: This function is identical to |
37125 | c_parser_objc_at_property_declaration for C. Keep them in sync. */ |
37126 | static void |
37127 | cp_parser_objc_at_property_declaration (cp_parser *parser) |
37128 | { |
37129 | /* Parse the optional attribute list. |
37130 | |
37131 | A list of parsed, but not verified, attributes. */ |
37132 | auto_delete_vec<property_attribute_info> prop_attr_list; |
37133 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37134 | |
37135 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@property'. */ |
37136 | |
37137 | /* Parse the optional attribute list... */ |
37138 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
37139 | { |
37140 | /* Eat the '('. */ |
37141 | matching_parens parens; |
37142 | location_t attr_start = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37143 | parens.consume_open (parser); |
37144 | bool syntax_error = false; |
37145 | |
37146 | /* Allow empty @property attribute lists, but with a warning. */ |
37147 | location_t attr_end = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37148 | location_t attr_comb; |
37149 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
37150 | { |
37151 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37152 | warning_at (attr_comb, OPT_Wattributes, |
37153 | "empty property attribute list" ); |
37154 | } |
37155 | else |
37156 | while (true) |
37157 | { |
37158 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
37159 | attr_start = token->location; |
37160 | attr_end = get_finish (loc: token->location); |
37161 | attr_comb = make_location (caret: attr_start, start: attr_start, finish: attr_end); |
37162 | |
37163 | if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA) |
37164 | { |
37165 | warning_at (attr_comb, OPT_Wattributes, |
37166 | "missing property attribute" ); |
37167 | if (token->type == CPP_CLOSE_PAREN) |
37168 | break; |
37169 | cp_lexer_consume_token (lexer: parser->lexer); |
37170 | continue; |
37171 | } |
37172 | |
37173 | tree attr_name = NULL_TREE; |
37174 | if (identifier_p (t: token->u.value)) |
37175 | attr_name = token->u.value; |
37176 | |
37177 | enum rid keyword; |
37178 | if (token->type == CPP_NAME) |
37179 | keyword = C_RID_CODE (token->u.value); |
37180 | else if (token->type == CPP_KEYWORD |
37181 | && token->keyword == RID_CLASS) |
37182 | /* Account for accepting the 'class' keyword in this context. */ |
37183 | keyword = RID_CLASS; |
37184 | else |
37185 | keyword = RID_MAX; /* By definition, an unknown property. */ |
37186 | cp_lexer_consume_token (lexer: parser->lexer); |
37187 | |
37188 | enum objc_property_attribute_kind prop_kind |
37189 | = objc_prop_attr_kind_for_rid (keyword); |
37190 | property_attribute_info *prop |
37191 | = new property_attribute_info (attr_name, attr_comb, prop_kind); |
37192 | prop_attr_list.safe_push (obj: prop); |
37193 | |
37194 | tree meth_name; |
37195 | switch (prop->prop_kind) |
37196 | { |
37197 | default: break; |
37198 | case OBJC_PROPERTY_ATTR_UNKNOWN: |
37199 | if (attr_name) |
37200 | error_at (attr_start, "unknown property attribute %qE" , |
37201 | attr_name); |
37202 | else |
37203 | error_at (attr_start, "unknown property attribute" ); |
37204 | prop->parse_error = syntax_error = true; |
37205 | break; |
37206 | |
37207 | case OBJC_PROPERTY_ATTR_GETTER: |
37208 | case OBJC_PROPERTY_ATTR_SETTER: |
37209 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ)) |
37210 | { |
37211 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37212 | error_at (attr_comb, "expected %<=%> after Objective-C %qE" , |
37213 | attr_name); |
37214 | prop->parse_error = syntax_error = true; |
37215 | break; |
37216 | } |
37217 | |
37218 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37219 | attr_end = token->location; |
37220 | cp_lexer_consume_token (lexer: parser->lexer); /* eat the = */ |
37221 | |
37222 | if (!cp_parser_objc_selector_p |
37223 | (type: cp_lexer_peek_token (lexer: parser->lexer)->type)) |
37224 | { |
37225 | attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end); |
37226 | error_at (attr_comb, "expected %qE selector name" , |
37227 | attr_name); |
37228 | prop->parse_error = syntax_error = true; |
37229 | break; |
37230 | } |
37231 | |
37232 | /* Get the end of the method name, and consume the name. */ |
37233 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37234 | attr_end = get_finish (loc: token->location); |
37235 | /* Because method names may contain C++ keywords, we have a |
37236 | routine to fetch them (this also consumes the token). */ |
37237 | meth_name = cp_parser_objc_selector (parser); |
37238 | |
37239 | if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER) |
37240 | { |
37241 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COLON)) |
37242 | { |
37243 | attr_comb = make_location (caret: attr_end, start: attr_start, |
37244 | finish: attr_end); |
37245 | error_at (attr_comb, "setter method names must" |
37246 | " terminate with %<:%>" ); |
37247 | prop->parse_error = syntax_error = true; |
37248 | } |
37249 | else |
37250 | { |
37251 | attr_end = get_finish (loc: cp_lexer_peek_token |
37252 | (lexer: parser->lexer)->location); |
37253 | cp_lexer_consume_token (lexer: parser->lexer); |
37254 | } |
37255 | attr_comb = make_location (caret: attr_start, start: attr_start, |
37256 | finish: attr_end); |
37257 | } |
37258 | else |
37259 | attr_comb = make_location (caret: attr_start, start: attr_start, |
37260 | finish: attr_end); |
37261 | prop->ident = meth_name; |
37262 | /* Updated location including all that was successfully |
37263 | parsed. */ |
37264 | prop->prop_loc = attr_comb; |
37265 | break; |
37266 | } |
37267 | |
37268 | /* If we see a comma here, then keep going - even if we already |
37269 | saw a syntax error. For simple mistakes e.g. (asign, getter=x) |
37270 | this makes a more useful output and avoid spurious warnings |
37271 | about missing attributes that are, in fact, specified after the |
37272 | one with the syntax error. */ |
37273 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37274 | cp_lexer_consume_token (lexer: parser->lexer); |
37275 | else |
37276 | break; |
37277 | } |
37278 | |
37279 | if (syntax_error || !parens.require_close (parser)) |
37280 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
37281 | /*or_comma=*/false, |
37282 | /*consume_paren=*/true); |
37283 | } |
37284 | |
37285 | /* 'properties' is the list of properties that we read. Usually a |
37286 | single one, but maybe more (eg, in "@property int a, b, c;" there |
37287 | are three). |
37288 | TODO: Update this parsing so that it accepts (erroneous) bitfields so |
37289 | that we can issue a meaningful and consistent (between C/C++) error |
37290 | message from objc_add_property_declaration (). */ |
37291 | tree properties = cp_parser_objc_struct_declaration (parser); |
37292 | |
37293 | if (properties == error_mark_node) |
37294 | cp_parser_skip_to_end_of_statement (parser); |
37295 | else if (properties == NULL_TREE) |
37296 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
37297 | else |
37298 | { |
37299 | /* Comma-separated properties are chained together in reverse order; |
37300 | add them one by one. */ |
37301 | properties = nreverse (properties); |
37302 | for (; properties; properties = TREE_CHAIN (properties)) |
37303 | objc_add_property_declaration (loc, copy_node (properties), |
37304 | prop_attr_list); |
37305 | } |
37306 | |
37307 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37308 | } |
37309 | |
37310 | /* Parse an Objective-C++ @synthesize declaration. The syntax is: |
37311 | |
37312 | objc-synthesize-declaration: |
37313 | @synthesize objc-synthesize-identifier-list ; |
37314 | |
37315 | objc-synthesize-identifier-list: |
37316 | objc-synthesize-identifier |
37317 | objc-synthesize-identifier-list, objc-synthesize-identifier |
37318 | |
37319 | objc-synthesize-identifier |
37320 | identifier |
37321 | identifier = identifier |
37322 | |
37323 | For example: |
37324 | @synthesize MyProperty; |
37325 | @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty; |
37326 | |
37327 | PS: This function is identical to c_parser_objc_at_synthesize_declaration |
37328 | for C. Keep them in sync. |
37329 | */ |
37330 | static void |
37331 | cp_parser_objc_at_synthesize_declaration (cp_parser *parser) |
37332 | { |
37333 | tree list = NULL_TREE; |
37334 | location_t loc; |
37335 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37336 | |
37337 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@synthesize'. */ |
37338 | while (true) |
37339 | { |
37340 | tree property, ivar; |
37341 | property = cp_parser_identifier (parser); |
37342 | if (property == error_mark_node) |
37343 | { |
37344 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37345 | return; |
37346 | } |
37347 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
37348 | { |
37349 | cp_lexer_consume_token (lexer: parser->lexer); |
37350 | ivar = cp_parser_identifier (parser); |
37351 | if (ivar == error_mark_node) |
37352 | { |
37353 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37354 | return; |
37355 | } |
37356 | } |
37357 | else |
37358 | ivar = NULL_TREE; |
37359 | list = chainon (list, build_tree_list (ivar, property)); |
37360 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37361 | cp_lexer_consume_token (lexer: parser->lexer); |
37362 | else |
37363 | break; |
37364 | } |
37365 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37366 | objc_add_synthesize_declaration (loc, list); |
37367 | } |
37368 | |
37369 | /* Parse an Objective-C++ @dynamic declaration. The syntax is: |
37370 | |
37371 | objc-dynamic-declaration: |
37372 | @dynamic identifier-list ; |
37373 | |
37374 | For example: |
37375 | @dynamic MyProperty; |
37376 | @dynamic MyProperty, AnotherProperty; |
37377 | |
37378 | PS: This function is identical to c_parser_objc_at_dynamic_declaration |
37379 | for C. Keep them in sync. |
37380 | */ |
37381 | static void |
37382 | cp_parser_objc_at_dynamic_declaration (cp_parser *parser) |
37383 | { |
37384 | tree list = NULL_TREE; |
37385 | location_t loc; |
37386 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37387 | |
37388 | cp_lexer_consume_token (lexer: parser->lexer); /* Eat '@dynamic'. */ |
37389 | while (true) |
37390 | { |
37391 | tree property; |
37392 | property = cp_parser_identifier (parser); |
37393 | if (property == error_mark_node) |
37394 | { |
37395 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37396 | return; |
37397 | } |
37398 | list = chainon (list, build_tree_list (NULL, property)); |
37399 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
37400 | cp_lexer_consume_token (lexer: parser->lexer); |
37401 | else |
37402 | break; |
37403 | } |
37404 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
37405 | objc_add_dynamic_declaration (loc, list); |
37406 | } |
37407 | |
37408 | |
37409 | /* OpenMP 2.5 / 3.0 / 3.1 / 4.0 / 4.5 / 5.0 parsing routines. */ |
37410 | |
37411 | /* Returns name of the next clause. |
37412 | If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and |
37413 | the token is not consumed. Otherwise appropriate pragma_omp_clause is |
37414 | returned and the token is consumed. */ |
37415 | |
37416 | static pragma_omp_clause |
37417 | cp_parser_omp_clause_name (cp_parser *parser) |
37418 | { |
37419 | pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE; |
37420 | |
37421 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
37422 | result = PRAGMA_OACC_CLAUSE_AUTO; |
37423 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
37424 | result = PRAGMA_OMP_CLAUSE_IF; |
37425 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT)) |
37426 | result = PRAGMA_OMP_CLAUSE_DEFAULT; |
37427 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DELETE)) |
37428 | result = PRAGMA_OACC_CLAUSE_DELETE; |
37429 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_PRIVATE)) |
37430 | result = PRAGMA_OMP_CLAUSE_PRIVATE; |
37431 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
37432 | result = PRAGMA_OMP_CLAUSE_FOR; |
37433 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
37434 | { |
37435 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
37436 | const char *p = IDENTIFIER_POINTER (id); |
37437 | |
37438 | switch (p[0]) |
37439 | { |
37440 | case 'a': |
37441 | if (!strcmp (s1: "affinity" , s2: p)) |
37442 | result = PRAGMA_OMP_CLAUSE_AFFINITY; |
37443 | else if (!strcmp (s1: "aligned" , s2: p)) |
37444 | result = PRAGMA_OMP_CLAUSE_ALIGNED; |
37445 | else if (!strcmp (s1: "allocate" , s2: p)) |
37446 | result = PRAGMA_OMP_CLAUSE_ALLOCATE; |
37447 | else if (!strcmp (s1: "async" , s2: p)) |
37448 | result = PRAGMA_OACC_CLAUSE_ASYNC; |
37449 | else if (!strcmp (s1: "attach" , s2: p)) |
37450 | result = PRAGMA_OACC_CLAUSE_ATTACH; |
37451 | break; |
37452 | case 'b': |
37453 | if (!strcmp (s1: "bind" , s2: p)) |
37454 | result = PRAGMA_OMP_CLAUSE_BIND; |
37455 | break; |
37456 | case 'c': |
37457 | if (!strcmp (s1: "collapse" , s2: p)) |
37458 | result = PRAGMA_OMP_CLAUSE_COLLAPSE; |
37459 | else if (!strcmp (s1: "copy" , s2: p)) |
37460 | result = PRAGMA_OACC_CLAUSE_COPY; |
37461 | else if (!strcmp (s1: "copyin" , s2: p)) |
37462 | result = PRAGMA_OMP_CLAUSE_COPYIN; |
37463 | else if (!strcmp (s1: "copyout" , s2: p)) |
37464 | result = PRAGMA_OACC_CLAUSE_COPYOUT; |
37465 | else if (!strcmp (s1: "copyprivate" , s2: p)) |
37466 | result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; |
37467 | else if (!strcmp (s1: "create" , s2: p)) |
37468 | result = PRAGMA_OACC_CLAUSE_CREATE; |
37469 | break; |
37470 | case 'd': |
37471 | if (!strcmp (s1: "defaultmap" , s2: p)) |
37472 | result = PRAGMA_OMP_CLAUSE_DEFAULTMAP; |
37473 | else if (!strcmp (s1: "depend" , s2: p)) |
37474 | result = PRAGMA_OMP_CLAUSE_DEPEND; |
37475 | else if (!strcmp (s1: "detach" , s2: p)) |
37476 | result = PRAGMA_OACC_CLAUSE_DETACH; |
37477 | else if (!strcmp (s1: "device" , s2: p)) |
37478 | result = PRAGMA_OMP_CLAUSE_DEVICE; |
37479 | else if (!strcmp (s1: "deviceptr" , s2: p)) |
37480 | result = PRAGMA_OACC_CLAUSE_DEVICEPTR; |
37481 | else if (!strcmp (s1: "device_resident" , s2: p)) |
37482 | result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT; |
37483 | else if (!strcmp (s1: "device_type" , s2: p)) |
37484 | result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; |
37485 | else if (!strcmp (s1: "dist_schedule" , s2: p)) |
37486 | result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; |
37487 | else if (!strcmp (s1: "doacross" , s2: p)) |
37488 | result = PRAGMA_OMP_CLAUSE_DOACROSS; |
37489 | break; |
37490 | case 'e': |
37491 | if (!strcmp (s1: "enter" , s2: p)) |
37492 | result = PRAGMA_OMP_CLAUSE_ENTER; |
37493 | break; |
37494 | case 'f': |
37495 | if (!strcmp (s1: "filter" , s2: p)) |
37496 | result = PRAGMA_OMP_CLAUSE_FILTER; |
37497 | else if (!strcmp (s1: "final" , s2: p)) |
37498 | result = PRAGMA_OMP_CLAUSE_FINAL; |
37499 | else if (!strcmp (s1: "finalize" , s2: p)) |
37500 | result = PRAGMA_OACC_CLAUSE_FINALIZE; |
37501 | else if (!strcmp (s1: "firstprivate" , s2: p)) |
37502 | result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; |
37503 | else if (!strcmp (s1: "from" , s2: p)) |
37504 | result = PRAGMA_OMP_CLAUSE_FROM; |
37505 | break; |
37506 | case 'g': |
37507 | if (!strcmp (s1: "gang" , s2: p)) |
37508 | result = PRAGMA_OACC_CLAUSE_GANG; |
37509 | else if (!strcmp (s1: "grainsize" , s2: p)) |
37510 | result = PRAGMA_OMP_CLAUSE_GRAINSIZE; |
37511 | break; |
37512 | case 'h': |
37513 | if (!strcmp (s1: "has_device_addr" , s2: p)) |
37514 | result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR; |
37515 | else if (!strcmp (s1: "hint" , s2: p)) |
37516 | result = PRAGMA_OMP_CLAUSE_HINT; |
37517 | else if (!strcmp (s1: "host" , s2: p)) |
37518 | result = PRAGMA_OACC_CLAUSE_HOST; |
37519 | break; |
37520 | case 'i': |
37521 | if (!strcmp (s1: "if_present" , s2: p)) |
37522 | result = PRAGMA_OACC_CLAUSE_IF_PRESENT; |
37523 | else if (!strcmp (s1: "in_reduction" , s2: p)) |
37524 | result = PRAGMA_OMP_CLAUSE_IN_REDUCTION; |
37525 | else if (!strcmp (s1: "inbranch" , s2: p)) |
37526 | result = PRAGMA_OMP_CLAUSE_INBRANCH; |
37527 | else if (!strcmp (s1: "indirect" , s2: p)) |
37528 | result = PRAGMA_OMP_CLAUSE_INDIRECT; |
37529 | else if (!strcmp (s1: "independent" , s2: p)) |
37530 | result = PRAGMA_OACC_CLAUSE_INDEPENDENT; |
37531 | else if (!strcmp (s1: "is_device_ptr" , s2: p)) |
37532 | result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR; |
37533 | break; |
37534 | case 'l': |
37535 | if (!strcmp (s1: "lastprivate" , s2: p)) |
37536 | result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; |
37537 | else if (!strcmp (s1: "linear" , s2: p)) |
37538 | result = PRAGMA_OMP_CLAUSE_LINEAR; |
37539 | else if (!strcmp (s1: "link" , s2: p)) |
37540 | result = PRAGMA_OMP_CLAUSE_LINK; |
37541 | break; |
37542 | case 'm': |
37543 | if (!strcmp (s1: "map" , s2: p)) |
37544 | result = PRAGMA_OMP_CLAUSE_MAP; |
37545 | else if (!strcmp (s1: "mergeable" , s2: p)) |
37546 | result = PRAGMA_OMP_CLAUSE_MERGEABLE; |
37547 | break; |
37548 | case 'n': |
37549 | if (!strcmp (s1: "no_create" , s2: p)) |
37550 | result = PRAGMA_OACC_CLAUSE_NO_CREATE; |
37551 | else if (!strcmp (s1: "nogroup" , s2: p)) |
37552 | result = PRAGMA_OMP_CLAUSE_NOGROUP; |
37553 | else if (!strcmp (s1: "nohost" , s2: p)) |
37554 | result = PRAGMA_OACC_CLAUSE_NOHOST; |
37555 | else if (!strcmp (s1: "nontemporal" , s2: p)) |
37556 | result = PRAGMA_OMP_CLAUSE_NONTEMPORAL; |
37557 | else if (!strcmp (s1: "notinbranch" , s2: p)) |
37558 | result = PRAGMA_OMP_CLAUSE_NOTINBRANCH; |
37559 | else if (!strcmp (s1: "nowait" , s2: p)) |
37560 | result = PRAGMA_OMP_CLAUSE_NOWAIT; |
37561 | else if (!strcmp (s1: "num_gangs" , s2: p)) |
37562 | result = PRAGMA_OACC_CLAUSE_NUM_GANGS; |
37563 | else if (!strcmp (s1: "num_tasks" , s2: p)) |
37564 | result = PRAGMA_OMP_CLAUSE_NUM_TASKS; |
37565 | else if (!strcmp (s1: "num_teams" , s2: p)) |
37566 | result = PRAGMA_OMP_CLAUSE_NUM_TEAMS; |
37567 | else if (!strcmp (s1: "num_threads" , s2: p)) |
37568 | result = PRAGMA_OMP_CLAUSE_NUM_THREADS; |
37569 | else if (!strcmp (s1: "num_workers" , s2: p)) |
37570 | result = PRAGMA_OACC_CLAUSE_NUM_WORKERS; |
37571 | break; |
37572 | case 'o': |
37573 | if (!strcmp (s1: "ordered" , s2: p)) |
37574 | result = PRAGMA_OMP_CLAUSE_ORDERED; |
37575 | else if (!strcmp (s1: "order" , s2: p)) |
37576 | result = PRAGMA_OMP_CLAUSE_ORDER; |
37577 | break; |
37578 | case 'p': |
37579 | if (!strcmp (s1: "parallel" , s2: p)) |
37580 | result = PRAGMA_OMP_CLAUSE_PARALLEL; |
37581 | else if (!strcmp (s1: "present" , s2: p)) |
37582 | result = PRAGMA_OACC_CLAUSE_PRESENT; |
37583 | else if (!strcmp (s1: "present_or_copy" , s2: p) |
37584 | || !strcmp (s1: "pcopy" , s2: p)) |
37585 | result = PRAGMA_OACC_CLAUSE_COPY; |
37586 | else if (!strcmp (s1: "present_or_copyin" , s2: p) |
37587 | || !strcmp (s1: "pcopyin" , s2: p)) |
37588 | result = PRAGMA_OACC_CLAUSE_COPYIN; |
37589 | else if (!strcmp (s1: "present_or_copyout" , s2: p) |
37590 | || !strcmp (s1: "pcopyout" , s2: p)) |
37591 | result = PRAGMA_OACC_CLAUSE_COPYOUT; |
37592 | else if (!strcmp (s1: "present_or_create" , s2: p) |
37593 | || !strcmp (s1: "pcreate" , s2: p)) |
37594 | result = PRAGMA_OACC_CLAUSE_CREATE; |
37595 | else if (!strcmp (s1: "priority" , s2: p)) |
37596 | result = PRAGMA_OMP_CLAUSE_PRIORITY; |
37597 | else if (!strcmp (s1: "proc_bind" , s2: p)) |
37598 | result = PRAGMA_OMP_CLAUSE_PROC_BIND; |
37599 | break; |
37600 | case 'r': |
37601 | if (!strcmp (s1: "reduction" , s2: p)) |
37602 | result = PRAGMA_OMP_CLAUSE_REDUCTION; |
37603 | break; |
37604 | case 's': |
37605 | if (!strcmp (s1: "safelen" , s2: p)) |
37606 | result = PRAGMA_OMP_CLAUSE_SAFELEN; |
37607 | else if (!strcmp (s1: "schedule" , s2: p)) |
37608 | result = PRAGMA_OMP_CLAUSE_SCHEDULE; |
37609 | else if (!strcmp (s1: "sections" , s2: p)) |
37610 | result = PRAGMA_OMP_CLAUSE_SECTIONS; |
37611 | else if (!strcmp (s1: "self" , s2: p)) |
37612 | result = PRAGMA_OACC_CLAUSE_SELF; |
37613 | else if (!strcmp (s1: "seq" , s2: p)) |
37614 | result = PRAGMA_OACC_CLAUSE_SEQ; |
37615 | else if (!strcmp (s1: "shared" , s2: p)) |
37616 | result = PRAGMA_OMP_CLAUSE_SHARED; |
37617 | else if (!strcmp (s1: "simd" , s2: p)) |
37618 | result = PRAGMA_OMP_CLAUSE_SIMD; |
37619 | else if (!strcmp (s1: "simdlen" , s2: p)) |
37620 | result = PRAGMA_OMP_CLAUSE_SIMDLEN; |
37621 | break; |
37622 | case 't': |
37623 | if (!strcmp (s1: "task_reduction" , s2: p)) |
37624 | result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION; |
37625 | else if (!strcmp (s1: "taskgroup" , s2: p)) |
37626 | result = PRAGMA_OMP_CLAUSE_TASKGROUP; |
37627 | else if (!strcmp (s1: "thread_limit" , s2: p)) |
37628 | result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT; |
37629 | else if (!strcmp (s1: "threads" , s2: p)) |
37630 | result = PRAGMA_OMP_CLAUSE_THREADS; |
37631 | else if (!strcmp (s1: "tile" , s2: p)) |
37632 | result = PRAGMA_OACC_CLAUSE_TILE; |
37633 | else if (!strcmp (s1: "to" , s2: p)) |
37634 | result = PRAGMA_OMP_CLAUSE_TO; |
37635 | break; |
37636 | case 'u': |
37637 | if (!strcmp (s1: "uniform" , s2: p)) |
37638 | result = PRAGMA_OMP_CLAUSE_UNIFORM; |
37639 | else if (!strcmp (s1: "untied" , s2: p)) |
37640 | result = PRAGMA_OMP_CLAUSE_UNTIED; |
37641 | else if (!strcmp (s1: "use_device" , s2: p)) |
37642 | result = PRAGMA_OACC_CLAUSE_USE_DEVICE; |
37643 | else if (!strcmp (s1: "use_device_addr" , s2: p)) |
37644 | result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR; |
37645 | else if (!strcmp (s1: "use_device_ptr" , s2: p)) |
37646 | result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR; |
37647 | break; |
37648 | case 'v': |
37649 | if (!strcmp (s1: "vector" , s2: p)) |
37650 | result = PRAGMA_OACC_CLAUSE_VECTOR; |
37651 | else if (!strcmp (s1: "vector_length" , s2: p)) |
37652 | result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH; |
37653 | break; |
37654 | case 'w': |
37655 | if (!strcmp (s1: "wait" , s2: p)) |
37656 | result = PRAGMA_OACC_CLAUSE_WAIT; |
37657 | else if (!strcmp (s1: "worker" , s2: p)) |
37658 | result = PRAGMA_OACC_CLAUSE_WORKER; |
37659 | break; |
37660 | } |
37661 | } |
37662 | |
37663 | if (result != PRAGMA_OMP_CLAUSE_NONE) |
37664 | cp_lexer_consume_token (lexer: parser->lexer); |
37665 | |
37666 | return result; |
37667 | } |
37668 | |
37669 | /* Validate that a clause of the given type does not already exist. */ |
37670 | |
37671 | static void |
37672 | check_no_duplicate_clause (tree clauses, enum omp_clause_code code, |
37673 | const char *name, location_t location) |
37674 | { |
37675 | if (omp_find_clause (clauses, kind: code)) |
37676 | error_at (location, "too many %qs clauses" , name); |
37677 | } |
37678 | |
37679 | /* OpenMP 2.5: |
37680 | variable-list: |
37681 | identifier |
37682 | variable-list , identifier |
37683 | |
37684 | In addition, we match a closing parenthesis (or, if COLON is non-NULL, |
37685 | colon). An opening parenthesis will have been consumed by the caller. |
37686 | |
37687 | If KIND is nonzero, create the appropriate node and install the decl |
37688 | in OMP_CLAUSE_DECL and add the node to the head of the list. |
37689 | |
37690 | If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; |
37691 | return the list created. |
37692 | |
37693 | COLON can be NULL if only closing parenthesis should end the list, |
37694 | or pointer to bool which will receive false if the list is terminated |
37695 | by closing parenthesis or true if the list is terminated by colon. |
37696 | |
37697 | The optional ALLOW_DEREF argument is true if list items can use the deref |
37698 | (->) operator. */ |
37699 | |
37700 | struct omp_dim |
37701 | { |
37702 | tree low_bound, length; |
37703 | location_t loc; |
37704 | bool no_colon; |
37705 | omp_dim (tree lb, tree len, location_t lo, bool nc) |
37706 | : low_bound (lb), length (len), loc (lo), no_colon (nc) {} |
37707 | }; |
37708 | |
37709 | static tree |
37710 | cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, |
37711 | tree list, bool *colon, |
37712 | bool allow_deref = false) |
37713 | { |
37714 | auto_vec<omp_dim> dims; |
37715 | bool array_section_p; |
37716 | cp_token *token; |
37717 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
37718 | if (colon) |
37719 | { |
37720 | parser->colon_corrects_to_scope_p = false; |
37721 | *colon = false; |
37722 | } |
37723 | while (1) |
37724 | { |
37725 | tree name, decl; |
37726 | |
37727 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37728 | cp_parser_parse_tentatively (parser); |
37729 | token = cp_lexer_peek_token (lexer: parser->lexer); |
37730 | if (kind != 0 |
37731 | && cp_parser_is_keyword (token, keyword: RID_THIS)) |
37732 | { |
37733 | decl = finish_this_expr (); |
37734 | if (TREE_CODE (decl) == NON_LVALUE_EXPR |
37735 | || CONVERT_EXPR_P (decl)) |
37736 | decl = TREE_OPERAND (decl, 0); |
37737 | cp_lexer_consume_token (lexer: parser->lexer); |
37738 | } |
37739 | else if (cp_parser_is_keyword (token, keyword: RID_FUNCTION_NAME) |
37740 | || cp_parser_is_keyword (token, keyword: RID_PRETTY_FUNCTION_NAME) |
37741 | || cp_parser_is_keyword (token, keyword: RID_C99_FUNCTION_NAME)) |
37742 | { |
37743 | cp_id_kind idk; |
37744 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, template_arg_p: false, |
37745 | idk: &idk); |
37746 | } |
37747 | else if (kind == OMP_CLAUSE_DEPEND |
37748 | && cp_parser_is_keyword (token, keyword: RID_OMP_ALL_MEMORY) |
37749 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
37750 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
37751 | type: CPP_CLOSE_PAREN))) |
37752 | { |
37753 | decl = ridpointers[RID_OMP_ALL_MEMORY]; |
37754 | cp_lexer_consume_token (lexer: parser->lexer); |
37755 | } |
37756 | else |
37757 | { |
37758 | name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
37759 | /*check_dependency_p=*/true, |
37760 | /*template_p=*/NULL, |
37761 | /*declarator_p=*/false, |
37762 | /*optional_p=*/false); |
37763 | if (name == error_mark_node) |
37764 | { |
37765 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37766 | && cp_parser_simulate_error (parser)) |
37767 | goto depend_lvalue; |
37768 | goto skip_comma; |
37769 | } |
37770 | |
37771 | if (identifier_p (t: name)) |
37772 | decl = cp_parser_lookup_name_simple (parser, name, location: token->location); |
37773 | else |
37774 | decl = name; |
37775 | if (decl == error_mark_node) |
37776 | { |
37777 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37778 | && cp_parser_simulate_error (parser)) |
37779 | goto depend_lvalue; |
37780 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, |
37781 | location: token->location); |
37782 | } |
37783 | } |
37784 | if (outer_automatic_var_p (decl)) |
37785 | decl = process_outer_var_ref (decl, tf_warning_or_error); |
37786 | if (decl == error_mark_node) |
37787 | ; |
37788 | else if (kind != 0) |
37789 | { |
37790 | switch (kind) |
37791 | { |
37792 | case OMP_CLAUSE__CACHE_: |
37793 | /* The OpenACC cache directive explicitly only allows "array |
37794 | elements or subarrays". */ |
37795 | if (cp_lexer_peek_token (lexer: parser->lexer)->type != CPP_OPEN_SQUARE) |
37796 | { |
37797 | error_at (token->location, "expected %<[%>" ); |
37798 | decl = error_mark_node; |
37799 | break; |
37800 | } |
37801 | /* FALLTHROUGH. */ |
37802 | case OMP_CLAUSE_MAP: |
37803 | case OMP_CLAUSE_FROM: |
37804 | case OMP_CLAUSE_TO: |
37805 | start_component_ref: |
37806 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
37807 | || (allow_deref |
37808 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DEREF))) |
37809 | { |
37810 | cpp_ttype ttype |
37811 | = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
37812 | ? CPP_DOT : CPP_DEREF; |
37813 | location_t loc |
37814 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37815 | cp_id_kind idk = CP_ID_KIND_NONE; |
37816 | cp_lexer_consume_token (lexer: parser->lexer); |
37817 | decl = convert_from_reference (decl); |
37818 | decl = (cp_parser_postfix_dot_deref_expression |
37819 | (parser, token_type: ttype, postfix_expression: cp_expr (decl, token->location), |
37820 | for_offsetof: false, idk: &idk, location: loc)); |
37821 | } |
37822 | /* FALLTHROUGH. */ |
37823 | case OMP_CLAUSE_AFFINITY: |
37824 | case OMP_CLAUSE_DEPEND: |
37825 | case OMP_CLAUSE_REDUCTION: |
37826 | case OMP_CLAUSE_IN_REDUCTION: |
37827 | case OMP_CLAUSE_TASK_REDUCTION: |
37828 | case OMP_CLAUSE_HAS_DEVICE_ADDR: |
37829 | array_section_p = false; |
37830 | dims.truncate (size: 0); |
37831 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
37832 | { |
37833 | location_t loc = UNKNOWN_LOCATION; |
37834 | tree low_bound = NULL_TREE, length = NULL_TREE; |
37835 | bool no_colon = false; |
37836 | |
37837 | parser->colon_corrects_to_scope_p = false; |
37838 | cp_lexer_consume_token (lexer: parser->lexer); |
37839 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
37840 | { |
37841 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37842 | low_bound = cp_parser_expression (parser); |
37843 | /* Later handling is not prepared to see through these. */ |
37844 | gcc_checking_assert (!location_wrapper_p (low_bound)); |
37845 | } |
37846 | if (!colon) |
37847 | parser->colon_corrects_to_scope_p |
37848 | = saved_colon_corrects_to_scope_p; |
37849 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_SQUARE)) |
37850 | { |
37851 | length = integer_one_node; |
37852 | no_colon = true; |
37853 | } |
37854 | else |
37855 | { |
37856 | /* Look for `:'. */ |
37857 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
37858 | { |
37859 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37860 | && cp_parser_simulate_error (parser)) |
37861 | goto depend_lvalue; |
37862 | goto skip_comma; |
37863 | } |
37864 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37865 | cp_parser_commit_to_tentative_parse (parser); |
37866 | else |
37867 | array_section_p = true; |
37868 | if (!cp_lexer_next_token_is (lexer: parser->lexer, |
37869 | type: CPP_CLOSE_SQUARE)) |
37870 | { |
37871 | length = cp_parser_expression (parser); |
37872 | /* Later handling is not prepared to see through these. */ |
37873 | gcc_checking_assert (!location_wrapper_p (length)); |
37874 | } |
37875 | } |
37876 | /* Look for the closing `]'. */ |
37877 | if (!cp_parser_require (parser, type: CPP_CLOSE_SQUARE, |
37878 | token_desc: RT_CLOSE_SQUARE)) |
37879 | { |
37880 | if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37881 | && cp_parser_simulate_error (parser)) |
37882 | goto depend_lvalue; |
37883 | goto skip_comma; |
37884 | } |
37885 | |
37886 | dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon)); |
37887 | } |
37888 | |
37889 | if ((kind == OMP_CLAUSE_MAP |
37890 | || kind == OMP_CLAUSE_FROM |
37891 | || kind == OMP_CLAUSE_TO) |
37892 | && !array_section_p |
37893 | && (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_DOT) |
37894 | || (allow_deref |
37895 | && cp_lexer_next_token_is (lexer: parser->lexer, |
37896 | type: CPP_DEREF)))) |
37897 | { |
37898 | for (unsigned i = 0; i < dims.length (); i++) |
37899 | { |
37900 | gcc_assert (dims[i].length == integer_one_node); |
37901 | decl = build_array_ref (dims[i].loc, |
37902 | decl, dims[i].low_bound); |
37903 | } |
37904 | goto start_component_ref; |
37905 | } |
37906 | else |
37907 | for (unsigned i = 0; i < dims.length (); i++) |
37908 | decl = tree_cons (dims[i].low_bound, dims[i].length, decl); |
37909 | |
37910 | break; |
37911 | default: |
37912 | break; |
37913 | } |
37914 | |
37915 | if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) |
37916 | { |
37917 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
37918 | && cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
37919 | && cp_parser_simulate_error (parser)) |
37920 | { |
37921 | depend_lvalue: |
37922 | cp_parser_abort_tentative_parse (parser); |
37923 | decl = cp_parser_assignment_expression (parser, NULL, |
37924 | cast_p: false, decltype_p: false); |
37925 | } |
37926 | else |
37927 | cp_parser_parse_definitely (parser); |
37928 | } |
37929 | |
37930 | tree u = build_omp_clause (token->location, kind); |
37931 | OMP_CLAUSE_DECL (u) = decl; |
37932 | OMP_CLAUSE_CHAIN (u) = list; |
37933 | list = u; |
37934 | } |
37935 | else |
37936 | list = tree_cons (decl, NULL_TREE, list); |
37937 | |
37938 | get_comma: |
37939 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
37940 | break; |
37941 | cp_lexer_consume_token (lexer: parser->lexer); |
37942 | } |
37943 | |
37944 | if (colon) |
37945 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
37946 | |
37947 | if (colon != NULL && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
37948 | { |
37949 | *colon = true; |
37950 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
37951 | return list; |
37952 | } |
37953 | |
37954 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_CLOSE_PAREN)) |
37955 | { |
37956 | int ending; |
37957 | |
37958 | /* Try to resync to an unnested comma. Copied from |
37959 | cp_parser_parenthesized_expression_list. */ |
37960 | skip_comma: |
37961 | if (colon) |
37962 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
37963 | ending = cp_parser_skip_to_closing_parenthesis (parser, |
37964 | /*recovering=*/true, |
37965 | /*or_comma=*/true, |
37966 | /*consume_paren=*/true); |
37967 | if (ending < 0) |
37968 | goto get_comma; |
37969 | } |
37970 | |
37971 | return list; |
37972 | } |
37973 | |
37974 | /* Similarly, but expect leading and trailing parenthesis. This is a very |
37975 | common case for omp clauses. */ |
37976 | |
37977 | static tree |
37978 | cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list, |
37979 | bool allow_deref = false) |
37980 | { |
37981 | if (parser->lexer->in_omp_decl_attribute) |
37982 | { |
37983 | if (kind) |
37984 | { |
37985 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
37986 | tree u = build_omp_clause (loc, kind); |
37987 | OMP_CLAUSE_DECL (u) = parser->lexer->in_omp_decl_attribute; |
37988 | OMP_CLAUSE_CHAIN (u) = list; |
37989 | return u; |
37990 | } |
37991 | else |
37992 | return tree_cons (parser->lexer->in_omp_decl_attribute, NULL_TREE, |
37993 | list); |
37994 | } |
37995 | |
37996 | if (cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
37997 | return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, |
37998 | allow_deref); |
37999 | return list; |
38000 | } |
38001 | |
38002 | /* OpenACC 2.0: |
38003 | copy ( variable-list ) |
38004 | copyin ( variable-list ) |
38005 | copyout ( variable-list ) |
38006 | create ( variable-list ) |
38007 | delete ( variable-list ) |
38008 | present ( variable-list ) |
38009 | |
38010 | OpenACC 2.6: |
38011 | no_create ( variable-list ) |
38012 | attach ( variable-list ) |
38013 | detach ( variable-list ) */ |
38014 | |
38015 | static tree |
38016 | cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind, |
38017 | tree list) |
38018 | { |
38019 | enum gomp_map_kind kind; |
38020 | switch (c_kind) |
38021 | { |
38022 | case PRAGMA_OACC_CLAUSE_ATTACH: |
38023 | kind = GOMP_MAP_ATTACH; |
38024 | break; |
38025 | case PRAGMA_OACC_CLAUSE_COPY: |
38026 | kind = GOMP_MAP_TOFROM; |
38027 | break; |
38028 | case PRAGMA_OACC_CLAUSE_COPYIN: |
38029 | kind = GOMP_MAP_TO; |
38030 | break; |
38031 | case PRAGMA_OACC_CLAUSE_COPYOUT: |
38032 | kind = GOMP_MAP_FROM; |
38033 | break; |
38034 | case PRAGMA_OACC_CLAUSE_CREATE: |
38035 | kind = GOMP_MAP_ALLOC; |
38036 | break; |
38037 | case PRAGMA_OACC_CLAUSE_DELETE: |
38038 | kind = GOMP_MAP_RELEASE; |
38039 | break; |
38040 | case PRAGMA_OACC_CLAUSE_DETACH: |
38041 | kind = GOMP_MAP_DETACH; |
38042 | break; |
38043 | case PRAGMA_OACC_CLAUSE_DEVICE: |
38044 | kind = GOMP_MAP_FORCE_TO; |
38045 | break; |
38046 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
38047 | kind = GOMP_MAP_DEVICE_RESIDENT; |
38048 | break; |
38049 | case PRAGMA_OACC_CLAUSE_LINK: |
38050 | kind = GOMP_MAP_LINK; |
38051 | break; |
38052 | case PRAGMA_OACC_CLAUSE_NO_CREATE: |
38053 | kind = GOMP_MAP_IF_PRESENT; |
38054 | break; |
38055 | case PRAGMA_OACC_CLAUSE_PRESENT: |
38056 | kind = GOMP_MAP_FORCE_PRESENT; |
38057 | break; |
38058 | case PRAGMA_OACC_CLAUSE_SELF: |
38059 | /* "The 'host' clause is a synonym for the 'self' clause." */ |
38060 | case PRAGMA_OACC_CLAUSE_HOST: |
38061 | kind = GOMP_MAP_FORCE_FROM; |
38062 | break; |
38063 | default: |
38064 | gcc_unreachable (); |
38065 | } |
38066 | tree nl, c; |
38067 | nl = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_MAP, list, allow_deref: true); |
38068 | |
38069 | for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
38070 | OMP_CLAUSE_SET_MAP_KIND (c, kind); |
38071 | |
38072 | return nl; |
38073 | } |
38074 | |
38075 | /* OpenACC 2.0: |
38076 | deviceptr ( variable-list ) */ |
38077 | |
38078 | static tree |
38079 | cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list) |
38080 | { |
38081 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38082 | tree vars, t; |
38083 | |
38084 | /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic |
38085 | cp_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR, |
38086 | variable-list must only allow for pointer variables. */ |
38087 | vars = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
38088 | for (t = vars; t; t = TREE_CHAIN (t)) |
38089 | { |
38090 | tree v = TREE_PURPOSE (t); |
38091 | tree u = build_omp_clause (loc, OMP_CLAUSE_MAP); |
38092 | OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR); |
38093 | OMP_CLAUSE_DECL (u) = v; |
38094 | OMP_CLAUSE_CHAIN (u) = list; |
38095 | list = u; |
38096 | } |
38097 | |
38098 | return list; |
38099 | } |
38100 | |
38101 | /* OpenACC 2.5: |
38102 | auto |
38103 | finalize |
38104 | independent |
38105 | nohost |
38106 | seq */ |
38107 | |
38108 | static tree |
38109 | cp_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code, |
38110 | tree list) |
38111 | { |
38112 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location: loc); |
38113 | |
38114 | tree c = build_omp_clause (loc, code); |
38115 | OMP_CLAUSE_CHAIN (c) = list; |
38116 | |
38117 | return c; |
38118 | } |
38119 | |
38120 | /* OpenACC: |
38121 | num_gangs ( expression ) |
38122 | num_workers ( expression ) |
38123 | vector_length ( expression ) */ |
38124 | |
38125 | static tree |
38126 | cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code, |
38127 | const char *str, tree list) |
38128 | { |
38129 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38130 | |
38131 | matching_parens parens; |
38132 | if (!parens.require_open (parser)) |
38133 | return list; |
38134 | |
38135 | tree t = cp_parser_assignment_expression (parser, NULL, cast_p: false, decltype_p: false); |
38136 | |
38137 | if (t == error_mark_node |
38138 | || !parens.require_close (parser)) |
38139 | { |
38140 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38141 | /*or_comma=*/false, |
38142 | /*consume_paren=*/true); |
38143 | return list; |
38144 | } |
38145 | |
38146 | check_no_duplicate_clause (clauses: list, code, name: str, location: loc); |
38147 | |
38148 | tree c = build_omp_clause (loc, code); |
38149 | OMP_CLAUSE_OPERAND (c, 0) = t; |
38150 | OMP_CLAUSE_CHAIN (c) = list; |
38151 | return c; |
38152 | } |
38153 | |
38154 | /* OpenACC: |
38155 | |
38156 | gang [( gang-arg-list )] |
38157 | worker [( [num:] int-expr )] |
38158 | vector [( [length:] int-expr )] |
38159 | |
38160 | where gang-arg is one of: |
38161 | |
38162 | [num:] int-expr |
38163 | static: size-expr |
38164 | |
38165 | and size-expr may be: |
38166 | |
38167 | * |
38168 | int-expr |
38169 | */ |
38170 | |
38171 | static tree |
38172 | cp_parser_oacc_shape_clause (cp_parser *parser, location_t loc, |
38173 | omp_clause_code kind, |
38174 | const char *str, tree list) |
38175 | { |
38176 | const char *id = "num" ; |
38177 | cp_lexer *lexer = parser->lexer; |
38178 | tree ops[2] = { NULL_TREE, NULL_TREE }, c; |
38179 | |
38180 | if (kind == OMP_CLAUSE_VECTOR) |
38181 | id = "length" ; |
38182 | |
38183 | if (cp_lexer_next_token_is (lexer, type: CPP_OPEN_PAREN)) |
38184 | { |
38185 | matching_parens parens; |
38186 | parens.consume_open (parser); |
38187 | |
38188 | do |
38189 | { |
38190 | cp_token *next = cp_lexer_peek_token (lexer); |
38191 | int idx = 0; |
38192 | |
38193 | /* Gang static argument. */ |
38194 | if (kind == OMP_CLAUSE_GANG |
38195 | && cp_lexer_next_token_is_keyword (lexer, keyword: RID_STATIC)) |
38196 | { |
38197 | cp_lexer_consume_token (lexer); |
38198 | |
38199 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
38200 | goto cleanup_error; |
38201 | |
38202 | idx = 1; |
38203 | if (ops[idx] != NULL) |
38204 | { |
38205 | cp_parser_error (parser, gmsgid: "too many %<static%> arguments" ); |
38206 | goto cleanup_error; |
38207 | } |
38208 | |
38209 | /* Check for the '*' argument. */ |
38210 | if (cp_lexer_next_token_is (lexer, type: CPP_MULT) |
38211 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
38212 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
38213 | type: CPP_CLOSE_PAREN))) |
38214 | { |
38215 | cp_lexer_consume_token (lexer); |
38216 | ops[idx] = integer_minus_one_node; |
38217 | |
38218 | if (cp_lexer_next_token_is (lexer, type: CPP_COMMA)) |
38219 | { |
38220 | cp_lexer_consume_token (lexer); |
38221 | continue; |
38222 | } |
38223 | else break; |
38224 | } |
38225 | } |
38226 | /* Worker num: argument and vector length: arguments. */ |
38227 | else if (cp_lexer_next_token_is (lexer, type: CPP_NAME) |
38228 | && id_equal (id: next->u.value, str: id) |
38229 | && cp_lexer_nth_token_is (lexer, n: 2, type: CPP_COLON)) |
38230 | { |
38231 | cp_lexer_consume_token (lexer); /* id */ |
38232 | cp_lexer_consume_token (lexer); /* ':' */ |
38233 | } |
38234 | |
38235 | /* Now collect the actual argument. */ |
38236 | if (ops[idx] != NULL_TREE) |
38237 | { |
38238 | cp_parser_error (parser, gmsgid: "unexpected argument" ); |
38239 | goto cleanup_error; |
38240 | } |
38241 | |
38242 | tree expr = cp_parser_assignment_expression (parser, NULL, cast_p: false, |
38243 | decltype_p: false); |
38244 | if (expr == error_mark_node) |
38245 | goto cleanup_error; |
38246 | |
38247 | mark_exp_read (expr); |
38248 | ops[idx] = expr; |
38249 | |
38250 | if (kind == OMP_CLAUSE_GANG |
38251 | && cp_lexer_next_token_is (lexer, type: CPP_COMMA)) |
38252 | { |
38253 | cp_lexer_consume_token (lexer); |
38254 | continue; |
38255 | } |
38256 | break; |
38257 | } |
38258 | while (1); |
38259 | |
38260 | if (!parens.require_close (parser)) |
38261 | goto cleanup_error; |
38262 | } |
38263 | |
38264 | check_no_duplicate_clause (clauses: list, code: kind, name: str, location: loc); |
38265 | |
38266 | c = build_omp_clause (loc, kind); |
38267 | |
38268 | if (ops[1]) |
38269 | OMP_CLAUSE_OPERAND (c, 1) = ops[1]; |
38270 | |
38271 | OMP_CLAUSE_OPERAND (c, 0) = ops[0]; |
38272 | OMP_CLAUSE_CHAIN (c) = list; |
38273 | |
38274 | return c; |
38275 | |
38276 | cleanup_error: |
38277 | cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, consume_paren: true); |
38278 | return list; |
38279 | } |
38280 | |
38281 | /* OpenACC 2.0: |
38282 | tile ( size-expr-list ) */ |
38283 | |
38284 | static tree |
38285 | cp_parser_oacc_clause_tile (cp_parser *parser, location_t clause_loc, tree list) |
38286 | { |
38287 | tree c, expr = error_mark_node; |
38288 | tree tile = NULL_TREE; |
38289 | |
38290 | /* Collapse and tile are mutually exclusive. (The spec doesn't say |
38291 | so, but the spec authors never considered such a case and have |
38292 | differing opinions on what it might mean, including 'not |
38293 | allowed'.) */ |
38294 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile" , location: clause_loc); |
38295 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse" , |
38296 | location: clause_loc); |
38297 | |
38298 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
38299 | return list; |
38300 | |
38301 | do |
38302 | { |
38303 | if (tile && !cp_parser_require (parser, type: CPP_COMMA, token_desc: RT_COMMA)) |
38304 | return list; |
38305 | |
38306 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MULT) |
38307 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA) |
38308 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN))) |
38309 | { |
38310 | cp_lexer_consume_token (lexer: parser->lexer); |
38311 | expr = integer_zero_node; |
38312 | } |
38313 | else |
38314 | expr = cp_parser_constant_expression (parser); |
38315 | |
38316 | tile = tree_cons (NULL_TREE, expr, tile); |
38317 | } |
38318 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)); |
38319 | |
38320 | /* Consume the trailing ')'. */ |
38321 | cp_lexer_consume_token (lexer: parser->lexer); |
38322 | |
38323 | c = build_omp_clause (clause_loc, OMP_CLAUSE_TILE); |
38324 | tile = nreverse (tile); |
38325 | OMP_CLAUSE_TILE_LIST (c) = tile; |
38326 | OMP_CLAUSE_CHAIN (c) = list; |
38327 | return c; |
38328 | } |
38329 | |
38330 | /* OpenACC 2.0 |
38331 | Parse wait clause or directive parameters. */ |
38332 | |
38333 | static tree |
38334 | cp_parser_oacc_wait_list (cp_parser *parser, location_t clause_loc, tree list) |
38335 | { |
38336 | vec<tree, va_gc> *args; |
38337 | tree t, args_tree; |
38338 | |
38339 | args = cp_parser_parenthesized_expression_list (parser, is_attribute_list: non_attr, |
38340 | /*cast_p=*/false, |
38341 | /*allow_expansion_p=*/true, |
38342 | /*non_constant_p=*/NULL); |
38343 | |
38344 | if (args == NULL || args->length () == 0) |
38345 | { |
38346 | if (args != NULL) |
38347 | { |
38348 | cp_parser_error (parser, gmsgid: "expected integer expression list" ); |
38349 | release_tree_vector (args); |
38350 | } |
38351 | return list; |
38352 | } |
38353 | |
38354 | args_tree = build_tree_list_vec (args); |
38355 | |
38356 | release_tree_vector (args); |
38357 | |
38358 | for (t = args_tree; t; t = TREE_CHAIN (t)) |
38359 | { |
38360 | tree targ = TREE_VALUE (t); |
38361 | |
38362 | if (targ != error_mark_node) |
38363 | { |
38364 | if (!INTEGRAL_TYPE_P (TREE_TYPE (targ))) |
38365 | error ("%<wait%> expression must be integral" ); |
38366 | else |
38367 | { |
38368 | tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT); |
38369 | |
38370 | targ = mark_rvalue_use (targ); |
38371 | OMP_CLAUSE_DECL (c) = targ; |
38372 | OMP_CLAUSE_CHAIN (c) = list; |
38373 | list = c; |
38374 | } |
38375 | } |
38376 | } |
38377 | |
38378 | return list; |
38379 | } |
38380 | |
38381 | /* OpenACC: |
38382 | wait [( int-expr-list )] */ |
38383 | |
38384 | static tree |
38385 | cp_parser_oacc_clause_wait (cp_parser *parser, tree list) |
38386 | { |
38387 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38388 | |
38389 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
38390 | list = cp_parser_oacc_wait_list (parser, clause_loc: location, list); |
38391 | else |
38392 | { |
38393 | tree c = build_omp_clause (location, OMP_CLAUSE_WAIT); |
38394 | |
38395 | OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL); |
38396 | OMP_CLAUSE_CHAIN (c) = list; |
38397 | list = c; |
38398 | } |
38399 | |
38400 | return list; |
38401 | } |
38402 | |
38403 | /* OpenMP 3.0: |
38404 | collapse ( constant-expression ) */ |
38405 | |
38406 | static tree |
38407 | cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location) |
38408 | { |
38409 | tree c, num; |
38410 | location_t loc; |
38411 | HOST_WIDE_INT n; |
38412 | |
38413 | loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
38414 | matching_parens parens; |
38415 | if (!parens.require_open (parser)) |
38416 | return list; |
38417 | |
38418 | num = cp_parser_constant_expression (parser); |
38419 | |
38420 | if (!parens.require_close (parser)) |
38421 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38422 | /*or_comma=*/false, |
38423 | /*consume_paren=*/true); |
38424 | |
38425 | if (num == error_mark_node) |
38426 | return list; |
38427 | num = fold_non_dependent_expr (num); |
38428 | if (!tree_fits_shwi_p (num) |
38429 | || !INTEGRAL_TYPE_P (TREE_TYPE (num)) |
38430 | || (n = tree_to_shwi (num)) <= 0 |
38431 | || (int) n != n) |
38432 | { |
38433 | error_at (loc, "collapse argument needs positive constant integer expression" ); |
38434 | return list; |
38435 | } |
38436 | |
38437 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse" , location); |
38438 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile" , location); |
38439 | c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); |
38440 | OMP_CLAUSE_CHAIN (c) = list; |
38441 | OMP_CLAUSE_COLLAPSE_EXPR (c) = num; |
38442 | |
38443 | return c; |
38444 | } |
38445 | |
38446 | /* OpenMP 2.5: |
38447 | default ( none | shared ) |
38448 | |
38449 | OpenMP 5.1: |
38450 | default ( private | firstprivate ) |
38451 | |
38452 | OpenACC: |
38453 | default ( none | present ) */ |
38454 | |
38455 | static tree |
38456 | cp_parser_omp_clause_default (cp_parser *parser, tree list, |
38457 | location_t location, bool is_oacc) |
38458 | { |
38459 | enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; |
38460 | tree c; |
38461 | |
38462 | matching_parens parens; |
38463 | if (!parens.require_open (parser)) |
38464 | return list; |
38465 | if (!is_oacc && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_PRIVATE)) |
38466 | { |
38467 | kind = OMP_CLAUSE_DEFAULT_PRIVATE; |
38468 | cp_lexer_consume_token (lexer: parser->lexer); |
38469 | } |
38470 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
38471 | { |
38472 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
38473 | const char *p = IDENTIFIER_POINTER (id); |
38474 | |
38475 | switch (p[0]) |
38476 | { |
38477 | case 'n': |
38478 | if (strcmp (s1: "none" , s2: p) != 0) |
38479 | goto invalid_kind; |
38480 | kind = OMP_CLAUSE_DEFAULT_NONE; |
38481 | break; |
38482 | |
38483 | case 'p': |
38484 | if (strcmp (s1: "present" , s2: p) != 0 || !is_oacc) |
38485 | goto invalid_kind; |
38486 | kind = OMP_CLAUSE_DEFAULT_PRESENT; |
38487 | break; |
38488 | |
38489 | case 'f': |
38490 | if (strcmp (s1: "firstprivate" , s2: p) != 0 || is_oacc) |
38491 | goto invalid_kind; |
38492 | kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; |
38493 | break; |
38494 | |
38495 | case 's': |
38496 | if (strcmp (s1: "shared" , s2: p) != 0 || is_oacc) |
38497 | goto invalid_kind; |
38498 | kind = OMP_CLAUSE_DEFAULT_SHARED; |
38499 | break; |
38500 | |
38501 | default: |
38502 | goto invalid_kind; |
38503 | } |
38504 | |
38505 | cp_lexer_consume_token (lexer: parser->lexer); |
38506 | } |
38507 | else |
38508 | { |
38509 | invalid_kind: |
38510 | if (is_oacc) |
38511 | cp_parser_error (parser, gmsgid: "expected %<none%> or %<present%>" ); |
38512 | else |
38513 | cp_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, " |
38514 | "%<private%> or %<firstprivate%>" ); |
38515 | } |
38516 | |
38517 | if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED |
38518 | || !parens.require_close (parser)) |
38519 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38520 | /*or_comma=*/false, |
38521 | /*consume_paren=*/true); |
38522 | |
38523 | if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) |
38524 | return list; |
38525 | |
38526 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default" , location); |
38527 | c = build_omp_clause (location, OMP_CLAUSE_DEFAULT); |
38528 | OMP_CLAUSE_CHAIN (c) = list; |
38529 | OMP_CLAUSE_DEFAULT_KIND (c) = kind; |
38530 | |
38531 | return c; |
38532 | } |
38533 | |
38534 | /* OpenMP 3.1: |
38535 | final ( expression ) */ |
38536 | |
38537 | static tree |
38538 | cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location) |
38539 | { |
38540 | tree t, c; |
38541 | |
38542 | matching_parens parens; |
38543 | if (!parens.require_open (parser)) |
38544 | return list; |
38545 | |
38546 | t = cp_parser_assignment_expression (parser); |
38547 | |
38548 | if (t == error_mark_node |
38549 | || !parens.require_close (parser)) |
38550 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38551 | /*or_comma=*/false, |
38552 | /*consume_paren=*/true); |
38553 | |
38554 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final" , location); |
38555 | |
38556 | c = build_omp_clause (location, OMP_CLAUSE_FINAL); |
38557 | OMP_CLAUSE_FINAL_EXPR (c) = t; |
38558 | OMP_CLAUSE_CHAIN (c) = list; |
38559 | |
38560 | return c; |
38561 | } |
38562 | |
38563 | /* OpenMP 5.1: |
38564 | indirect [( expression )] |
38565 | */ |
38566 | |
38567 | static tree |
38568 | cp_parser_omp_clause_indirect (cp_parser *parser, tree list, |
38569 | location_t location) |
38570 | { |
38571 | tree t; |
38572 | |
38573 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
38574 | { |
38575 | matching_parens parens; |
38576 | if (!parens.require_open (parser)) |
38577 | return list; |
38578 | |
38579 | bool non_constant_p; |
38580 | t = cp_parser_constant_expression (parser, allow_non_constant_p: true, non_constant_p: &non_constant_p); |
38581 | |
38582 | if (t != error_mark_node && non_constant_p) |
38583 | error_at (location, "expected constant logical expression" ); |
38584 | |
38585 | if (t == error_mark_node |
38586 | || !parens.require_close (parser)) |
38587 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38588 | /*or_comma=*/false, |
38589 | /*consume_paren=*/true); |
38590 | } |
38591 | else |
38592 | t = integer_one_node; |
38593 | |
38594 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect" , location); |
38595 | |
38596 | tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT); |
38597 | OMP_CLAUSE_INDIRECT_EXPR (c) = t; |
38598 | OMP_CLAUSE_CHAIN (c) = list; |
38599 | |
38600 | return c; |
38601 | } |
38602 | |
38603 | /* OpenMP 2.5: |
38604 | if ( expression ) |
38605 | |
38606 | OpenMP 4.5: |
38607 | if ( directive-name-modifier : expression ) |
38608 | |
38609 | directive-name-modifier: |
38610 | parallel | task | taskloop | target data | target | target update |
38611 | | target enter data | target exit data |
38612 | |
38613 | OpenMP 5.0: |
38614 | directive-name-modifier: |
38615 | ... | simd | cancel */ |
38616 | |
38617 | static tree |
38618 | cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location, |
38619 | bool is_omp) |
38620 | { |
38621 | tree t, c; |
38622 | enum tree_code if_modifier = ERROR_MARK; |
38623 | |
38624 | matching_parens parens; |
38625 | if (!parens.require_open (parser)) |
38626 | return list; |
38627 | |
38628 | if (is_omp && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
38629 | { |
38630 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
38631 | const char *p = IDENTIFIER_POINTER (id); |
38632 | int n = 2; |
38633 | |
38634 | if (strcmp (s1: "cancel" , s2: p) == 0) |
38635 | if_modifier = VOID_CST; |
38636 | else if (strcmp (s1: "parallel" , s2: p) == 0) |
38637 | if_modifier = OMP_PARALLEL; |
38638 | else if (strcmp (s1: "simd" , s2: p) == 0) |
38639 | if_modifier = OMP_SIMD; |
38640 | else if (strcmp (s1: "task" , s2: p) == 0) |
38641 | if_modifier = OMP_TASK; |
38642 | else if (strcmp (s1: "taskloop" , s2: p) == 0) |
38643 | if_modifier = OMP_TASKLOOP; |
38644 | else if (strcmp (s1: "target" , s2: p) == 0) |
38645 | { |
38646 | if_modifier = OMP_TARGET; |
38647 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
38648 | { |
38649 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->u.value; |
38650 | p = IDENTIFIER_POINTER (id); |
38651 | if (strcmp (s1: "data" , s2: p) == 0) |
38652 | if_modifier = OMP_TARGET_DATA; |
38653 | else if (strcmp (s1: "update" , s2: p) == 0) |
38654 | if_modifier = OMP_TARGET_UPDATE; |
38655 | else if (strcmp (s1: "enter" , s2: p) == 0) |
38656 | if_modifier = OMP_TARGET_ENTER_DATA; |
38657 | else if (strcmp (s1: "exit" , s2: p) == 0) |
38658 | if_modifier = OMP_TARGET_EXIT_DATA; |
38659 | if (if_modifier != OMP_TARGET) |
38660 | n = 3; |
38661 | else |
38662 | { |
38663 | location_t loc |
38664 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->location; |
38665 | error_at (loc, "expected %<data%>, %<update%>, %<enter%> " |
38666 | "or %<exit%>" ); |
38667 | if_modifier = ERROR_MARK; |
38668 | } |
38669 | if (if_modifier == OMP_TARGET_ENTER_DATA |
38670 | || if_modifier == OMP_TARGET_EXIT_DATA) |
38671 | { |
38672 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NAME)) |
38673 | { |
38674 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->u.value; |
38675 | p = IDENTIFIER_POINTER (id); |
38676 | if (strcmp (s1: "data" , s2: p) == 0) |
38677 | n = 4; |
38678 | } |
38679 | if (n != 4) |
38680 | { |
38681 | location_t loc |
38682 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->location; |
38683 | error_at (loc, "expected %<data%>" ); |
38684 | if_modifier = ERROR_MARK; |
38685 | } |
38686 | } |
38687 | } |
38688 | } |
38689 | if (if_modifier != ERROR_MARK) |
38690 | { |
38691 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_COLON)) |
38692 | { |
38693 | while (n-- > 0) |
38694 | cp_lexer_consume_token (lexer: parser->lexer); |
38695 | } |
38696 | else |
38697 | { |
38698 | if (n > 2) |
38699 | { |
38700 | location_t loc |
38701 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n)->location; |
38702 | error_at (loc, "expected %<:%>" ); |
38703 | } |
38704 | if_modifier = ERROR_MARK; |
38705 | } |
38706 | } |
38707 | } |
38708 | |
38709 | t = cp_parser_assignment_expression (parser); |
38710 | |
38711 | if (t == error_mark_node |
38712 | || !parens.require_close (parser)) |
38713 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38714 | /*or_comma=*/false, |
38715 | /*consume_paren=*/true); |
38716 | |
38717 | for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) |
38718 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) |
38719 | { |
38720 | if (if_modifier != ERROR_MARK |
38721 | && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) |
38722 | { |
38723 | const char *p = NULL; |
38724 | switch (if_modifier) |
38725 | { |
38726 | case VOID_CST: p = "cancel" ; break; |
38727 | case OMP_PARALLEL: p = "parallel" ; break; |
38728 | case OMP_SIMD: p = "simd" ; break; |
38729 | case OMP_TASK: p = "task" ; break; |
38730 | case OMP_TASKLOOP: p = "taskloop" ; break; |
38731 | case OMP_TARGET_DATA: p = "target data" ; break; |
38732 | case OMP_TARGET: p = "target" ; break; |
38733 | case OMP_TARGET_UPDATE: p = "target update" ; break; |
38734 | case OMP_TARGET_ENTER_DATA: p = "target enter data" ; break; |
38735 | case OMP_TARGET_EXIT_DATA: p = "target exit data" ; break; |
38736 | default: gcc_unreachable (); |
38737 | } |
38738 | error_at (location, "too many %<if%> clauses with %qs modifier" , |
38739 | p); |
38740 | return list; |
38741 | } |
38742 | else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier) |
38743 | { |
38744 | if (!is_omp) |
38745 | error_at (location, "too many %<if%> clauses" ); |
38746 | else |
38747 | error_at (location, "too many %<if%> clauses without modifier" ); |
38748 | return list; |
38749 | } |
38750 | else if (if_modifier == ERROR_MARK |
38751 | || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK) |
38752 | { |
38753 | error_at (location, "if any %<if%> clause has modifier, then all " |
38754 | "%<if%> clauses have to use modifier" ); |
38755 | return list; |
38756 | } |
38757 | } |
38758 | |
38759 | c = build_omp_clause (location, OMP_CLAUSE_IF); |
38760 | OMP_CLAUSE_IF_MODIFIER (c) = if_modifier; |
38761 | OMP_CLAUSE_IF_EXPR (c) = t; |
38762 | OMP_CLAUSE_CHAIN (c) = list; |
38763 | |
38764 | return c; |
38765 | } |
38766 | |
38767 | /* OpenMP 3.1: |
38768 | mergeable */ |
38769 | |
38770 | static tree |
38771 | cp_parser_omp_clause_mergeable (cp_parser * /*parser*/, |
38772 | tree list, location_t location) |
38773 | { |
38774 | tree c; |
38775 | |
38776 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable" , |
38777 | location); |
38778 | |
38779 | c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE); |
38780 | OMP_CLAUSE_CHAIN (c) = list; |
38781 | return c; |
38782 | } |
38783 | |
38784 | /* OpenMP 2.5: |
38785 | nowait */ |
38786 | |
38787 | static tree |
38788 | cp_parser_omp_clause_nowait (cp_parser * /*parser*/, |
38789 | tree list, location_t location) |
38790 | { |
38791 | tree c; |
38792 | |
38793 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait" , location); |
38794 | |
38795 | c = build_omp_clause (location, OMP_CLAUSE_NOWAIT); |
38796 | OMP_CLAUSE_CHAIN (c) = list; |
38797 | return c; |
38798 | } |
38799 | |
38800 | /* OpenMP 2.5: |
38801 | num_threads ( expression ) */ |
38802 | |
38803 | static tree |
38804 | cp_parser_omp_clause_num_threads (cp_parser *parser, tree list, |
38805 | location_t location) |
38806 | { |
38807 | tree t, c; |
38808 | |
38809 | matching_parens parens; |
38810 | if (!parens.require_open (parser)) |
38811 | return list; |
38812 | |
38813 | t = cp_parser_assignment_expression (parser); |
38814 | |
38815 | if (t == error_mark_node |
38816 | || !parens.require_close (parser)) |
38817 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38818 | /*or_comma=*/false, |
38819 | /*consume_paren=*/true); |
38820 | |
38821 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, |
38822 | name: "num_threads" , location); |
38823 | |
38824 | c = build_omp_clause (location, OMP_CLAUSE_NUM_THREADS); |
38825 | OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; |
38826 | OMP_CLAUSE_CHAIN (c) = list; |
38827 | |
38828 | return c; |
38829 | } |
38830 | |
38831 | /* OpenMP 4.5: |
38832 | num_tasks ( expression ) |
38833 | |
38834 | OpenMP 5.1: |
38835 | num_tasks ( strict : expression ) */ |
38836 | |
38837 | static tree |
38838 | cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list, |
38839 | location_t location) |
38840 | { |
38841 | tree t, c; |
38842 | |
38843 | matching_parens parens; |
38844 | if (!parens.require_open (parser)) |
38845 | return list; |
38846 | |
38847 | bool strict = false; |
38848 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
38849 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
38850 | { |
38851 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
38852 | if (!strcmp (IDENTIFIER_POINTER (id), s2: "strict" )) |
38853 | { |
38854 | strict = true; |
38855 | cp_lexer_consume_token (lexer: parser->lexer); |
38856 | cp_lexer_consume_token (lexer: parser->lexer); |
38857 | } |
38858 | } |
38859 | |
38860 | t = cp_parser_assignment_expression (parser); |
38861 | |
38862 | if (t == error_mark_node |
38863 | || !parens.require_close (parser)) |
38864 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38865 | /*or_comma=*/false, |
38866 | /*consume_paren=*/true); |
38867 | |
38868 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, |
38869 | name: "num_tasks" , location); |
38870 | |
38871 | c = build_omp_clause (location, OMP_CLAUSE_NUM_TASKS); |
38872 | OMP_CLAUSE_NUM_TASKS_EXPR (c) = t; |
38873 | OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict; |
38874 | OMP_CLAUSE_CHAIN (c) = list; |
38875 | |
38876 | return c; |
38877 | } |
38878 | |
38879 | /* OpenMP 4.5: |
38880 | grainsize ( expression ) |
38881 | |
38882 | OpenMP 5.1: |
38883 | grainsize ( strict : expression ) */ |
38884 | |
38885 | static tree |
38886 | cp_parser_omp_clause_grainsize (cp_parser *parser, tree list, |
38887 | location_t location) |
38888 | { |
38889 | tree t, c; |
38890 | |
38891 | matching_parens parens; |
38892 | if (!parens.require_open (parser)) |
38893 | return list; |
38894 | |
38895 | bool strict = false; |
38896 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
38897 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
38898 | { |
38899 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
38900 | if (!strcmp (IDENTIFIER_POINTER (id), s2: "strict" )) |
38901 | { |
38902 | strict = true; |
38903 | cp_lexer_consume_token (lexer: parser->lexer); |
38904 | cp_lexer_consume_token (lexer: parser->lexer); |
38905 | } |
38906 | } |
38907 | |
38908 | t = cp_parser_assignment_expression (parser); |
38909 | |
38910 | if (t == error_mark_node |
38911 | || !parens.require_close (parser)) |
38912 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38913 | /*or_comma=*/false, |
38914 | /*consume_paren=*/true); |
38915 | |
38916 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, |
38917 | name: "grainsize" , location); |
38918 | |
38919 | c = build_omp_clause (location, OMP_CLAUSE_GRAINSIZE); |
38920 | OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; |
38921 | OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict; |
38922 | OMP_CLAUSE_CHAIN (c) = list; |
38923 | |
38924 | return c; |
38925 | } |
38926 | |
38927 | /* OpenMP 4.5: |
38928 | priority ( expression ) */ |
38929 | |
38930 | static tree |
38931 | cp_parser_omp_clause_priority (cp_parser *parser, tree list, |
38932 | location_t location) |
38933 | { |
38934 | tree t, c; |
38935 | |
38936 | matching_parens parens; |
38937 | if (!parens.require_open (parser)) |
38938 | return list; |
38939 | |
38940 | t = cp_parser_assignment_expression (parser); |
38941 | |
38942 | if (t == error_mark_node |
38943 | || !parens.require_close (parser)) |
38944 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38945 | /*or_comma=*/false, |
38946 | /*consume_paren=*/true); |
38947 | |
38948 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, |
38949 | name: "priority" , location); |
38950 | |
38951 | c = build_omp_clause (location, OMP_CLAUSE_PRIORITY); |
38952 | OMP_CLAUSE_PRIORITY_EXPR (c) = t; |
38953 | OMP_CLAUSE_CHAIN (c) = list; |
38954 | |
38955 | return c; |
38956 | } |
38957 | |
38958 | /* OpenMP 4.5: |
38959 | hint ( expression ) */ |
38960 | |
38961 | static tree |
38962 | cp_parser_omp_clause_hint (cp_parser *parser, tree list, location_t location) |
38963 | { |
38964 | tree t, c; |
38965 | |
38966 | matching_parens parens; |
38967 | if (!parens.require_open (parser)) |
38968 | return list; |
38969 | |
38970 | t = cp_parser_assignment_expression (parser); |
38971 | |
38972 | if (t != error_mark_node) |
38973 | { |
38974 | t = fold_non_dependent_expr (t); |
38975 | if (!value_dependent_expression_p (t) |
38976 | && (!INTEGRAL_TYPE_P (TREE_TYPE (t)) |
38977 | || !tree_fits_shwi_p (t) |
38978 | || tree_int_cst_sgn (t) == -1)) |
38979 | error_at (location, "expected constant integer expression with " |
38980 | "valid sync-hint value" ); |
38981 | } |
38982 | if (t == error_mark_node |
38983 | || !parens.require_close (parser)) |
38984 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
38985 | /*or_comma=*/false, |
38986 | /*consume_paren=*/true); |
38987 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint" , location); |
38988 | |
38989 | c = build_omp_clause (location, OMP_CLAUSE_HINT); |
38990 | OMP_CLAUSE_HINT_EXPR (c) = t; |
38991 | OMP_CLAUSE_CHAIN (c) = list; |
38992 | |
38993 | return c; |
38994 | } |
38995 | |
38996 | /* OpenMP 5.1: |
38997 | filter ( integer-expression ) */ |
38998 | |
38999 | static tree |
39000 | cp_parser_omp_clause_filter (cp_parser *parser, tree list, location_t location) |
39001 | { |
39002 | tree t, c; |
39003 | |
39004 | matching_parens parens; |
39005 | if (!parens.require_open (parser)) |
39006 | return list; |
39007 | |
39008 | t = cp_parser_assignment_expression (parser); |
39009 | |
39010 | if (t == error_mark_node |
39011 | || !parens.require_close (parser)) |
39012 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39013 | /*or_comma=*/false, |
39014 | /*consume_paren=*/true); |
39015 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter" , location); |
39016 | |
39017 | c = build_omp_clause (location, OMP_CLAUSE_FILTER); |
39018 | OMP_CLAUSE_FILTER_EXPR (c) = t; |
39019 | OMP_CLAUSE_CHAIN (c) = list; |
39020 | |
39021 | return c; |
39022 | } |
39023 | |
39024 | /* OpenMP 4.5: |
39025 | defaultmap ( tofrom : scalar ) |
39026 | |
39027 | OpenMP 5.0: |
39028 | defaultmap ( implicit-behavior [ : variable-category ] ) */ |
39029 | |
39030 | static tree |
39031 | cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list, |
39032 | location_t location) |
39033 | { |
39034 | tree c, id; |
39035 | const char *p; |
39036 | enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; |
39037 | enum omp_clause_defaultmap_kind category |
39038 | = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED; |
39039 | |
39040 | matching_parens parens; |
39041 | if (!parens.require_open (parser)) |
39042 | return list; |
39043 | |
39044 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT)) |
39045 | p = "default" ; |
39046 | else if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39047 | { |
39048 | invalid_behavior: |
39049 | cp_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, " |
39050 | "%<tofrom%>, %<firstprivate%>, %<none%> " |
39051 | "or %<default%>" ); |
39052 | goto out_err; |
39053 | } |
39054 | else |
39055 | { |
39056 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39057 | p = IDENTIFIER_POINTER (id); |
39058 | } |
39059 | |
39060 | switch (p[0]) |
39061 | { |
39062 | case 'a': |
39063 | if (strcmp (s1: "alloc" , s2: p) == 0) |
39064 | behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC; |
39065 | else |
39066 | goto invalid_behavior; |
39067 | break; |
39068 | |
39069 | case 'd': |
39070 | if (strcmp (s1: "default" , s2: p) == 0) |
39071 | behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; |
39072 | else |
39073 | goto invalid_behavior; |
39074 | break; |
39075 | |
39076 | case 'f': |
39077 | if (strcmp (s1: "firstprivate" , s2: p) == 0) |
39078 | behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE; |
39079 | else if (strcmp (s1: "from" , s2: p) == 0) |
39080 | behavior = OMP_CLAUSE_DEFAULTMAP_FROM; |
39081 | else |
39082 | goto invalid_behavior; |
39083 | break; |
39084 | |
39085 | case 'n': |
39086 | if (strcmp (s1: "none" , s2: p) == 0) |
39087 | behavior = OMP_CLAUSE_DEFAULTMAP_NONE; |
39088 | else |
39089 | goto invalid_behavior; |
39090 | break; |
39091 | |
39092 | case 'p': |
39093 | if (strcmp (s1: "present" , s2: p) == 0) |
39094 | behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT; |
39095 | else |
39096 | goto invalid_behavior; |
39097 | break; |
39098 | |
39099 | case 't': |
39100 | if (strcmp (s1: "tofrom" , s2: p) == 0) |
39101 | behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM; |
39102 | else if (strcmp (s1: "to" , s2: p) == 0) |
39103 | behavior = OMP_CLAUSE_DEFAULTMAP_TO; |
39104 | else |
39105 | goto invalid_behavior; |
39106 | break; |
39107 | |
39108 | default: |
39109 | goto invalid_behavior; |
39110 | } |
39111 | cp_lexer_consume_token (lexer: parser->lexer); |
39112 | |
39113 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
39114 | { |
39115 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
39116 | goto out_err; |
39117 | |
39118 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39119 | { |
39120 | invalid_category: |
39121 | cp_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, " |
39122 | "%<all%>" ); |
39123 | goto out_err; |
39124 | } |
39125 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39126 | p = IDENTIFIER_POINTER (id); |
39127 | |
39128 | switch (p[0]) |
39129 | { |
39130 | case 'a': |
39131 | if (strcmp (s1: "aggregate" , s2: p) == 0) |
39132 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE; |
39133 | else if (strcmp (s1: "all" , s2: p) == 0) |
39134 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL; |
39135 | else |
39136 | goto invalid_category; |
39137 | break; |
39138 | |
39139 | case 'p': |
39140 | if (strcmp (s1: "pointer" , s2: p) == 0) |
39141 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER; |
39142 | else |
39143 | goto invalid_category; |
39144 | break; |
39145 | |
39146 | case 's': |
39147 | if (strcmp (s1: "scalar" , s2: p) == 0) |
39148 | category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR; |
39149 | else |
39150 | goto invalid_category; |
39151 | break; |
39152 | |
39153 | default: |
39154 | goto invalid_category; |
39155 | } |
39156 | |
39157 | cp_lexer_consume_token (lexer: parser->lexer); |
39158 | } |
39159 | if (!parens.require_close (parser)) |
39160 | goto out_err; |
39161 | |
39162 | for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) |
39163 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP |
39164 | && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED |
39165 | || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL |
39166 | || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category |
39167 | || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39168 | == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED) |
39169 | || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39170 | == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL))) |
39171 | { |
39172 | enum omp_clause_defaultmap_kind cat = category; |
39173 | location_t loc = OMP_CLAUSE_LOCATION (c); |
39174 | if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED |
39175 | || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL |
39176 | && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) |
39177 | != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED))) |
39178 | cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c); |
39179 | p = NULL; |
39180 | switch (cat) |
39181 | { |
39182 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED: |
39183 | p = NULL; |
39184 | break; |
39185 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL: |
39186 | p = "all" ; |
39187 | break; |
39188 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE: |
39189 | p = "aggregate" ; |
39190 | break; |
39191 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER: |
39192 | p = "pointer" ; |
39193 | break; |
39194 | case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR: |
39195 | p = "scalar" ; |
39196 | break; |
39197 | default: |
39198 | gcc_unreachable (); |
39199 | } |
39200 | if (p) |
39201 | error_at (loc, "too many %<defaultmap%> clauses with %qs category" , |
39202 | p); |
39203 | else |
39204 | error_at (loc, "too many %<defaultmap%> clauses with unspecified " |
39205 | "category" ); |
39206 | break; |
39207 | } |
39208 | |
39209 | c = build_omp_clause (location, OMP_CLAUSE_DEFAULTMAP); |
39210 | OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category); |
39211 | OMP_CLAUSE_CHAIN (c) = list; |
39212 | return c; |
39213 | |
39214 | out_err: |
39215 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39216 | /*or_comma=*/false, |
39217 | /*consume_paren=*/true); |
39218 | return list; |
39219 | } |
39220 | |
39221 | /* OpenMP 5.0: |
39222 | order ( concurrent ) |
39223 | |
39224 | OpenMP 5.1: |
39225 | order ( order-modifier : concurrent ) |
39226 | |
39227 | order-modifier: |
39228 | reproducible |
39229 | unconstrained */ |
39230 | |
39231 | static tree |
39232 | cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location) |
39233 | { |
39234 | tree c, id; |
39235 | const char *p; |
39236 | bool unconstrained = false; |
39237 | bool reproducible = false; |
39238 | |
39239 | matching_parens parens; |
39240 | if (!parens.require_open (parser)) |
39241 | return list; |
39242 | |
39243 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39244 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
39245 | { |
39246 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39247 | p = IDENTIFIER_POINTER (id); |
39248 | if (strcmp (s1: p, s2: "unconstrained" ) == 0) |
39249 | unconstrained = true; |
39250 | else if (strcmp (s1: p, s2: "reproducible" ) == 0) |
39251 | reproducible = true; |
39252 | else |
39253 | { |
39254 | cp_parser_error (parser, gmsgid: "expected %<reproducible%> or " |
39255 | "%<unconstrained%>" ); |
39256 | goto out_err; |
39257 | } |
39258 | cp_lexer_consume_token (lexer: parser->lexer); |
39259 | cp_lexer_consume_token (lexer: parser->lexer); |
39260 | } |
39261 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39262 | { |
39263 | cp_parser_error (parser, gmsgid: "expected %<concurrent%>" ); |
39264 | goto out_err; |
39265 | } |
39266 | else |
39267 | { |
39268 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39269 | p = IDENTIFIER_POINTER (id); |
39270 | } |
39271 | if (strcmp (s1: p, s2: "concurrent" ) != 0) |
39272 | { |
39273 | cp_parser_error (parser, gmsgid: "expected %<concurrent%>" ); |
39274 | goto out_err; |
39275 | } |
39276 | cp_lexer_consume_token (lexer: parser->lexer); |
39277 | if (!parens.require_close (parser)) |
39278 | goto out_err; |
39279 | |
39280 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order" , location); |
39281 | c = build_omp_clause (location, OMP_CLAUSE_ORDER); |
39282 | OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained; |
39283 | OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible; |
39284 | OMP_CLAUSE_CHAIN (c) = list; |
39285 | return c; |
39286 | |
39287 | out_err: |
39288 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39289 | /*or_comma=*/false, |
39290 | /*consume_paren=*/true); |
39291 | return list; |
39292 | } |
39293 | |
39294 | /* OpenMP 5.0: |
39295 | bind ( teams | parallel | thread ) */ |
39296 | |
39297 | static tree |
39298 | cp_parser_omp_clause_bind (cp_parser *parser, tree list, |
39299 | location_t location) |
39300 | { |
39301 | tree c; |
39302 | const char *p; |
39303 | enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; |
39304 | |
39305 | matching_parens parens; |
39306 | if (!parens.require_open (parser)) |
39307 | return list; |
39308 | |
39309 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39310 | { |
39311 | invalid: |
39312 | cp_parser_error (parser, |
39313 | gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>" ); |
39314 | goto out_err; |
39315 | } |
39316 | else |
39317 | { |
39318 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39319 | p = IDENTIFIER_POINTER (id); |
39320 | } |
39321 | if (strcmp (s1: p, s2: "teams" ) == 0) |
39322 | kind = OMP_CLAUSE_BIND_TEAMS; |
39323 | else if (strcmp (s1: p, s2: "parallel" ) == 0) |
39324 | kind = OMP_CLAUSE_BIND_PARALLEL; |
39325 | else if (strcmp (s1: p, s2: "thread" ) != 0) |
39326 | goto invalid; |
39327 | cp_lexer_consume_token (lexer: parser->lexer); |
39328 | if (!parens.require_close (parser)) |
39329 | goto out_err; |
39330 | |
39331 | /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind", location); */ |
39332 | c = build_omp_clause (location, OMP_CLAUSE_BIND); |
39333 | OMP_CLAUSE_BIND_KIND (c) = kind; |
39334 | OMP_CLAUSE_CHAIN (c) = list; |
39335 | return c; |
39336 | |
39337 | out_err: |
39338 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39339 | /*or_comma=*/false, |
39340 | /*consume_paren=*/true); |
39341 | return list; |
39342 | } |
39343 | |
39344 | /* OpenMP 2.5: |
39345 | ordered |
39346 | |
39347 | OpenMP 4.5: |
39348 | ordered ( constant-expression ) */ |
39349 | |
39350 | static tree |
39351 | cp_parser_omp_clause_ordered (cp_parser *parser, |
39352 | tree list, location_t location) |
39353 | { |
39354 | tree c, num = NULL_TREE; |
39355 | HOST_WIDE_INT n; |
39356 | |
39357 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, |
39358 | name: "ordered" , location); |
39359 | |
39360 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
39361 | { |
39362 | matching_parens parens; |
39363 | parens.consume_open (parser); |
39364 | |
39365 | num = cp_parser_constant_expression (parser); |
39366 | |
39367 | if (!parens.require_close (parser)) |
39368 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39369 | /*or_comma=*/false, |
39370 | /*consume_paren=*/true); |
39371 | |
39372 | if (num == error_mark_node) |
39373 | return list; |
39374 | num = fold_non_dependent_expr (num); |
39375 | if (!tree_fits_shwi_p (num) |
39376 | || !INTEGRAL_TYPE_P (TREE_TYPE (num)) |
39377 | || (n = tree_to_shwi (num)) <= 0 |
39378 | || (int) n != n) |
39379 | { |
39380 | error_at (location, |
39381 | "ordered argument needs positive constant integer " |
39382 | "expression" ); |
39383 | return list; |
39384 | } |
39385 | } |
39386 | |
39387 | c = build_omp_clause (location, OMP_CLAUSE_ORDERED); |
39388 | OMP_CLAUSE_ORDERED_EXPR (c) = num; |
39389 | OMP_CLAUSE_CHAIN (c) = list; |
39390 | return c; |
39391 | } |
39392 | |
39393 | /* OpenMP 2.5: |
39394 | reduction ( reduction-operator : variable-list ) |
39395 | |
39396 | reduction-operator: |
39397 | One of: + * - & ^ | && || |
39398 | |
39399 | OpenMP 3.1: |
39400 | |
39401 | reduction-operator: |
39402 | One of: + * - & ^ | && || min max |
39403 | |
39404 | OpenMP 4.0: |
39405 | |
39406 | reduction-operator: |
39407 | One of: + * - & ^ | && || |
39408 | id-expression |
39409 | |
39410 | OpenMP 5.0: |
39411 | reduction ( reduction-modifier, reduction-operator : variable-list ) |
39412 | in_reduction ( reduction-operator : variable-list ) |
39413 | task_reduction ( reduction-operator : variable-list ) */ |
39414 | |
39415 | static tree |
39416 | cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, |
39417 | bool is_omp, tree list) |
39418 | { |
39419 | enum tree_code code = ERROR_MARK; |
39420 | tree nlist, c, id = NULL_TREE; |
39421 | bool task = false; |
39422 | bool inscan = false; |
39423 | |
39424 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
39425 | return list; |
39426 | |
39427 | if (kind == OMP_CLAUSE_REDUCTION && is_omp) |
39428 | { |
39429 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DEFAULT) |
39430 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA)) |
39431 | { |
39432 | cp_lexer_consume_token (lexer: parser->lexer); |
39433 | cp_lexer_consume_token (lexer: parser->lexer); |
39434 | } |
39435 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39436 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COMMA)) |
39437 | { |
39438 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39439 | const char *p = IDENTIFIER_POINTER (id); |
39440 | if (strcmp (s1: p, s2: "task" ) == 0) |
39441 | task = true; |
39442 | else if (strcmp (s1: p, s2: "inscan" ) == 0) |
39443 | inscan = true; |
39444 | if (task || inscan) |
39445 | { |
39446 | cp_lexer_consume_token (lexer: parser->lexer); |
39447 | cp_lexer_consume_token (lexer: parser->lexer); |
39448 | } |
39449 | } |
39450 | } |
39451 | |
39452 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
39453 | { |
39454 | case CPP_PLUS: code = PLUS_EXPR; break; |
39455 | case CPP_MULT: code = MULT_EXPR; break; |
39456 | case CPP_MINUS: code = MINUS_EXPR; break; |
39457 | case CPP_AND: code = BIT_AND_EXPR; break; |
39458 | case CPP_XOR: code = BIT_XOR_EXPR; break; |
39459 | case CPP_OR: code = BIT_IOR_EXPR; break; |
39460 | case CPP_AND_AND: code = TRUTH_ANDIF_EXPR; break; |
39461 | case CPP_OR_OR: code = TRUTH_ORIF_EXPR; break; |
39462 | default: break; |
39463 | } |
39464 | |
39465 | if (code != ERROR_MARK) |
39466 | cp_lexer_consume_token (lexer: parser->lexer); |
39467 | else |
39468 | { |
39469 | bool saved_colon_corrects_to_scope_p; |
39470 | saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
39471 | parser->colon_corrects_to_scope_p = false; |
39472 | id = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
39473 | /*check_dependency_p=*/true, |
39474 | /*template_p=*/NULL, |
39475 | /*declarator_p=*/false, |
39476 | /*optional_p=*/false); |
39477 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
39478 | if (identifier_p (t: id)) |
39479 | { |
39480 | const char *p = IDENTIFIER_POINTER (id); |
39481 | |
39482 | if (strcmp (s1: p, s2: "min" ) == 0) |
39483 | code = MIN_EXPR; |
39484 | else if (strcmp (s1: p, s2: "max" ) == 0) |
39485 | code = MAX_EXPR; |
39486 | else if (id == ovl_op_identifier (isass: false, code: PLUS_EXPR)) |
39487 | code = PLUS_EXPR; |
39488 | else if (id == ovl_op_identifier (isass: false, code: MULT_EXPR)) |
39489 | code = MULT_EXPR; |
39490 | else if (id == ovl_op_identifier (isass: false, code: MINUS_EXPR)) |
39491 | code = MINUS_EXPR; |
39492 | else if (id == ovl_op_identifier (isass: false, code: BIT_AND_EXPR)) |
39493 | code = BIT_AND_EXPR; |
39494 | else if (id == ovl_op_identifier (isass: false, code: BIT_IOR_EXPR)) |
39495 | code = BIT_IOR_EXPR; |
39496 | else if (id == ovl_op_identifier (isass: false, code: BIT_XOR_EXPR)) |
39497 | code = BIT_XOR_EXPR; |
39498 | else if (id == ovl_op_identifier (isass: false, code: TRUTH_ANDIF_EXPR)) |
39499 | code = TRUTH_ANDIF_EXPR; |
39500 | else if (id == ovl_op_identifier (isass: false, code: TRUTH_ORIF_EXPR)) |
39501 | code = TRUTH_ORIF_EXPR; |
39502 | id = omp_reduction_id (code, id, NULL_TREE); |
39503 | tree scope = parser->scope; |
39504 | if (scope) |
39505 | id = build_qualified_name (NULL_TREE, scope, id, false); |
39506 | parser->scope = NULL_TREE; |
39507 | parser->qualifying_scope = NULL_TREE; |
39508 | parser->object_scope = NULL_TREE; |
39509 | } |
39510 | else |
39511 | { |
39512 | error ("invalid reduction-identifier" ); |
39513 | resync_fail: |
39514 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39515 | /*or_comma=*/false, |
39516 | /*consume_paren=*/true); |
39517 | return list; |
39518 | } |
39519 | } |
39520 | |
39521 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
39522 | goto resync_fail; |
39523 | |
39524 | nlist = cp_parser_omp_var_list_no_open (parser, kind, list, |
39525 | NULL); |
39526 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
39527 | { |
39528 | OMP_CLAUSE_REDUCTION_CODE (c) = code; |
39529 | if (task) |
39530 | OMP_CLAUSE_REDUCTION_TASK (c) = 1; |
39531 | else if (inscan) |
39532 | OMP_CLAUSE_REDUCTION_INSCAN (c) = 1; |
39533 | OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id; |
39534 | } |
39535 | |
39536 | return nlist; |
39537 | } |
39538 | |
39539 | /* OpenMP 2.5: |
39540 | schedule ( schedule-kind ) |
39541 | schedule ( schedule-kind , expression ) |
39542 | |
39543 | schedule-kind: |
39544 | static | dynamic | guided | runtime | auto |
39545 | |
39546 | OpenMP 4.5: |
39547 | schedule ( schedule-modifier : schedule-kind ) |
39548 | schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression ) |
39549 | |
39550 | schedule-modifier: |
39551 | simd |
39552 | monotonic |
39553 | nonmonotonic */ |
39554 | |
39555 | static tree |
39556 | cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location) |
39557 | { |
39558 | tree c, t; |
39559 | int modifiers = 0, nmodifiers = 0; |
39560 | |
39561 | matching_parens parens; |
39562 | if (!parens.require_open (parser)) |
39563 | return list; |
39564 | |
39565 | c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE); |
39566 | |
39567 | location_t comma = UNKNOWN_LOCATION; |
39568 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39569 | { |
39570 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39571 | const char *p = IDENTIFIER_POINTER (id); |
39572 | if (strcmp (s1: "simd" , s2: p) == 0) |
39573 | OMP_CLAUSE_SCHEDULE_SIMD (c) = 1; |
39574 | else if (strcmp (s1: "monotonic" , s2: p) == 0) |
39575 | modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC; |
39576 | else if (strcmp (s1: "nonmonotonic" , s2: p) == 0) |
39577 | modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC; |
39578 | else |
39579 | break; |
39580 | comma = UNKNOWN_LOCATION; |
39581 | cp_lexer_consume_token (lexer: parser->lexer); |
39582 | if (nmodifiers++ == 0 |
39583 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
39584 | { |
39585 | comma = cp_lexer_peek_token (lexer: parser->lexer)->location; |
39586 | cp_lexer_consume_token (lexer: parser->lexer); |
39587 | } |
39588 | else |
39589 | { |
39590 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
39591 | break; |
39592 | } |
39593 | } |
39594 | if (comma != UNKNOWN_LOCATION) |
39595 | error_at (comma, "expected %<:%>" ); |
39596 | |
39597 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
39598 | { |
39599 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39600 | const char *p = IDENTIFIER_POINTER (id); |
39601 | |
39602 | switch (p[0]) |
39603 | { |
39604 | case 'd': |
39605 | if (strcmp (s1: "dynamic" , s2: p) != 0) |
39606 | goto invalid_kind; |
39607 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; |
39608 | break; |
39609 | |
39610 | case 'g': |
39611 | if (strcmp (s1: "guided" , s2: p) != 0) |
39612 | goto invalid_kind; |
39613 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; |
39614 | break; |
39615 | |
39616 | case 'r': |
39617 | if (strcmp (s1: "runtime" , s2: p) != 0) |
39618 | goto invalid_kind; |
39619 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; |
39620 | break; |
39621 | |
39622 | default: |
39623 | goto invalid_kind; |
39624 | } |
39625 | } |
39626 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC)) |
39627 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; |
39628 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_AUTO)) |
39629 | OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO; |
39630 | else |
39631 | goto invalid_kind; |
39632 | cp_lexer_consume_token (lexer: parser->lexer); |
39633 | |
39634 | if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC |
39635 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) |
39636 | == (OMP_CLAUSE_SCHEDULE_MONOTONIC |
39637 | | OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) |
39638 | { |
39639 | error_at (location, "both %<monotonic%> and %<nonmonotonic%> modifiers " |
39640 | "specified" ); |
39641 | modifiers = 0; |
39642 | } |
39643 | |
39644 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
39645 | { |
39646 | cp_token *token; |
39647 | cp_lexer_consume_token (lexer: parser->lexer); |
39648 | |
39649 | token = cp_lexer_peek_token (lexer: parser->lexer); |
39650 | t = cp_parser_assignment_expression (parser); |
39651 | |
39652 | if (t == error_mark_node) |
39653 | goto resync_fail; |
39654 | else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) |
39655 | error_at (token->location, "schedule %<runtime%> does not take " |
39656 | "a %<chunk_size%> parameter" ); |
39657 | else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) |
39658 | error_at (token->location, "schedule %<auto%> does not take " |
39659 | "a %<chunk_size%> parameter" ); |
39660 | else |
39661 | OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; |
39662 | |
39663 | if (!parens.require_close (parser)) |
39664 | goto resync_fail; |
39665 | } |
39666 | else if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
39667 | goto resync_fail; |
39668 | |
39669 | OMP_CLAUSE_SCHEDULE_KIND (c) |
39670 | = (enum omp_clause_schedule_kind) |
39671 | (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers); |
39672 | |
39673 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule" , location); |
39674 | OMP_CLAUSE_CHAIN (c) = list; |
39675 | return c; |
39676 | |
39677 | invalid_kind: |
39678 | cp_parser_error (parser, gmsgid: "invalid schedule kind" ); |
39679 | resync_fail: |
39680 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39681 | /*or_comma=*/false, |
39682 | /*consume_paren=*/true); |
39683 | return list; |
39684 | } |
39685 | |
39686 | /* OpenMP 3.0: |
39687 | untied */ |
39688 | |
39689 | static tree |
39690 | cp_parser_omp_clause_untied (cp_parser * /*parser*/, |
39691 | tree list, location_t location) |
39692 | { |
39693 | tree c; |
39694 | |
39695 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied" , location); |
39696 | |
39697 | c = build_omp_clause (location, OMP_CLAUSE_UNTIED); |
39698 | OMP_CLAUSE_CHAIN (c) = list; |
39699 | return c; |
39700 | } |
39701 | |
39702 | /* OpenMP 4.0: |
39703 | inbranch |
39704 | notinbranch */ |
39705 | |
39706 | static tree |
39707 | cp_parser_omp_clause_branch (cp_parser * /*parser*/, enum omp_clause_code code, |
39708 | tree list, location_t location) |
39709 | { |
39710 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location); |
39711 | tree c = build_omp_clause (location, code); |
39712 | OMP_CLAUSE_CHAIN (c) = list; |
39713 | return c; |
39714 | } |
39715 | |
39716 | /* OpenMP 4.0: |
39717 | parallel |
39718 | for |
39719 | sections |
39720 | taskgroup */ |
39721 | |
39722 | static tree |
39723 | cp_parser_omp_clause_cancelkind (cp_parser * /*parser*/, |
39724 | enum omp_clause_code code, |
39725 | tree list, location_t location) |
39726 | { |
39727 | tree c = build_omp_clause (location, code); |
39728 | OMP_CLAUSE_CHAIN (c) = list; |
39729 | return c; |
39730 | } |
39731 | |
39732 | /* OpenMP 4.5: |
39733 | nogroup */ |
39734 | |
39735 | static tree |
39736 | cp_parser_omp_clause_nogroup (cp_parser * /*parser*/, |
39737 | tree list, location_t location) |
39738 | { |
39739 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup" , location); |
39740 | tree c = build_omp_clause (location, OMP_CLAUSE_NOGROUP); |
39741 | OMP_CLAUSE_CHAIN (c) = list; |
39742 | return c; |
39743 | } |
39744 | |
39745 | /* OpenMP 4.5: |
39746 | simd |
39747 | threads */ |
39748 | |
39749 | static tree |
39750 | cp_parser_omp_clause_orderedkind (cp_parser * /*parser*/, |
39751 | enum omp_clause_code code, |
39752 | tree list, location_t location) |
39753 | { |
39754 | check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code], location); |
39755 | tree c = build_omp_clause (location, code); |
39756 | OMP_CLAUSE_CHAIN (c) = list; |
39757 | return c; |
39758 | } |
39759 | |
39760 | /* OpenMP 4.0: |
39761 | num_teams ( expression ) |
39762 | |
39763 | OpenMP 5.1: |
39764 | num_teams ( expression : expression ) */ |
39765 | |
39766 | static tree |
39767 | cp_parser_omp_clause_num_teams (cp_parser *parser, tree list, |
39768 | location_t location) |
39769 | { |
39770 | tree upper, lower = NULL_TREE, c; |
39771 | |
39772 | matching_parens parens; |
39773 | if (!parens.require_open (parser)) |
39774 | return list; |
39775 | |
39776 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
39777 | parser->colon_corrects_to_scope_p = false; |
39778 | upper = cp_parser_assignment_expression (parser); |
39779 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
39780 | |
39781 | if (upper != error_mark_node |
39782 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
39783 | { |
39784 | lower = upper; |
39785 | cp_lexer_consume_token (lexer: parser->lexer); |
39786 | upper = cp_parser_assignment_expression (parser); |
39787 | } |
39788 | |
39789 | if (upper == error_mark_node |
39790 | || !parens.require_close (parser)) |
39791 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39792 | /*or_comma=*/false, |
39793 | /*consume_paren=*/true); |
39794 | |
39795 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, |
39796 | name: "num_teams" , location); |
39797 | |
39798 | c = build_omp_clause (location, OMP_CLAUSE_NUM_TEAMS); |
39799 | OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper; |
39800 | OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower; |
39801 | OMP_CLAUSE_CHAIN (c) = list; |
39802 | |
39803 | return c; |
39804 | } |
39805 | |
39806 | /* OpenMP 4.0: |
39807 | thread_limit ( expression ) */ |
39808 | |
39809 | static tree |
39810 | cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list, |
39811 | location_t location) |
39812 | { |
39813 | tree t, c; |
39814 | |
39815 | matching_parens parens; |
39816 | if (!parens.require_open (parser)) |
39817 | return list; |
39818 | |
39819 | t = cp_parser_assignment_expression (parser); |
39820 | |
39821 | if (t == error_mark_node |
39822 | || !parens.require_close (parser)) |
39823 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39824 | /*or_comma=*/false, |
39825 | /*consume_paren=*/true); |
39826 | |
39827 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT, |
39828 | name: "thread_limit" , location); |
39829 | |
39830 | c = build_omp_clause (location, OMP_CLAUSE_THREAD_LIMIT); |
39831 | OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t; |
39832 | OMP_CLAUSE_CHAIN (c) = list; |
39833 | |
39834 | return c; |
39835 | } |
39836 | |
39837 | /* OpenMP 4.0: |
39838 | aligned ( variable-list ) |
39839 | aligned ( variable-list : constant-expression ) */ |
39840 | |
39841 | static tree |
39842 | cp_parser_omp_clause_aligned (cp_parser *parser, tree list) |
39843 | { |
39844 | tree nlist, c, alignment = NULL_TREE; |
39845 | bool colon; |
39846 | |
39847 | matching_parens parens; |
39848 | if (!parens.require_open (parser)) |
39849 | return list; |
39850 | |
39851 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_ALIGNED, list, |
39852 | colon: &colon); |
39853 | |
39854 | if (colon) |
39855 | { |
39856 | alignment = cp_parser_constant_expression (parser); |
39857 | |
39858 | if (!parens.require_close (parser)) |
39859 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
39860 | /*or_comma=*/false, |
39861 | /*consume_paren=*/true); |
39862 | |
39863 | if (alignment == error_mark_node) |
39864 | alignment = NULL_TREE; |
39865 | } |
39866 | |
39867 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
39868 | OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; |
39869 | |
39870 | return nlist; |
39871 | } |
39872 | |
39873 | /* OpenMP 5.0: |
39874 | allocate ( variable-list ) |
39875 | allocate ( expression : variable-list ) |
39876 | |
39877 | OpenMP 5.1: |
39878 | allocate ( allocator-modifier : variable-list ) |
39879 | allocate ( allocator-modifier , allocator-modifier : variable-list ) |
39880 | |
39881 | allocator-modifier: |
39882 | allocator ( expression ) |
39883 | align ( expression ) */ |
39884 | |
39885 | static tree |
39886 | cp_parser_omp_clause_allocate (cp_parser *parser, tree list) |
39887 | { |
39888 | tree nlist, c, allocator = NULL_TREE, align = NULL_TREE; |
39889 | bool colon, has_modifiers = false; |
39890 | |
39891 | matching_parens parens; |
39892 | if (!parens.require_open (parser)) |
39893 | return list; |
39894 | |
39895 | cp_parser_parse_tentatively (parser); |
39896 | bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
39897 | parser->colon_corrects_to_scope_p = false; |
39898 | for (int mod = 0; mod < 2; mod++) |
39899 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39900 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
39901 | { |
39902 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39903 | const char *p = IDENTIFIER_POINTER (id); |
39904 | if (strcmp (s1: p, s2: "allocator" ) != 0 && strcmp (s1: p, s2: "align" ) != 0) |
39905 | break; |
39906 | cp_lexer_consume_token (lexer: parser->lexer); |
39907 | matching_parens parens2; |
39908 | if (!parens2.require_open (parser)) |
39909 | break; |
39910 | if (strcmp (s1: p, s2: "allocator" ) == 0) |
39911 | { |
39912 | if (allocator != NULL_TREE) |
39913 | break; |
39914 | allocator = cp_parser_assignment_expression (parser); |
39915 | } |
39916 | else |
39917 | { |
39918 | if (align != NULL_TREE) |
39919 | break; |
39920 | align = cp_parser_assignment_expression (parser); |
39921 | } |
39922 | if (!parens2.require_close (parser)) |
39923 | break; |
39924 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
39925 | { |
39926 | has_modifiers = true; |
39927 | break; |
39928 | } |
39929 | if (mod != 0 || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA)) |
39930 | break; |
39931 | cp_lexer_consume_token (lexer: parser->lexer); |
39932 | } |
39933 | else |
39934 | break; |
39935 | if (!has_modifiers) |
39936 | { |
39937 | cp_parser_abort_tentative_parse (parser); |
39938 | align = NULL_TREE; |
39939 | allocator = NULL_TREE; |
39940 | cp_parser_parse_tentatively (parser); |
39941 | allocator = cp_parser_assignment_expression (parser); |
39942 | } |
39943 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
39944 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
39945 | { |
39946 | cp_parser_parse_definitely (parser); |
39947 | cp_lexer_consume_token (lexer: parser->lexer); |
39948 | if (allocator == error_mark_node) |
39949 | allocator = NULL_TREE; |
39950 | if (align == error_mark_node) |
39951 | align = NULL_TREE; |
39952 | } |
39953 | else |
39954 | { |
39955 | cp_parser_abort_tentative_parse (parser); |
39956 | allocator = NULL_TREE; |
39957 | align = NULL_TREE; |
39958 | } |
39959 | |
39960 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_ALLOCATE, list, |
39961 | colon: &colon); |
39962 | |
39963 | if (allocator || align) |
39964 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
39965 | { |
39966 | OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; |
39967 | OMP_CLAUSE_ALLOCATE_ALIGN (c) = align; |
39968 | } |
39969 | |
39970 | return nlist; |
39971 | } |
39972 | |
39973 | /* OpenMP 2.5: |
39974 | lastprivate ( variable-list ) |
39975 | |
39976 | OpenMP 5.0: |
39977 | lastprivate ( [ lastprivate-modifier : ] variable-list ) */ |
39978 | |
39979 | static tree |
39980 | cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list) |
39981 | { |
39982 | bool conditional = false; |
39983 | |
39984 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
39985 | return list; |
39986 | |
39987 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
39988 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
39989 | { |
39990 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
39991 | const char *p = IDENTIFIER_POINTER (id); |
39992 | |
39993 | if (strcmp (s1: "conditional" , s2: p) == 0) |
39994 | { |
39995 | conditional = true; |
39996 | cp_lexer_consume_token (lexer: parser->lexer); |
39997 | cp_lexer_consume_token (lexer: parser->lexer); |
39998 | } |
39999 | } |
40000 | |
40001 | tree nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_LASTPRIVATE, |
40002 | list, NULL); |
40003 | |
40004 | if (conditional) |
40005 | for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40006 | OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1; |
40007 | return nlist; |
40008 | } |
40009 | |
40010 | /* OpenMP 4.0: |
40011 | linear ( variable-list ) |
40012 | linear ( variable-list : expression ) |
40013 | |
40014 | OpenMP 4.5: |
40015 | linear ( modifier ( variable-list ) ) |
40016 | linear ( modifier ( variable-list ) : expression ) |
40017 | |
40018 | modifier: |
40019 | val |
40020 | ref |
40021 | uval |
40022 | |
40023 | OpenMP 5.2: |
40024 | linear ( variable-list : modifiers-list ) |
40025 | |
40026 | modifiers: |
40027 | val |
40028 | ref |
40029 | uval |
40030 | step ( expression ) */ |
40031 | |
40032 | static tree |
40033 | cp_parser_omp_clause_linear (cp_parser *parser, tree list, |
40034 | bool declare_simd) |
40035 | { |
40036 | tree nlist, c, step = integer_one_node; |
40037 | bool colon; |
40038 | enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; |
40039 | bool old_linear_modifier = false; |
40040 | |
40041 | matching_parens parens; |
40042 | if (!parens.require_open (parser)) |
40043 | return list; |
40044 | |
40045 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40046 | { |
40047 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40048 | const char *p = IDENTIFIER_POINTER (id); |
40049 | |
40050 | if (strcmp (s1: "ref" , s2: p) == 0) |
40051 | kind = OMP_CLAUSE_LINEAR_REF; |
40052 | else if (strcmp (s1: "val" , s2: p) == 0) |
40053 | kind = OMP_CLAUSE_LINEAR_VAL; |
40054 | else if (strcmp (s1: "uval" , s2: p) == 0) |
40055 | kind = OMP_CLAUSE_LINEAR_UVAL; |
40056 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
40057 | { |
40058 | cp_lexer_consume_token (lexer: parser->lexer); |
40059 | old_linear_modifier = true; |
40060 | } |
40061 | else |
40062 | kind = OMP_CLAUSE_LINEAR_DEFAULT; |
40063 | } |
40064 | |
40065 | if (kind == OMP_CLAUSE_LINEAR_DEFAULT) |
40066 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_LINEAR, list, |
40067 | colon: &colon); |
40068 | else |
40069 | { |
40070 | nlist = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_LINEAR, list); |
40071 | colon = cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON); |
40072 | if (colon) |
40073 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
40074 | else if (!parens.require_close (parser)) |
40075 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40076 | /*or_comma=*/false, |
40077 | /*consume_paren=*/true); |
40078 | } |
40079 | |
40080 | if (colon) |
40081 | { |
40082 | bool has_modifiers = false; |
40083 | if (kind == OMP_CLAUSE_LINEAR_DEFAULT |
40084 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40085 | { |
40086 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40087 | const char *p = IDENTIFIER_POINTER (id); |
40088 | size_t pos = 0; |
40089 | if (strcmp (s1: "ref" , s2: p) == 0 |
40090 | || strcmp (s1: "val" , s2: p) == 0 |
40091 | || strcmp (s1: "uval" , s2: p) == 0) |
40092 | pos = 2; |
40093 | else if (strcmp (s1: "step" , s2: p) == 0 |
40094 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
40095 | { |
40096 | pos = cp_parser_skip_balanced_tokens (parser, n: 2); |
40097 | if (pos == 2) |
40098 | pos = 0; |
40099 | } |
40100 | if (pos != 0 |
40101 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: pos, type: CPP_COMMA) |
40102 | || cp_lexer_nth_token_is (lexer: parser->lexer, n: pos, |
40103 | type: CPP_CLOSE_PAREN))) |
40104 | has_modifiers = true; |
40105 | } |
40106 | |
40107 | step = NULL_TREE; |
40108 | if (has_modifiers) |
40109 | { |
40110 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40111 | { |
40112 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40113 | const char *p = IDENTIFIER_POINTER (id); |
40114 | enum omp_clause_linear_kind nkind = OMP_CLAUSE_LINEAR_DEFAULT; |
40115 | if (strcmp (s1: "ref" , s2: p) == 0) |
40116 | nkind = OMP_CLAUSE_LINEAR_REF; |
40117 | else if (strcmp (s1: "val" , s2: p) == 0) |
40118 | nkind = OMP_CLAUSE_LINEAR_VAL; |
40119 | else if (strcmp (s1: "uval" , s2: p) == 0) |
40120 | nkind = OMP_CLAUSE_LINEAR_UVAL; |
40121 | if (nkind != OMP_CLAUSE_LINEAR_DEFAULT) |
40122 | { |
40123 | if (kind != OMP_CLAUSE_LINEAR_DEFAULT) |
40124 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
40125 | "multiple linear modifiers" ); |
40126 | kind = nkind; |
40127 | cp_lexer_consume_token (lexer: parser->lexer); |
40128 | } |
40129 | else if (strcmp (s1: "step" , s2: p) == 0) |
40130 | { |
40131 | location_t step_loc |
40132 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40133 | cp_lexer_consume_token (lexer: parser->lexer); |
40134 | matching_parens parens2; |
40135 | if (parens2.require_open (parser)) |
40136 | { |
40137 | if (step) |
40138 | error_at (step_loc, "multiple %<step%> modifiers" ); |
40139 | if (declare_simd |
40140 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40141 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
40142 | type: CPP_CLOSE_PAREN)) |
40143 | { |
40144 | cp_token *token |
40145 | = cp_lexer_peek_token (lexer: parser->lexer); |
40146 | location_t tok_loc = token->location; |
40147 | cp_parser_parse_tentatively (parser); |
40148 | step = cp_parser_id_expression (parser, template_keyword_p: false, check_dependency_p: true, |
40149 | NULL, declarator_p: false, optional_p: false); |
40150 | if (step != error_mark_node) |
40151 | step = cp_parser_lookup_name_simple (parser, name: step, |
40152 | location: tok_loc); |
40153 | if (step == error_mark_node) |
40154 | { |
40155 | step = NULL_TREE; |
40156 | cp_parser_abort_tentative_parse (parser); |
40157 | } |
40158 | else if (!cp_parser_parse_definitely (parser)) |
40159 | step = NULL_TREE; |
40160 | } |
40161 | if (!step) |
40162 | step = cp_parser_assignment_expression (parser); |
40163 | if (!parens2.require_close (parser)) |
40164 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, |
40165 | or_comma: false, consume_paren: true); |
40166 | } |
40167 | else |
40168 | break; |
40169 | } |
40170 | else |
40171 | break; |
40172 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
40173 | { |
40174 | cp_lexer_consume_token (lexer: parser->lexer); |
40175 | continue; |
40176 | } |
40177 | break; |
40178 | } |
40179 | if (!step) |
40180 | step = integer_one_node; |
40181 | } |
40182 | else if (declare_simd |
40183 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40184 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_CLOSE_PAREN)) |
40185 | { |
40186 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
40187 | cp_parser_parse_tentatively (parser); |
40188 | step = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
40189 | /*check_dependency_p=*/true, |
40190 | /*template_p=*/NULL, |
40191 | /*declarator_p=*/false, |
40192 | /*optional_p=*/false); |
40193 | if (step != error_mark_node) |
40194 | step = cp_parser_lookup_name_simple (parser, name: step, location: token->location); |
40195 | if (step == error_mark_node) |
40196 | { |
40197 | step = NULL_TREE; |
40198 | cp_parser_abort_tentative_parse (parser); |
40199 | } |
40200 | else if (!cp_parser_parse_definitely (parser)) |
40201 | step = NULL_TREE; |
40202 | } |
40203 | if (!step) |
40204 | step = cp_parser_assignment_expression (parser); |
40205 | |
40206 | if (!parens.require_close (parser)) |
40207 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40208 | /*or_comma=*/false, |
40209 | /*consume_paren=*/true); |
40210 | |
40211 | if (step == error_mark_node) |
40212 | return list; |
40213 | } |
40214 | |
40215 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40216 | { |
40217 | OMP_CLAUSE_LINEAR_STEP (c) = step; |
40218 | OMP_CLAUSE_LINEAR_KIND (c) = kind; |
40219 | OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier; |
40220 | } |
40221 | |
40222 | return nlist; |
40223 | } |
40224 | |
40225 | /* OpenMP 4.0: |
40226 | safelen ( constant-expression ) */ |
40227 | |
40228 | static tree |
40229 | cp_parser_omp_clause_safelen (cp_parser *parser, tree list, |
40230 | location_t location) |
40231 | { |
40232 | tree t, c; |
40233 | |
40234 | matching_parens parens; |
40235 | if (!parens.require_open (parser)) |
40236 | return list; |
40237 | |
40238 | t = cp_parser_constant_expression (parser); |
40239 | |
40240 | if (t == error_mark_node |
40241 | || !parens.require_close (parser)) |
40242 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40243 | /*or_comma=*/false, |
40244 | /*consume_paren=*/true); |
40245 | |
40246 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen" , location); |
40247 | |
40248 | c = build_omp_clause (location, OMP_CLAUSE_SAFELEN); |
40249 | OMP_CLAUSE_SAFELEN_EXPR (c) = t; |
40250 | OMP_CLAUSE_CHAIN (c) = list; |
40251 | |
40252 | return c; |
40253 | } |
40254 | |
40255 | /* OpenMP 4.0: |
40256 | simdlen ( constant-expression ) */ |
40257 | |
40258 | static tree |
40259 | cp_parser_omp_clause_simdlen (cp_parser *parser, tree list, |
40260 | location_t location) |
40261 | { |
40262 | tree t, c; |
40263 | |
40264 | matching_parens parens; |
40265 | if (!parens.require_open (parser)) |
40266 | return list; |
40267 | |
40268 | t = cp_parser_constant_expression (parser); |
40269 | |
40270 | if (t == error_mark_node |
40271 | || !parens.require_close (parser)) |
40272 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40273 | /*or_comma=*/false, |
40274 | /*consume_paren=*/true); |
40275 | |
40276 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen" , location); |
40277 | |
40278 | c = build_omp_clause (location, OMP_CLAUSE_SIMDLEN); |
40279 | OMP_CLAUSE_SIMDLEN_EXPR (c) = t; |
40280 | OMP_CLAUSE_CHAIN (c) = list; |
40281 | |
40282 | return c; |
40283 | } |
40284 | |
40285 | /* OpenMP 4.5: |
40286 | vec: |
40287 | identifier [+/- integer] |
40288 | vec , identifier [+/- integer] |
40289 | */ |
40290 | |
40291 | static tree |
40292 | cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc, |
40293 | tree list, bool depend_p) |
40294 | { |
40295 | tree vec = NULL; |
40296 | |
40297 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
40298 | { |
40299 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
40300 | return list; |
40301 | } |
40302 | |
40303 | if (!depend_p) |
40304 | { |
40305 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40306 | if (strcmp (IDENTIFIER_POINTER (id), s2: "omp_cur_iteration" ) == 0 |
40307 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_MINUS) |
40308 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 3, type: CPP_NUMBER) |
40309 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 4, type: CPP_CLOSE_PAREN)) |
40310 | { |
40311 | tree val = cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->u.value; |
40312 | if (integer_onep (val)) |
40313 | { |
40314 | cp_lexer_consume_token (lexer: parser->lexer); |
40315 | cp_lexer_consume_token (lexer: parser->lexer); |
40316 | cp_lexer_consume_token (lexer: parser->lexer); |
40317 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); |
40318 | OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; |
40319 | OMP_CLAUSE_CHAIN (u) = list; |
40320 | return u; |
40321 | } |
40322 | } |
40323 | } |
40324 | |
40325 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40326 | { |
40327 | location_t id_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40328 | tree t, identifier = cp_parser_identifier (parser); |
40329 | tree addend = NULL; |
40330 | |
40331 | if (identifier == error_mark_node) |
40332 | t = error_mark_node; |
40333 | else |
40334 | { |
40335 | t = cp_parser_lookup_name_simple |
40336 | (parser, name: identifier, |
40337 | location: cp_lexer_peek_token (lexer: parser->lexer)->location); |
40338 | if (t == error_mark_node) |
40339 | cp_parser_name_lookup_error (parser, name: identifier, decl: t, desired: NLE_NULL, |
40340 | location: id_loc); |
40341 | } |
40342 | |
40343 | bool neg = false; |
40344 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_MINUS)) |
40345 | neg = true; |
40346 | else if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PLUS)) |
40347 | { |
40348 | addend = integer_zero_node; |
40349 | goto add_to_vector; |
40350 | } |
40351 | cp_lexer_consume_token (lexer: parser->lexer); |
40352 | |
40353 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NUMBER)) |
40354 | { |
40355 | cp_parser_error (parser, gmsgid: "expected integer" ); |
40356 | return list; |
40357 | } |
40358 | |
40359 | addend = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40360 | if (TREE_CODE (addend) != INTEGER_CST) |
40361 | { |
40362 | cp_parser_error (parser, gmsgid: "expected integer" ); |
40363 | return list; |
40364 | } |
40365 | cp_lexer_consume_token (lexer: parser->lexer); |
40366 | |
40367 | add_to_vector: |
40368 | if (t != error_mark_node) |
40369 | { |
40370 | vec = tree_cons (addend, t, vec); |
40371 | if (neg) |
40372 | OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; |
40373 | } |
40374 | |
40375 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_COMMA) |
40376 | || !cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
40377 | break; |
40378 | |
40379 | cp_lexer_consume_token (lexer: parser->lexer); |
40380 | } |
40381 | |
40382 | if (vec) |
40383 | { |
40384 | tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); |
40385 | OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; |
40386 | OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; |
40387 | OMP_CLAUSE_DECL (u) = nreverse (vec); |
40388 | OMP_CLAUSE_CHAIN (u) = list; |
40389 | return u; |
40390 | } |
40391 | return list; |
40392 | } |
40393 | |
40394 | /* OpenMP 5.0: |
40395 | detach ( event-handle ) */ |
40396 | |
40397 | static tree |
40398 | cp_parser_omp_clause_detach (cp_parser *parser, tree list) |
40399 | { |
40400 | matching_parens parens; |
40401 | |
40402 | if (!parens.require_open (parser)) |
40403 | return list; |
40404 | |
40405 | cp_token *token; |
40406 | tree name, decl; |
40407 | |
40408 | token = cp_lexer_peek_token (lexer: parser->lexer); |
40409 | name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
40410 | /*check_dependency_p=*/true, |
40411 | /*template_p=*/NULL, |
40412 | /*declarator_p=*/false, |
40413 | /*optional_p=*/false); |
40414 | if (name == error_mark_node) |
40415 | decl = error_mark_node; |
40416 | else |
40417 | { |
40418 | if (identifier_p (t: name)) |
40419 | decl = cp_parser_lookup_name_simple (parser, name, location: token->location); |
40420 | else |
40421 | decl = name; |
40422 | if (decl == error_mark_node) |
40423 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, |
40424 | location: token->location); |
40425 | } |
40426 | |
40427 | if (decl == error_mark_node |
40428 | || !parens.require_close (parser)) |
40429 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40430 | /*or_comma=*/false, |
40431 | /*consume_paren=*/true); |
40432 | |
40433 | tree u = build_omp_clause (token->location, OMP_CLAUSE_DETACH); |
40434 | OMP_CLAUSE_DECL (u) = decl; |
40435 | OMP_CLAUSE_CHAIN (u) = list; |
40436 | |
40437 | return u; |
40438 | } |
40439 | |
40440 | /* OpenMP 5.0: |
40441 | iterators ( iterators-definition ) |
40442 | |
40443 | iterators-definition: |
40444 | iterator-specifier |
40445 | iterator-specifier , iterators-definition |
40446 | |
40447 | iterator-specifier: |
40448 | identifier = range-specification |
40449 | iterator-type identifier = range-specification |
40450 | |
40451 | range-specification: |
40452 | begin : end |
40453 | begin : end : step */ |
40454 | |
40455 | static tree |
40456 | cp_parser_omp_iterators (cp_parser *parser) |
40457 | { |
40458 | tree ret = NULL_TREE, *last = &ret; |
40459 | cp_lexer_consume_token (lexer: parser->lexer); |
40460 | |
40461 | matching_parens parens; |
40462 | if (!parens.require_open (parser)) |
40463 | return error_mark_node; |
40464 | |
40465 | bool saved_colon_corrects_to_scope_p |
40466 | = parser->colon_corrects_to_scope_p; |
40467 | bool saved_colon_doesnt_start_class_def_p |
40468 | = parser->colon_doesnt_start_class_def_p; |
40469 | |
40470 | do |
40471 | { |
40472 | tree iter_type; |
40473 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40474 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_EQ)) |
40475 | iter_type = integer_type_node; |
40476 | else |
40477 | { |
40478 | const char *saved_message |
40479 | = parser->type_definition_forbidden_message; |
40480 | parser->type_definition_forbidden_message |
40481 | = G_("types may not be defined in iterator type" ); |
40482 | |
40483 | iter_type = cp_parser_type_id (parser); |
40484 | |
40485 | parser->type_definition_forbidden_message = saved_message; |
40486 | } |
40487 | |
40488 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
40489 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
40490 | { |
40491 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
40492 | break; |
40493 | } |
40494 | |
40495 | tree id = cp_parser_identifier (parser); |
40496 | if (id == error_mark_node) |
40497 | break; |
40498 | |
40499 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
40500 | break; |
40501 | |
40502 | parser->colon_corrects_to_scope_p = false; |
40503 | parser->colon_doesnt_start_class_def_p = true; |
40504 | tree begin = cp_parser_assignment_expression (parser); |
40505 | |
40506 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
40507 | break; |
40508 | |
40509 | tree end = cp_parser_assignment_expression (parser); |
40510 | |
40511 | tree step = integer_one_node; |
40512 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
40513 | { |
40514 | cp_lexer_consume_token (lexer: parser->lexer); |
40515 | step = cp_parser_assignment_expression (parser); |
40516 | } |
40517 | |
40518 | tree iter_var = build_decl (loc, VAR_DECL, id, iter_type); |
40519 | DECL_ARTIFICIAL (iter_var) = 1; |
40520 | DECL_CONTEXT (iter_var) = current_function_decl; |
40521 | pushdecl (iter_var); |
40522 | |
40523 | *last = make_tree_vec (6); |
40524 | TREE_VEC_ELT (*last, 0) = iter_var; |
40525 | TREE_VEC_ELT (*last, 1) = begin; |
40526 | TREE_VEC_ELT (*last, 2) = end; |
40527 | TREE_VEC_ELT (*last, 3) = step; |
40528 | last = &TREE_CHAIN (*last); |
40529 | |
40530 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
40531 | { |
40532 | cp_lexer_consume_token (lexer: parser->lexer); |
40533 | continue; |
40534 | } |
40535 | break; |
40536 | } |
40537 | while (1); |
40538 | |
40539 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
40540 | parser->colon_doesnt_start_class_def_p |
40541 | = saved_colon_doesnt_start_class_def_p; |
40542 | |
40543 | if (!parens.require_close (parser)) |
40544 | cp_parser_skip_to_closing_parenthesis (parser, |
40545 | /*recovering=*/true, |
40546 | /*or_comma=*/false, |
40547 | /*consume_paren=*/true); |
40548 | |
40549 | return ret ? ret : error_mark_node; |
40550 | } |
40551 | |
40552 | /* OpenMP 5.0: |
40553 | affinity ( [aff-modifier :] variable-list ) |
40554 | aff-modifier: |
40555 | iterator ( iterators-definition ) */ |
40556 | |
40557 | static tree |
40558 | cp_parser_omp_clause_affinity (cp_parser *parser, tree list) |
40559 | { |
40560 | tree nlist, c, iterators = NULL_TREE; |
40561 | |
40562 | matching_parens parens; |
40563 | if (!parens.require_open (parser)) |
40564 | return list; |
40565 | |
40566 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40567 | { |
40568 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40569 | const char *p = IDENTIFIER_POINTER (id); |
40570 | bool parse_iter = ((strcmp (s1: "iterator" , s2: p) == 0) |
40571 | && (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
40572 | type: CPP_OPEN_PAREN))); |
40573 | if (parse_iter) |
40574 | { |
40575 | size_t n = cp_parser_skip_balanced_tokens (parser, n: 2); |
40576 | parse_iter = cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_COLON); |
40577 | } |
40578 | if (parse_iter) |
40579 | { |
40580 | begin_scope (sk_omp, NULL); |
40581 | iterators = cp_parser_omp_iterators (parser); |
40582 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
40583 | { |
40584 | if (iterators) |
40585 | poplevel (0, 1, 0); |
40586 | cp_parser_skip_to_closing_parenthesis (parser, |
40587 | /*recovering=*/true, |
40588 | /*or_comma=*/false, |
40589 | /*consume_paren=*/true); |
40590 | return list; |
40591 | } |
40592 | } |
40593 | } |
40594 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_AFFINITY, |
40595 | list, NULL); |
40596 | if (iterators) |
40597 | { |
40598 | tree block = poplevel (1, 1, 0); |
40599 | if (iterators != error_mark_node) |
40600 | { |
40601 | TREE_VEC_ELT (iterators, 5) = block; |
40602 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40603 | OMP_CLAUSE_DECL (c) = build_tree_list (iterators, |
40604 | OMP_CLAUSE_DECL (c)); |
40605 | } |
40606 | } |
40607 | return nlist; |
40608 | } |
40609 | |
40610 | /* OpenMP 4.0: |
40611 | depend ( depend-kind : variable-list ) |
40612 | |
40613 | depend-kind: |
40614 | in | out | inout |
40615 | |
40616 | OpenMP 4.5: |
40617 | depend ( source ) |
40618 | |
40619 | depend ( sink : vec ) |
40620 | |
40621 | OpenMP 5.0: |
40622 | depend ( depend-modifier , depend-kind: variable-list ) |
40623 | |
40624 | depend-kind: |
40625 | in | out | inout | mutexinoutset | depobj |
40626 | |
40627 | depend-modifier: |
40628 | iterator ( iterators-definition ) */ |
40629 | |
40630 | static tree |
40631 | cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) |
40632 | { |
40633 | tree nlist, c, iterators = NULL_TREE; |
40634 | enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; |
40635 | enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; |
40636 | |
40637 | matching_parens parens; |
40638 | if (!parens.require_open (parser)) |
40639 | return list; |
40640 | |
40641 | do |
40642 | { |
40643 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
40644 | goto invalid_kind; |
40645 | |
40646 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40647 | const char *p = IDENTIFIER_POINTER (id); |
40648 | |
40649 | if (strcmp (s1: "iterator" , s2: p) == 0 && iterators == NULL_TREE) |
40650 | { |
40651 | begin_scope (sk_omp, NULL); |
40652 | iterators = cp_parser_omp_iterators (parser); |
40653 | cp_parser_require (parser, type: CPP_COMMA, token_desc: RT_COMMA); |
40654 | continue; |
40655 | } |
40656 | if (strcmp (s1: "in" , s2: p) == 0) |
40657 | kind = OMP_CLAUSE_DEPEND_IN; |
40658 | else if (strcmp (s1: "inout" , s2: p) == 0) |
40659 | kind = OMP_CLAUSE_DEPEND_INOUT; |
40660 | else if (strcmp (s1: "inoutset" , s2: p) == 0) |
40661 | kind = OMP_CLAUSE_DEPEND_INOUTSET; |
40662 | else if (strcmp (s1: "mutexinoutset" , s2: p) == 0) |
40663 | kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET; |
40664 | else if (strcmp (s1: "out" , s2: p) == 0) |
40665 | kind = OMP_CLAUSE_DEPEND_OUT; |
40666 | else if (strcmp (s1: "depobj" , s2: p) == 0) |
40667 | kind = OMP_CLAUSE_DEPEND_DEPOBJ; |
40668 | else if (strcmp (s1: "sink" , s2: p) == 0) |
40669 | dkind = OMP_CLAUSE_DOACROSS_SINK; |
40670 | else if (strcmp (s1: "source" , s2: p) == 0) |
40671 | dkind = OMP_CLAUSE_DOACROSS_SOURCE; |
40672 | else |
40673 | goto invalid_kind; |
40674 | break; |
40675 | } |
40676 | while (1); |
40677 | |
40678 | cp_lexer_consume_token (lexer: parser->lexer); |
40679 | |
40680 | if (iterators |
40681 | && (dkind == OMP_CLAUSE_DOACROSS_SOURCE |
40682 | || dkind == OMP_CLAUSE_DOACROSS_SINK)) |
40683 | { |
40684 | poplevel (0, 1, 0); |
40685 | error_at (loc, "%<iterator%> modifier incompatible with %qs" , |
40686 | dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink" ); |
40687 | iterators = NULL_TREE; |
40688 | } |
40689 | |
40690 | if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) |
40691 | { |
40692 | c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); |
40693 | OMP_CLAUSE_DOACROSS_KIND (c) = dkind; |
40694 | OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; |
40695 | OMP_CLAUSE_DECL (c) = NULL_TREE; |
40696 | OMP_CLAUSE_CHAIN (c) = list; |
40697 | if (!parens.require_close (parser)) |
40698 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40699 | /*or_comma=*/false, |
40700 | /*consume_paren=*/true); |
40701 | return c; |
40702 | } |
40703 | |
40704 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
40705 | goto resync_fail; |
40706 | |
40707 | if (dkind == OMP_CLAUSE_DOACROSS_SINK) |
40708 | { |
40709 | nlist = cp_parser_omp_clause_doacross_sink (parser, clause_loc: loc, list, depend_p: true); |
40710 | if (!parens.require_close (parser)) |
40711 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40712 | /*or_comma=*/false, |
40713 | /*consume_paren=*/true); |
40714 | } |
40715 | else |
40716 | { |
40717 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_DEPEND, |
40718 | list, NULL); |
40719 | |
40720 | if (iterators) |
40721 | { |
40722 | tree block = poplevel (1, 1, 0); |
40723 | if (iterators == error_mark_node) |
40724 | iterators = NULL_TREE; |
40725 | else |
40726 | TREE_VEC_ELT (iterators, 5) = block; |
40727 | } |
40728 | |
40729 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40730 | { |
40731 | OMP_CLAUSE_DEPEND_KIND (c) = kind; |
40732 | if (iterators) |
40733 | OMP_CLAUSE_DECL (c) |
40734 | = build_tree_list (iterators, OMP_CLAUSE_DECL (c)); |
40735 | } |
40736 | } |
40737 | return nlist; |
40738 | |
40739 | invalid_kind: |
40740 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
40741 | resync_fail: |
40742 | if (iterators) |
40743 | poplevel (0, 1, 0); |
40744 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40745 | /*or_comma=*/false, |
40746 | /*consume_paren=*/true); |
40747 | return list; |
40748 | } |
40749 | |
40750 | /* OpenMP 5.2: |
40751 | doacross ( source : ) |
40752 | doacross ( source : omp_cur_iteration ) |
40753 | |
40754 | doacross ( sink : vec ) |
40755 | doacross ( sink : omp_cur_iteration - logical_iteration ) */ |
40756 | |
40757 | static tree |
40758 | cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) |
40759 | { |
40760 | tree nlist; |
40761 | enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; |
40762 | |
40763 | matching_parens parens; |
40764 | if (!parens.require_open (parser)) |
40765 | return list; |
40766 | |
40767 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
40768 | { |
40769 | invalid_kind: |
40770 | cp_parser_error (parser, gmsgid: "invalid doacross kind" ); |
40771 | resync_fail: |
40772 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40773 | /*or_comma=*/false, |
40774 | /*consume_paren=*/true); |
40775 | return list; |
40776 | } |
40777 | |
40778 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40779 | const char *p = IDENTIFIER_POINTER (id); |
40780 | |
40781 | if (strcmp (s1: "sink" , s2: p) == 0) |
40782 | kind = OMP_CLAUSE_DOACROSS_SINK; |
40783 | else if (strcmp (s1: "source" , s2: p) == 0) |
40784 | kind = OMP_CLAUSE_DOACROSS_SOURCE; |
40785 | else |
40786 | goto invalid_kind; |
40787 | |
40788 | cp_lexer_consume_token (lexer: parser->lexer); |
40789 | |
40790 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
40791 | goto resync_fail; |
40792 | |
40793 | if (kind == OMP_CLAUSE_DOACROSS_SOURCE) |
40794 | { |
40795 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
40796 | { |
40797 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40798 | p = IDENTIFIER_POINTER (id); |
40799 | if (strcmp (s1: p, s2: "omp_cur_iteration" ) == 0) |
40800 | cp_lexer_consume_token (lexer: parser->lexer); |
40801 | } |
40802 | nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); |
40803 | OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE; |
40804 | OMP_CLAUSE_DECL (nlist) = NULL_TREE; |
40805 | OMP_CLAUSE_CHAIN (nlist) = list; |
40806 | } |
40807 | else |
40808 | nlist = cp_parser_omp_clause_doacross_sink (parser, clause_loc: loc, list, depend_p: false); |
40809 | |
40810 | if (!parens.require_close (parser)) |
40811 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40812 | /*or_comma=*/false, |
40813 | /*consume_paren=*/true); |
40814 | return nlist; |
40815 | } |
40816 | |
40817 | /* OpenMP 4.0: |
40818 | from ( variable-list ) |
40819 | to ( variable-list ) |
40820 | |
40821 | OpenMP 5.1: |
40822 | from ( [present :] variable-list ) |
40823 | to ( [present :] variable-list ) */ |
40824 | |
40825 | static tree |
40826 | cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, |
40827 | tree list) |
40828 | { |
40829 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
40830 | return list; |
40831 | |
40832 | bool present = false; |
40833 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
40834 | |
40835 | if (token->type == CPP_NAME |
40836 | && strcmp (IDENTIFIER_POINTER (token->u.value), s2: "present" ) == 0 |
40837 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
40838 | { |
40839 | present = true; |
40840 | cp_lexer_consume_token (lexer: parser->lexer); |
40841 | cp_lexer_consume_token (lexer: parser->lexer); |
40842 | } |
40843 | |
40844 | tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, allow_deref: true); |
40845 | if (present) |
40846 | for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
40847 | OMP_CLAUSE_MOTION_PRESENT (c) = 1; |
40848 | |
40849 | return nl; |
40850 | } |
40851 | |
40852 | /* OpenMP 4.0: |
40853 | map ( map-kind : variable-list ) |
40854 | map ( variable-list ) |
40855 | |
40856 | map-kind: |
40857 | alloc | to | from | tofrom |
40858 | |
40859 | OpenMP 4.5: |
40860 | map-kind: |
40861 | alloc | to | from | tofrom | release | delete |
40862 | |
40863 | map ( always [,] map-kind: variable-list ) |
40864 | |
40865 | OpenMP 5.0: |
40866 | map ( [map-type-modifier[,] ...] map-kind: variable-list ) |
40867 | |
40868 | map-type-modifier: |
40869 | always | close */ |
40870 | |
40871 | static tree |
40872 | cp_parser_omp_clause_map (cp_parser *parser, tree list) |
40873 | { |
40874 | tree nlist, c; |
40875 | enum gomp_map_kind kind = GOMP_MAP_TOFROM; |
40876 | |
40877 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
40878 | return list; |
40879 | |
40880 | int pos = 1; |
40881 | int map_kind_pos = 0; |
40882 | while (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos)->type == CPP_NAME |
40883 | || cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos)->keyword == RID_DELETE) |
40884 | { |
40885 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos + 1)->type == CPP_COLON) |
40886 | { |
40887 | map_kind_pos = pos; |
40888 | break; |
40889 | } |
40890 | |
40891 | if (cp_lexer_peek_nth_token (lexer: parser->lexer, n: pos + 1)->type == CPP_COMMA) |
40892 | pos++; |
40893 | pos++; |
40894 | } |
40895 | |
40896 | bool always_modifier = false; |
40897 | bool close_modifier = false; |
40898 | bool present_modifier = false; |
40899 | for (int pos = 1; pos < map_kind_pos; ++pos) |
40900 | { |
40901 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
40902 | if (tok->type == CPP_COMMA) |
40903 | { |
40904 | cp_lexer_consume_token (lexer: parser->lexer); |
40905 | continue; |
40906 | } |
40907 | |
40908 | const char *p = IDENTIFIER_POINTER (tok->u.value); |
40909 | if (strcmp (s1: "always" , s2: p) == 0) |
40910 | { |
40911 | if (always_modifier) |
40912 | { |
40913 | cp_parser_error (parser, gmsgid: "too many %<always%> modifiers" ); |
40914 | cp_parser_skip_to_closing_parenthesis (parser, |
40915 | /*recovering=*/true, |
40916 | /*or_comma=*/false, |
40917 | /*consume_paren=*/true); |
40918 | return list; |
40919 | } |
40920 | always_modifier = true; |
40921 | } |
40922 | else if (strcmp (s1: "close" , s2: p) == 0) |
40923 | { |
40924 | if (close_modifier) |
40925 | { |
40926 | cp_parser_error (parser, gmsgid: "too many %<close%> modifiers" ); |
40927 | cp_parser_skip_to_closing_parenthesis (parser, |
40928 | /*recovering=*/true, |
40929 | /*or_comma=*/false, |
40930 | /*consume_paren=*/true); |
40931 | return list; |
40932 | } |
40933 | close_modifier = true; |
40934 | } |
40935 | else if (strcmp (s1: "present" , s2: p) == 0) |
40936 | { |
40937 | if (present_modifier) |
40938 | { |
40939 | cp_parser_error (parser, gmsgid: "too many %<present%> modifiers" ); |
40940 | cp_parser_skip_to_closing_parenthesis (parser, |
40941 | /*recovering=*/true, |
40942 | /*or_comma=*/false, |
40943 | /*consume_paren=*/true); |
40944 | return list; |
40945 | } |
40946 | present_modifier = true; |
40947 | } |
40948 | else |
40949 | { |
40950 | cp_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other" |
40951 | " than %<always%>, %<close%> or %<present%>" ); |
40952 | cp_parser_skip_to_closing_parenthesis (parser, |
40953 | /*recovering=*/true, |
40954 | /*or_comma=*/false, |
40955 | /*consume_paren=*/true); |
40956 | return list; |
40957 | } |
40958 | |
40959 | cp_lexer_consume_token (lexer: parser->lexer); |
40960 | } |
40961 | |
40962 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
40963 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
40964 | { |
40965 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
40966 | const char *p = IDENTIFIER_POINTER (id); |
40967 | int always_present_modifier = always_modifier && present_modifier; |
40968 | |
40969 | if (strcmp (s1: "alloc" , s2: p) == 0) |
40970 | kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC; |
40971 | else if (strcmp (s1: "to" , s2: p) == 0) |
40972 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO |
40973 | : present_modifier ? GOMP_MAP_PRESENT_TO |
40974 | : always_modifier ? GOMP_MAP_ALWAYS_TO |
40975 | : GOMP_MAP_TO); |
40976 | else if (strcmp (s1: "from" , s2: p) == 0) |
40977 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM |
40978 | : present_modifier ? GOMP_MAP_PRESENT_FROM |
40979 | : always_modifier ? GOMP_MAP_ALWAYS_FROM |
40980 | : GOMP_MAP_FROM); |
40981 | else if (strcmp (s1: "tofrom" , s2: p) == 0) |
40982 | kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM |
40983 | : present_modifier ? GOMP_MAP_PRESENT_TOFROM |
40984 | : always_modifier ? GOMP_MAP_ALWAYS_TOFROM |
40985 | : GOMP_MAP_TOFROM); |
40986 | else if (strcmp (s1: "release" , s2: p) == 0) |
40987 | kind = GOMP_MAP_RELEASE; |
40988 | else |
40989 | { |
40990 | cp_parser_error (parser, gmsgid: "invalid map kind" ); |
40991 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
40992 | /*or_comma=*/false, |
40993 | /*consume_paren=*/true); |
40994 | return list; |
40995 | } |
40996 | cp_lexer_consume_token (lexer: parser->lexer); |
40997 | cp_lexer_consume_token (lexer: parser->lexer); |
40998 | } |
40999 | else if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_DELETE) |
41000 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type == CPP_COLON) |
41001 | { |
41002 | kind = GOMP_MAP_DELETE; |
41003 | cp_lexer_consume_token (lexer: parser->lexer); |
41004 | cp_lexer_consume_token (lexer: parser->lexer); |
41005 | } |
41006 | |
41007 | nlist = cp_parser_omp_var_list_no_open (parser, kind: OMP_CLAUSE_MAP, list, |
41008 | NULL, allow_deref: true); |
41009 | |
41010 | for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) |
41011 | OMP_CLAUSE_SET_MAP_KIND (c, kind); |
41012 | |
41013 | return nlist; |
41014 | } |
41015 | |
41016 | /* OpenMP 4.0: |
41017 | device ( expression ) |
41018 | |
41019 | OpenMP 5.0: |
41020 | device ( [device-modifier :] integer-expression ) |
41021 | |
41022 | device-modifier: |
41023 | ancestor | device_num */ |
41024 | |
41025 | static tree |
41026 | cp_parser_omp_clause_device (cp_parser *parser, tree list, |
41027 | location_t location) |
41028 | { |
41029 | tree t, c; |
41030 | bool ancestor = false; |
41031 | |
41032 | matching_parens parens; |
41033 | if (!parens.require_open (parser)) |
41034 | return list; |
41035 | |
41036 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
41037 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_COLON)) |
41038 | { |
41039 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
41040 | const char *p = IDENTIFIER_POINTER (tok->u.value); |
41041 | if (strcmp (s1: "ancestor" , s2: p) == 0) |
41042 | { |
41043 | ancestor = true; |
41044 | |
41045 | /* A requires directive with the reverse_offload clause must be |
41046 | specified. */ |
41047 | if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) |
41048 | { |
41049 | error_at (tok->location, "%<ancestor%> device modifier not " |
41050 | "preceded by %<requires%> directive " |
41051 | "with %<reverse_offload%> clause" ); |
41052 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
41053 | return list; |
41054 | } |
41055 | } |
41056 | else if (strcmp (s1: "device_num" , s2: p) == 0) |
41057 | ; |
41058 | else |
41059 | { |
41060 | error_at (tok->location, "expected %<ancestor%> or %<device_num%>" ); |
41061 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
41062 | return list; |
41063 | } |
41064 | cp_lexer_consume_token (lexer: parser->lexer); |
41065 | cp_lexer_consume_token (lexer: parser->lexer); |
41066 | } |
41067 | |
41068 | t = cp_parser_assignment_expression (parser); |
41069 | |
41070 | if (t == error_mark_node |
41071 | || !parens.require_close (parser)) |
41072 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41073 | /*or_comma=*/false, |
41074 | /*consume_paren=*/true); |
41075 | |
41076 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, |
41077 | name: "device" , location); |
41078 | |
41079 | c = build_omp_clause (location, OMP_CLAUSE_DEVICE); |
41080 | OMP_CLAUSE_DEVICE_ID (c) = t; |
41081 | OMP_CLAUSE_CHAIN (c) = list; |
41082 | OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor; |
41083 | |
41084 | return c; |
41085 | } |
41086 | |
41087 | /* OpenMP 4.0: |
41088 | dist_schedule ( static ) |
41089 | dist_schedule ( static , expression ) */ |
41090 | |
41091 | static tree |
41092 | cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, |
41093 | location_t location) |
41094 | { |
41095 | tree c, t; |
41096 | |
41097 | matching_parens parens; |
41098 | if (!parens.require_open (parser)) |
41099 | return list; |
41100 | |
41101 | c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE); |
41102 | |
41103 | if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_STATIC)) |
41104 | goto invalid_kind; |
41105 | cp_lexer_consume_token (lexer: parser->lexer); |
41106 | |
41107 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41108 | { |
41109 | cp_lexer_consume_token (lexer: parser->lexer); |
41110 | |
41111 | t = cp_parser_assignment_expression (parser); |
41112 | |
41113 | if (t == error_mark_node) |
41114 | goto resync_fail; |
41115 | OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; |
41116 | |
41117 | if (!parens.require_close (parser)) |
41118 | goto resync_fail; |
41119 | } |
41120 | else if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41121 | goto resync_fail; |
41122 | |
41123 | /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, |
41124 | "dist_schedule", location); */ |
41125 | if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE)) |
41126 | warning_at (location, 0, "too many %qs clauses" , "dist_schedule" ); |
41127 | OMP_CLAUSE_CHAIN (c) = list; |
41128 | return c; |
41129 | |
41130 | invalid_kind: |
41131 | cp_parser_error (parser, gmsgid: "invalid dist_schedule kind" ); |
41132 | resync_fail: |
41133 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41134 | /*or_comma=*/false, |
41135 | /*consume_paren=*/true); |
41136 | return list; |
41137 | } |
41138 | |
41139 | /* OpenMP 4.0: |
41140 | proc_bind ( proc-bind-kind ) |
41141 | |
41142 | proc-bind-kind: |
41143 | primary | master | close | spread |
41144 | where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */ |
41145 | |
41146 | static tree |
41147 | cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list, |
41148 | location_t location) |
41149 | { |
41150 | tree c; |
41151 | enum omp_clause_proc_bind_kind kind; |
41152 | |
41153 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41154 | return list; |
41155 | |
41156 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41157 | { |
41158 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41159 | const char *p = IDENTIFIER_POINTER (id); |
41160 | |
41161 | if (strcmp (s1: "primary" , s2: p) == 0) |
41162 | kind = OMP_CLAUSE_PROC_BIND_PRIMARY; |
41163 | else if (strcmp (s1: "master" , s2: p) == 0) |
41164 | kind = OMP_CLAUSE_PROC_BIND_MASTER; |
41165 | else if (strcmp (s1: "close" , s2: p) == 0) |
41166 | kind = OMP_CLAUSE_PROC_BIND_CLOSE; |
41167 | else if (strcmp (s1: "spread" , s2: p) == 0) |
41168 | kind = OMP_CLAUSE_PROC_BIND_SPREAD; |
41169 | else |
41170 | goto invalid_kind; |
41171 | } |
41172 | else |
41173 | goto invalid_kind; |
41174 | |
41175 | cp_lexer_consume_token (lexer: parser->lexer); |
41176 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41177 | goto resync_fail; |
41178 | |
41179 | c = build_omp_clause (location, OMP_CLAUSE_PROC_BIND); |
41180 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind" , |
41181 | location); |
41182 | OMP_CLAUSE_PROC_BIND_KIND (c) = kind; |
41183 | OMP_CLAUSE_CHAIN (c) = list; |
41184 | return c; |
41185 | |
41186 | invalid_kind: |
41187 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
41188 | resync_fail: |
41189 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41190 | /*or_comma=*/false, |
41191 | /*consume_paren=*/true); |
41192 | return list; |
41193 | } |
41194 | |
41195 | /* OpenMP 5.0: |
41196 | device_type ( host | nohost | any ) */ |
41197 | |
41198 | static tree |
41199 | cp_parser_omp_clause_device_type (cp_parser *parser, tree list, |
41200 | location_t location) |
41201 | { |
41202 | tree c; |
41203 | enum omp_clause_device_type_kind kind; |
41204 | |
41205 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
41206 | return list; |
41207 | |
41208 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
41209 | { |
41210 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
41211 | const char *p = IDENTIFIER_POINTER (id); |
41212 | |
41213 | if (strcmp (s1: "host" , s2: p) == 0) |
41214 | kind = OMP_CLAUSE_DEVICE_TYPE_HOST; |
41215 | else if (strcmp (s1: "nohost" , s2: p) == 0) |
41216 | kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST; |
41217 | else if (strcmp (s1: "any" , s2: p) == 0) |
41218 | kind = OMP_CLAUSE_DEVICE_TYPE_ANY; |
41219 | else |
41220 | goto invalid_kind; |
41221 | } |
41222 | else |
41223 | goto invalid_kind; |
41224 | |
41225 | cp_lexer_consume_token (lexer: parser->lexer); |
41226 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_COMMA_CLOSE_PAREN)) |
41227 | goto resync_fail; |
41228 | |
41229 | c = build_omp_clause (location, OMP_CLAUSE_DEVICE_TYPE); |
41230 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE, name: "device_type" , |
41231 | location); |
41232 | OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind; |
41233 | OMP_CLAUSE_CHAIN (c) = list; |
41234 | return c; |
41235 | |
41236 | invalid_kind: |
41237 | cp_parser_error (parser, gmsgid: "invalid depend kind" ); |
41238 | resync_fail: |
41239 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41240 | /*or_comma=*/false, |
41241 | /*consume_paren=*/true); |
41242 | return list; |
41243 | } |
41244 | |
41245 | /* OpenACC: |
41246 | async [( int-expr )] */ |
41247 | |
41248 | static tree |
41249 | cp_parser_oacc_clause_async (cp_parser *parser, tree list) |
41250 | { |
41251 | tree c, t; |
41252 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41253 | |
41254 | t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL); |
41255 | |
41256 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
41257 | { |
41258 | matching_parens parens; |
41259 | parens.consume_open (parser); |
41260 | |
41261 | t = cp_parser_assignment_expression (parser); |
41262 | if (t == error_mark_node |
41263 | || !parens.require_close (parser)) |
41264 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41265 | /*or_comma=*/false, |
41266 | /*consume_paren=*/true); |
41267 | } |
41268 | |
41269 | check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async" , location: loc); |
41270 | |
41271 | c = build_omp_clause (loc, OMP_CLAUSE_ASYNC); |
41272 | OMP_CLAUSE_ASYNC_EXPR (c) = t; |
41273 | OMP_CLAUSE_CHAIN (c) = list; |
41274 | list = c; |
41275 | |
41276 | return list; |
41277 | } |
41278 | |
41279 | /* OpenACC 2.7: |
41280 | self [( expression )] */ |
41281 | |
41282 | static tree |
41283 | cp_parser_oacc_compute_clause_self (cp_parser *parser, tree list) |
41284 | { |
41285 | tree t; |
41286 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41287 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
41288 | { |
41289 | matching_parens parens; |
41290 | parens.consume_open (parser); |
41291 | t = cp_parser_assignment_expression (parser); |
41292 | if (t == error_mark_node |
41293 | || !parens.require_close (parser)) |
41294 | { |
41295 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
41296 | /*or_comma=*/false, |
41297 | /*consume_paren=*/true); |
41298 | return list; |
41299 | } |
41300 | } |
41301 | else |
41302 | t = truthvalue_true_node; |
41303 | |
41304 | for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c)) |
41305 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF) |
41306 | { |
41307 | error_at (location, "too many %<self%> clauses" ); |
41308 | return list; |
41309 | } |
41310 | |
41311 | tree c = build_omp_clause (location, OMP_CLAUSE_SELF); |
41312 | OMP_CLAUSE_SELF_EXPR (c) = t; |
41313 | OMP_CLAUSE_CHAIN (c) = list; |
41314 | return c; |
41315 | } |
41316 | |
41317 | /* Parse all OpenACC clauses. The set clauses allowed by the directive |
41318 | is a bitmask in MASK. Return the list of clauses found. */ |
41319 | |
41320 | static tree |
41321 | cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask, |
41322 | const char *where, cp_token *pragma_tok, |
41323 | bool finish_p = true) |
41324 | { |
41325 | tree clauses = NULL; |
41326 | bool first = true; |
41327 | |
41328 | /* Don't create location wrapper nodes within OpenACC clauses. */ |
41329 | auto_suppress_location_wrappers sentinel; |
41330 | |
41331 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
41332 | { |
41333 | location_t here; |
41334 | pragma_omp_clause c_kind; |
41335 | omp_clause_code code; |
41336 | const char *c_name; |
41337 | tree prev = clauses; |
41338 | |
41339 | if (!first && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41340 | cp_lexer_consume_token (lexer: parser->lexer); |
41341 | |
41342 | here = cp_lexer_peek_token (lexer: parser->lexer)->location; |
41343 | c_kind = cp_parser_omp_clause_name (parser); |
41344 | |
41345 | switch (c_kind) |
41346 | { |
41347 | case PRAGMA_OACC_CLAUSE_ASYNC: |
41348 | clauses = cp_parser_oacc_clause_async (parser, list: clauses); |
41349 | c_name = "async" ; |
41350 | break; |
41351 | case PRAGMA_OACC_CLAUSE_AUTO: |
41352 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO, |
41353 | list: clauses); |
41354 | c_name = "auto" ; |
41355 | break; |
41356 | case PRAGMA_OACC_CLAUSE_ATTACH: |
41357 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41358 | c_name = "attach" ; |
41359 | break; |
41360 | case PRAGMA_OACC_CLAUSE_COLLAPSE: |
41361 | clauses = cp_parser_omp_clause_collapse (parser, list: clauses, location: here); |
41362 | c_name = "collapse" ; |
41363 | break; |
41364 | case PRAGMA_OACC_CLAUSE_COPY: |
41365 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41366 | c_name = "copy" ; |
41367 | break; |
41368 | case PRAGMA_OACC_CLAUSE_COPYIN: |
41369 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41370 | c_name = "copyin" ; |
41371 | break; |
41372 | case PRAGMA_OACC_CLAUSE_COPYOUT: |
41373 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41374 | c_name = "copyout" ; |
41375 | break; |
41376 | case PRAGMA_OACC_CLAUSE_CREATE: |
41377 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41378 | c_name = "create" ; |
41379 | break; |
41380 | case PRAGMA_OACC_CLAUSE_DELETE: |
41381 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41382 | c_name = "delete" ; |
41383 | break; |
41384 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
41385 | clauses = cp_parser_omp_clause_default (parser, list: clauses, location: here, is_oacc: true); |
41386 | c_name = "default" ; |
41387 | break; |
41388 | case PRAGMA_OACC_CLAUSE_DETACH: |
41389 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41390 | c_name = "detach" ; |
41391 | break; |
41392 | case PRAGMA_OACC_CLAUSE_DEVICE: |
41393 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41394 | c_name = "device" ; |
41395 | break; |
41396 | case PRAGMA_OACC_CLAUSE_DEVICEPTR: |
41397 | clauses = cp_parser_oacc_data_clause_deviceptr (parser, list: clauses); |
41398 | c_name = "deviceptr" ; |
41399 | break; |
41400 | case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT: |
41401 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41402 | c_name = "device_resident" ; |
41403 | break; |
41404 | case PRAGMA_OACC_CLAUSE_FINALIZE: |
41405 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE, |
41406 | list: clauses); |
41407 | c_name = "finalize" ; |
41408 | break; |
41409 | case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE: |
41410 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, |
41411 | list: clauses); |
41412 | c_name = "firstprivate" ; |
41413 | break; |
41414 | case PRAGMA_OACC_CLAUSE_GANG: |
41415 | c_name = "gang" ; |
41416 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG, |
41417 | str: c_name, list: clauses); |
41418 | break; |
41419 | case PRAGMA_OACC_CLAUSE_HOST: |
41420 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41421 | c_name = "host" ; |
41422 | break; |
41423 | case PRAGMA_OACC_CLAUSE_IF: |
41424 | clauses = cp_parser_omp_clause_if (parser, list: clauses, location: here, is_omp: false); |
41425 | c_name = "if" ; |
41426 | break; |
41427 | case PRAGMA_OACC_CLAUSE_IF_PRESENT: |
41428 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT, |
41429 | list: clauses); |
41430 | c_name = "if_present" ; |
41431 | break; |
41432 | case PRAGMA_OACC_CLAUSE_INDEPENDENT: |
41433 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT, |
41434 | list: clauses); |
41435 | c_name = "independent" ; |
41436 | break; |
41437 | case PRAGMA_OACC_CLAUSE_LINK: |
41438 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41439 | c_name = "link" ; |
41440 | break; |
41441 | case PRAGMA_OACC_CLAUSE_NO_CREATE: |
41442 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41443 | c_name = "no_create" ; |
41444 | break; |
41445 | case PRAGMA_OACC_CLAUSE_NOHOST: |
41446 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST, |
41447 | list: clauses); |
41448 | c_name = "nohost" ; |
41449 | break; |
41450 | case PRAGMA_OACC_CLAUSE_NUM_GANGS: |
41451 | code = OMP_CLAUSE_NUM_GANGS; |
41452 | c_name = "num_gangs" ; |
41453 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
41454 | list: clauses); |
41455 | break; |
41456 | case PRAGMA_OACC_CLAUSE_NUM_WORKERS: |
41457 | c_name = "num_workers" ; |
41458 | code = OMP_CLAUSE_NUM_WORKERS; |
41459 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
41460 | list: clauses); |
41461 | break; |
41462 | case PRAGMA_OACC_CLAUSE_PRESENT: |
41463 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41464 | c_name = "present" ; |
41465 | break; |
41466 | case PRAGMA_OACC_CLAUSE_PRIVATE: |
41467 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_PRIVATE, |
41468 | list: clauses); |
41469 | c_name = "private" ; |
41470 | break; |
41471 | case PRAGMA_OACC_CLAUSE_REDUCTION: |
41472 | clauses |
41473 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION, |
41474 | is_omp: false, list: clauses); |
41475 | c_name = "reduction" ; |
41476 | break; |
41477 | case PRAGMA_OACC_CLAUSE_SELF: |
41478 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0) |
41479 | /* OpenACC compute construct */ |
41480 | clauses = cp_parser_oacc_compute_clause_self (parser, list: clauses); |
41481 | else |
41482 | /* OpenACC 'update' directive */ |
41483 | clauses = cp_parser_oacc_data_clause (parser, c_kind, list: clauses); |
41484 | c_name = "self" ; |
41485 | break; |
41486 | case PRAGMA_OACC_CLAUSE_SEQ: |
41487 | clauses = cp_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ, |
41488 | list: clauses); |
41489 | c_name = "seq" ; |
41490 | break; |
41491 | case PRAGMA_OACC_CLAUSE_TILE: |
41492 | clauses = cp_parser_oacc_clause_tile (parser, clause_loc: here, list: clauses); |
41493 | c_name = "tile" ; |
41494 | break; |
41495 | case PRAGMA_OACC_CLAUSE_USE_DEVICE: |
41496 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR, |
41497 | list: clauses); |
41498 | c_name = "use_device" ; |
41499 | break; |
41500 | case PRAGMA_OACC_CLAUSE_VECTOR: |
41501 | c_name = "vector" ; |
41502 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, |
41503 | kind: OMP_CLAUSE_VECTOR, |
41504 | str: c_name, list: clauses); |
41505 | break; |
41506 | case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH: |
41507 | c_name = "vector_length" ; |
41508 | code = OMP_CLAUSE_VECTOR_LENGTH; |
41509 | clauses = cp_parser_oacc_single_int_clause (parser, code, str: c_name, |
41510 | list: clauses); |
41511 | break; |
41512 | case PRAGMA_OACC_CLAUSE_WAIT: |
41513 | clauses = cp_parser_oacc_clause_wait (parser, list: clauses); |
41514 | c_name = "wait" ; |
41515 | break; |
41516 | case PRAGMA_OACC_CLAUSE_WORKER: |
41517 | c_name = "worker" ; |
41518 | clauses = cp_parser_oacc_shape_clause (parser, loc: here, |
41519 | kind: OMP_CLAUSE_WORKER, |
41520 | str: c_name, list: clauses); |
41521 | break; |
41522 | default: |
41523 | cp_parser_error (parser, gmsgid: "expected an OpenACC clause" ); |
41524 | goto saw_error; |
41525 | } |
41526 | |
41527 | first = false; |
41528 | |
41529 | if (((mask >> c_kind) & 1) == 0) |
41530 | { |
41531 | /* Remove the invalid clause(s) from the list to avoid |
41532 | confusing the rest of the compiler. */ |
41533 | clauses = prev; |
41534 | error_at (here, "%qs is not valid for %qs" , c_name, where); |
41535 | } |
41536 | } |
41537 | |
41538 | saw_error: |
41539 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
41540 | |
41541 | if (finish_p) |
41542 | return finish_omp_clauses (clauses, C_ORT_ACC); |
41543 | |
41544 | return clauses; |
41545 | } |
41546 | |
41547 | /* Parse all OpenMP clauses. The set clauses allowed by the directive |
41548 | is a bitmask in MASK. Return the list of clauses found. |
41549 | FINISH_P set if finish_omp_clauses should be called. |
41550 | NESTED non-zero if clauses should be terminated by closing paren instead |
41551 | of end of pragma. If it is 2, additionally commas are required in between |
41552 | the clauses. */ |
41553 | |
41554 | static tree |
41555 | cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, |
41556 | const char *where, cp_token *pragma_tok, |
41557 | bool finish_p = true, int nested = 0) |
41558 | { |
41559 | tree clauses = NULL; |
41560 | bool first = true; |
41561 | cp_token *token = NULL; |
41562 | |
41563 | /* Don't create location wrapper nodes within OpenMP clauses. */ |
41564 | auto_suppress_location_wrappers sentinel; |
41565 | |
41566 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
41567 | { |
41568 | pragma_omp_clause c_kind; |
41569 | const char *c_name; |
41570 | tree prev = clauses; |
41571 | |
41572 | if (nested && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
41573 | break; |
41574 | |
41575 | if (!first || nested != 2) |
41576 | { |
41577 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
41578 | cp_lexer_consume_token (lexer: parser->lexer); |
41579 | else if (nested == 2) |
41580 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
41581 | "clauses in %<simd%> trait should be separated " |
41582 | "by %<,%>" ); |
41583 | } |
41584 | |
41585 | token = cp_lexer_peek_token (lexer: parser->lexer); |
41586 | c_kind = cp_parser_omp_clause_name (parser); |
41587 | |
41588 | switch (c_kind) |
41589 | { |
41590 | case PRAGMA_OMP_CLAUSE_BIND: |
41591 | clauses = cp_parser_omp_clause_bind (parser, list: clauses, |
41592 | location: token->location); |
41593 | c_name = "bind" ; |
41594 | break; |
41595 | case PRAGMA_OMP_CLAUSE_COLLAPSE: |
41596 | clauses = cp_parser_omp_clause_collapse (parser, list: clauses, |
41597 | location: token->location); |
41598 | c_name = "collapse" ; |
41599 | break; |
41600 | case PRAGMA_OMP_CLAUSE_COPYIN: |
41601 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_COPYIN, list: clauses); |
41602 | c_name = "copyin" ; |
41603 | break; |
41604 | case PRAGMA_OMP_CLAUSE_COPYPRIVATE: |
41605 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_COPYPRIVATE, |
41606 | list: clauses); |
41607 | c_name = "copyprivate" ; |
41608 | break; |
41609 | case PRAGMA_OMP_CLAUSE_DEFAULT: |
41610 | clauses = cp_parser_omp_clause_default (parser, list: clauses, |
41611 | location: token->location, is_oacc: false); |
41612 | c_name = "default" ; |
41613 | break; |
41614 | case PRAGMA_OMP_CLAUSE_FILTER: |
41615 | clauses = cp_parser_omp_clause_filter (parser, list: clauses, |
41616 | location: token->location); |
41617 | c_name = "filter" ; |
41618 | break; |
41619 | case PRAGMA_OMP_CLAUSE_FINAL: |
41620 | clauses = cp_parser_omp_clause_final (parser, list: clauses, location: token->location); |
41621 | c_name = "final" ; |
41622 | break; |
41623 | case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: |
41624 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, |
41625 | list: clauses); |
41626 | c_name = "firstprivate" ; |
41627 | break; |
41628 | case PRAGMA_OMP_CLAUSE_GRAINSIZE: |
41629 | clauses = cp_parser_omp_clause_grainsize (parser, list: clauses, |
41630 | location: token->location); |
41631 | c_name = "grainsize" ; |
41632 | break; |
41633 | case PRAGMA_OMP_CLAUSE_HINT: |
41634 | clauses = cp_parser_omp_clause_hint (parser, list: clauses, |
41635 | location: token->location); |
41636 | c_name = "hint" ; |
41637 | break; |
41638 | case PRAGMA_OMP_CLAUSE_DEFAULTMAP: |
41639 | clauses = cp_parser_omp_clause_defaultmap (parser, list: clauses, |
41640 | location: token->location); |
41641 | c_name = "defaultmap" ; |
41642 | break; |
41643 | case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR: |
41644 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR, |
41645 | list: clauses); |
41646 | c_name = "use_device_ptr" ; |
41647 | break; |
41648 | case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR: |
41649 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR, |
41650 | list: clauses); |
41651 | c_name = "use_device_addr" ; |
41652 | break; |
41653 | case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR: |
41654 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, |
41655 | list: clauses); |
41656 | c_name = "is_device_ptr" ; |
41657 | break; |
41658 | case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR: |
41659 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR, |
41660 | list: clauses); |
41661 | c_name = "has_device_addr" ; |
41662 | break; |
41663 | case PRAGMA_OMP_CLAUSE_IF: |
41664 | clauses = cp_parser_omp_clause_if (parser, list: clauses, location: token->location, |
41665 | is_omp: true); |
41666 | c_name = "if" ; |
41667 | break; |
41668 | case PRAGMA_OMP_CLAUSE_IN_REDUCTION: |
41669 | clauses |
41670 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION, |
41671 | is_omp: true, list: clauses); |
41672 | c_name = "in_reduction" ; |
41673 | break; |
41674 | case PRAGMA_OMP_CLAUSE_INDIRECT: |
41675 | clauses = cp_parser_omp_clause_indirect (parser, list: clauses, |
41676 | location: token->location); |
41677 | c_name = "indirect" ; |
41678 | break; |
41679 | case PRAGMA_OMP_CLAUSE_LASTPRIVATE: |
41680 | clauses = cp_parser_omp_clause_lastprivate (parser, list: clauses); |
41681 | c_name = "lastprivate" ; |
41682 | break; |
41683 | case PRAGMA_OMP_CLAUSE_MERGEABLE: |
41684 | clauses = cp_parser_omp_clause_mergeable (parser, list: clauses, |
41685 | location: token->location); |
41686 | c_name = "mergeable" ; |
41687 | break; |
41688 | case PRAGMA_OMP_CLAUSE_NOWAIT: |
41689 | clauses = cp_parser_omp_clause_nowait (parser, list: clauses, |
41690 | location: token->location); |
41691 | c_name = "nowait" ; |
41692 | break; |
41693 | case PRAGMA_OMP_CLAUSE_NUM_TASKS: |
41694 | clauses = cp_parser_omp_clause_num_tasks (parser, list: clauses, |
41695 | location: token->location); |
41696 | c_name = "num_tasks" ; |
41697 | break; |
41698 | case PRAGMA_OMP_CLAUSE_NUM_THREADS: |
41699 | clauses = cp_parser_omp_clause_num_threads (parser, list: clauses, |
41700 | location: token->location); |
41701 | c_name = "num_threads" ; |
41702 | break; |
41703 | case PRAGMA_OMP_CLAUSE_ORDER: |
41704 | clauses = cp_parser_omp_clause_order (parser, list: clauses, |
41705 | location: token->location); |
41706 | c_name = "order" ; |
41707 | break; |
41708 | case PRAGMA_OMP_CLAUSE_ORDERED: |
41709 | clauses = cp_parser_omp_clause_ordered (parser, list: clauses, |
41710 | location: token->location); |
41711 | c_name = "ordered" ; |
41712 | break; |
41713 | case PRAGMA_OMP_CLAUSE_PRIORITY: |
41714 | clauses = cp_parser_omp_clause_priority (parser, list: clauses, |
41715 | location: token->location); |
41716 | c_name = "priority" ; |
41717 | break; |
41718 | case PRAGMA_OMP_CLAUSE_PRIVATE: |
41719 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_PRIVATE, |
41720 | list: clauses); |
41721 | c_name = "private" ; |
41722 | break; |
41723 | case PRAGMA_OMP_CLAUSE_REDUCTION: |
41724 | clauses |
41725 | = cp_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION, |
41726 | is_omp: true, list: clauses); |
41727 | c_name = "reduction" ; |
41728 | break; |
41729 | case PRAGMA_OMP_CLAUSE_SCHEDULE: |
41730 | clauses = cp_parser_omp_clause_schedule (parser, list: clauses, |
41731 | location: token->location); |
41732 | c_name = "schedule" ; |
41733 | break; |
41734 | case PRAGMA_OMP_CLAUSE_SHARED: |
41735 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_SHARED, |
41736 | list: clauses); |
41737 | c_name = "shared" ; |
41738 | break; |
41739 | case PRAGMA_OMP_CLAUSE_TASK_REDUCTION: |
41740 | clauses |
41741 | = cp_parser_omp_clause_reduction (parser, |
41742 | kind: OMP_CLAUSE_TASK_REDUCTION, |
41743 | is_omp: true, list: clauses); |
41744 | c_name = "task_reduction" ; |
41745 | break; |
41746 | case PRAGMA_OMP_CLAUSE_UNTIED: |
41747 | clauses = cp_parser_omp_clause_untied (parser, list: clauses, |
41748 | location: token->location); |
41749 | c_name = "untied" ; |
41750 | break; |
41751 | case PRAGMA_OMP_CLAUSE_INBRANCH: |
41752 | clauses = cp_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH, |
41753 | list: clauses, location: token->location); |
41754 | c_name = "inbranch" ; |
41755 | break; |
41756 | case PRAGMA_OMP_CLAUSE_NONTEMPORAL: |
41757 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_NONTEMPORAL, |
41758 | list: clauses); |
41759 | c_name = "nontemporal" ; |
41760 | break; |
41761 | case PRAGMA_OMP_CLAUSE_NOTINBRANCH: |
41762 | clauses = cp_parser_omp_clause_branch (parser, |
41763 | code: OMP_CLAUSE_NOTINBRANCH, |
41764 | list: clauses, location: token->location); |
41765 | c_name = "notinbranch" ; |
41766 | break; |
41767 | case PRAGMA_OMP_CLAUSE_PARALLEL: |
41768 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL, |
41769 | list: clauses, location: token->location); |
41770 | c_name = "parallel" ; |
41771 | if (!first) |
41772 | { |
41773 | clause_not_first: |
41774 | error_at (token->location, "%qs must be the first clause of %qs" , |
41775 | c_name, where); |
41776 | clauses = prev; |
41777 | } |
41778 | break; |
41779 | case PRAGMA_OMP_CLAUSE_FOR: |
41780 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR, |
41781 | list: clauses, location: token->location); |
41782 | c_name = "for" ; |
41783 | if (!first) |
41784 | goto clause_not_first; |
41785 | break; |
41786 | case PRAGMA_OMP_CLAUSE_SECTIONS: |
41787 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS, |
41788 | list: clauses, location: token->location); |
41789 | c_name = "sections" ; |
41790 | if (!first) |
41791 | goto clause_not_first; |
41792 | break; |
41793 | case PRAGMA_OMP_CLAUSE_TASKGROUP: |
41794 | clauses = cp_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP, |
41795 | list: clauses, location: token->location); |
41796 | c_name = "taskgroup" ; |
41797 | if (!first) |
41798 | goto clause_not_first; |
41799 | break; |
41800 | case PRAGMA_OMP_CLAUSE_LINK: |
41801 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_LINK, list: clauses); |
41802 | c_name = "link" ; |
41803 | break; |
41804 | case PRAGMA_OMP_CLAUSE_TO: |
41805 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0) |
41806 | { |
41807 | tree nl = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
41808 | list: clauses); |
41809 | for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c)) |
41810 | OMP_CLAUSE_ENTER_TO (c) = 1; |
41811 | clauses = nl; |
41812 | } |
41813 | else |
41814 | clauses = cp_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO, |
41815 | list: clauses); |
41816 | c_name = "to" ; |
41817 | break; |
41818 | case PRAGMA_OMP_CLAUSE_FROM: |
41819 | clauses = cp_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM, |
41820 | list: clauses); |
41821 | c_name = "from" ; |
41822 | break; |
41823 | case PRAGMA_OMP_CLAUSE_UNIFORM: |
41824 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_UNIFORM, |
41825 | list: clauses); |
41826 | c_name = "uniform" ; |
41827 | break; |
41828 | case PRAGMA_OMP_CLAUSE_NUM_TEAMS: |
41829 | clauses = cp_parser_omp_clause_num_teams (parser, list: clauses, |
41830 | location: token->location); |
41831 | c_name = "num_teams" ; |
41832 | break; |
41833 | case PRAGMA_OMP_CLAUSE_THREAD_LIMIT: |
41834 | clauses = cp_parser_omp_clause_thread_limit (parser, list: clauses, |
41835 | location: token->location); |
41836 | c_name = "thread_limit" ; |
41837 | break; |
41838 | case PRAGMA_OMP_CLAUSE_ALIGNED: |
41839 | clauses = cp_parser_omp_clause_aligned (parser, list: clauses); |
41840 | c_name = "aligned" ; |
41841 | break; |
41842 | case PRAGMA_OMP_CLAUSE_ALLOCATE: |
41843 | clauses = cp_parser_omp_clause_allocate (parser, list: clauses); |
41844 | c_name = "allocate" ; |
41845 | break; |
41846 | case PRAGMA_OMP_CLAUSE_LINEAR: |
41847 | { |
41848 | bool declare_simd = false; |
41849 | if (((mask >> PRAGMA_OMP_CLAUSE_UNIFORM) & 1) != 0) |
41850 | declare_simd = true; |
41851 | clauses = cp_parser_omp_clause_linear (parser, list: clauses, declare_simd); |
41852 | } |
41853 | c_name = "linear" ; |
41854 | break; |
41855 | case PRAGMA_OMP_CLAUSE_AFFINITY: |
41856 | clauses = cp_parser_omp_clause_affinity (parser, list: clauses); |
41857 | c_name = "affinity" ; |
41858 | break; |
41859 | case PRAGMA_OMP_CLAUSE_DEPEND: |
41860 | clauses = cp_parser_omp_clause_depend (parser, list: clauses, |
41861 | loc: token->location); |
41862 | c_name = "depend" ; |
41863 | break; |
41864 | case PRAGMA_OMP_CLAUSE_DOACROSS: |
41865 | clauses = cp_parser_omp_clause_doacross (parser, list: clauses, |
41866 | loc: token->location); |
41867 | c_name = "doacross" ; |
41868 | break; |
41869 | case PRAGMA_OMP_CLAUSE_DETACH: |
41870 | clauses = cp_parser_omp_clause_detach (parser, list: clauses); |
41871 | c_name = "detach" ; |
41872 | break; |
41873 | case PRAGMA_OMP_CLAUSE_MAP: |
41874 | clauses = cp_parser_omp_clause_map (parser, list: clauses); |
41875 | c_name = "map" ; |
41876 | break; |
41877 | case PRAGMA_OMP_CLAUSE_DEVICE: |
41878 | clauses = cp_parser_omp_clause_device (parser, list: clauses, |
41879 | location: token->location); |
41880 | c_name = "device" ; |
41881 | break; |
41882 | case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE: |
41883 | clauses = cp_parser_omp_clause_dist_schedule (parser, list: clauses, |
41884 | location: token->location); |
41885 | c_name = "dist_schedule" ; |
41886 | break; |
41887 | case PRAGMA_OMP_CLAUSE_PROC_BIND: |
41888 | clauses = cp_parser_omp_clause_proc_bind (parser, list: clauses, |
41889 | location: token->location); |
41890 | c_name = "proc_bind" ; |
41891 | break; |
41892 | case PRAGMA_OMP_CLAUSE_DEVICE_TYPE: |
41893 | clauses = cp_parser_omp_clause_device_type (parser, list: clauses, |
41894 | location: token->location); |
41895 | c_name = "device_type" ; |
41896 | break; |
41897 | case PRAGMA_OMP_CLAUSE_SAFELEN: |
41898 | clauses = cp_parser_omp_clause_safelen (parser, list: clauses, |
41899 | location: token->location); |
41900 | c_name = "safelen" ; |
41901 | break; |
41902 | case PRAGMA_OMP_CLAUSE_SIMDLEN: |
41903 | clauses = cp_parser_omp_clause_simdlen (parser, list: clauses, |
41904 | location: token->location); |
41905 | c_name = "simdlen" ; |
41906 | break; |
41907 | case PRAGMA_OMP_CLAUSE_NOGROUP: |
41908 | clauses = cp_parser_omp_clause_nogroup (parser, list: clauses, |
41909 | location: token->location); |
41910 | c_name = "nogroup" ; |
41911 | break; |
41912 | case PRAGMA_OMP_CLAUSE_THREADS: |
41913 | clauses |
41914 | = cp_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS, |
41915 | list: clauses, location: token->location); |
41916 | c_name = "threads" ; |
41917 | break; |
41918 | case PRAGMA_OMP_CLAUSE_SIMD: |
41919 | clauses |
41920 | = cp_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD, |
41921 | list: clauses, location: token->location); |
41922 | c_name = "simd" ; |
41923 | break; |
41924 | case PRAGMA_OMP_CLAUSE_ENTER: |
41925 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
41926 | list: clauses); |
41927 | c_name = "enter" ; |
41928 | break; |
41929 | default: |
41930 | cp_parser_error (parser, gmsgid: "expected an OpenMP clause" ); |
41931 | goto saw_error; |
41932 | } |
41933 | |
41934 | first = false; |
41935 | |
41936 | if (((mask >> c_kind) & 1) == 0) |
41937 | { |
41938 | /* Remove the invalid clause(s) from the list to avoid |
41939 | confusing the rest of the compiler. */ |
41940 | clauses = prev; |
41941 | error_at (token->location, "%qs is not valid for %qs" , c_name, where); |
41942 | } |
41943 | } |
41944 | saw_error: |
41945 | if (!nested) |
41946 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
41947 | if (finish_p) |
41948 | { |
41949 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0) |
41950 | return finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD); |
41951 | else |
41952 | return finish_omp_clauses (clauses, C_ORT_OMP); |
41953 | } |
41954 | return clauses; |
41955 | } |
41956 | |
41957 | /* OpenMP 2.5: |
41958 | structured-block: |
41959 | statement |
41960 | |
41961 | In practice, we're also interested in adding the statement to an |
41962 | outer node. So it is convenient if we work around the fact that |
41963 | cp_parser_statement calls add_stmt. */ |
41964 | |
41965 | static unsigned |
41966 | cp_parser_begin_omp_structured_block (cp_parser *parser) |
41967 | { |
41968 | unsigned save = parser->in_statement; |
41969 | |
41970 | /* Only move the values to IN_OMP_BLOCK if they weren't false. |
41971 | This preserves the "not within loop or switch" style error messages |
41972 | for nonsense cases like |
41973 | void foo() { |
41974 | #pragma omp single |
41975 | break; |
41976 | } |
41977 | */ |
41978 | if (parser->in_statement) |
41979 | parser->in_statement = IN_OMP_BLOCK; |
41980 | |
41981 | return save; |
41982 | } |
41983 | |
41984 | static void |
41985 | cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save) |
41986 | { |
41987 | parser->in_statement = save; |
41988 | } |
41989 | |
41990 | static tree |
41991 | cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) |
41992 | { |
41993 | tree stmt = begin_omp_structured_block (); |
41994 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
41995 | |
41996 | parser->omp_attrs_forbidden_p = true; |
41997 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
41998 | |
41999 | cp_parser_end_omp_structured_block (parser, save); |
42000 | return finish_omp_structured_block (stmt); |
42001 | } |
42002 | |
42003 | /* OpenMP 5.x: |
42004 | # pragma omp allocate (list) clauses |
42005 | |
42006 | OpenMP 5.0 clause: |
42007 | allocator (omp_allocator_handle_t expression) |
42008 | |
42009 | OpenMP 5.1 additional clause: |
42010 | align (constant-expression)] */ |
42011 | |
42012 | static void |
42013 | cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) |
42014 | { |
42015 | tree allocator = NULL_TREE; |
42016 | tree alignment = NULL_TREE; |
42017 | location_t loc = pragma_tok->location; |
42018 | tree nl = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE); |
42019 | |
42020 | do |
42021 | { |
42022 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
42023 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
42024 | cp_lexer_consume_token (lexer: parser->lexer); |
42025 | |
42026 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42027 | break; |
42028 | matching_parens parens; |
42029 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42030 | const char *p = IDENTIFIER_POINTER (id); |
42031 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42032 | cp_lexer_consume_token (lexer: parser->lexer); |
42033 | if (strcmp (s1: p, s2: "allocator" ) != 0 && strcmp (s1: p, s2: "align" ) != 0) |
42034 | { |
42035 | error_at (cloc, "expected %<allocator%> or %<align%>" ); |
42036 | break; |
42037 | } |
42038 | if (!parens.require_open (parser)) |
42039 | break; |
42040 | tree expr = cp_parser_assignment_expression (parser); |
42041 | if (p[2] == 'i' && alignment) |
42042 | { |
42043 | error_at (cloc, "too many %qs clauses" , "align" ); |
42044 | break; |
42045 | } |
42046 | else if (p[2] == 'i') |
42047 | { |
42048 | if (expr != error_mark_node) |
42049 | alignment = expr; |
42050 | /* FIXME: Remove when adding check to semantics.cc; cf FIXME below. */ |
42051 | if (alignment |
42052 | && !type_dependent_expression_p (alignment) |
42053 | && !INTEGRAL_TYPE_P (TREE_TYPE (alignment))) |
42054 | { |
42055 | error_at (cloc, "%<align%> clause argument needs to be " |
42056 | "positive constant power of two integer " |
42057 | "expression" ); |
42058 | alignment = NULL_TREE; |
42059 | } |
42060 | else if (alignment) |
42061 | { |
42062 | alignment = mark_rvalue_use (alignment); |
42063 | if (!processing_template_decl) |
42064 | { |
42065 | alignment = maybe_constant_value (alignment); |
42066 | if (TREE_CODE (alignment) != INTEGER_CST |
42067 | || !tree_fits_uhwi_p (alignment) |
42068 | || !integer_pow2p (alignment)) |
42069 | { |
42070 | error_at (cloc, "%<align%> clause argument needs to be " |
42071 | "positive constant power of two integer " |
42072 | "expression" ); |
42073 | alignment = NULL_TREE; |
42074 | } |
42075 | } |
42076 | } |
42077 | } |
42078 | else if (allocator) |
42079 | { |
42080 | error_at (cloc, "too many %qs clauses" , "allocator" ); |
42081 | break; |
42082 | } |
42083 | else |
42084 | { |
42085 | if (expr != error_mark_node) |
42086 | allocator = expr; |
42087 | } |
42088 | parens.require_close (parser); |
42089 | } while (true); |
42090 | cp_parser_require_pragma_eol (parser, pragma_tok); |
42091 | |
42092 | if (allocator || alignment) |
42093 | for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) |
42094 | { |
42095 | OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; |
42096 | OMP_CLAUSE_ALLOCATE_ALIGN (c) = alignment; |
42097 | } |
42098 | |
42099 | /* FIXME: When implementing properly, delete the align/allocate expr error |
42100 | check above and add one in semantics.cc (to properly handle templates). |
42101 | Base this on the allocator/align modifiers check for the 'allocate' clause |
42102 | in semantics.cc's finish_omp_clauses. */ |
42103 | sorry_at (loc, "%<#pragma omp allocate%> not yet supported" ); |
42104 | } |
42105 | |
42106 | /* OpenMP 2.5: |
42107 | # pragma omp atomic new-line |
42108 | expression-stmt |
42109 | |
42110 | expression-stmt: |
42111 | x binop= expr | x++ | ++x | x-- | --x |
42112 | binop: |
42113 | +, *, -, /, &, ^, |, <<, >> |
42114 | |
42115 | where x is an lvalue expression with scalar type. |
42116 | |
42117 | OpenMP 3.1: |
42118 | # pragma omp atomic new-line |
42119 | update-stmt |
42120 | |
42121 | # pragma omp atomic read new-line |
42122 | read-stmt |
42123 | |
42124 | # pragma omp atomic write new-line |
42125 | write-stmt |
42126 | |
42127 | # pragma omp atomic update new-line |
42128 | update-stmt |
42129 | |
42130 | # pragma omp atomic capture new-line |
42131 | capture-stmt |
42132 | |
42133 | # pragma omp atomic capture new-line |
42134 | capture-block |
42135 | |
42136 | read-stmt: |
42137 | v = x |
42138 | write-stmt: |
42139 | x = expr |
42140 | update-stmt: |
42141 | expression-stmt | x = x binop expr |
42142 | capture-stmt: |
42143 | v = expression-stmt |
42144 | capture-block: |
42145 | { v = x; update-stmt; } | { update-stmt; v = x; } |
42146 | |
42147 | OpenMP 4.0: |
42148 | update-stmt: |
42149 | expression-stmt | x = x binop expr | x = expr binop x |
42150 | capture-stmt: |
42151 | v = update-stmt |
42152 | capture-block: |
42153 | { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; } |
42154 | |
42155 | OpenMP 5.1: |
42156 | # pragma omp atomic compare new-line |
42157 | conditional-update-atomic |
42158 | |
42159 | # pragma omp atomic compare capture new-line |
42160 | conditional-update-capture-atomic |
42161 | |
42162 | conditional-update-atomic: |
42163 | cond-expr-stmt | cond-update-stmt |
42164 | cond-expr-stmt: |
42165 | x = expr ordop x ? expr : x; |
42166 | x = x ordop expr ? expr : x; |
42167 | x = x == e ? d : x; |
42168 | cond-update-stmt: |
42169 | if (expr ordop x) { x = expr; } |
42170 | if (x ordop expr) { x = expr; } |
42171 | if (x == e) { x = d; } |
42172 | ordop: |
42173 | <, > |
42174 | conditional-update-capture-atomic: |
42175 | v = cond-expr-stmt |
42176 | { v = x; cond-expr-stmt } |
42177 | { cond-expr-stmt v = x; } |
42178 | { v = x; cond-update-stmt } |
42179 | { cond-update-stmt v = x; } |
42180 | if (x == e) { x = d; } else { v = x; } |
42181 | { r = x == e; if (r) { x = d; } } |
42182 | { r = x == e; if (r) { x = d; } else { v = x; } } |
42183 | |
42184 | where x, r and v are lvalue expressions with scalar type, |
42185 | expr, e and d are expressions with scalar type and e might be |
42186 | the same as v. */ |
42187 | |
42188 | static void |
42189 | cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) |
42190 | { |
42191 | tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE; |
42192 | tree rhs1 = NULL_TREE, orig_lhs, r = NULL_TREE; |
42193 | location_t loc = pragma_tok->location; |
42194 | enum tree_code code = ERROR_MARK, opcode = NOP_EXPR; |
42195 | enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED; |
42196 | bool structured_block = false; |
42197 | tree clauses = NULL_TREE; |
42198 | bool capture = false; |
42199 | bool compare = false; |
42200 | bool weak = false; |
42201 | enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42202 | bool no_semicolon = false; |
42203 | bool = false; |
42204 | |
42205 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
42206 | { |
42207 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
42208 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
42209 | cp_lexer_consume_token (lexer: parser->lexer); |
42210 | |
42211 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42212 | { |
42213 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42214 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42215 | const char *p = IDENTIFIER_POINTER (id); |
42216 | enum tree_code new_code = ERROR_MARK; |
42217 | enum omp_memory_order new_memory_order |
42218 | = OMP_MEMORY_ORDER_UNSPECIFIED; |
42219 | bool new_capture = false; |
42220 | bool new_compare = false; |
42221 | bool new_weak = false; |
42222 | enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42223 | |
42224 | if (!strcmp (s1: p, s2: "read" )) |
42225 | new_code = OMP_ATOMIC_READ; |
42226 | else if (!strcmp (s1: p, s2: "write" )) |
42227 | new_code = NOP_EXPR; |
42228 | else if (!strcmp (s1: p, s2: "update" )) |
42229 | new_code = OMP_ATOMIC; |
42230 | else if (openacc && !strcmp (s1: p, s2: "capture" )) |
42231 | new_code = OMP_ATOMIC_CAPTURE_NEW; |
42232 | else if (openacc) |
42233 | { |
42234 | p = NULL; |
42235 | error_at (cloc, "expected %<read%>, %<write%>, %<update%>, " |
42236 | "or %<capture%> clause" ); |
42237 | } |
42238 | else if (!strcmp (s1: p, s2: "capture" )) |
42239 | new_capture = true; |
42240 | else if (!strcmp (s1: p, s2: "compare" )) |
42241 | new_compare = true; |
42242 | else if (!strcmp (s1: p, s2: "weak" )) |
42243 | new_weak = true; |
42244 | else if (!strcmp (s1: p, s2: "fail" )) |
42245 | { |
42246 | matching_parens parens; |
42247 | |
42248 | cp_lexer_consume_token (lexer: parser->lexer); |
42249 | if (!parens.require_open (parser)) |
42250 | continue; |
42251 | |
42252 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
42253 | { |
42254 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
42255 | const char *q = IDENTIFIER_POINTER (id); |
42256 | |
42257 | if (!strcmp (s1: q, s2: "seq_cst" )) |
42258 | new_fail = OMP_MEMORY_ORDER_SEQ_CST; |
42259 | else if (!strcmp (s1: q, s2: "acquire" )) |
42260 | new_fail = OMP_MEMORY_ORDER_ACQUIRE; |
42261 | else if (!strcmp (s1: q, s2: "relaxed" )) |
42262 | new_fail = OMP_MEMORY_ORDER_RELAXED; |
42263 | } |
42264 | |
42265 | if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
42266 | { |
42267 | cp_lexer_consume_token (lexer: parser->lexer); |
42268 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
42269 | error_at (cloc, "too many %qs clauses" , "fail" ); |
42270 | else |
42271 | fail = new_fail; |
42272 | } |
42273 | else |
42274 | cp_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> " |
42275 | "or %<relaxed%>" ); |
42276 | if (new_fail == OMP_MEMORY_ORDER_UNSPECIFIED |
42277 | || !parens.require_close (parser)) |
42278 | cp_parser_skip_to_closing_parenthesis (parser, |
42279 | /*recovering=*/true, |
42280 | /*or_comma=*/false, |
42281 | /*consume_paren=*/true); |
42282 | continue; |
42283 | } |
42284 | else if (!strcmp (s1: p, s2: "seq_cst" )) |
42285 | new_memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42286 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
42287 | new_memory_order = OMP_MEMORY_ORDER_ACQ_REL; |
42288 | else if (!strcmp (s1: p, s2: "release" )) |
42289 | new_memory_order = OMP_MEMORY_ORDER_RELEASE; |
42290 | else if (!strcmp (s1: p, s2: "acquire" )) |
42291 | new_memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42292 | else if (!strcmp (s1: p, s2: "relaxed" )) |
42293 | new_memory_order = OMP_MEMORY_ORDER_RELAXED; |
42294 | else if (!strcmp (s1: p, s2: "hint" )) |
42295 | { |
42296 | cp_lexer_consume_token (lexer: parser->lexer); |
42297 | clauses = cp_parser_omp_clause_hint (parser, list: clauses, location: cloc); |
42298 | continue; |
42299 | } |
42300 | else |
42301 | { |
42302 | p = NULL; |
42303 | error_at (cloc, "expected %<read%>, %<write%>, %<update%>, " |
42304 | "%<capture%>, %<compare%>, %<weak%>, %<fail%>, " |
42305 | "%<seq_cst%>, %<acq_rel%>, %<release%>, " |
42306 | "%<relaxed%> or %<hint%> clause" ); |
42307 | } |
42308 | if (p) |
42309 | { |
42310 | if (new_code != ERROR_MARK) |
42311 | { |
42312 | /* OpenACC permits 'update capture'. */ |
42313 | if (openacc |
42314 | && code == OMP_ATOMIC |
42315 | && new_code == OMP_ATOMIC_CAPTURE_NEW) |
42316 | code = new_code; |
42317 | else if (code != ERROR_MARK) |
42318 | error_at (cloc, "too many atomic clauses" ); |
42319 | else |
42320 | code = new_code; |
42321 | } |
42322 | else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED) |
42323 | { |
42324 | if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED) |
42325 | error_at (cloc, "too many memory order clauses" ); |
42326 | else |
42327 | memory_order = new_memory_order; |
42328 | } |
42329 | else if (new_capture) |
42330 | { |
42331 | if (capture) |
42332 | error_at (cloc, "too many %qs clauses" , "capture" ); |
42333 | else |
42334 | capture = true; |
42335 | } |
42336 | else if (new_compare) |
42337 | { |
42338 | if (compare) |
42339 | error_at (cloc, "too many %qs clauses" , "compare" ); |
42340 | else |
42341 | compare = true; |
42342 | } |
42343 | else if (new_weak) |
42344 | { |
42345 | if (weak) |
42346 | error_at (cloc, "too many %qs clauses" , "weak" ); |
42347 | else |
42348 | weak = true; |
42349 | } |
42350 | cp_lexer_consume_token (lexer: parser->lexer); |
42351 | continue; |
42352 | } |
42353 | } |
42354 | break; |
42355 | } |
42356 | cp_parser_require_pragma_eol (parser, pragma_tok); |
42357 | |
42358 | if (code == ERROR_MARK) |
42359 | code = OMP_ATOMIC; |
42360 | if (capture) |
42361 | { |
42362 | if (code != OMP_ATOMIC) |
42363 | error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> " |
42364 | "clauses" , "capture" ); |
42365 | else |
42366 | code = OMP_ATOMIC_CAPTURE_NEW; |
42367 | } |
42368 | if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW) |
42369 | { |
42370 | error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> " |
42371 | "clauses" , "compare" ); |
42372 | compare = false; |
42373 | } |
42374 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare) |
42375 | { |
42376 | error_at (loc, "%qs clause requires %qs clause" , "fail" , "compare" ); |
42377 | fail = OMP_MEMORY_ORDER_UNSPECIFIED; |
42378 | } |
42379 | if (weak && !compare) |
42380 | { |
42381 | error_at (loc, "%qs clause requires %qs clause" , "weak" , "compare" ); |
42382 | weak = false; |
42383 | } |
42384 | if (openacc) |
42385 | memory_order = OMP_MEMORY_ORDER_RELAXED; |
42386 | else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED) |
42387 | { |
42388 | omp_requires_mask |
42389 | = (enum omp_requires) (omp_requires_mask |
42390 | | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED); |
42391 | switch ((enum omp_memory_order) |
42392 | (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER)) |
42393 | { |
42394 | case OMP_MEMORY_ORDER_UNSPECIFIED: |
42395 | case OMP_MEMORY_ORDER_RELAXED: |
42396 | memory_order = OMP_MEMORY_ORDER_RELAXED; |
42397 | break; |
42398 | case OMP_MEMORY_ORDER_SEQ_CST: |
42399 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42400 | break; |
42401 | case OMP_MEMORY_ORDER_ACQ_REL: |
42402 | switch (code) |
42403 | { |
42404 | case OMP_ATOMIC_READ: |
42405 | memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42406 | break; |
42407 | case NOP_EXPR: /* atomic write */ |
42408 | memory_order = OMP_MEMORY_ORDER_RELEASE; |
42409 | break; |
42410 | default: |
42411 | memory_order = OMP_MEMORY_ORDER_ACQ_REL; |
42412 | break; |
42413 | } |
42414 | break; |
42415 | default: |
42416 | gcc_unreachable (); |
42417 | } |
42418 | } |
42419 | else |
42420 | switch (code) |
42421 | { |
42422 | case OMP_ATOMIC_READ: |
42423 | if (memory_order == OMP_MEMORY_ORDER_RELEASE) |
42424 | { |
42425 | error_at (loc, "%<#pragma omp atomic read%> incompatible with " |
42426 | "%<release%> clause" ); |
42427 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42428 | } |
42429 | else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) |
42430 | memory_order = OMP_MEMORY_ORDER_ACQUIRE; |
42431 | break; |
42432 | case NOP_EXPR: /* atomic write */ |
42433 | if (memory_order == OMP_MEMORY_ORDER_ACQUIRE) |
42434 | { |
42435 | error_at (loc, "%<#pragma omp atomic write%> incompatible with " |
42436 | "%<acquire%> clause" ); |
42437 | memory_order = OMP_MEMORY_ORDER_SEQ_CST; |
42438 | } |
42439 | else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL) |
42440 | memory_order = OMP_MEMORY_ORDER_RELEASE; |
42441 | break; |
42442 | default: |
42443 | break; |
42444 | } |
42445 | if (fail != OMP_MEMORY_ORDER_UNSPECIFIED) |
42446 | memory_order |
42447 | = (enum omp_memory_order) (memory_order |
42448 | | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT)); |
42449 | |
42450 | switch (code) |
42451 | { |
42452 | case OMP_ATOMIC_READ: |
42453 | case NOP_EXPR: /* atomic write */ |
42454 | v = cp_parser_unary_expression (parser); |
42455 | if (v == error_mark_node) |
42456 | goto saw_error; |
42457 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
42458 | goto saw_error; |
42459 | if (code == NOP_EXPR) |
42460 | lhs = cp_parser_expression (parser); |
42461 | else |
42462 | lhs = cp_parser_unary_expression (parser); |
42463 | if (lhs == error_mark_node) |
42464 | goto saw_error; |
42465 | if (code == NOP_EXPR) |
42466 | { |
42467 | /* atomic write is represented by OMP_ATOMIC with NOP_EXPR |
42468 | opcode. */ |
42469 | code = OMP_ATOMIC; |
42470 | rhs = lhs; |
42471 | lhs = v; |
42472 | v = NULL_TREE; |
42473 | } |
42474 | goto done; |
42475 | case OMP_ATOMIC_CAPTURE_NEW: |
42476 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
42477 | { |
42478 | cp_lexer_consume_token (lexer: parser->lexer); |
42479 | structured_block = true; |
42480 | } |
42481 | else if (compare |
42482 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
42483 | break; |
42484 | else |
42485 | { |
42486 | v = cp_parser_unary_expression (parser); |
42487 | if (v == error_mark_node) |
42488 | goto saw_error; |
42489 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
42490 | goto saw_error; |
42491 | if (compare |
42492 | && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
42493 | { |
42494 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42495 | error_at (eloc, "expected expression" ); |
42496 | goto saw_error; |
42497 | } |
42498 | } |
42499 | default: |
42500 | break; |
42501 | } |
42502 | |
42503 | restart: |
42504 | if (compare && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_IF)) |
42505 | { |
42506 | cp_lexer_consume_token (lexer: parser->lexer); |
42507 | |
42508 | matching_parens parens; |
42509 | if (!parens.require_open (parser)) |
42510 | goto saw_error; |
42511 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42512 | tree cmp_expr; |
42513 | if (r) |
42514 | cmp_expr = cp_parser_unary_expression (parser); |
42515 | else |
42516 | cmp_expr = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
42517 | prec: PREC_NOT_OPERATOR, NULL); |
42518 | if (!parens.require_close (parser)) |
42519 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
42520 | if (cmp_expr == error_mark_node) |
42521 | goto saw_error; |
42522 | if (r) |
42523 | { |
42524 | if (!cp_tree_equal (cmp_expr, r)) |
42525 | goto bad_if; |
42526 | cmp_expr = rhs; |
42527 | rhs = NULL_TREE; |
42528 | gcc_assert (TREE_CODE (cmp_expr) == EQ_EXPR); |
42529 | } |
42530 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
42531 | ; |
42532 | else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW) |
42533 | { |
42534 | error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc), |
42535 | "expected %<==%> comparison in %<if%> condition" ); |
42536 | goto saw_error; |
42537 | } |
42538 | else if (TREE_CODE (cmp_expr) != GT_EXPR |
42539 | && TREE_CODE (cmp_expr) != LT_EXPR) |
42540 | { |
42541 | error_at (EXPR_LOC_OR_LOC (cmp_expr, eloc), |
42542 | "expected %<==%>, %<<%> or %<>%> comparison in %<if%> " |
42543 | "condition" ); |
42544 | goto saw_error; |
42545 | } |
42546 | if (!cp_parser_require (parser, type: CPP_OPEN_BRACE, token_desc: RT_OPEN_BRACE)) |
42547 | goto saw_error; |
42548 | |
42549 | extra_scope = true; |
42550 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42551 | lhs = cp_parser_unary_expression (parser); |
42552 | orig_lhs = lhs; |
42553 | if (lhs == error_mark_node) |
42554 | goto saw_error; |
42555 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
42556 | { |
42557 | cp_parser_error (parser, gmsgid: "expected %<=%>" ); |
42558 | goto saw_error; |
42559 | } |
42560 | cp_lexer_consume_token (lexer: parser->lexer); |
42561 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42562 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
42563 | rhs1 = cp_parser_expression (parser); |
42564 | else |
42565 | rhs1 = cp_parser_simple_cast_expression (parser); |
42566 | |
42567 | if (!cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
42568 | goto saw_error; |
42569 | |
42570 | if (!cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE)) |
42571 | goto saw_error; |
42572 | |
42573 | extra_scope = false; |
42574 | no_semicolon = true; |
42575 | |
42576 | if (cp_tree_equal (TREE_OPERAND (cmp_expr, 0), lhs)) |
42577 | { |
42578 | if (TREE_CODE (cmp_expr) == EQ_EXPR) |
42579 | { |
42580 | opcode = COND_EXPR; |
42581 | rhs = TREE_OPERAND (cmp_expr, 1); |
42582 | } |
42583 | else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), rhs1)) |
42584 | { |
42585 | opcode = (TREE_CODE (cmp_expr) == GT_EXPR |
42586 | ? MIN_EXPR : MAX_EXPR); |
42587 | rhs = rhs1; |
42588 | rhs1 = TREE_OPERAND (cmp_expr, 0); |
42589 | } |
42590 | else |
42591 | goto bad_if; |
42592 | } |
42593 | else if (TREE_CODE (cmp_expr) == EQ_EXPR) |
42594 | goto bad_if; |
42595 | else if (cp_tree_equal (TREE_OPERAND (cmp_expr, 1), lhs) |
42596 | && cp_tree_equal (TREE_OPERAND (cmp_expr, 0), rhs1)) |
42597 | { |
42598 | opcode = (TREE_CODE (cmp_expr) == GT_EXPR |
42599 | ? MAX_EXPR : MIN_EXPR); |
42600 | rhs = rhs1; |
42601 | rhs1 = TREE_OPERAND (cmp_expr, 1); |
42602 | } |
42603 | else |
42604 | { |
42605 | bad_if: |
42606 | cp_parser_error (parser, |
42607 | gmsgid: "invalid form of %<#pragma omp atomic compare%>" ); |
42608 | goto saw_error; |
42609 | } |
42610 | |
42611 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ELSE)) |
42612 | { |
42613 | if (code != OMP_ATOMIC_CAPTURE_NEW |
42614 | || (structured_block && r == NULL_TREE) |
42615 | || TREE_CODE (cmp_expr) != EQ_EXPR) |
42616 | { |
42617 | eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
42618 | error_at (eloc, "unexpected %<else%>" ); |
42619 | goto saw_error; |
42620 | } |
42621 | |
42622 | cp_lexer_consume_token (lexer: parser->lexer); |
42623 | |
42624 | if (!cp_parser_require (parser, type: CPP_OPEN_BRACE, token_desc: RT_OPEN_BRACE)) |
42625 | goto saw_error; |
42626 | |
42627 | extra_scope = true; |
42628 | v = cp_parser_unary_expression (parser); |
42629 | if (v == error_mark_node) |
42630 | goto saw_error; |
42631 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
42632 | goto saw_error; |
42633 | |
42634 | tree expr = cp_parser_simple_cast_expression (parser); |
42635 | |
42636 | if (!cp_tree_equal (expr, lhs)) |
42637 | goto bad_if; |
42638 | |
42639 | if (!cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
42640 | goto saw_error; |
42641 | |
42642 | if (!cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE)) |
42643 | goto saw_error; |
42644 | |
42645 | extra_scope = false; |
42646 | code = OMP_ATOMIC_CAPTURE_OLD; |
42647 | if (r == NULL_TREE) |
42648 | /* Signal to c_finish_omp_atomic that in |
42649 | if (x == e) { x = d; } else { v = x; } |
42650 | case the store to v should be conditional. */ |
42651 | r = void_list_node; |
42652 | } |
42653 | else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
42654 | { |
42655 | cp_parser_error (parser, gmsgid: "expected %<else%>" ); |
42656 | goto saw_error; |
42657 | } |
42658 | else if (code == OMP_ATOMIC_CAPTURE_NEW |
42659 | && r != NULL_TREE |
42660 | && v == NULL_TREE) |
42661 | code = OMP_ATOMIC; |
42662 | goto stmt_done; |
42663 | } |
42664 | lhs = cp_parser_unary_expression (parser); |
42665 | orig_lhs = lhs; |
42666 | switch (TREE_CODE (lhs)) |
42667 | { |
42668 | case ERROR_MARK: |
42669 | goto saw_error; |
42670 | |
42671 | case POSTINCREMENT_EXPR: |
42672 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
42673 | code = OMP_ATOMIC_CAPTURE_OLD; |
42674 | /* FALLTHROUGH */ |
42675 | case PREINCREMENT_EXPR: |
42676 | lhs = TREE_OPERAND (lhs, 0); |
42677 | opcode = PLUS_EXPR; |
42678 | rhs = integer_one_node; |
42679 | if (compare) |
42680 | goto invalid_compare; |
42681 | break; |
42682 | |
42683 | case POSTDECREMENT_EXPR: |
42684 | if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) |
42685 | code = OMP_ATOMIC_CAPTURE_OLD; |
42686 | /* FALLTHROUGH */ |
42687 | case PREDECREMENT_EXPR: |
42688 | lhs = TREE_OPERAND (lhs, 0); |
42689 | opcode = MINUS_EXPR; |
42690 | rhs = integer_one_node; |
42691 | if (compare) |
42692 | goto invalid_compare; |
42693 | break; |
42694 | |
42695 | case COMPOUND_EXPR: |
42696 | if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR |
42697 | && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR |
42698 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR |
42699 | && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0) |
42700 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND |
42701 | (TREE_OPERAND (lhs, 1), 0), 0))) |
42702 | == BOOLEAN_TYPE) |
42703 | /* Undo effects of boolean_increment for post {in,de}crement. */ |
42704 | lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0); |
42705 | /* FALLTHRU */ |
42706 | case MODIFY_EXPR: |
42707 | if (TREE_CODE (lhs) == MODIFY_EXPR |
42708 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE) |
42709 | { |
42710 | /* Undo effects of boolean_increment. */ |
42711 | if (integer_onep (TREE_OPERAND (lhs, 1))) |
42712 | { |
42713 | /* This is pre or post increment. */ |
42714 | rhs = TREE_OPERAND (lhs, 1); |
42715 | lhs = TREE_OPERAND (lhs, 0); |
42716 | opcode = NOP_EXPR; |
42717 | if (code == OMP_ATOMIC_CAPTURE_NEW |
42718 | && !structured_block |
42719 | && TREE_CODE (orig_lhs) == COMPOUND_EXPR) |
42720 | code = OMP_ATOMIC_CAPTURE_OLD; |
42721 | if (compare) |
42722 | goto invalid_compare; |
42723 | break; |
42724 | } |
42725 | } |
42726 | /* FALLTHRU */ |
42727 | default: |
42728 | if (compare && !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_EQ)) |
42729 | { |
42730 | cp_parser_error (parser, gmsgid: "expected %<=%>" ); |
42731 | goto saw_error; |
42732 | } |
42733 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
42734 | { |
42735 | case CPP_MULT_EQ: |
42736 | opcode = MULT_EXPR; |
42737 | break; |
42738 | case CPP_DIV_EQ: |
42739 | opcode = TRUNC_DIV_EXPR; |
42740 | break; |
42741 | case CPP_PLUS_EQ: |
42742 | opcode = PLUS_EXPR; |
42743 | break; |
42744 | case CPP_MINUS_EQ: |
42745 | opcode = MINUS_EXPR; |
42746 | break; |
42747 | case CPP_LSHIFT_EQ: |
42748 | opcode = LSHIFT_EXPR; |
42749 | break; |
42750 | case CPP_RSHIFT_EQ: |
42751 | opcode = RSHIFT_EXPR; |
42752 | break; |
42753 | case CPP_AND_EQ: |
42754 | opcode = BIT_AND_EXPR; |
42755 | break; |
42756 | case CPP_OR_EQ: |
42757 | opcode = BIT_IOR_EXPR; |
42758 | break; |
42759 | case CPP_XOR_EQ: |
42760 | opcode = BIT_XOR_EXPR; |
42761 | break; |
42762 | case CPP_EQ: |
42763 | enum cp_parser_prec oprec; |
42764 | cp_token *token; |
42765 | cp_lexer_consume_token (lexer: parser->lexer); |
42766 | cp_parser_parse_tentatively (parser); |
42767 | rhs1 = cp_parser_simple_cast_expression (parser); |
42768 | if (rhs1 == error_mark_node) |
42769 | { |
42770 | cp_parser_abort_tentative_parse (parser); |
42771 | cp_parser_simple_cast_expression (parser); |
42772 | goto saw_error; |
42773 | } |
42774 | token = cp_lexer_peek_token (lexer: parser->lexer); |
42775 | if (token->type != CPP_SEMICOLON |
42776 | && (!compare || token->type != CPP_QUERY) |
42777 | && !cp_tree_equal (lhs, rhs1)) |
42778 | { |
42779 | cp_parser_abort_tentative_parse (parser); |
42780 | cp_parser_parse_tentatively (parser); |
42781 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
42782 | prec: PREC_NOT_OPERATOR, NULL); |
42783 | if (rhs == error_mark_node) |
42784 | { |
42785 | cp_parser_abort_tentative_parse (parser); |
42786 | cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
42787 | prec: PREC_NOT_OPERATOR, NULL); |
42788 | goto saw_error; |
42789 | } |
42790 | switch (TREE_CODE (rhs)) |
42791 | { |
42792 | case MULT_EXPR: |
42793 | case TRUNC_DIV_EXPR: |
42794 | case RDIV_EXPR: |
42795 | case PLUS_EXPR: |
42796 | case MINUS_EXPR: |
42797 | case LSHIFT_EXPR: |
42798 | case RSHIFT_EXPR: |
42799 | case BIT_AND_EXPR: |
42800 | case BIT_IOR_EXPR: |
42801 | case BIT_XOR_EXPR: |
42802 | if (compare) |
42803 | break; |
42804 | if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1))) |
42805 | { |
42806 | if (cp_parser_parse_definitely (parser)) |
42807 | { |
42808 | opcode = TREE_CODE (rhs); |
42809 | rhs1 = TREE_OPERAND (rhs, 0); |
42810 | rhs = TREE_OPERAND (rhs, 1); |
42811 | goto stmt_done; |
42812 | } |
42813 | else |
42814 | goto saw_error; |
42815 | } |
42816 | break; |
42817 | case EQ_EXPR: |
42818 | if (!compare |
42819 | || code != OMP_ATOMIC_CAPTURE_NEW |
42820 | || !structured_block |
42821 | || v |
42822 | || r) |
42823 | break; |
42824 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON) |
42825 | && cp_lexer_nth_token_is_keyword (lexer: parser->lexer, |
42826 | n: 2, keyword: RID_IF)) |
42827 | { |
42828 | if (cp_parser_parse_definitely (parser)) |
42829 | { |
42830 | r = lhs; |
42831 | lhs = NULL_TREE; |
42832 | rhs1 = NULL_TREE; |
42833 | cp_lexer_consume_token (lexer: parser->lexer); |
42834 | goto restart; |
42835 | } |
42836 | } |
42837 | break; |
42838 | case GT_EXPR: |
42839 | case LT_EXPR: |
42840 | if (compare |
42841 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY) |
42842 | && cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)) |
42843 | && cp_parser_parse_definitely (parser)) |
42844 | { |
42845 | opcode = TREE_CODE (rhs); |
42846 | rhs1 = TREE_OPERAND (rhs, 0); |
42847 | rhs = TREE_OPERAND (rhs, 1); |
42848 | cond_expr: |
42849 | cp_lexer_consume_token (lexer: parser->lexer); |
42850 | bool saved_colon_corrects_to_scope_p |
42851 | = parser->colon_corrects_to_scope_p; |
42852 | parser->colon_corrects_to_scope_p = false; |
42853 | tree e1 = cp_parser_expression (parser); |
42854 | parser->colon_corrects_to_scope_p |
42855 | = saved_colon_corrects_to_scope_p; |
42856 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
42857 | tree e2 = cp_parser_simple_cast_expression (parser); |
42858 | if (cp_tree_equal (lhs, e2)) |
42859 | { |
42860 | if (cp_tree_equal (lhs, rhs1)) |
42861 | { |
42862 | if (opcode == EQ_EXPR) |
42863 | { |
42864 | opcode = COND_EXPR; |
42865 | rhs1 = e1; |
42866 | goto stmt_done; |
42867 | } |
42868 | if (cp_tree_equal (rhs, e1)) |
42869 | { |
42870 | opcode |
42871 | = opcode == GT_EXPR ? MIN_EXPR : MAX_EXPR; |
42872 | rhs = e1; |
42873 | goto stmt_done; |
42874 | } |
42875 | } |
42876 | else |
42877 | { |
42878 | gcc_assert (opcode != EQ_EXPR); |
42879 | if (cp_tree_equal (rhs1, e1)) |
42880 | { |
42881 | opcode |
42882 | = opcode == GT_EXPR ? MAX_EXPR : MIN_EXPR; |
42883 | rhs1 = rhs; |
42884 | rhs = e1; |
42885 | goto stmt_done; |
42886 | } |
42887 | } |
42888 | } |
42889 | cp_parser_error (parser, |
42890 | gmsgid: "invalid form of " |
42891 | "%<#pragma omp atomic compare%>" ); |
42892 | goto saw_error; |
42893 | } |
42894 | break; |
42895 | default: |
42896 | break; |
42897 | } |
42898 | cp_parser_abort_tentative_parse (parser); |
42899 | if (structured_block |
42900 | && code == OMP_ATOMIC_CAPTURE_OLD |
42901 | && !compare) |
42902 | { |
42903 | rhs = cp_parser_expression (parser); |
42904 | if (rhs == error_mark_node) |
42905 | goto saw_error; |
42906 | opcode = NOP_EXPR; |
42907 | rhs1 = NULL_TREE; |
42908 | goto stmt_done; |
42909 | } |
42910 | cp_parser_error (parser, |
42911 | gmsgid: "invalid form of %<#pragma omp atomic%>" ); |
42912 | goto saw_error; |
42913 | } |
42914 | if (!cp_parser_parse_definitely (parser)) |
42915 | goto saw_error; |
42916 | switch (token->type) |
42917 | { |
42918 | case CPP_SEMICOLON: |
42919 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW) |
42920 | { |
42921 | code = OMP_ATOMIC_CAPTURE_OLD; |
42922 | v = lhs; |
42923 | lhs = NULL_TREE; |
42924 | lhs1 = rhs1; |
42925 | rhs1 = NULL_TREE; |
42926 | cp_lexer_consume_token (lexer: parser->lexer); |
42927 | goto restart; |
42928 | } |
42929 | else if (structured_block && !compare) |
42930 | { |
42931 | opcode = NOP_EXPR; |
42932 | rhs = rhs1; |
42933 | rhs1 = NULL_TREE; |
42934 | goto stmt_done; |
42935 | } |
42936 | cp_parser_error (parser, |
42937 | gmsgid: "invalid form of %<#pragma omp atomic%>" ); |
42938 | goto saw_error; |
42939 | case CPP_MULT: |
42940 | opcode = MULT_EXPR; |
42941 | break; |
42942 | case CPP_DIV: |
42943 | opcode = TRUNC_DIV_EXPR; |
42944 | break; |
42945 | case CPP_PLUS: |
42946 | opcode = PLUS_EXPR; |
42947 | break; |
42948 | case CPP_MINUS: |
42949 | opcode = MINUS_EXPR; |
42950 | break; |
42951 | case CPP_LSHIFT: |
42952 | opcode = LSHIFT_EXPR; |
42953 | break; |
42954 | case CPP_RSHIFT: |
42955 | opcode = RSHIFT_EXPR; |
42956 | break; |
42957 | case CPP_AND: |
42958 | opcode = BIT_AND_EXPR; |
42959 | break; |
42960 | case CPP_OR: |
42961 | opcode = BIT_IOR_EXPR; |
42962 | break; |
42963 | case CPP_XOR: |
42964 | opcode = BIT_XOR_EXPR; |
42965 | break; |
42966 | case CPP_EQ_EQ: |
42967 | opcode = EQ_EXPR; |
42968 | break; |
42969 | case CPP_GREATER: |
42970 | opcode = GT_EXPR; |
42971 | break; |
42972 | case CPP_LESS: |
42973 | opcode = LT_EXPR; |
42974 | break; |
42975 | default: |
42976 | cp_parser_error (parser, |
42977 | gmsgid: "invalid operator for %<#pragma omp atomic%>" ); |
42978 | goto saw_error; |
42979 | } |
42980 | if (compare |
42981 | && TREE_CODE_CLASS (opcode) != tcc_comparison) |
42982 | { |
42983 | cp_parser_error (parser, |
42984 | gmsgid: "invalid form of " |
42985 | "%<#pragma omp atomic compare%>" ); |
42986 | goto saw_error; |
42987 | } |
42988 | oprec = TOKEN_PRECEDENCE (token); |
42989 | gcc_assert (oprec != PREC_NOT_OPERATOR); |
42990 | if (commutative_tree_code (opcode)) |
42991 | oprec = (enum cp_parser_prec) (oprec - 1); |
42992 | cp_lexer_consume_token (lexer: parser->lexer); |
42993 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
42994 | prec: oprec, NULL); |
42995 | if (rhs == error_mark_node) |
42996 | goto saw_error; |
42997 | if (compare) |
42998 | { |
42999 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_QUERY)) |
43000 | { |
43001 | cp_parser_error (parser, |
43002 | gmsgid: "invalid form of " |
43003 | "%<#pragma omp atomic compare%>" ); |
43004 | goto saw_error; |
43005 | } |
43006 | goto cond_expr; |
43007 | } |
43008 | goto stmt_done; |
43009 | default: |
43010 | cp_parser_error (parser, |
43011 | gmsgid: "invalid operator for %<#pragma omp atomic%>" ); |
43012 | goto saw_error; |
43013 | } |
43014 | cp_lexer_consume_token (lexer: parser->lexer); |
43015 | |
43016 | rhs = cp_parser_expression (parser); |
43017 | if (rhs == error_mark_node) |
43018 | goto saw_error; |
43019 | break; |
43020 | } |
43021 | stmt_done: |
43022 | if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE) |
43023 | { |
43024 | if (!no_semicolon |
43025 | && !cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON)) |
43026 | goto saw_error; |
43027 | no_semicolon = false; |
43028 | v = cp_parser_unary_expression (parser); |
43029 | if (v == error_mark_node) |
43030 | goto saw_error; |
43031 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
43032 | goto saw_error; |
43033 | lhs1 = cp_parser_unary_expression (parser); |
43034 | if (lhs1 == error_mark_node) |
43035 | goto saw_error; |
43036 | } |
43037 | if (structured_block) |
43038 | { |
43039 | if (!no_semicolon) |
43040 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
43041 | cp_parser_require (parser, type: CPP_CLOSE_BRACE, token_desc: RT_CLOSE_BRACE); |
43042 | } |
43043 | done: |
43044 | if (weak && opcode != COND_EXPR) |
43045 | { |
43046 | error_at (loc, "%<weak%> clause requires atomic equality comparison" ); |
43047 | weak = false; |
43048 | } |
43049 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
43050 | finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1, |
43051 | rhs1, r, clauses, memory_order, weak); |
43052 | if (!structured_block && !no_semicolon) |
43053 | cp_parser_consume_semicolon_at_end_of_statement (parser); |
43054 | return; |
43055 | |
43056 | invalid_compare: |
43057 | error ("invalid form of %<pragma omp atomic compare%>" ); |
43058 | /* FALLTHRU */ |
43059 | saw_error: |
43060 | cp_parser_skip_to_end_of_block_or_statement (parser); |
43061 | if (extra_scope && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43062 | cp_lexer_consume_token (lexer: parser->lexer); |
43063 | if (structured_block) |
43064 | { |
43065 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43066 | cp_lexer_consume_token (lexer: parser->lexer); |
43067 | else if (code == OMP_ATOMIC_CAPTURE_NEW) |
43068 | { |
43069 | cp_parser_skip_to_end_of_block_or_statement (parser); |
43070 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
43071 | cp_lexer_consume_token (lexer: parser->lexer); |
43072 | } |
43073 | } |
43074 | } |
43075 | |
43076 | |
43077 | /* OpenMP 2.5: |
43078 | # pragma omp barrier new-line */ |
43079 | |
43080 | static void |
43081 | cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok) |
43082 | { |
43083 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43084 | finish_omp_barrier (); |
43085 | } |
43086 | |
43087 | /* OpenMP 2.5: |
43088 | # pragma omp critical [(name)] new-line |
43089 | structured-block |
43090 | |
43091 | OpenMP 4.5: |
43092 | # pragma omp critical [(name) [hint(expression)]] new-line |
43093 | structured-block */ |
43094 | |
43095 | #define OMP_CRITICAL_CLAUSE_MASK \ |
43096 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) ) |
43097 | |
43098 | static tree |
43099 | cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
43100 | { |
43101 | tree stmt, name = NULL_TREE, clauses = NULL_TREE; |
43102 | |
43103 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
43104 | { |
43105 | matching_parens parens; |
43106 | parens.consume_open (parser); |
43107 | |
43108 | name = cp_parser_identifier (parser); |
43109 | |
43110 | if (name == error_mark_node |
43111 | || !parens.require_close (parser)) |
43112 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
43113 | /*or_comma=*/false, |
43114 | /*consume_paren=*/true); |
43115 | if (name == error_mark_node) |
43116 | name = NULL; |
43117 | |
43118 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
43119 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
43120 | cp_lexer_consume_token (lexer: parser->lexer); |
43121 | } |
43122 | |
43123 | clauses = cp_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK, |
43124 | where: "#pragma omp critical" , pragma_tok); |
43125 | |
43126 | stmt = cp_parser_omp_structured_block (parser, if_p); |
43127 | return c_finish_omp_critical (input_location, stmt, name, clauses); |
43128 | } |
43129 | |
43130 | /* OpenMP 5.0: |
43131 | # pragma omp depobj ( depobj ) depobj-clause new-line |
43132 | |
43133 | depobj-clause: |
43134 | depend (dependence-type : locator) |
43135 | destroy |
43136 | update (dependence-type) |
43137 | |
43138 | dependence-type: |
43139 | in |
43140 | out |
43141 | inout |
43142 | mutexinout */ |
43143 | |
43144 | static void |
43145 | cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) |
43146 | { |
43147 | location_t loc = pragma_tok->location; |
43148 | matching_parens parens; |
43149 | if (!parens.require_open (parser)) |
43150 | { |
43151 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
43152 | return; |
43153 | } |
43154 | |
43155 | tree depobj = cp_parser_assignment_expression (parser); |
43156 | |
43157 | if (!parens.require_close (parser)) |
43158 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
43159 | /*or_comma=*/false, |
43160 | /*consume_paren=*/true); |
43161 | |
43162 | tree clause = NULL_TREE; |
43163 | enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; |
43164 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
43165 | cp_lexer_consume_token (lexer: parser->lexer); |
43166 | location_t c_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43167 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43168 | { |
43169 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43170 | const char *p = IDENTIFIER_POINTER (id); |
43171 | |
43172 | cp_lexer_consume_token (lexer: parser->lexer); |
43173 | if (!strcmp (s1: "depend" , s2: p)) |
43174 | { |
43175 | /* Don't create location wrapper nodes within the depend clause. */ |
43176 | auto_suppress_location_wrappers sentinel; |
43177 | clause = cp_parser_omp_clause_depend (parser, NULL_TREE, loc: c_loc); |
43178 | if (clause) |
43179 | clause = finish_omp_clauses (clause, C_ORT_OMP); |
43180 | if (!clause) |
43181 | clause = error_mark_node; |
43182 | } |
43183 | else if (!strcmp (s1: "destroy" , s2: p)) |
43184 | kind = OMP_CLAUSE_DEPEND_LAST; |
43185 | else if (!strcmp (s1: "update" , s2: p)) |
43186 | { |
43187 | matching_parens c_parens; |
43188 | if (c_parens.require_open (parser)) |
43189 | { |
43190 | location_t c2_loc |
43191 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43192 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43193 | { |
43194 | tree id2 = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43195 | const char *p2 = IDENTIFIER_POINTER (id2); |
43196 | |
43197 | cp_lexer_consume_token (lexer: parser->lexer); |
43198 | if (!strcmp (s1: "in" , s2: p2)) |
43199 | kind = OMP_CLAUSE_DEPEND_IN; |
43200 | else if (!strcmp (s1: "out" , s2: p2)) |
43201 | kind = OMP_CLAUSE_DEPEND_OUT; |
43202 | else if (!strcmp (s1: "inout" , s2: p2)) |
43203 | kind = OMP_CLAUSE_DEPEND_INOUT; |
43204 | else if (!strcmp (s1: "mutexinoutset" , s2: p2)) |
43205 | kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET; |
43206 | else if (!strcmp (s1: "inoutset" , s2: p2)) |
43207 | kind = OMP_CLAUSE_DEPEND_INOUTSET; |
43208 | } |
43209 | if (kind == OMP_CLAUSE_DEPEND_INVALID) |
43210 | { |
43211 | clause = error_mark_node; |
43212 | error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " |
43213 | "%<mutexinoutset%> or %<inoutset%>" ); |
43214 | } |
43215 | if (!c_parens.require_close (parser)) |
43216 | cp_parser_skip_to_closing_parenthesis (parser, |
43217 | /*recovering=*/true, |
43218 | /*or_comma=*/false, |
43219 | /*consume_paren=*/true); |
43220 | } |
43221 | else |
43222 | clause = error_mark_node; |
43223 | } |
43224 | } |
43225 | if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) |
43226 | { |
43227 | clause = error_mark_node; |
43228 | error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause" ); |
43229 | } |
43230 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43231 | |
43232 | finish_omp_depobj (loc, depobj, kind, clause); |
43233 | } |
43234 | |
43235 | |
43236 | /* OpenMP 2.5: |
43237 | # pragma omp flush flush-vars[opt] new-line |
43238 | |
43239 | flush-vars: |
43240 | ( variable-list ) |
43241 | |
43242 | OpenMP 5.0: |
43243 | # pragma omp flush memory-order-clause new-line */ |
43244 | |
43245 | static void |
43246 | cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) |
43247 | { |
43248 | enum memmodel mo = MEMMODEL_LAST; |
43249 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
43250 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
43251 | cp_lexer_consume_token (lexer: parser->lexer); |
43252 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
43253 | { |
43254 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
43255 | const char *p = IDENTIFIER_POINTER (id); |
43256 | if (!strcmp (s1: p, s2: "seq_cst" )) |
43257 | mo = MEMMODEL_SEQ_CST; |
43258 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
43259 | mo = MEMMODEL_ACQ_REL; |
43260 | else if (!strcmp (s1: p, s2: "release" )) |
43261 | mo = MEMMODEL_RELEASE; |
43262 | else if (!strcmp (s1: p, s2: "acquire" )) |
43263 | mo = MEMMODEL_ACQUIRE; |
43264 | else |
43265 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
43266 | "expected %<seq_cst%>, %<acq_rel%>, %<release%> or " |
43267 | "%<acquire%>" ); |
43268 | cp_lexer_consume_token (lexer: parser->lexer); |
43269 | } |
43270 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
43271 | { |
43272 | if (mo != MEMMODEL_LAST) |
43273 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
43274 | "%<flush%> list specified together with memory order " |
43275 | "clause" ); |
43276 | (void) cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
43277 | } |
43278 | cp_parser_require_pragma_eol (parser, pragma_tok); |
43279 | |
43280 | finish_omp_flush (mo); |
43281 | } |
43282 | |
43283 | /* Helper function, to parse omp for increment expression. */ |
43284 | |
43285 | static tree |
43286 | cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code) |
43287 | { |
43288 | tree cond = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: true, |
43289 | prec: PREC_NOT_OPERATOR, NULL); |
43290 | if (cond == error_mark_node |
43291 | || cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
43292 | { |
43293 | cp_parser_skip_to_end_of_statement (parser); |
43294 | return error_mark_node; |
43295 | } |
43296 | |
43297 | switch (TREE_CODE (cond)) |
43298 | { |
43299 | case GT_EXPR: |
43300 | case GE_EXPR: |
43301 | case LT_EXPR: |
43302 | case LE_EXPR: |
43303 | break; |
43304 | case NE_EXPR: |
43305 | if (code != OACC_LOOP) |
43306 | break; |
43307 | gcc_fallthrough (); |
43308 | default: |
43309 | return error_mark_node; |
43310 | } |
43311 | |
43312 | /* If decl is an iterator, preserve LHS and RHS of the relational |
43313 | expr until finish_omp_for. */ |
43314 | if (decl |
43315 | && (type_dependent_expression_p (decl) |
43316 | || CLASS_TYPE_P (TREE_TYPE (decl)))) |
43317 | return cond; |
43318 | |
43319 | return build_x_binary_op (cp_expr_loc_or_input_loc (t: cond), |
43320 | TREE_CODE (cond), |
43321 | TREE_OPERAND (cond, 0), ERROR_MARK, |
43322 | TREE_OPERAND (cond, 1), ERROR_MARK, |
43323 | NULL_TREE, /*overload=*/NULL, tf_warning_or_error); |
43324 | } |
43325 | |
43326 | /* Helper function, to parse omp for increment expression. */ |
43327 | |
43328 | static tree |
43329 | cp_parser_omp_for_incr (cp_parser *parser, tree decl) |
43330 | { |
43331 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
43332 | enum tree_code op; |
43333 | tree lhs, rhs; |
43334 | cp_id_kind idk; |
43335 | bool decl_first; |
43336 | |
43337 | if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) |
43338 | { |
43339 | op = (token->type == CPP_PLUS_PLUS |
43340 | ? PREINCREMENT_EXPR : PREDECREMENT_EXPR); |
43341 | cp_lexer_consume_token (lexer: parser->lexer); |
43342 | lhs = cp_parser_simple_cast_expression (parser); |
43343 | if (lhs != decl |
43344 | && (!processing_template_decl || !cp_tree_equal (lhs, decl))) |
43345 | return error_mark_node; |
43346 | return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); |
43347 | } |
43348 | |
43349 | lhs = cp_parser_primary_expression (parser, address_p: false, cast_p: false, template_arg_p: false, idk: &idk); |
43350 | if (lhs != decl |
43351 | && (!processing_template_decl || !cp_tree_equal (lhs, decl))) |
43352 | return error_mark_node; |
43353 | |
43354 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43355 | if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS) |
43356 | { |
43357 | op = (token->type == CPP_PLUS_PLUS |
43358 | ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR); |
43359 | cp_lexer_consume_token (lexer: parser->lexer); |
43360 | return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); |
43361 | } |
43362 | |
43363 | op = cp_parser_assignment_operator_opt (parser); |
43364 | if (op == ERROR_MARK) |
43365 | return error_mark_node; |
43366 | |
43367 | if (op != NOP_EXPR) |
43368 | { |
43369 | rhs = cp_parser_assignment_expression (parser); |
43370 | rhs = build2 (op, TREE_TYPE (decl), decl, rhs); |
43371 | return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs); |
43372 | } |
43373 | |
43374 | lhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
43375 | prec: PREC_ADDITIVE_EXPRESSION, NULL); |
43376 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43377 | decl_first = (lhs == decl |
43378 | || (processing_template_decl && cp_tree_equal (lhs, decl))); |
43379 | if (decl_first) |
43380 | lhs = NULL_TREE; |
43381 | if (token->type != CPP_PLUS |
43382 | && token->type != CPP_MINUS) |
43383 | return error_mark_node; |
43384 | |
43385 | do |
43386 | { |
43387 | op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR; |
43388 | cp_lexer_consume_token (lexer: parser->lexer); |
43389 | rhs = cp_parser_binary_expression (parser, cast_p: false, no_toplevel_fold_p: false, |
43390 | prec: PREC_ADDITIVE_EXPRESSION, NULL); |
43391 | token = cp_lexer_peek_token (lexer: parser->lexer); |
43392 | if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first) |
43393 | { |
43394 | if (lhs == NULL_TREE) |
43395 | { |
43396 | if (op == PLUS_EXPR) |
43397 | lhs = rhs; |
43398 | else |
43399 | lhs = build_x_unary_op (input_location, NEGATE_EXPR, rhs, |
43400 | NULL_TREE, tf_warning_or_error); |
43401 | } |
43402 | else |
43403 | lhs = build_x_binary_op (input_location, op, |
43404 | lhs, ERROR_MARK, |
43405 | rhs, ERROR_MARK, |
43406 | NULL_TREE, NULL, tf_warning_or_error); |
43407 | } |
43408 | } |
43409 | while (token->type == CPP_PLUS || token->type == CPP_MINUS); |
43410 | |
43411 | if (!decl_first) |
43412 | { |
43413 | if ((rhs != decl |
43414 | && (!processing_template_decl || !cp_tree_equal (rhs, decl))) |
43415 | || op == MINUS_EXPR) |
43416 | return error_mark_node; |
43417 | rhs = build2 (op, TREE_TYPE (decl), lhs, decl); |
43418 | } |
43419 | else |
43420 | rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs); |
43421 | |
43422 | return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs); |
43423 | } |
43424 | |
43425 | /* Parse the initialization statement of an OpenMP for loop. Range-for |
43426 | is handled separately in cp_convert_omp_range_for. |
43427 | |
43428 | On entry SL is the current statement list. Parsing of some forms |
43429 | of initialization pops this list and stores its contents in either INIT |
43430 | or THIS_PRE_BODY, and sets SL to null. Initialization for class |
43431 | iterators is added directly to SL and it is not popped until later. |
43432 | |
43433 | On return, DECL is set if the initialization is by binding the |
43434 | iteration variable. If the initialization is by assignment, REAL_DECL |
43435 | is set to point to a variable in an outer scope. ORIG_INIT is set |
43436 | if the iteration variable is of class type; this is a copy saved for |
43437 | error checking in finish_omp_for. |
43438 | |
43439 | Return true if the resulting construct should have an |
43440 | OMP_CLAUSE_PRIVATE added to it. */ |
43441 | |
43442 | static tree |
43443 | cp_parser_omp_for_loop_init (cp_parser *parser, |
43444 | tree &this_pre_body, |
43445 | tree &sl, |
43446 | tree &init, |
43447 | tree &orig_init, |
43448 | tree &decl, |
43449 | tree &real_decl) |
43450 | { |
43451 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_SEMICOLON)) |
43452 | return NULL_TREE; |
43453 | |
43454 | tree add_private_clause = NULL_TREE; |
43455 | |
43456 | /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too): |
43457 | |
43458 | init-expr: |
43459 | var = lb |
43460 | integer-type var = lb |
43461 | random-access-iterator-type var = lb |
43462 | pointer-type var = lb |
43463 | */ |
43464 | cp_decl_specifier_seq type_specifiers; |
43465 | |
43466 | /* First, try to parse as an initialized declaration. See |
43467 | cp_parser_condition, from whence the bulk of this is copied. */ |
43468 | |
43469 | cp_parser_parse_tentatively (parser); |
43470 | cp_parser_type_specifier_seq (parser, flags: CP_PARSER_FLAGS_NONE, |
43471 | /*is_declaration=*/true, |
43472 | /*is_trailing_return=*/false, |
43473 | type_specifier_seq: &type_specifiers); |
43474 | if (cp_parser_parse_definitely (parser)) |
43475 | { |
43476 | /* If parsing a type specifier seq succeeded, then this |
43477 | MUST be a initialized declaration. */ |
43478 | tree asm_specification, attributes; |
43479 | cp_declarator *declarator; |
43480 | |
43481 | declarator = cp_parser_declarator (parser, |
43482 | dcl_kind: CP_PARSER_DECLARATOR_NAMED, |
43483 | flags: CP_PARSER_FLAGS_NONE, |
43484 | /*ctor_dtor_or_conv_p=*/NULL, |
43485 | /*parenthesized_p=*/NULL, |
43486 | /*member_p=*/false, |
43487 | /*friend_p=*/false, |
43488 | /*static_p=*/false); |
43489 | attributes = cp_parser_attributes_opt (parser); |
43490 | asm_specification = cp_parser_asm_specification_opt (parser); |
43491 | |
43492 | if (declarator == cp_error_declarator) |
43493 | cp_parser_skip_to_end_of_statement (parser); |
43494 | |
43495 | else |
43496 | { |
43497 | tree pushed_scope, auto_node; |
43498 | |
43499 | decl = start_decl (declarator, &type_specifiers, |
43500 | SD_INITIALIZED, attributes, |
43501 | /*prefix_attributes=*/NULL_TREE, |
43502 | &pushed_scope); |
43503 | |
43504 | auto_node = type_uses_auto (TREE_TYPE (decl)); |
43505 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_EQ)) |
43506 | { |
43507 | if (cp_lexer_next_token_is (lexer: parser->lexer, |
43508 | type: CPP_OPEN_PAREN)) |
43509 | error ("parenthesized initialization is not allowed in " |
43510 | "OpenMP %<for%> loop" ); |
43511 | else |
43512 | /* Trigger an error. */ |
43513 | cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ); |
43514 | |
43515 | init = error_mark_node; |
43516 | cp_parser_skip_to_end_of_statement (parser); |
43517 | } |
43518 | else if (CLASS_TYPE_P (TREE_TYPE (decl)) |
43519 | || type_dependent_expression_p (decl) |
43520 | || auto_node) |
43521 | { |
43522 | bool is_non_constant_init; |
43523 | |
43524 | init = cp_parser_initializer (parser, |
43525 | /*is_direct_init=*/nullptr, |
43526 | non_constant_p: &is_non_constant_init); |
43527 | |
43528 | if (auto_node) |
43529 | { |
43530 | TREE_TYPE (decl) |
43531 | = do_auto_deduction (TREE_TYPE (decl), init, |
43532 | auto_node); |
43533 | |
43534 | if (!CLASS_TYPE_P (TREE_TYPE (decl)) |
43535 | && !type_dependent_expression_p (decl)) |
43536 | goto non_class; |
43537 | } |
43538 | |
43539 | cp_finish_decl (decl, init, !is_non_constant_init, |
43540 | asm_specification, |
43541 | LOOKUP_ONLYCONVERTING); |
43542 | orig_init = init; |
43543 | |
43544 | /* In the case of a class iterator, do not pop sl here. |
43545 | Both class initialization and finalization must happen in |
43546 | the enclosing init block scope. For now set the init |
43547 | expression to null; it'll be filled in properly in |
43548 | finish_omp_for before stuffing it in the OMP_FOR. */ |
43549 | if (CLASS_TYPE_P (TREE_TYPE (decl))) |
43550 | init = NULL_TREE; |
43551 | else /* It is a parameterized type. */ |
43552 | { |
43553 | init = pop_stmt_list (sl); |
43554 | sl = NULL_TREE; |
43555 | if (init && TREE_CODE (init) == STATEMENT_LIST) |
43556 | { |
43557 | tree_stmt_iterator i = tsi_start (t: init); |
43558 | /* Move lambda DECL_EXPRs to the enclosing block. */ |
43559 | while (!tsi_end_p (i)) |
43560 | { |
43561 | tree t = tsi_stmt (i); |
43562 | if (TREE_CODE (t) == DECL_EXPR |
43563 | && TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) |
43564 | { |
43565 | tsi_delink (&i); |
43566 | add_stmt (t); |
43567 | continue; |
43568 | } |
43569 | break; |
43570 | } |
43571 | if (tsi_one_before_end_p (i)) |
43572 | { |
43573 | tree t = tsi_stmt (i); |
43574 | tsi_delink (&i); |
43575 | free_stmt_list (init); |
43576 | init = t; |
43577 | } |
43578 | } |
43579 | } |
43580 | } |
43581 | else |
43582 | /* This is an initialized declaration of non-class, |
43583 | non-parameterized type iteration variable. */ |
43584 | { |
43585 | /* Consume '='. */ |
43586 | cp_lexer_consume_token (lexer: parser->lexer); |
43587 | init = cp_parser_assignment_expression (parser); |
43588 | |
43589 | non_class: |
43590 | if (TYPE_REF_P (TREE_TYPE (decl))) |
43591 | init = error_mark_node; |
43592 | else |
43593 | cp_finish_decl (decl, NULL_TREE, |
43594 | /*init_const_expr_p=*/false, |
43595 | asm_specification, |
43596 | LOOKUP_ONLYCONVERTING); |
43597 | this_pre_body = pop_stmt_list (sl); |
43598 | sl = NULL_TREE; |
43599 | } |
43600 | |
43601 | if (pushed_scope) |
43602 | pop_scope (pushed_scope); |
43603 | } |
43604 | } |
43605 | else |
43606 | { |
43607 | cp_id_kind idk; |
43608 | /* If parsing a type specifier sequence failed, then |
43609 | this MUST be a simple expression. */ |
43610 | cp_parser_parse_tentatively (parser); |
43611 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, |
43612 | template_arg_p: false, idk: &idk); |
43613 | cp_token *last_tok = cp_lexer_peek_token (lexer: parser->lexer); |
43614 | if (!cp_parser_error_occurred (parser) |
43615 | && decl |
43616 | && (TREE_CODE (decl) == COMPONENT_REF |
43617 | || (TREE_CODE (decl) == SCOPE_REF && TREE_TYPE (decl)))) |
43618 | { |
43619 | cp_parser_abort_tentative_parse (parser); |
43620 | cp_parser_parse_tentatively (parser); |
43621 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
43622 | tree name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
43623 | /*check_dependency_p=*/true, |
43624 | /*template_p=*/NULL, |
43625 | /*declarator_p=*/false, |
43626 | /*optional_p=*/false); |
43627 | if (name != error_mark_node |
43628 | && last_tok == cp_lexer_peek_token (lexer: parser->lexer)) |
43629 | { |
43630 | decl = cp_parser_lookup_name_simple (parser, name, |
43631 | location: token->location); |
43632 | if (TREE_CODE (decl) == FIELD_DECL) |
43633 | add_private_clause = omp_privatize_field (decl, false); |
43634 | } |
43635 | cp_parser_abort_tentative_parse (parser); |
43636 | cp_parser_parse_tentatively (parser); |
43637 | decl = cp_parser_primary_expression (parser, address_p: false, cast_p: false, |
43638 | template_arg_p: false, idk: &idk); |
43639 | } |
43640 | if (!cp_parser_error_occurred (parser) |
43641 | && decl |
43642 | && DECL_P (decl) |
43643 | && CLASS_TYPE_P (TREE_TYPE (decl))) |
43644 | { |
43645 | tree rhs; |
43646 | |
43647 | cp_parser_parse_definitely (parser); |
43648 | cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ); |
43649 | rhs = cp_parser_assignment_expression (parser); |
43650 | orig_init = rhs; |
43651 | finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs), |
43652 | decl, NOP_EXPR, |
43653 | rhs, NULL_TREE, |
43654 | tf_warning_or_error)); |
43655 | if (!add_private_clause) |
43656 | add_private_clause = decl; |
43657 | } |
43658 | else |
43659 | { |
43660 | decl = NULL; |
43661 | cp_parser_abort_tentative_parse (parser); |
43662 | init = cp_parser_expression (parser); |
43663 | if (init) |
43664 | { |
43665 | if (TREE_CODE (init) == MODIFY_EXPR |
43666 | || TREE_CODE (init) == MODOP_EXPR) |
43667 | real_decl = TREE_OPERAND (init, 0); |
43668 | } |
43669 | } |
43670 | this_pre_body = pop_stmt_list (sl); |
43671 | sl = NULL_TREE; |
43672 | } |
43673 | return add_private_clause; |
43674 | } |
43675 | |
43676 | /* Helper for cp_parser_omp_loop_nest, handle one range-for loop |
43677 | including introducing new temporaries for the range start and end, |
43678 | doing auto deduction, and processing decomposition variables. |
43679 | |
43680 | This function is also called from pt.cc during template instantiation. |
43681 | In that case SL is NULL_TREE, otherwise it is the current statement |
43682 | list. */ |
43683 | void |
43684 | cp_convert_omp_range_for (tree &this_pre_body, tree &sl, |
43685 | tree &decl, tree &orig_decl, tree &init, |
43686 | tree &orig_init, tree &cond, tree &incr) |
43687 | { |
43688 | tree begin, end, range_temp_decl = NULL_TREE; |
43689 | tree iter_type, begin_expr, end_expr; |
43690 | bool clear_has_value_expr = false; |
43691 | |
43692 | if (processing_template_decl) |
43693 | { |
43694 | if (check_for_bare_parameter_packs (init)) |
43695 | init = error_mark_node; |
43696 | if (!type_dependent_expression_p (init) |
43697 | /* do_auto_deduction doesn't mess with template init-lists. */ |
43698 | && !BRACE_ENCLOSED_INITIALIZER_P (init)) |
43699 | { |
43700 | tree d = decl; |
43701 | cp_decomp decomp_d, *decomp = NULL; |
43702 | if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl)) |
43703 | { |
43704 | tree v = DECL_VALUE_EXPR (decl); |
43705 | if (TREE_CODE (v) == ARRAY_REF |
43706 | && VAR_P (TREE_OPERAND (v, 0)) |
43707 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
43708 | { |
43709 | d = TREE_OPERAND (v, 0); |
43710 | decomp = &decomp_d; |
43711 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
43712 | decomp->decl = decl; |
43713 | } |
43714 | } |
43715 | do_range_for_auto_deduction (decl: d, range_expr: init, decomp); |
43716 | } |
43717 | cond = global_namespace; |
43718 | incr = NULL_TREE; |
43719 | orig_init = init; |
43720 | if (sl) |
43721 | { |
43722 | this_pre_body = pop_stmt_list (sl); |
43723 | sl = NULL_TREE; |
43724 | } |
43725 | return; |
43726 | } |
43727 | |
43728 | init = mark_lvalue_use (init); |
43729 | |
43730 | if (decl == error_mark_node || init == error_mark_node) |
43731 | /* If an error happened previously do nothing or else a lot of |
43732 | unhelpful errors would be issued. */ |
43733 | begin_expr = end_expr = iter_type = error_mark_node; |
43734 | else |
43735 | { |
43736 | tree range_temp; |
43737 | |
43738 | if (VAR_P (init) |
43739 | && array_of_runtime_bound_p (TREE_TYPE (init))) |
43740 | /* Can't bind a reference to an array of runtime bound. */ |
43741 | range_temp = init; |
43742 | else |
43743 | { |
43744 | range_temp = build_range_temp (range_expr: init); |
43745 | DECL_NAME (range_temp) = NULL_TREE; |
43746 | pushdecl (range_temp); |
43747 | cp_finish_decl (range_temp, init, |
43748 | /*is_constant_init*/false, NULL_TREE, |
43749 | LOOKUP_ONLYCONVERTING); |
43750 | range_temp_decl = range_temp; |
43751 | range_temp = convert_from_reference (range_temp); |
43752 | } |
43753 | iter_type = cp_parser_perform_range_for_lookup (range: range_temp, |
43754 | begin: &begin_expr, end: &end_expr); |
43755 | } |
43756 | |
43757 | tree end_iter_type = iter_type; |
43758 | if (cxx_dialect >= cxx17) |
43759 | end_iter_type = cv_unqualified (TREE_TYPE (end_expr)); |
43760 | end = build_decl (input_location, VAR_DECL, NULL_TREE, end_iter_type); |
43761 | TREE_USED (end) = 1; |
43762 | DECL_ARTIFICIAL (end) = 1; |
43763 | pushdecl (end); |
43764 | cp_finish_decl (end, end_expr, |
43765 | /*is_constant_init*/false, NULL_TREE, |
43766 | LOOKUP_ONLYCONVERTING); |
43767 | |
43768 | /* The new for initialization statement. */ |
43769 | begin = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type); |
43770 | TREE_USED (begin) = 1; |
43771 | DECL_ARTIFICIAL (begin) = 1; |
43772 | pushdecl (begin); |
43773 | orig_init = init; |
43774 | if (CLASS_TYPE_P (iter_type)) |
43775 | init = NULL_TREE; |
43776 | else |
43777 | { |
43778 | init = begin_expr; |
43779 | begin_expr = NULL_TREE; |
43780 | } |
43781 | cp_finish_decl (begin, begin_expr, |
43782 | /*is_constant_init*/false, NULL_TREE, |
43783 | LOOKUP_ONLYCONVERTING); |
43784 | |
43785 | /* The new for condition. */ |
43786 | if (CLASS_TYPE_P (iter_type)) |
43787 | cond = build2 (NE_EXPR, boolean_type_node, begin, end); |
43788 | else |
43789 | cond = build_x_binary_op (input_location, NE_EXPR, |
43790 | begin, ERROR_MARK, |
43791 | end, ERROR_MARK, |
43792 | NULL_TREE, NULL, tf_warning_or_error); |
43793 | |
43794 | /* The new increment expression. */ |
43795 | if (CLASS_TYPE_P (iter_type)) |
43796 | incr = build2 (PREINCREMENT_EXPR, iter_type, begin, NULL_TREE); |
43797 | else |
43798 | incr = finish_unary_op_expr (input_location, |
43799 | PREINCREMENT_EXPR, begin, |
43800 | tf_warning_or_error); |
43801 | |
43802 | orig_decl = decl; |
43803 | decl = begin; |
43804 | /* Defer popping sl here. */ |
43805 | |
43806 | cp_decomp decomp_d, *decomp = NULL; |
43807 | if (orig_decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (orig_decl)) |
43808 | { |
43809 | tree v = DECL_VALUE_EXPR (orig_decl); |
43810 | if (TREE_CODE (v) == ARRAY_REF |
43811 | && VAR_P (TREE_OPERAND (v, 0)) |
43812 | && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) |
43813 | { |
43814 | tree d = orig_decl; |
43815 | orig_decl = TREE_OPERAND (v, 0); |
43816 | decomp = &decomp_d; |
43817 | decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; |
43818 | decomp->decl = d; |
43819 | } |
43820 | } |
43821 | |
43822 | tree auto_node = type_uses_auto (TREE_TYPE (orig_decl)); |
43823 | if (auto_node) |
43824 | { |
43825 | tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
43826 | NULL_TREE, tf_none); |
43827 | if (!error_operand_p (t)) |
43828 | { |
43829 | TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl), |
43830 | t, auto_node); |
43831 | if (decomp) |
43832 | { |
43833 | ++processing_template_decl; |
43834 | cp_finish_decomp (orig_decl, decomp); |
43835 | --processing_template_decl; |
43836 | if (!processing_template_decl) |
43837 | clear_has_value_expr = true; |
43838 | } |
43839 | } |
43840 | } |
43841 | |
43842 | /* The output ORIG_DECL is not a decl. Instead, it is a tree structure |
43843 | that holds decls for variables implementing the iterator, represented |
43844 | as a TREE_LIST whose TREE_CHAIN is a vector. The first two elements |
43845 | of the vector are decls of scratch variables for the range start and |
43846 | end that will eventually be bound in the implicit scope surrounding |
43847 | the whole loop nest. The remaining elements are decls of derived |
43848 | decomposition variables that are bound inside the loop body. This |
43849 | structure is further mangled by finish_omp_for into the form required |
43850 | for the OMP_FOR_ORIG_DECLS field of the OMP_FOR tree node. */\ |
43851 | unsigned decomp_cnt = decomp ? decomp->count : 0; |
43852 | tree v = make_tree_vec (decomp_cnt + 3); |
43853 | TREE_VEC_ELT (v, 0) = range_temp_decl; |
43854 | TREE_VEC_ELT (v, 1) = end; |
43855 | TREE_VEC_ELT (v, 2) = orig_decl; |
43856 | if (clear_has_value_expr) |
43857 | TREE_PUBLIC (v) = 1; |
43858 | for (unsigned i = 0; i < decomp_cnt; i++) |
43859 | { |
43860 | if (clear_has_value_expr) |
43861 | { |
43862 | /* If cp_finish_decomp was called with processing_template_decl |
43863 | temporarily set to 1, then decomp names will have deduced |
43864 | name but the DECL_VALUE_EXPR will be dependent. Hide those |
43865 | from folding of other loop initializers e.g. for warning |
43866 | purposes until cp_finish_omp_range_for. */ |
43867 | gcc_checking_assert (DECL_HAS_VALUE_EXPR_P (decomp->decl) |
43868 | || (TREE_TYPE (decomp->decl) |
43869 | == error_mark_node)); |
43870 | DECL_HAS_VALUE_EXPR_P (decomp->decl) = 0; |
43871 | } |
43872 | TREE_VEC_ELT (v, i + 3) = decomp->decl; |
43873 | decomp->decl = DECL_CHAIN (decomp->decl); |
43874 | } |
43875 | orig_decl = tree_cons (NULL_TREE, NULL_TREE, v); |
43876 | } |
43877 | |
43878 | /* Helper for cp_parser_omp_for_loop, finalize part of range for |
43879 | inside of the collapsed body. */ |
43880 | |
43881 | void |
43882 | cp_finish_omp_range_for (tree orig, tree begin) |
43883 | { |
43884 | gcc_assert (TREE_CODE (orig) == TREE_LIST |
43885 | && TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC); |
43886 | tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2); |
43887 | cp_decomp decomp_d, *decomp = NULL; |
43888 | |
43889 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
43890 | { |
43891 | decomp = &decomp_d; |
43892 | decomp_d.decl = TREE_VEC_ELT (TREE_CHAIN (orig), 3); |
43893 | decomp_d.count = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3; |
43894 | if (TREE_PUBLIC (TREE_CHAIN (orig))) |
43895 | { |
43896 | /* Undo temporary clearing of DECL_HAS_VALUE_EXPR_P done |
43897 | by cp_convert_omp_range_for above. */ |
43898 | TREE_PUBLIC (TREE_CHAIN (orig)) = 0; |
43899 | tree d = decomp_d.decl; |
43900 | for (unsigned i = 0; i < decomp_d.count; i++) |
43901 | { |
43902 | if (TREE_TYPE (d) != error_mark_node) |
43903 | DECL_HAS_VALUE_EXPR_P (d) = 1; |
43904 | d = DECL_CHAIN (d); |
43905 | } |
43906 | } |
43907 | } |
43908 | |
43909 | /* The declaration is initialized with *__begin inside the loop body. */ |
43910 | cp_finish_decl (decl, |
43911 | build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, |
43912 | NULL_TREE, tf_warning_or_error), |
43913 | /*is_constant_init*/false, NULL_TREE, |
43914 | LOOKUP_ONLYCONVERTING, decomp); |
43915 | if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) |
43916 | cp_finish_decomp (decl, decomp); |
43917 | } |
43918 | |
43919 | /* Return true if next tokens contain a standard attribute that contains |
43920 | omp::directive (DIRECTIVE). */ |
43921 | |
43922 | static bool |
43923 | cp_parser_omp_section_scan (cp_parser *parser, const char *directive, |
43924 | bool tentative) |
43925 | { |
43926 | size_t n = cp_parser_skip_attributes_opt (parser, n: 1), i; |
43927 | if (n < 10) |
43928 | return false; |
43929 | for (i = 5; i < n - 4; i++) |
43930 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i, type: CPP_NAME) |
43931 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, type: CPP_OPEN_PAREN) |
43932 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 2, type: CPP_NAME)) |
43933 | { |
43934 | tree first = cp_lexer_peek_nth_token (lexer: parser->lexer, n: i)->u.value; |
43935 | tree second = cp_lexer_peek_nth_token (lexer: parser->lexer, n: i + 2)->u.value; |
43936 | if (strcmp (IDENTIFIER_POINTER (first), s2: "directive" ) |
43937 | && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__" )) |
43938 | continue; |
43939 | if (strcmp (IDENTIFIER_POINTER (second), s2: directive) == 0) |
43940 | break; |
43941 | } |
43942 | if (i == n - 4) |
43943 | return false; |
43944 | cp_parser_parse_tentatively (parser); |
43945 | location_t first_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
43946 | location_t last_loc |
43947 | = cp_lexer_peek_nth_token (lexer: parser->lexer, n: n - 1)->location; |
43948 | location_t middle_loc = UNKNOWN_LOCATION; |
43949 | tree std_attrs = cp_parser_std_attribute_spec_seq (parser); |
43950 | int cnt = 0; |
43951 | bool seen = false; |
43952 | for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr)) |
43953 | if (get_attribute_namespace (attr) == omp_identifier |
43954 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (attr))) |
43955 | { |
43956 | for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a)) |
43957 | { |
43958 | tree d = TREE_VALUE (a); |
43959 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
43960 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
43961 | cnt++; |
43962 | if (first->type == CPP_NAME |
43963 | && strcmp (IDENTIFIER_POINTER (first->u.value), |
43964 | s2: directive) == 0) |
43965 | { |
43966 | seen = true; |
43967 | if (middle_loc == UNKNOWN_LOCATION) |
43968 | middle_loc = first->location; |
43969 | } |
43970 | } |
43971 | } |
43972 | if (!seen || tentative) |
43973 | { |
43974 | cp_parser_abort_tentative_parse (parser); |
43975 | return seen; |
43976 | } |
43977 | if (cnt != 1 || TREE_CHAIN (std_attrs)) |
43978 | { |
43979 | error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc), |
43980 | "%<[[omp::directive(%s)]]%> must be the only specified " |
43981 | "attribute on a statement" , directive); |
43982 | cp_parser_abort_tentative_parse (parser); |
43983 | return false; |
43984 | } |
43985 | if (!cp_parser_parse_definitely (parser)) |
43986 | return false; |
43987 | cp_parser_handle_statement_omp_attributes (parser, attrs: std_attrs); |
43988 | return true; |
43989 | } |
43990 | |
43991 | /* Parse an OpenMP structured block sequence. KIND is the corresponding |
43992 | separating directive. */ |
43993 | |
43994 | static tree |
43995 | cp_parser_omp_structured_block_sequence (cp_parser *parser, |
43996 | enum pragma_kind kind) |
43997 | { |
43998 | tree stmt = begin_omp_structured_block (); |
43999 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
44000 | |
44001 | cp_parser_statement (parser, NULL_TREE, in_compound: false, NULL); |
44002 | while (true) |
44003 | { |
44004 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
44005 | |
44006 | if (token->type == CPP_CLOSE_BRACE |
44007 | || token->type == CPP_EOF |
44008 | || token->type == CPP_PRAGMA_EOL |
44009 | || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END) |
44010 | || (kind != PRAGMA_NONE |
44011 | && cp_parser_pragma_kind (token) == kind)) |
44012 | break; |
44013 | |
44014 | if (kind != PRAGMA_NONE |
44015 | && cp_parser_omp_section_scan (parser, |
44016 | directive: kind == PRAGMA_OMP_SCAN |
44017 | ? "scan" : "section" , tentative: false)) |
44018 | break; |
44019 | |
44020 | cp_parser_statement (parser, NULL_TREE, in_compound: false, NULL); |
44021 | } |
44022 | |
44023 | cp_parser_end_omp_structured_block (parser, save); |
44024 | return finish_omp_structured_block (stmt); |
44025 | } |
44026 | |
44027 | |
44028 | /* OpenMP 5.0: |
44029 | |
44030 | scan-loop-body: |
44031 | { structured-block scan-directive structured-block } */ |
44032 | |
44033 | static void |
44034 | cp_parser_omp_scan_loop_body (cp_parser *parser) |
44035 | { |
44036 | tree substmt, clauses = NULL_TREE; |
44037 | bool found_scan = false; |
44038 | |
44039 | matching_braces braces; |
44040 | if (!braces.require_open (parser)) |
44041 | return; |
44042 | |
44043 | cp_token *tok = cp_lexer_peek_token (lexer: parser->lexer); |
44044 | if (cp_parser_pragma_kind (token: tok) != PRAGMA_OMP_SCAN) |
44045 | substmt = cp_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN); |
44046 | else |
44047 | { |
44048 | warning_at (tok->location, 0, "%<#pragma omp scan%> with zero preceding " |
44049 | "executable statements" ); |
44050 | substmt = build_empty_stmt (tok->location); |
44051 | } |
44052 | substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); |
44053 | add_stmt (substmt); |
44054 | |
44055 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
44056 | if (cp_parser_pragma_kind (token: tok) == PRAGMA_OMP_SCAN) |
44057 | { |
44058 | enum omp_clause_code clause = OMP_CLAUSE_ERROR; |
44059 | found_scan = true; |
44060 | |
44061 | cp_lexer_consume_token (lexer: parser->lexer); |
44062 | |
44063 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
44064 | cp_lexer_consume_token (lexer: parser->lexer); |
44065 | |
44066 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
44067 | { |
44068 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
44069 | const char *p = IDENTIFIER_POINTER (id); |
44070 | if (strcmp (s1: p, s2: "inclusive" ) == 0) |
44071 | clause = OMP_CLAUSE_INCLUSIVE; |
44072 | else if (strcmp (s1: p, s2: "exclusive" ) == 0) |
44073 | clause = OMP_CLAUSE_EXCLUSIVE; |
44074 | } |
44075 | if (clause != OMP_CLAUSE_ERROR) |
44076 | { |
44077 | cp_lexer_consume_token (lexer: parser->lexer); |
44078 | clauses = cp_parser_omp_var_list (parser, kind: clause, NULL_TREE); |
44079 | } |
44080 | else |
44081 | cp_parser_error (parser, gmsgid: "expected %<inclusive%> or " |
44082 | "%<exclusive%> clause" ); |
44083 | |
44084 | cp_parser_require_pragma_eol (parser, pragma_tok: tok); |
44085 | } |
44086 | else |
44087 | error ("expected %<#pragma omp scan%>" ); |
44088 | |
44089 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
44090 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_BRACE)) |
44091 | substmt = cp_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE); |
44092 | else |
44093 | { |
44094 | if (found_scan) |
44095 | warning_at (tok->location, 0, "%<#pragma omp scan%> with zero " |
44096 | "succeeding executable statements" ); |
44097 | substmt = build_empty_stmt (tok->location); |
44098 | } |
44099 | substmt = build2_loc (loc: tok->location, code: OMP_SCAN, void_type_node, arg0: substmt, |
44100 | arg1: clauses); |
44101 | add_stmt (substmt); |
44102 | |
44103 | braces.require_close (parser); |
44104 | } |
44105 | |
44106 | |
44107 | /* This function parses a single level of a loop nest, invoking itself |
44108 | recursively if necessary. |
44109 | |
44110 | loop-nest :: for (...) loop-body |
44111 | loop-body :: loop-nest |
44112 | | { [intervening-code] loop-body [intervening-code] } |
44113 | | final-loop-body |
44114 | intervening-code :: structured-block-sequence |
44115 | final-loop-body :: structured-block |
44116 | |
44117 | For a collapsed loop nest, only a single OMP_FOR is built, pulling out |
44118 | all the iterator information from the inner loops into vectors in the |
44119 | parser->omp_for_parse_state structure. |
44120 | |
44121 | In the "range for" case, it is transformed into a regular "for" iterator |
44122 | by introducing some temporary variables for the begin/end, |
44123 | as well as bindings of the actual iteration variables which are |
44124 | injected into the body of the loop. |
44125 | |
44126 | Initialization code for iterator variables may end up either in the |
44127 | init vector (simple assignments), in omp_for_parse_state->pre_body |
44128 | (decl_exprs for iterators bound in the for statement), or in the |
44129 | scope surrounding this level of loop initialization. |
44130 | |
44131 | The scopes of class iterator variables and their finalizers need to |
44132 | be adjusted after parsing so that all of the initialization happens |
44133 | in a scope surrounding all of the intervening and body code. For |
44134 | this reason we separately store the initialization and body blocks |
44135 | for each level of loops in the omp_for_parse_state structure and |
44136 | reassemble/reorder them in cp_parser_omp_for. See additional |
44137 | comments there about the use of placeholders, etc. */ |
44138 | |
44139 | static tree |
44140 | cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) |
44141 | { |
44142 | tree decl, cond, incr, init; |
44143 | tree orig_init, real_decl, orig_decl; |
44144 | tree init_block, body_block; |
44145 | tree init_placeholder, body_placeholder; |
44146 | tree init_scope; |
44147 | tree this_pre_body = NULL_TREE; |
44148 | bool moreloops; |
44149 | unsigned char save_in_statement; |
44150 | tree add_private_clause = NULL_TREE; |
44151 | location_t loc; |
44152 | bool is_range_for = false; |
44153 | tree sl = NULL_TREE; |
44154 | struct omp_for_parse_data *omp_for_parse_state |
44155 | = parser->omp_for_parse_state; |
44156 | gcc_assert (omp_for_parse_state); |
44157 | int depth = omp_for_parse_state->depth; |
44158 | |
44159 | /* We have already matched the FOR token but not consumed it yet. */ |
44160 | gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)); |
44161 | loc = cp_lexer_consume_token (lexer: parser->lexer)->location; |
44162 | |
44163 | /* Forbid break/continue in the loop initializer, condition, and |
44164 | increment expressions. */ |
44165 | save_in_statement = parser->in_statement; |
44166 | parser->in_statement = IN_OMP_BLOCK; |
44167 | |
44168 | /* We are not in intervening code now. */ |
44169 | omp_for_parse_state->in_intervening_code = false; |
44170 | |
44171 | /* Don't create location wrapper nodes within an OpenMP "for" |
44172 | statement. */ |
44173 | auto_suppress_location_wrappers sentinel; |
44174 | |
44175 | matching_parens parens; |
44176 | if (!parens.require_open (parser)) |
44177 | return NULL; |
44178 | |
44179 | init = orig_init = decl = real_decl = orig_decl = NULL_TREE; |
44180 | |
44181 | init_placeholder = build_stmt (input_location, EXPR_STMT, |
44182 | integer_zero_node); |
44183 | vec_safe_push (r&: omp_for_parse_state->init_placeholderv, t: init_placeholder); |
44184 | |
44185 | /* The init_block acts as a container for this level of loop goo. */ |
44186 | init_block = push_stmt_list (); |
44187 | vec_safe_push (r&: omp_for_parse_state->init_blockv, t: init_block); |
44188 | |
44189 | /* Wrap a scope around this entire level of loop to hold bindings |
44190 | of loop iteration variables. We can't insert them directly |
44191 | in the containing scope because that would cause their visibility to |
44192 | be incorrect with respect to intervening code after this loop. |
44193 | We will combine the nested init_scopes in postprocessing after the |
44194 | entire loop is parsed. */ |
44195 | init_scope = begin_compound_stmt (0); |
44196 | |
44197 | /* Now we need another level of statement list container to capture the |
44198 | initialization (and possible finalization) bits. In some cases this |
44199 | container may be popped off during initializer parsing to store code in |
44200 | INIT or THIS_PRE_BODY, depending on the form of initialization. If |
44201 | we have a class iterator we will pop it at the end of parsing this |
44202 | level, so the cleanups are handled correctly. */ |
44203 | sl = push_stmt_list (); |
44204 | |
44205 | if (omp_for_parse_state->code != OACC_LOOP && cxx_dialect >= cxx11) |
44206 | { |
44207 | /* Save tokens so that we can put them back. */ |
44208 | cp_lexer_save_tokens (lexer: parser->lexer); |
44209 | |
44210 | /* Look for ':' that is not nested in () or {}. */ |
44211 | is_range_for |
44212 | = (cp_parser_skip_to_closing_parenthesis_1 (parser, |
44213 | /*recovering=*/false, |
44214 | or_ttype: CPP_COLON, |
44215 | /*consume_paren=*/ |
44216 | false) == -1); |
44217 | |
44218 | /* Roll back the tokens we skipped. */ |
44219 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
44220 | |
44221 | if (is_range_for) |
44222 | { |
44223 | bool saved_colon_corrects_to_scope_p |
44224 | = parser->colon_corrects_to_scope_p; |
44225 | |
44226 | /* A colon is used in range-based for. */ |
44227 | parser->colon_corrects_to_scope_p = false; |
44228 | |
44229 | /* Parse the declaration. */ |
44230 | cp_parser_simple_declaration (parser, |
44231 | /*function_definition_allowed_p=*/ |
44232 | false, maybe_range_for_decl: &decl); |
44233 | parser->colon_corrects_to_scope_p |
44234 | = saved_colon_corrects_to_scope_p; |
44235 | |
44236 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
44237 | |
44238 | init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, range_decl: decl, |
44239 | ivdep: false, unroll: 0, novector: false, is_omp: true); |
44240 | |
44241 | cp_convert_omp_range_for (this_pre_body, sl, decl, |
44242 | orig_decl, init, orig_init, |
44243 | cond, incr); |
44244 | |
44245 | if (omp_for_parse_state->ordered_cl) |
44246 | error_at (OMP_CLAUSE_LOCATION (omp_for_parse_state->ordered_cl), |
44247 | "%<ordered%> clause with parameter on " |
44248 | "range-based %<for%> loop" ); |
44249 | |
44250 | goto parse_close_paren; |
44251 | } |
44252 | } |
44253 | |
44254 | add_private_clause |
44255 | = cp_parser_omp_for_loop_init (parser, this_pre_body, sl, |
44256 | init, orig_init, decl, real_decl); |
44257 | |
44258 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
44259 | |
44260 | /* If the iteration variable was introduced via a declaration in the |
44261 | for statement, DECL points at it. Otherwise DECL is null and |
44262 | REAL_DECL is a variable previously declared in an outer scope. |
44263 | Make REAL_DECL point at the iteration variable no matter where it |
44264 | was introduced. */ |
44265 | if (decl) |
44266 | real_decl = decl; |
44267 | |
44268 | /* Some clauses treat iterator variables specially. */ |
44269 | if (omp_for_parse_state->cclauses != NULL |
44270 | && omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL |
44271 | && real_decl != NULL_TREE |
44272 | && omp_for_parse_state->code != OMP_LOOP) |
44273 | { |
44274 | tree *c; |
44275 | for (c = &(omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]); |
44276 | *c ; ) |
44277 | if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE |
44278 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44279 | { |
44280 | error_at (loc, "iteration variable %qD" |
44281 | " should not be firstprivate" , real_decl); |
44282 | *c = OMP_CLAUSE_CHAIN (*c); |
44283 | } |
44284 | else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE |
44285 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44286 | { |
44287 | /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ |
44288 | tree l = *c; |
44289 | *c = OMP_CLAUSE_CHAIN (*c); |
44290 | if (omp_for_parse_state->code == OMP_SIMD) |
44291 | { |
44292 | OMP_CLAUSE_CHAIN (l) |
44293 | = omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
44294 | omp_for_parse_state->cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l; |
44295 | } |
44296 | else |
44297 | { |
44298 | OMP_CLAUSE_CHAIN (l) = omp_for_parse_state->clauses; |
44299 | omp_for_parse_state->clauses = l; |
44300 | } |
44301 | add_private_clause = NULL_TREE; |
44302 | } |
44303 | else |
44304 | { |
44305 | if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE |
44306 | && OMP_CLAUSE_DECL (*c) == real_decl) |
44307 | add_private_clause = NULL_TREE; |
44308 | c = &OMP_CLAUSE_CHAIN (*c); |
44309 | } |
44310 | } |
44311 | |
44312 | if (add_private_clause) |
44313 | { |
44314 | tree c; |
44315 | for (c = omp_for_parse_state->clauses; c ; c = OMP_CLAUSE_CHAIN (c)) |
44316 | { |
44317 | if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE |
44318 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) |
44319 | && OMP_CLAUSE_DECL (c) == decl) |
44320 | break; |
44321 | else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE |
44322 | && OMP_CLAUSE_DECL (c) == decl) |
44323 | error_at (loc, "iteration variable %qD " |
44324 | "should not be firstprivate" , |
44325 | decl); |
44326 | else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION |
44327 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) |
44328 | && OMP_CLAUSE_DECL (c) == decl) |
44329 | error_at (loc, "iteration variable %qD should not be reduction" , |
44330 | decl); |
44331 | } |
44332 | if (c == NULL) |
44333 | { |
44334 | if ((omp_for_parse_state->code == OMP_SIMD |
44335 | && omp_for_parse_state->count != 1) |
44336 | || omp_for_parse_state->code == OMP_LOOP) |
44337 | c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE); |
44338 | else if (omp_for_parse_state->code != OMP_SIMD) |
44339 | c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE); |
44340 | else |
44341 | c = build_omp_clause (loc, OMP_CLAUSE_LINEAR); |
44342 | OMP_CLAUSE_DECL (c) = add_private_clause; |
44343 | c = finish_omp_clauses (c, C_ORT_OMP); |
44344 | if (c) |
44345 | { |
44346 | OMP_CLAUSE_CHAIN (c) = omp_for_parse_state->clauses; |
44347 | omp_for_parse_state->clauses = c; |
44348 | /* For linear, signal that we need to fill up |
44349 | the so far unknown linear step. */ |
44350 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR) |
44351 | OMP_CLAUSE_LINEAR_STEP (c) = NULL_TREE; |
44352 | } |
44353 | } |
44354 | } |
44355 | |
44356 | cond = NULL; |
44357 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_SEMICOLON)) |
44358 | cond = cp_parser_omp_for_cond (parser, decl, code: omp_for_parse_state->code); |
44359 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
44360 | |
44361 | incr = NULL; |
44362 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_CLOSE_PAREN)) |
44363 | { |
44364 | /* If decl is an iterator, preserve the operator on decl |
44365 | until finish_omp_for. */ |
44366 | if (real_decl |
44367 | && ((processing_template_decl |
44368 | && (TREE_TYPE (real_decl) == NULL_TREE |
44369 | || !INDIRECT_TYPE_P (TREE_TYPE (real_decl)))) |
44370 | || CLASS_TYPE_P (TREE_TYPE (real_decl)))) |
44371 | incr = cp_parser_omp_for_incr (parser, decl: real_decl); |
44372 | else |
44373 | incr = cp_parser_expression (parser); |
44374 | protected_set_expr_location_if_unset (incr, input_location); |
44375 | } |
44376 | |
44377 | parse_close_paren: |
44378 | if (!parens.require_close (parser)) |
44379 | cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, |
44380 | /*or_comma=*/false, |
44381 | /*consume_paren=*/true); |
44382 | |
44383 | /* We've parsed all the for (...) stuff now. Store the bits. */ |
44384 | TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl; |
44385 | TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init; |
44386 | TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond; |
44387 | TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr; |
44388 | if (orig_init) |
44389 | { |
44390 | omp_for_parse_state->orig_inits.safe_grow_cleared (len: depth + 1, exact: true); |
44391 | omp_for_parse_state->orig_inits[depth] = orig_init; |
44392 | } |
44393 | if (orig_decl) |
44394 | { |
44395 | if (!omp_for_parse_state->orig_declv) |
44396 | omp_for_parse_state->orig_declv |
44397 | = copy_node (omp_for_parse_state->declv); |
44398 | TREE_VEC_ELT (omp_for_parse_state->orig_declv, depth) = orig_decl; |
44399 | } |
44400 | else if (omp_for_parse_state->orig_declv) |
44401 | TREE_VEC_ELT (omp_for_parse_state->orig_declv, depth) = decl; |
44402 | if (this_pre_body) |
44403 | append_to_statement_list_force (this_pre_body, |
44404 | &(omp_for_parse_state->pre_body)); |
44405 | |
44406 | /* Start a nested block for the loop body. */ |
44407 | body_placeholder = build_stmt (input_location, EXPR_STMT, |
44408 | integer_zero_node); |
44409 | vec_safe_push (r&: omp_for_parse_state->body_placeholderv, t: body_placeholder); |
44410 | body_block = push_stmt_list (); |
44411 | vec_safe_push (r&: omp_for_parse_state->body_blockv, t: body_block); |
44412 | |
44413 | moreloops = depth < omp_for_parse_state->count - 1; |
44414 | omp_for_parse_state->want_nested_loop = moreloops; |
44415 | if (moreloops && cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
44416 | { |
44417 | omp_for_parse_state->depth++; |
44418 | add_stmt (cp_parser_omp_loop_nest (parser, if_p)); |
44419 | omp_for_parse_state->depth--; |
44420 | } |
44421 | else if (moreloops |
44422 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_BRACE)) |
44423 | { |
44424 | /* This is the open brace in the loop-body grammar production. Rather |
44425 | than trying to special-case braces, just parse it as a compound |
44426 | statement and handle the nested loop-body case there. Note that |
44427 | when we see a further open brace inside the compound statement |
44428 | loop-body, we don't know whether it is the start of intervening |
44429 | code that is a compound statement, or a level of braces |
44430 | surrounding a nested loop-body. Use the WANT_NESTED_LOOP state |
44431 | bit to ensure we have only one nested loop at each level. */ |
44432 | |
44433 | omp_for_parse_state->in_intervening_code = true; |
44434 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_NORMAL, function_body: false); |
44435 | omp_for_parse_state->in_intervening_code = false; |
44436 | |
44437 | if (omp_for_parse_state->want_nested_loop) |
44438 | { |
44439 | /* We have already parsed the whole loop body and not found a |
44440 | nested loop. */ |
44441 | error_at (omp_for_parse_state->for_loc, |
44442 | "not enough nested loops" ); |
44443 | omp_for_parse_state->fail = true; |
44444 | } |
44445 | if_p = NULL; |
44446 | } |
44447 | else |
44448 | { |
44449 | /* This is the final-loop-body case in the grammar: we have something |
44450 | that is not a FOR and not an open brace. */ |
44451 | if (moreloops) |
44452 | { |
44453 | /* If we were expecting a nested loop, give an error and mark |
44454 | that parsing has failed, and try to recover by parsing the |
44455 | body as regular code without further collapsing. */ |
44456 | error_at (omp_for_parse_state->for_loc, |
44457 | "not enough nested loops" ); |
44458 | omp_for_parse_state->fail = true; |
44459 | } |
44460 | parser->in_statement = IN_OMP_FOR; |
44461 | |
44462 | /* Generate the parts of range for that belong in the loop body, |
44463 | to be executed on every iteration. This includes setting the |
44464 | user-declared decomposition variables from the compiler-generated |
44465 | temporaries that are the real iteration variables for OMP_FOR. |
44466 | FIXME: Not sure if this is correct with respect to visibility |
44467 | of the variables from intervening code. However, putting this |
44468 | code in each level of loop instead of all around the innermost |
44469 | body also makes the decomposition variables visible to the |
44470 | inner for init/bound/step exressions, which is not supposed to |
44471 | happen and causes test failures. */ |
44472 | if (omp_for_parse_state->orig_declv) |
44473 | for (int i = 0; i < omp_for_parse_state->count; i++) |
44474 | { |
44475 | tree o = TREE_VEC_ELT (omp_for_parse_state->orig_declv, i); |
44476 | tree d = TREE_VEC_ELT (omp_for_parse_state->declv, i); |
44477 | if (o != d) |
44478 | cp_finish_omp_range_for (orig: o, begin: d); |
44479 | } |
44480 | |
44481 | /* Now parse the final-loop-body for the innermost loop. */ |
44482 | parser->omp_for_parse_state = NULL; |
44483 | if (omp_for_parse_state->inscan) |
44484 | cp_parser_omp_scan_loop_body (parser); |
44485 | else |
44486 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
44487 | parser->omp_for_parse_state = omp_for_parse_state; |
44488 | } |
44489 | parser->in_statement = save_in_statement; |
44490 | omp_for_parse_state->want_nested_loop = false; |
44491 | omp_for_parse_state->in_intervening_code = true; |
44492 | |
44493 | /* Pop and remember the body block. Add the body placeholder |
44494 | to the surrounding statement list instead. This is just a unique |
44495 | token that will be replaced when we reassemble the generated |
44496 | code for the entire omp for statement. */ |
44497 | body_block = pop_stmt_list (body_block); |
44498 | omp_for_parse_state->body_blockv[depth] = body_block; |
44499 | add_stmt (body_placeholder); |
44500 | |
44501 | /* Pop and remember the init block. */ |
44502 | if (sl) |
44503 | add_stmt (pop_stmt_list (sl)); |
44504 | finish_compound_stmt (init_scope); |
44505 | init_block = pop_stmt_list (init_block); |
44506 | omp_for_parse_state->init_blockv[depth] = init_block; |
44507 | |
44508 | /* Return the init placeholder rather than the remembered init block. |
44509 | Again, this is just a unique cookie that will be used to reassemble |
44510 | code pieces when the entire omp for statement has been parsed. */ |
44511 | return init_placeholder; |
44512 | } |
44513 | |
44514 | /* Worker for find_structured_blocks. *TP points to a STATEMENT_LIST |
44515 | and ITER is the element that is or contains a nested loop. This |
44516 | function moves the statements before and after ITER into |
44517 | OMP_STRUCTURED_BLOCKs and modifies *TP. */ |
44518 | static void |
44519 | insert_structured_blocks (tree *tp, tree_stmt_iterator iter) |
44520 | { |
44521 | tree sl = push_stmt_list (); |
44522 | for (tree_stmt_iterator i = tsi_start (t: *tp); !tsi_end_p (i); ) |
44523 | if (i == iter) |
44524 | { |
44525 | sl = pop_stmt_list (sl); |
44526 | if (TREE_CODE (sl) != STATEMENT_LIST || !tsi_end_p (i: tsi_start (t: sl))) |
44527 | tsi_link_before (&i, |
44528 | build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl), |
44529 | TSI_SAME_STMT); |
44530 | i++; |
44531 | sl = push_stmt_list (); |
44532 | } |
44533 | else |
44534 | { |
44535 | tree s = tsi_stmt (i); |
44536 | tsi_delink (&i); /* Advances i to next statement. */ |
44537 | add_stmt (s); |
44538 | } |
44539 | sl = pop_stmt_list (sl); |
44540 | if (TREE_CODE (sl) != STATEMENT_LIST || !tsi_end_p (i: tsi_start (t: sl))) |
44541 | tsi_link_after (&iter, |
44542 | build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl), |
44543 | TSI_SAME_STMT); |
44544 | } |
44545 | |
44546 | /* Helper to find and mark structured blocks in intervening code for a |
44547 | single loop level with markers for later error checking. *TP is the |
44548 | piece of code to be marked and INNER is the inner loop placeholder. |
44549 | Returns true if INNER was found (recursively) in *TP. */ |
44550 | static bool |
44551 | find_structured_blocks (tree *tp, tree inner) |
44552 | { |
44553 | if (*tp == inner) |
44554 | return true; |
44555 | else if (TREE_CODE (*tp) == BIND_EXPR) |
44556 | return find_structured_blocks (tp: &(BIND_EXPR_BODY (*tp)), inner); |
44557 | else if (TREE_CODE (*tp) == STATEMENT_LIST) |
44558 | { |
44559 | for (tree_stmt_iterator i = tsi_start (t: *tp); !tsi_end_p (i); ++i) |
44560 | { |
44561 | tree *p = tsi_stmt_ptr (i); |
44562 | /* The normal case is that there is no intervening code and we |
44563 | do not have to insert any OMP_STRUCTURED_BLOCK markers. */ |
44564 | if (find_structured_blocks (tp: p, inner)) |
44565 | { |
44566 | if (!(i == tsi_start (t: *tp) && i == tsi_last (t: *tp))) |
44567 | insert_structured_blocks (tp, iter: i); |
44568 | return true; |
44569 | } |
44570 | } |
44571 | return false; |
44572 | } |
44573 | else if (TREE_CODE (*tp) == TRY_FINALLY_EXPR) |
44574 | return find_structured_blocks (tp: &(TREE_OPERAND (*tp, 0)), inner); |
44575 | else if (TREE_CODE (*tp) == CLEANUP_STMT) |
44576 | return find_structured_blocks (tp: &(CLEANUP_BODY (*tp)), inner); |
44577 | else |
44578 | return false; |
44579 | } |
44580 | |
44581 | /* Helpers used for relinking tree structures: In tree rooted at |
44582 | CONTEXT, replace ORIG with REPLACEMENT. If FLATTEN is true, try to combine |
44583 | nested BIND_EXPRs. Gives an assertion if it fails to find ORIG. */ |
44584 | |
44585 | struct sit_data { |
44586 | tree orig; |
44587 | tree repl; |
44588 | bool flatten; |
44589 | }; |
44590 | |
44591 | static tree |
44592 | substitute_in_tree_walker (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, |
44593 | void *dp) |
44594 | { |
44595 | struct sit_data *sit = (struct sit_data *)dp; |
44596 | if (*tp == sit->orig) |
44597 | { |
44598 | *tp = sit->repl; |
44599 | return *tp; |
44600 | } |
44601 | /* Remove redundant BIND_EXPRs with no bindings even when not specifically |
44602 | trying to flatten. */ |
44603 | else if (TREE_CODE (*tp) == BIND_EXPR |
44604 | && BIND_EXPR_BODY (*tp) == sit->orig |
44605 | && !BIND_EXPR_VARS (*tp) |
44606 | && (sit->flatten || TREE_CODE (sit->repl) == BIND_EXPR)) |
44607 | { |
44608 | *tp = sit->repl; |
44609 | return *tp; |
44610 | } |
44611 | else if (sit->flatten |
44612 | && TREE_CODE (*tp) == BIND_EXPR |
44613 | && TREE_CODE (sit->repl) == BIND_EXPR) |
44614 | { |
44615 | if (BIND_EXPR_BODY (*tp) == sit->orig) |
44616 | { |
44617 | /* Merge binding lists for two directly nested BIND_EXPRs, |
44618 | keeping the outer one. */ |
44619 | BIND_EXPR_VARS (*tp) = chainon (BIND_EXPR_VARS (*tp), |
44620 | BIND_EXPR_VARS (sit->repl)); |
44621 | BIND_EXPR_BODY (*tp) = BIND_EXPR_BODY (sit->repl); |
44622 | return *tp; |
44623 | } |
44624 | else if (TREE_CODE (BIND_EXPR_BODY (*tp)) == STATEMENT_LIST) |
44625 | /* There might be a statement list containing cleanup_points |
44626 | etc between the two levels of BIND_EXPR. We can still merge |
44627 | them, again keeping the outer BIND_EXPR. */ |
44628 | for (tree_stmt_iterator i = tsi_start (BIND_EXPR_BODY (*tp)); |
44629 | !tsi_end_p (i); ++i) |
44630 | { |
44631 | tree *p = tsi_stmt_ptr (i); |
44632 | if (*p == sit->orig) |
44633 | { |
44634 | BIND_EXPR_VARS (*tp) = chainon (BIND_EXPR_VARS (*tp), |
44635 | BIND_EXPR_VARS (sit->repl)); |
44636 | *p = BIND_EXPR_BODY (sit->repl); |
44637 | return *tp; |
44638 | } |
44639 | } |
44640 | } |
44641 | return NULL; |
44642 | } |
44643 | |
44644 | static void |
44645 | substitute_in_tree (tree *context, tree orig, tree repl, bool flatten) |
44646 | { |
44647 | struct sit_data data; |
44648 | |
44649 | gcc_assert (*context && orig && repl); |
44650 | if (TREE_CODE (repl) == BIND_EXPR && !BIND_EXPR_VARS (repl)) |
44651 | repl = BIND_EXPR_BODY (repl); |
44652 | data.orig = orig; |
44653 | data.repl = repl; |
44654 | data.flatten = flatten; |
44655 | |
44656 | tree result = cp_walk_tree (context, substitute_in_tree_walker, |
44657 | (void *)&data, NULL); |
44658 | gcc_assert (result != NULL_TREE); |
44659 | } |
44660 | |
44661 | /* Walker to patch up the BLOCK_NODE hierarchy after the above surgery. |
44662 | *DP is is the parent block. */ |
44663 | |
44664 | static tree |
44665 | fixup_blocks_walker (tree *tp, int *walk_subtrees, void *dp) |
44666 | { |
44667 | tree superblock = *(tree *)dp; |
44668 | |
44669 | /* BIND_EXPR_BLOCK may be null if the expression is not a |
44670 | full-expression; if there's no block, no patching is necessary |
44671 | for this node. */ |
44672 | if (TREE_CODE (*tp) == BIND_EXPR && BIND_EXPR_BLOCK (*tp)) |
44673 | { |
44674 | tree block = BIND_EXPR_BLOCK (*tp); |
44675 | if (superblock) |
44676 | { |
44677 | BLOCK_SUPERCONTEXT (block) = superblock; |
44678 | BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (superblock); |
44679 | BLOCK_SUBBLOCKS (superblock) = block; |
44680 | } |
44681 | BLOCK_SUBBLOCKS (block) = NULL_TREE; |
44682 | cp_walk_tree (&BIND_EXPR_BODY (*tp), fixup_blocks_walker, |
44683 | (void *)&block, NULL); |
44684 | *walk_subtrees = 0; |
44685 | } |
44686 | |
44687 | return NULL; |
44688 | } |
44689 | |
44690 | /* Parse the restricted form of the for statement allowed by OpenMP. */ |
44691 | |
44692 | static tree |
44693 | cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, |
44694 | tree *cclauses, bool *if_p) |
44695 | { |
44696 | tree ret; |
44697 | tree cl, ordered_cl = NULL_TREE; |
44698 | int collapse = 1, ordered = 0; |
44699 | unsigned int count; |
44700 | bool tiling = false; |
44701 | bool inscan = false; |
44702 | struct omp_for_parse_data data; |
44703 | struct omp_for_parse_data *save_data = parser->omp_for_parse_state; |
44704 | tree result; |
44705 | location_t loc_first = cp_lexer_peek_token (lexer: parser->lexer)->location; |
44706 | |
44707 | for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) |
44708 | if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) |
44709 | collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); |
44710 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE) |
44711 | { |
44712 | tiling = true; |
44713 | collapse = list_length (OMP_CLAUSE_TILE_LIST (cl)); |
44714 | } |
44715 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED |
44716 | && OMP_CLAUSE_ORDERED_EXPR (cl)) |
44717 | { |
44718 | ordered_cl = cl; |
44719 | ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); |
44720 | } |
44721 | else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION |
44722 | && OMP_CLAUSE_REDUCTION_INSCAN (cl) |
44723 | && (code == OMP_SIMD || code == OMP_FOR)) |
44724 | inscan = true; |
44725 | |
44726 | if (ordered && ordered < collapse) |
44727 | { |
44728 | error_at (OMP_CLAUSE_LOCATION (ordered_cl), |
44729 | "%<ordered%> clause parameter is less than %<collapse%>" ); |
44730 | OMP_CLAUSE_ORDERED_EXPR (ordered_cl) |
44731 | = build_int_cst (NULL_TREE, collapse); |
44732 | ordered = collapse; |
44733 | } |
44734 | |
44735 | gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); |
44736 | count = ordered ? ordered : collapse; |
44737 | |
44738 | if (!cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
44739 | { |
44740 | cp_parser_error (parser, gmsgid: "for statement expected" ); |
44741 | return NULL; |
44742 | } |
44743 | |
44744 | /* Initialize parse state for recursive descent. */ |
44745 | data.declv = make_tree_vec (count); |
44746 | data.initv = make_tree_vec (count); |
44747 | data.condv = make_tree_vec (count); |
44748 | data.incrv = make_tree_vec (count); |
44749 | data.pre_body = NULL_TREE; |
44750 | data.for_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
44751 | data.count = count; |
44752 | data.depth = 0; |
44753 | data.want_nested_loop = true; |
44754 | data.ordered = ordered > 0; |
44755 | data.in_intervening_code = false; |
44756 | data.perfect_nesting_fail = false; |
44757 | data.fail = false; |
44758 | data.inscan = inscan; |
44759 | data.saw_intervening_code = false; |
44760 | data.code = code; |
44761 | data.orig_declv = NULL_TREE; |
44762 | data.clauses = clauses; |
44763 | data.cclauses = cclauses; |
44764 | data.ordered_cl = ordered_cl; |
44765 | parser->omp_for_parse_state = &data; |
44766 | |
44767 | cp_parser_omp_loop_nest (parser, if_p); |
44768 | |
44769 | /* Bomb out early if there was an error (not enough loops, etc). */ |
44770 | if (data.fail || data.declv == NULL_TREE) |
44771 | { |
44772 | parser->omp_for_parse_state = save_data; |
44773 | return NULL_TREE; |
44774 | } |
44775 | |
44776 | /* Relink the init and body blocks that were built during parsing. At |
44777 | this point we have a structure nested like |
44778 | init 0 |
44779 | body 0 |
44780 | init 1 |
44781 | body 1 |
44782 | init 2 |
44783 | body 2 |
44784 | and we want to turn it into |
44785 | init 0 |
44786 | init 1 |
44787 | init 2 |
44788 | omp_for |
44789 | body 0 |
44790 | body 1 |
44791 | body 2 |
44792 | We also need to flatten the init blocks, as some code for later |
44793 | processing of combined directives gets confused otherwise. */ |
44794 | |
44795 | gcc_assert (vec_safe_length (data.init_blockv) == count); |
44796 | gcc_assert (vec_safe_length (data.body_blockv) == count); |
44797 | gcc_assert (vec_safe_length (data.init_placeholderv) == count); |
44798 | gcc_assert (vec_safe_length (data.body_placeholderv) == count); |
44799 | |
44800 | /* First insert markers for structured blocks for intervening code in |
44801 | the loop bodies. */ |
44802 | for (unsigned int i = 0; i < count - 1; i++) |
44803 | { |
44804 | bool good = find_structured_blocks (tp: &(data.body_blockv[i]), |
44805 | inner: data.init_placeholderv[i+1]); |
44806 | gcc_assert (good); |
44807 | } |
44808 | |
44809 | /* Do the substitution from the inside out. */ |
44810 | for (unsigned int i = count - 1; i > 0; i--) |
44811 | { |
44812 | substitute_in_tree (context: &(data.body_blockv[i-1]), |
44813 | orig: data.init_placeholderv[i], |
44814 | repl: data.body_blockv[i], flatten: false); |
44815 | substitute_in_tree (context: &(data.init_blockv[i-1]), |
44816 | orig: data.body_placeholderv[i-1], |
44817 | repl: data.init_blockv[i], flatten: true); |
44818 | } |
44819 | |
44820 | /* Generate the OMP_FOR. Note finish_omp_for adds the OMP_FOR |
44821 | (and possibly other stuff) to the current statement list but |
44822 | returns a pointer to the OMP_FOR itself, or null in case of error. */ |
44823 | result = push_stmt_list (); |
44824 | ret = finish_omp_for (loc_first, code, data.declv, data.orig_declv, |
44825 | data.initv, data.condv, data.incrv, |
44826 | data.body_blockv[0], |
44827 | data.pre_body, &data.orig_inits, data.clauses); |
44828 | result = pop_stmt_list (result); |
44829 | |
44830 | /* Check for errors involving lb/ub/incr expressions referencing |
44831 | variables declared in intervening code. */ |
44832 | if (data.saw_intervening_code |
44833 | && !c_omp_check_loop_binding_exprs (ret, &data.orig_inits)) |
44834 | ret = NULL_TREE; |
44835 | |
44836 | if (ret) |
44837 | { |
44838 | /* Splice the omp_for into the nest of init blocks. */ |
44839 | substitute_in_tree (context: &(data.init_blockv[0]), |
44840 | orig: data.body_placeholderv[count - 1], |
44841 | repl: result, flatten: true); |
44842 | |
44843 | /* Some later processing for combined directives assumes |
44844 | that the BIND_EXPR containing range for variables appears |
44845 | at top level in the OMP_FOR body. Fix that up if it's |
44846 | not the case, e.g. because there is intervening code. */ |
44847 | if (code != OACC_LOOP) |
44848 | finish_omp_for_block (data.init_blockv[0], ret); |
44849 | |
44850 | /* Clean up the block subblock/superblock links. Per comment in |
44851 | begin_compound_stmt, "we don't build BLOCK nodes when processing |
44852 | templates", so skip this step in that case. */ |
44853 | if (!processing_template_decl) |
44854 | { |
44855 | tree superblock = NULL_TREE; |
44856 | cp_walk_tree (&data.init_blockv[0], fixup_blocks_walker, |
44857 | (void *)&superblock, NULL); |
44858 | } |
44859 | |
44860 | /* Finally record the result. */ |
44861 | add_stmt (data.init_blockv[0]); |
44862 | } |
44863 | |
44864 | parser->omp_for_parse_state = save_data; |
44865 | return ret; |
44866 | } |
44867 | |
44868 | /* Helper function for OpenMP parsing, split clauses and call |
44869 | finish_omp_clauses on each of the set of clauses afterwards. */ |
44870 | |
44871 | static void |
44872 | cp_omp_split_clauses (location_t loc, enum tree_code code, |
44873 | omp_clause_mask mask, tree clauses, tree *cclauses) |
44874 | { |
44875 | int i; |
44876 | c_omp_split_clauses (loc, code, mask, clauses, cclauses); |
44877 | for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) |
44878 | if (cclauses[i]) |
44879 | cclauses[i] = finish_omp_clauses (cclauses[i], |
44880 | i == C_OMP_CLAUSE_SPLIT_TARGET |
44881 | ? C_ORT_OMP_TARGET : C_ORT_OMP); |
44882 | } |
44883 | |
44884 | /* OpenMP 5.0: |
44885 | #pragma omp loop loop-clause[optseq] new-line |
44886 | for-loop */ |
44887 | |
44888 | #define OMP_LOOP_CLAUSE_MASK \ |
44889 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
44890 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
44891 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
44892 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
44893 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \ |
44894 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
44895 | |
44896 | static tree |
44897 | cp_parser_omp_loop (cp_parser *parser, cp_token *pragma_tok, |
44898 | char *p_name, omp_clause_mask mask, tree *cclauses, |
44899 | bool *if_p) |
44900 | { |
44901 | tree clauses, sb, ret; |
44902 | unsigned int save; |
44903 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
44904 | |
44905 | strcat (dest: p_name, src: " loop" ); |
44906 | mask |= OMP_LOOP_CLAUSE_MASK; |
44907 | |
44908 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
44909 | finish_p: cclauses == NULL); |
44910 | if (cclauses) |
44911 | { |
44912 | cp_omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses); |
44913 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP]; |
44914 | } |
44915 | |
44916 | keep_next_level (true); |
44917 | sb = begin_omp_structured_block (); |
44918 | save = cp_parser_begin_omp_structured_block (parser); |
44919 | |
44920 | ret = cp_parser_omp_for_loop (parser, code: OMP_LOOP, clauses, cclauses, if_p); |
44921 | |
44922 | cp_parser_end_omp_structured_block (parser, save); |
44923 | add_stmt (finish_omp_structured_block (sb)); |
44924 | |
44925 | return ret; |
44926 | } |
44927 | |
44928 | /* OpenMP 4.0: |
44929 | #pragma omp simd simd-clause[optseq] new-line |
44930 | for-loop */ |
44931 | |
44932 | #define OMP_SIMD_CLAUSE_MASK \ |
44933 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \ |
44934 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ |
44935 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
44936 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ |
44937 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
44938 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
44939 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
44940 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
44941 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
44942 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \ |
44943 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
44944 | |
44945 | static tree |
44946 | cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, |
44947 | char *p_name, omp_clause_mask mask, tree *cclauses, |
44948 | bool *if_p) |
44949 | { |
44950 | tree clauses, sb, ret; |
44951 | unsigned int save; |
44952 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
44953 | |
44954 | strcat (dest: p_name, src: " simd" ); |
44955 | mask |= OMP_SIMD_CLAUSE_MASK; |
44956 | |
44957 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
44958 | finish_p: cclauses == NULL); |
44959 | if (cclauses) |
44960 | { |
44961 | cp_omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses); |
44962 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; |
44963 | } |
44964 | |
44965 | keep_next_level (true); |
44966 | sb = begin_omp_structured_block (); |
44967 | save = cp_parser_begin_omp_structured_block (parser); |
44968 | |
44969 | ret = cp_parser_omp_for_loop (parser, code: OMP_SIMD, clauses, cclauses, if_p); |
44970 | |
44971 | cp_parser_end_omp_structured_block (parser, save); |
44972 | add_stmt (finish_omp_structured_block (sb)); |
44973 | |
44974 | return ret; |
44975 | } |
44976 | |
44977 | /* OpenMP 2.5: |
44978 | #pragma omp for for-clause[optseq] new-line |
44979 | for-loop |
44980 | |
44981 | OpenMP 4.0: |
44982 | #pragma omp for simd for-simd-clause[optseq] new-line |
44983 | for-loop */ |
44984 | |
44985 | #define OMP_FOR_CLAUSE_MASK \ |
44986 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
44987 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
44988 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
44989 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
44990 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
44991 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ |
44992 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ |
44993 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ |
44994 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
44995 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
44996 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
44997 | |
44998 | static tree |
44999 | cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok, |
45000 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45001 | bool *if_p) |
45002 | { |
45003 | tree clauses, sb, ret; |
45004 | unsigned int save; |
45005 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45006 | |
45007 | strcat (dest: p_name, src: " for" ); |
45008 | mask |= OMP_FOR_CLAUSE_MASK; |
45009 | /* parallel for{, simd} disallows nowait clause, but for |
45010 | target {teams distribute ,}parallel for{, simd} it should be accepted. */ |
45011 | if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0) |
45012 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); |
45013 | /* Composite distribute parallel for{, simd} disallows ordered clause. */ |
45014 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
45015 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED); |
45016 | |
45017 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45018 | { |
45019 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45020 | const char *p = IDENTIFIER_POINTER (id); |
45021 | |
45022 | if (strcmp (s1: p, s2: "simd" ) == 0) |
45023 | { |
45024 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45025 | if (cclauses == NULL) |
45026 | cclauses = cclauses_buf; |
45027 | |
45028 | cp_lexer_consume_token (lexer: parser->lexer); |
45029 | if (!flag_openmp) /* flag_openmp_simd */ |
45030 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45031 | cclauses, if_p); |
45032 | sb = begin_omp_structured_block (); |
45033 | save = cp_parser_begin_omp_structured_block (parser); |
45034 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45035 | cclauses, if_p); |
45036 | cp_parser_end_omp_structured_block (parser, save); |
45037 | tree body = finish_omp_structured_block (sb); |
45038 | if (ret == NULL) |
45039 | return ret; |
45040 | ret = make_node (OMP_FOR); |
45041 | TREE_TYPE (ret) = void_type_node; |
45042 | OMP_FOR_BODY (ret) = body; |
45043 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
45044 | SET_EXPR_LOCATION (ret, loc); |
45045 | add_stmt (ret); |
45046 | return ret; |
45047 | } |
45048 | } |
45049 | if (!flag_openmp) /* flag_openmp_simd */ |
45050 | { |
45051 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45052 | return NULL_TREE; |
45053 | } |
45054 | |
45055 | /* Composite distribute parallel for disallows linear clause. */ |
45056 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
45057 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR); |
45058 | |
45059 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45060 | finish_p: cclauses == NULL); |
45061 | if (cclauses) |
45062 | { |
45063 | cp_omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses); |
45064 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; |
45065 | } |
45066 | |
45067 | keep_next_level (true); |
45068 | sb = begin_omp_structured_block (); |
45069 | save = cp_parser_begin_omp_structured_block (parser); |
45070 | |
45071 | ret = cp_parser_omp_for_loop (parser, code: OMP_FOR, clauses, cclauses, if_p); |
45072 | |
45073 | cp_parser_end_omp_structured_block (parser, save); |
45074 | add_stmt (finish_omp_structured_block (sb)); |
45075 | |
45076 | return ret; |
45077 | } |
45078 | |
45079 | static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *, |
45080 | omp_clause_mask, tree *, bool *); |
45081 | |
45082 | /* OpenMP 2.5: |
45083 | # pragma omp master new-line |
45084 | structured-block */ |
45085 | |
45086 | static tree |
45087 | cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, |
45088 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45089 | bool *if_p) |
45090 | { |
45091 | tree clauses, sb, ret; |
45092 | unsigned int save; |
45093 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45094 | |
45095 | strcat (dest: p_name, src: " master" ); |
45096 | |
45097 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45098 | { |
45099 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45100 | const char *p = IDENTIFIER_POINTER (id); |
45101 | |
45102 | if (strcmp (s1: p, s2: "taskloop" ) == 0) |
45103 | { |
45104 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45105 | if (cclauses == NULL) |
45106 | cclauses = cclauses_buf; |
45107 | |
45108 | cp_lexer_consume_token (lexer: parser->lexer); |
45109 | if (!flag_openmp) /* flag_openmp_simd */ |
45110 | return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45111 | cclauses, if_p); |
45112 | sb = begin_omp_structured_block (); |
45113 | save = cp_parser_begin_omp_structured_block (parser); |
45114 | ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45115 | cclauses, if_p); |
45116 | cp_parser_end_omp_structured_block (parser, save); |
45117 | tree body = finish_omp_structured_block (sb); |
45118 | if (ret == NULL) |
45119 | return ret; |
45120 | ret = c_finish_omp_master (loc, body); |
45121 | OMP_MASTER_COMBINED (ret) = 1; |
45122 | return ret; |
45123 | } |
45124 | } |
45125 | if (!flag_openmp) /* flag_openmp_simd */ |
45126 | { |
45127 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45128 | return NULL_TREE; |
45129 | } |
45130 | |
45131 | if (cclauses) |
45132 | { |
45133 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45134 | finish_p: false); |
45135 | cp_omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses); |
45136 | } |
45137 | else |
45138 | cp_parser_require_pragma_eol (parser, pragma_tok); |
45139 | |
45140 | return c_finish_omp_master (loc, |
45141 | cp_parser_omp_structured_block (parser, if_p)); |
45142 | } |
45143 | |
45144 | /* OpenMP 5.1: |
45145 | # pragma omp masked masked-clauses new-line |
45146 | structured-block */ |
45147 | |
45148 | #define OMP_MASKED_CLAUSE_MASK \ |
45149 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER) |
45150 | |
45151 | static tree |
45152 | cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok, |
45153 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45154 | bool *if_p) |
45155 | { |
45156 | tree clauses, sb, ret; |
45157 | unsigned int save; |
45158 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45159 | |
45160 | strcat (dest: p_name, src: " masked" ); |
45161 | mask |= OMP_MASKED_CLAUSE_MASK; |
45162 | |
45163 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45164 | { |
45165 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45166 | const char *p = IDENTIFIER_POINTER (id); |
45167 | |
45168 | if (strcmp (s1: p, s2: "taskloop" ) == 0) |
45169 | { |
45170 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45171 | if (cclauses == NULL) |
45172 | cclauses = cclauses_buf; |
45173 | |
45174 | cp_lexer_consume_token (lexer: parser->lexer); |
45175 | if (!flag_openmp) /* flag_openmp_simd */ |
45176 | return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45177 | cclauses, if_p); |
45178 | sb = begin_omp_structured_block (); |
45179 | save = cp_parser_begin_omp_structured_block (parser); |
45180 | ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, |
45181 | cclauses, if_p); |
45182 | cp_parser_end_omp_structured_block (parser, save); |
45183 | tree body = finish_omp_structured_block (sb); |
45184 | if (ret == NULL) |
45185 | return ret; |
45186 | ret = c_finish_omp_masked (loc, body, |
45187 | cclauses[C_OMP_CLAUSE_SPLIT_MASKED]); |
45188 | OMP_MASKED_COMBINED (ret) = 1; |
45189 | return ret; |
45190 | } |
45191 | } |
45192 | if (!flag_openmp) /* flag_openmp_simd */ |
45193 | { |
45194 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45195 | return NULL_TREE; |
45196 | } |
45197 | |
45198 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45199 | finish_p: cclauses == NULL); |
45200 | if (cclauses) |
45201 | { |
45202 | cp_omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses); |
45203 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED]; |
45204 | } |
45205 | |
45206 | return c_finish_omp_masked (loc, |
45207 | cp_parser_omp_structured_block (parser, if_p), |
45208 | clauses); |
45209 | } |
45210 | |
45211 | /* OpenMP 2.5: |
45212 | # pragma omp ordered new-line |
45213 | structured-block |
45214 | |
45215 | OpenMP 4.5: |
45216 | # pragma omp ordered ordered-clauses new-line |
45217 | structured-block */ |
45218 | |
45219 | #define OMP_ORDERED_CLAUSE_MASK \ |
45220 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ |
45221 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) |
45222 | |
45223 | #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ |
45224 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
45225 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) |
45226 | |
45227 | static bool |
45228 | cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, |
45229 | enum pragma_context context, bool *if_p) |
45230 | { |
45231 | location_t loc = pragma_tok->location; |
45232 | int n = 1; |
45233 | |
45234 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
45235 | n = 2; |
45236 | |
45237 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n, type: CPP_NAME)) |
45238 | { |
45239 | tree id = cp_lexer_peek_nth_token (lexer: parser->lexer, n)->u.value; |
45240 | const char *p = IDENTIFIER_POINTER (id); |
45241 | |
45242 | if (strcmp (s1: p, s2: "depend" ) == 0 || strcmp (s1: p, s2: "doacross" ) == 0) |
45243 | { |
45244 | if (!flag_openmp) /* flag_openmp_simd */ |
45245 | { |
45246 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45247 | return false; |
45248 | } |
45249 | if (context == pragma_stmt) |
45250 | { |
45251 | error_at (pragma_tok->location, "%<#pragma omp ordered%> with " |
45252 | "%qs clause may only be used in compound " |
45253 | "statements" , p); |
45254 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45255 | return true; |
45256 | } |
45257 | tree clauses |
45258 | = cp_parser_omp_all_clauses (parser, |
45259 | OMP_ORDERED_DEPEND_CLAUSE_MASK, |
45260 | where: "#pragma omp ordered" , pragma_tok); |
45261 | c_finish_omp_ordered (loc, clauses, NULL_TREE); |
45262 | return false; |
45263 | } |
45264 | } |
45265 | |
45266 | tree clauses |
45267 | = cp_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK, |
45268 | where: "#pragma omp ordered" , pragma_tok); |
45269 | |
45270 | if (!flag_openmp /* flag_openmp_simd */ |
45271 | && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE) |
45272 | return false; |
45273 | |
45274 | c_finish_omp_ordered (loc, clauses, |
45275 | cp_parser_omp_structured_block (parser, if_p)); |
45276 | return true; |
45277 | } |
45278 | |
45279 | /* OpenMP 2.5: |
45280 | |
45281 | section-scope: |
45282 | { section-sequence } |
45283 | |
45284 | section-sequence: |
45285 | section-directive[opt] structured-block |
45286 | section-sequence section-directive structured-block */ |
45287 | |
45288 | static tree |
45289 | cp_parser_omp_sections_scope (cp_parser *parser) |
45290 | { |
45291 | tree stmt, substmt; |
45292 | bool error_suppress = false; |
45293 | cp_token *tok; |
45294 | |
45295 | matching_braces braces; |
45296 | if (!braces.require_open (parser)) |
45297 | return NULL_TREE; |
45298 | |
45299 | stmt = push_stmt_list (); |
45300 | |
45301 | if (cp_parser_pragma_kind (token: cp_lexer_peek_token (lexer: parser->lexer)) |
45302 | != PRAGMA_OMP_SECTION |
45303 | && !cp_parser_omp_section_scan (parser, directive: "section" , tentative: true)) |
45304 | { |
45305 | substmt = cp_parser_omp_structured_block_sequence (parser, |
45306 | kind: PRAGMA_OMP_SECTION); |
45307 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
45308 | add_stmt (substmt); |
45309 | } |
45310 | |
45311 | while (1) |
45312 | { |
45313 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
45314 | if (tok->type == CPP_CLOSE_BRACE) |
45315 | break; |
45316 | if (tok->type == CPP_EOF) |
45317 | break; |
45318 | |
45319 | if (cp_parser_omp_section_scan (parser, directive: "section" , tentative: false)) |
45320 | tok = cp_lexer_peek_token (lexer: parser->lexer); |
45321 | if (cp_parser_pragma_kind (token: tok) == PRAGMA_OMP_SECTION) |
45322 | { |
45323 | cp_lexer_consume_token (lexer: parser->lexer); |
45324 | cp_parser_require_pragma_eol (parser, pragma_tok: tok); |
45325 | error_suppress = false; |
45326 | } |
45327 | else if (!error_suppress) |
45328 | { |
45329 | cp_parser_error (parser, gmsgid: "expected %<#pragma omp section%> or %<}%>" ); |
45330 | error_suppress = true; |
45331 | } |
45332 | |
45333 | substmt = cp_parser_omp_structured_block_sequence (parser, |
45334 | kind: PRAGMA_OMP_SECTION); |
45335 | substmt = build1 (OMP_SECTION, void_type_node, substmt); |
45336 | add_stmt (substmt); |
45337 | } |
45338 | braces.require_close (parser); |
45339 | |
45340 | substmt = pop_stmt_list (stmt); |
45341 | |
45342 | stmt = make_node (OMP_SECTIONS); |
45343 | TREE_TYPE (stmt) = void_type_node; |
45344 | OMP_SECTIONS_BODY (stmt) = substmt; |
45345 | |
45346 | add_stmt (stmt); |
45347 | return stmt; |
45348 | } |
45349 | |
45350 | /* OpenMP 2.5: |
45351 | # pragma omp sections sections-clause[optseq] newline |
45352 | sections-scope */ |
45353 | |
45354 | #define OMP_SECTIONS_CLAUSE_MASK \ |
45355 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45356 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45357 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45358 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45359 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45360 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
45361 | |
45362 | static tree |
45363 | cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok, |
45364 | char *p_name, omp_clause_mask mask, tree *cclauses) |
45365 | { |
45366 | tree clauses, ret; |
45367 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45368 | |
45369 | strcat (dest: p_name, src: " sections" ); |
45370 | mask |= OMP_SECTIONS_CLAUSE_MASK; |
45371 | if (cclauses) |
45372 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); |
45373 | |
45374 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45375 | finish_p: cclauses == NULL); |
45376 | if (cclauses) |
45377 | { |
45378 | cp_omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses); |
45379 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]; |
45380 | } |
45381 | |
45382 | ret = cp_parser_omp_sections_scope (parser); |
45383 | if (ret) |
45384 | OMP_SECTIONS_CLAUSES (ret) = clauses; |
45385 | |
45386 | return ret; |
45387 | } |
45388 | |
45389 | /* OpenMP 2.5: |
45390 | # pragma omp parallel parallel-clause[optseq] new-line |
45391 | structured-block |
45392 | # pragma omp parallel for parallel-for-clause[optseq] new-line |
45393 | structured-block |
45394 | # pragma omp parallel sections parallel-sections-clause[optseq] new-line |
45395 | structured-block |
45396 | |
45397 | OpenMP 4.0: |
45398 | # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line |
45399 | structured-block */ |
45400 | |
45401 | #define OMP_PARALLEL_CLAUSE_MASK \ |
45402 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
45403 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45404 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45405 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
45406 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
45407 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \ |
45408 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45409 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \ |
45410 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45411 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) |
45412 | |
45413 | static tree |
45414 | cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, |
45415 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45416 | bool *if_p) |
45417 | { |
45418 | tree stmt, clauses, block; |
45419 | unsigned int save; |
45420 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45421 | |
45422 | strcat (dest: p_name, src: " parallel" ); |
45423 | mask |= OMP_PARALLEL_CLAUSE_MASK; |
45424 | /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */ |
45425 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0 |
45426 | && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0) |
45427 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN); |
45428 | |
45429 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_FOR)) |
45430 | { |
45431 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45432 | if (cclauses == NULL) |
45433 | cclauses = cclauses_buf; |
45434 | |
45435 | cp_lexer_consume_token (lexer: parser->lexer); |
45436 | if (!flag_openmp) /* flag_openmp_simd */ |
45437 | return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses, |
45438 | if_p); |
45439 | block = begin_omp_parallel (); |
45440 | save = cp_parser_begin_omp_structured_block (parser); |
45441 | tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses, |
45442 | if_p); |
45443 | cp_parser_end_omp_structured_block (parser, save); |
45444 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
45445 | block); |
45446 | if (ret == NULL_TREE) |
45447 | return ret; |
45448 | OMP_PARALLEL_COMBINED (stmt) = 1; |
45449 | return stmt; |
45450 | } |
45451 | /* When combined with distribute, parallel has to be followed by for. |
45452 | #pragma omp target parallel is allowed though. */ |
45453 | else if (cclauses |
45454 | && (mask & (OMP_CLAUSE_MASK_1 |
45455 | << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0) |
45456 | { |
45457 | error_at (loc, "expected %<for%> after %qs" , p_name); |
45458 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45459 | return NULL_TREE; |
45460 | } |
45461 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45462 | { |
45463 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45464 | const char *p = IDENTIFIER_POINTER (id); |
45465 | if (cclauses == NULL && strcmp (s1: p, s2: "masked" ) == 0) |
45466 | { |
45467 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45468 | cclauses = cclauses_buf; |
45469 | |
45470 | cp_lexer_consume_token (lexer: parser->lexer); |
45471 | if (!flag_openmp) /* flag_openmp_simd */ |
45472 | return cp_parser_omp_masked (parser, pragma_tok, p_name, mask, |
45473 | cclauses, if_p); |
45474 | block = begin_omp_parallel (); |
45475 | save = cp_parser_begin_omp_structured_block (parser); |
45476 | tree ret = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, |
45477 | cclauses, if_p); |
45478 | cp_parser_end_omp_structured_block (parser, save); |
45479 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
45480 | block); |
45481 | if (ret == NULL_TREE) |
45482 | return ret; |
45483 | /* masked does have just filter clause, but during gimplification |
45484 | isn't represented by a gimplification omp context, so for |
45485 | #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED, |
45486 | so that |
45487 | #pragma omp parallel masked |
45488 | #pragma omp taskloop simd lastprivate (x) |
45489 | isn't confused with |
45490 | #pragma omp parallel masked taskloop simd lastprivate (x) */ |
45491 | if (OMP_MASKED_COMBINED (ret)) |
45492 | OMP_PARALLEL_COMBINED (stmt) = 1; |
45493 | return stmt; |
45494 | } |
45495 | else if (cclauses == NULL && strcmp (s1: p, s2: "master" ) == 0) |
45496 | { |
45497 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45498 | cclauses = cclauses_buf; |
45499 | |
45500 | cp_lexer_consume_token (lexer: parser->lexer); |
45501 | if (!flag_openmp) /* flag_openmp_simd */ |
45502 | return cp_parser_omp_master (parser, pragma_tok, p_name, mask, |
45503 | cclauses, if_p); |
45504 | block = begin_omp_parallel (); |
45505 | save = cp_parser_begin_omp_structured_block (parser); |
45506 | tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask, |
45507 | cclauses, if_p); |
45508 | cp_parser_end_omp_structured_block (parser, save); |
45509 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
45510 | block); |
45511 | if (ret == NULL_TREE) |
45512 | return ret; |
45513 | /* master doesn't have any clauses and during gimplification |
45514 | isn't represented by a gimplification omp context, so for |
45515 | #pragma omp parallel master don't set OMP_PARALLEL_COMBINED, |
45516 | so that |
45517 | #pragma omp parallel master |
45518 | #pragma omp taskloop simd lastprivate (x) |
45519 | isn't confused with |
45520 | #pragma omp parallel master taskloop simd lastprivate (x) */ |
45521 | if (OMP_MASTER_COMBINED (ret)) |
45522 | OMP_PARALLEL_COMBINED (stmt) = 1; |
45523 | return stmt; |
45524 | } |
45525 | else if (strcmp (s1: p, s2: "loop" ) == 0) |
45526 | { |
45527 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45528 | if (cclauses == NULL) |
45529 | cclauses = cclauses_buf; |
45530 | |
45531 | cp_lexer_consume_token (lexer: parser->lexer); |
45532 | if (!flag_openmp) /* flag_openmp_simd */ |
45533 | return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
45534 | cclauses, if_p); |
45535 | block = begin_omp_parallel (); |
45536 | save = cp_parser_begin_omp_structured_block (parser); |
45537 | tree ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
45538 | cclauses, if_p); |
45539 | cp_parser_end_omp_structured_block (parser, save); |
45540 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
45541 | block); |
45542 | if (ret == NULL_TREE) |
45543 | return ret; |
45544 | OMP_PARALLEL_COMBINED (stmt) = 1; |
45545 | return stmt; |
45546 | } |
45547 | else if (!flag_openmp) /* flag_openmp_simd */ |
45548 | { |
45549 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45550 | return NULL_TREE; |
45551 | } |
45552 | else if (cclauses == NULL && strcmp (s1: p, s2: "sections" ) == 0) |
45553 | { |
45554 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45555 | cclauses = cclauses_buf; |
45556 | |
45557 | cp_lexer_consume_token (lexer: parser->lexer); |
45558 | block = begin_omp_parallel (); |
45559 | save = cp_parser_begin_omp_structured_block (parser); |
45560 | cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses); |
45561 | cp_parser_end_omp_structured_block (parser, save); |
45562 | stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], |
45563 | block); |
45564 | OMP_PARALLEL_COMBINED (stmt) = 1; |
45565 | return stmt; |
45566 | } |
45567 | } |
45568 | else if (!flag_openmp) /* flag_openmp_simd */ |
45569 | { |
45570 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45571 | return NULL_TREE; |
45572 | } |
45573 | |
45574 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45575 | finish_p: cclauses == NULL); |
45576 | if (cclauses) |
45577 | { |
45578 | cp_omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses); |
45579 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; |
45580 | } |
45581 | |
45582 | block = begin_omp_parallel (); |
45583 | save = cp_parser_begin_omp_structured_block (parser); |
45584 | parser->omp_attrs_forbidden_p = true; |
45585 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
45586 | cp_parser_end_omp_structured_block (parser, save); |
45587 | stmt = finish_omp_parallel (clauses, block); |
45588 | return stmt; |
45589 | } |
45590 | |
45591 | /* OpenMP 2.5: |
45592 | # pragma omp single single-clause[optseq] new-line |
45593 | structured-block */ |
45594 | |
45595 | #define OMP_SINGLE_CLAUSE_MASK \ |
45596 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45597 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45598 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ |
45599 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45600 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
45601 | |
45602 | static tree |
45603 | cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
45604 | { |
45605 | tree stmt = make_node (OMP_SINGLE); |
45606 | TREE_TYPE (stmt) = void_type_node; |
45607 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
45608 | |
45609 | OMP_SINGLE_CLAUSES (stmt) |
45610 | = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, |
45611 | where: "#pragma omp single" , pragma_tok); |
45612 | OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
45613 | |
45614 | return add_stmt (stmt); |
45615 | } |
45616 | |
45617 | /* OpenMP 5.1: |
45618 | # pragma omp scope scope-clause[optseq] new-line |
45619 | structured-block */ |
45620 | |
45621 | #define OMP_SCOPE_CLAUSE_MASK \ |
45622 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45623 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45624 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45625 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45626 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
45627 | |
45628 | static tree |
45629 | cp_parser_omp_scope (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
45630 | { |
45631 | tree stmt = make_node (OMP_SCOPE); |
45632 | TREE_TYPE (stmt) = void_type_node; |
45633 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
45634 | |
45635 | OMP_SCOPE_CLAUSES (stmt) |
45636 | = cp_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK, |
45637 | where: "#pragma omp scope" , pragma_tok); |
45638 | OMP_SCOPE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
45639 | |
45640 | return add_stmt (stmt); |
45641 | } |
45642 | |
45643 | /* OpenMP 3.0: |
45644 | # pragma omp task task-clause[optseq] new-line |
45645 | structured-block */ |
45646 | |
45647 | #define OMP_TASK_CLAUSE_MASK \ |
45648 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
45649 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ |
45650 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
45651 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45652 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45653 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
45654 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ |
45655 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ |
45656 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
45657 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ |
45658 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45659 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ |
45660 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \ |
45661 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY)) |
45662 | |
45663 | static tree |
45664 | cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
45665 | { |
45666 | tree clauses, block; |
45667 | unsigned int save; |
45668 | |
45669 | clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK, |
45670 | where: "#pragma omp task" , pragma_tok); |
45671 | block = begin_omp_task (); |
45672 | save = cp_parser_begin_omp_structured_block (parser); |
45673 | parser->omp_attrs_forbidden_p = true; |
45674 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
45675 | cp_parser_end_omp_structured_block (parser, save); |
45676 | return finish_omp_task (clauses, block); |
45677 | } |
45678 | |
45679 | /* OpenMP 3.0: |
45680 | # pragma omp taskwait new-line |
45681 | |
45682 | OpenMP 5.0: |
45683 | # pragma omp taskwait taskwait-clause[opt] new-line */ |
45684 | |
45685 | #define OMP_TASKWAIT_CLAUSE_MASK \ |
45686 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
45687 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
45688 | |
45689 | static void |
45690 | cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok) |
45691 | { |
45692 | tree clauses |
45693 | = cp_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK, |
45694 | where: "#pragma omp taskwait" , pragma_tok); |
45695 | |
45696 | if (clauses) |
45697 | { |
45698 | tree stmt = make_node (OMP_TASK); |
45699 | TREE_TYPE (stmt) = void_node; |
45700 | OMP_TASK_CLAUSES (stmt) = clauses; |
45701 | OMP_TASK_BODY (stmt) = NULL_TREE; |
45702 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
45703 | add_stmt (stmt); |
45704 | } |
45705 | else |
45706 | finish_omp_taskwait (); |
45707 | } |
45708 | |
45709 | /* OpenMP 3.1: |
45710 | # pragma omp taskyield new-line */ |
45711 | |
45712 | static void |
45713 | cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok) |
45714 | { |
45715 | cp_parser_require_pragma_eol (parser, pragma_tok); |
45716 | finish_omp_taskyield (); |
45717 | } |
45718 | |
45719 | /* OpenMP 4.0: |
45720 | # pragma omp taskgroup new-line |
45721 | structured-block |
45722 | |
45723 | OpenMP 5.0: |
45724 | # pragma omp taskgroup taskgroup-clause[optseq] new-line */ |
45725 | |
45726 | #define OMP_TASKGROUP_CLAUSE_MASK \ |
45727 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45728 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION)) |
45729 | |
45730 | static tree |
45731 | cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
45732 | { |
45733 | tree clauses |
45734 | = cp_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK, |
45735 | where: "#pragma omp taskgroup" , pragma_tok); |
45736 | return c_finish_omp_taskgroup (input_location, |
45737 | cp_parser_omp_structured_block (parser, |
45738 | if_p), |
45739 | clauses); |
45740 | } |
45741 | |
45742 | |
45743 | /* OpenMP 2.5: |
45744 | # pragma omp threadprivate (variable-list) */ |
45745 | |
45746 | static void |
45747 | cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok) |
45748 | { |
45749 | tree vars; |
45750 | |
45751 | vars = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ERROR, NULL); |
45752 | cp_parser_require_pragma_eol (parser, pragma_tok); |
45753 | |
45754 | finish_omp_threadprivate (vars); |
45755 | } |
45756 | |
45757 | /* OpenMP 4.0: |
45758 | # pragma omp cancel cancel-clause[optseq] new-line */ |
45759 | |
45760 | #define OMP_CANCEL_CLAUSE_MASK \ |
45761 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ |
45762 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ |
45763 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ |
45764 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \ |
45765 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)) |
45766 | |
45767 | static void |
45768 | cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok) |
45769 | { |
45770 | tree clauses = cp_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK, |
45771 | where: "#pragma omp cancel" , pragma_tok); |
45772 | finish_omp_cancel (clauses); |
45773 | } |
45774 | |
45775 | /* OpenMP 4.0: |
45776 | # pragma omp cancellation point cancelpt-clause[optseq] new-line */ |
45777 | |
45778 | #define OMP_CANCELLATION_POINT_CLAUSE_MASK \ |
45779 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \ |
45780 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \ |
45781 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \ |
45782 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP)) |
45783 | |
45784 | static bool |
45785 | cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok, |
45786 | enum pragma_context context) |
45787 | { |
45788 | tree clauses; |
45789 | bool point_seen = false; |
45790 | |
45791 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45792 | { |
45793 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45794 | const char *p = IDENTIFIER_POINTER (id); |
45795 | |
45796 | if (strcmp (s1: p, s2: "point" ) == 0) |
45797 | { |
45798 | cp_lexer_consume_token (lexer: parser->lexer); |
45799 | point_seen = true; |
45800 | } |
45801 | } |
45802 | if (!point_seen) |
45803 | { |
45804 | cp_parser_error (parser, gmsgid: "expected %<point%>" ); |
45805 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45806 | return false; |
45807 | } |
45808 | |
45809 | if (context != pragma_compound) |
45810 | { |
45811 | if (context == pragma_stmt) |
45812 | error_at (pragma_tok->location, |
45813 | "%<#pragma %s%> may only be used in compound statements" , |
45814 | "omp cancellation point" ); |
45815 | else |
45816 | cp_parser_error (parser, gmsgid: "expected declaration specifiers" ); |
45817 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45818 | return true; |
45819 | } |
45820 | |
45821 | clauses = cp_parser_omp_all_clauses (parser, |
45822 | OMP_CANCELLATION_POINT_CLAUSE_MASK, |
45823 | where: "#pragma omp cancellation point" , |
45824 | pragma_tok); |
45825 | finish_omp_cancellation_point (clauses); |
45826 | return true; |
45827 | } |
45828 | |
45829 | /* OpenMP 4.0: |
45830 | #pragma omp distribute distribute-clause[optseq] new-line |
45831 | for-loop */ |
45832 | |
45833 | #define OMP_DISTRIBUTE_CLAUSE_MASK \ |
45834 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45835 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45836 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
45837 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ |
45838 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45839 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
45840 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) |
45841 | |
45842 | static tree |
45843 | cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok, |
45844 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45845 | bool *if_p) |
45846 | { |
45847 | tree clauses, sb, ret; |
45848 | unsigned int save; |
45849 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45850 | |
45851 | strcat (dest: p_name, src: " distribute" ); |
45852 | mask |= OMP_DISTRIBUTE_CLAUSE_MASK; |
45853 | |
45854 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45855 | { |
45856 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45857 | const char *p = IDENTIFIER_POINTER (id); |
45858 | bool simd = false; |
45859 | bool parallel = false; |
45860 | |
45861 | if (strcmp (s1: p, s2: "simd" ) == 0) |
45862 | simd = true; |
45863 | else |
45864 | parallel = strcmp (s1: p, s2: "parallel" ) == 0; |
45865 | if (parallel || simd) |
45866 | { |
45867 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45868 | if (cclauses == NULL) |
45869 | cclauses = cclauses_buf; |
45870 | cp_lexer_consume_token (lexer: parser->lexer); |
45871 | if (!flag_openmp) /* flag_openmp_simd */ |
45872 | { |
45873 | if (simd) |
45874 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45875 | cclauses, if_p); |
45876 | else |
45877 | return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, |
45878 | cclauses, if_p); |
45879 | } |
45880 | sb = begin_omp_structured_block (); |
45881 | save = cp_parser_begin_omp_structured_block (parser); |
45882 | if (simd) |
45883 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
45884 | cclauses, if_p); |
45885 | else |
45886 | ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, |
45887 | cclauses, if_p); |
45888 | cp_parser_end_omp_structured_block (parser, save); |
45889 | tree body = finish_omp_structured_block (sb); |
45890 | if (ret == NULL) |
45891 | return ret; |
45892 | ret = make_node (OMP_DISTRIBUTE); |
45893 | TREE_TYPE (ret) = void_type_node; |
45894 | OMP_FOR_BODY (ret) = body; |
45895 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; |
45896 | SET_EXPR_LOCATION (ret, loc); |
45897 | add_stmt (ret); |
45898 | return ret; |
45899 | } |
45900 | } |
45901 | if (!flag_openmp) /* flag_openmp_simd */ |
45902 | { |
45903 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
45904 | return NULL_TREE; |
45905 | } |
45906 | |
45907 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
45908 | finish_p: cclauses == NULL); |
45909 | if (cclauses) |
45910 | { |
45911 | cp_omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses); |
45912 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; |
45913 | } |
45914 | |
45915 | keep_next_level (true); |
45916 | sb = begin_omp_structured_block (); |
45917 | save = cp_parser_begin_omp_structured_block (parser); |
45918 | |
45919 | ret = cp_parser_omp_for_loop (parser, code: OMP_DISTRIBUTE, clauses, NULL, if_p); |
45920 | |
45921 | cp_parser_end_omp_structured_block (parser, save); |
45922 | add_stmt (finish_omp_structured_block (sb)); |
45923 | |
45924 | return ret; |
45925 | } |
45926 | |
45927 | /* OpenMP 4.0: |
45928 | # pragma omp teams teams-clause[optseq] new-line |
45929 | structured-block */ |
45930 | |
45931 | #define OMP_TEAMS_CLAUSE_MASK \ |
45932 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
45933 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
45934 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
45935 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
45936 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \ |
45937 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ |
45938 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
45939 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)) |
45940 | |
45941 | static tree |
45942 | cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok, |
45943 | char *p_name, omp_clause_mask mask, tree *cclauses, |
45944 | bool *if_p) |
45945 | { |
45946 | tree clauses, sb, ret; |
45947 | unsigned int save; |
45948 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
45949 | |
45950 | strcat (dest: p_name, src: " teams" ); |
45951 | mask |= OMP_TEAMS_CLAUSE_MASK; |
45952 | |
45953 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
45954 | { |
45955 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
45956 | const char *p = IDENTIFIER_POINTER (id); |
45957 | if (strcmp (s1: p, s2: "distribute" ) == 0) |
45958 | { |
45959 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45960 | if (cclauses == NULL) |
45961 | cclauses = cclauses_buf; |
45962 | |
45963 | cp_lexer_consume_token (lexer: parser->lexer); |
45964 | if (!flag_openmp) /* flag_openmp_simd */ |
45965 | return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, |
45966 | cclauses, if_p); |
45967 | keep_next_level (true); |
45968 | sb = begin_omp_structured_block (); |
45969 | save = cp_parser_begin_omp_structured_block (parser); |
45970 | ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, |
45971 | cclauses, if_p); |
45972 | cp_parser_end_omp_structured_block (parser, save); |
45973 | tree body = finish_omp_structured_block (sb); |
45974 | if (ret == NULL) |
45975 | return ret; |
45976 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
45977 | ret = make_node (OMP_TEAMS); |
45978 | TREE_TYPE (ret) = void_type_node; |
45979 | OMP_TEAMS_CLAUSES (ret) = clauses; |
45980 | OMP_TEAMS_BODY (ret) = body; |
45981 | OMP_TEAMS_COMBINED (ret) = 1; |
45982 | SET_EXPR_LOCATION (ret, loc); |
45983 | return add_stmt (ret); |
45984 | } |
45985 | else if (strcmp (s1: p, s2: "loop" ) == 0) |
45986 | { |
45987 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
45988 | if (cclauses == NULL) |
45989 | cclauses = cclauses_buf; |
45990 | |
45991 | cp_lexer_consume_token (lexer: parser->lexer); |
45992 | if (!flag_openmp) /* flag_openmp_simd */ |
45993 | return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
45994 | cclauses, if_p); |
45995 | keep_next_level (true); |
45996 | sb = begin_omp_structured_block (); |
45997 | save = cp_parser_begin_omp_structured_block (parser); |
45998 | ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, |
45999 | cclauses, if_p); |
46000 | cp_parser_end_omp_structured_block (parser, save); |
46001 | tree body = finish_omp_structured_block (sb); |
46002 | if (ret == NULL) |
46003 | return ret; |
46004 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46005 | ret = make_node (OMP_TEAMS); |
46006 | TREE_TYPE (ret) = void_type_node; |
46007 | OMP_TEAMS_CLAUSES (ret) = clauses; |
46008 | OMP_TEAMS_BODY (ret) = body; |
46009 | OMP_TEAMS_COMBINED (ret) = 1; |
46010 | SET_EXPR_LOCATION (ret, loc); |
46011 | return add_stmt (ret); |
46012 | } |
46013 | } |
46014 | if (!flag_openmp) /* flag_openmp_simd */ |
46015 | { |
46016 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46017 | return NULL_TREE; |
46018 | } |
46019 | |
46020 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
46021 | finish_p: cclauses == NULL); |
46022 | if (cclauses) |
46023 | { |
46024 | cp_omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses); |
46025 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46026 | } |
46027 | |
46028 | tree stmt = make_node (OMP_TEAMS); |
46029 | TREE_TYPE (stmt) = void_type_node; |
46030 | OMP_TEAMS_CLAUSES (stmt) = clauses; |
46031 | keep_next_level (true); |
46032 | OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46033 | SET_EXPR_LOCATION (stmt, loc); |
46034 | |
46035 | return add_stmt (stmt); |
46036 | } |
46037 | |
46038 | /* OpenMP 4.0: |
46039 | # pragma omp target data target-data-clause[optseq] new-line |
46040 | structured-block */ |
46041 | |
46042 | #define OMP_TARGET_DATA_CLAUSE_MASK \ |
46043 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46044 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46045 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46046 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \ |
46047 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR)) |
46048 | |
46049 | static tree |
46050 | cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46051 | { |
46052 | if (flag_openmp) |
46053 | omp_requires_mask |
46054 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46055 | |
46056 | tree clauses |
46057 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK, |
46058 | where: "#pragma omp target data" , pragma_tok); |
46059 | c_omp_adjust_map_clauses (clauses, false); |
46060 | int map_seen = 0; |
46061 | for (tree *pc = &clauses; *pc;) |
46062 | { |
46063 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46064 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46065 | { |
46066 | case GOMP_MAP_TO: |
46067 | case GOMP_MAP_ALWAYS_TO: |
46068 | case GOMP_MAP_PRESENT_TO: |
46069 | case GOMP_MAP_ALWAYS_PRESENT_TO: |
46070 | case GOMP_MAP_FROM: |
46071 | case GOMP_MAP_ALWAYS_FROM: |
46072 | case GOMP_MAP_PRESENT_FROM: |
46073 | case GOMP_MAP_ALWAYS_PRESENT_FROM: |
46074 | case GOMP_MAP_TOFROM: |
46075 | case GOMP_MAP_ALWAYS_TOFROM: |
46076 | case GOMP_MAP_PRESENT_TOFROM: |
46077 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46078 | case GOMP_MAP_ALLOC: |
46079 | case GOMP_MAP_PRESENT_ALLOC: |
46080 | map_seen = 3; |
46081 | break; |
46082 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46083 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46084 | case GOMP_MAP_ALWAYS_POINTER: |
46085 | case GOMP_MAP_ATTACH_DETACH: |
46086 | break; |
46087 | default: |
46088 | map_seen |= 1; |
46089 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46090 | "%<#pragma omp target data%> with map-type other " |
46091 | "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> " |
46092 | "on %<map%> clause" ); |
46093 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46094 | continue; |
46095 | } |
46096 | else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR |
46097 | || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR) |
46098 | map_seen = 3; |
46099 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46100 | } |
46101 | |
46102 | if (map_seen != 3) |
46103 | { |
46104 | if (map_seen == 0) |
46105 | error_at (pragma_tok->location, |
46106 | "%<#pragma omp target data%> must contain at least " |
46107 | "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> " |
46108 | "clause" ); |
46109 | return NULL_TREE; |
46110 | } |
46111 | |
46112 | tree stmt = make_node (OMP_TARGET_DATA); |
46113 | TREE_TYPE (stmt) = void_type_node; |
46114 | OMP_TARGET_DATA_CLAUSES (stmt) = clauses; |
46115 | |
46116 | keep_next_level (true); |
46117 | OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); |
46118 | |
46119 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46120 | return add_stmt (stmt); |
46121 | } |
46122 | |
46123 | /* OpenMP 4.5: |
46124 | # pragma omp target enter data target-enter-data-clause[optseq] new-line |
46125 | structured-block */ |
46126 | |
46127 | #define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \ |
46128 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46129 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46130 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46131 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46132 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46133 | |
46134 | static bool |
46135 | cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok, |
46136 | enum pragma_context context) |
46137 | { |
46138 | bool data_seen = false; |
46139 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46140 | { |
46141 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46142 | const char *p = IDENTIFIER_POINTER (id); |
46143 | |
46144 | if (strcmp (s1: p, s2: "data" ) == 0) |
46145 | { |
46146 | cp_lexer_consume_token (lexer: parser->lexer); |
46147 | data_seen = true; |
46148 | } |
46149 | } |
46150 | if (!data_seen) |
46151 | { |
46152 | cp_parser_error (parser, gmsgid: "expected %<data%>" ); |
46153 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46154 | return false; |
46155 | } |
46156 | |
46157 | if (context == pragma_stmt) |
46158 | { |
46159 | error_at (pragma_tok->location, |
46160 | "%<#pragma %s%> may only be used in compound statements" , |
46161 | "omp target enter data" ); |
46162 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46163 | return true; |
46164 | } |
46165 | |
46166 | if (flag_openmp) |
46167 | omp_requires_mask |
46168 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46169 | |
46170 | tree clauses |
46171 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK, |
46172 | where: "#pragma omp target enter data" , pragma_tok); |
46173 | c_omp_adjust_map_clauses (clauses, false); |
46174 | int map_seen = 0; |
46175 | for (tree *pc = &clauses; *pc;) |
46176 | { |
46177 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46178 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46179 | { |
46180 | case GOMP_MAP_TO: |
46181 | case GOMP_MAP_ALWAYS_TO: |
46182 | case GOMP_MAP_PRESENT_TO: |
46183 | case GOMP_MAP_ALWAYS_PRESENT_TO: |
46184 | case GOMP_MAP_ALLOC: |
46185 | case GOMP_MAP_PRESENT_ALLOC: |
46186 | map_seen = 3; |
46187 | break; |
46188 | case GOMP_MAP_TOFROM: |
46189 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO); |
46190 | map_seen = 3; |
46191 | break; |
46192 | case GOMP_MAP_ALWAYS_TOFROM: |
46193 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO); |
46194 | map_seen = 3; |
46195 | break; |
46196 | case GOMP_MAP_PRESENT_TOFROM: |
46197 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO); |
46198 | map_seen = 3; |
46199 | break; |
46200 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46201 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO); |
46202 | map_seen = 3; |
46203 | break; |
46204 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46205 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46206 | case GOMP_MAP_ALWAYS_POINTER: |
46207 | case GOMP_MAP_ATTACH_DETACH: |
46208 | break; |
46209 | default: |
46210 | map_seen |= 1; |
46211 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46212 | "%<#pragma omp target enter data%> with map-type other " |
46213 | "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause" ); |
46214 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46215 | continue; |
46216 | } |
46217 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46218 | } |
46219 | |
46220 | if (map_seen != 3) |
46221 | { |
46222 | if (map_seen == 0) |
46223 | error_at (pragma_tok->location, |
46224 | "%<#pragma omp target enter data%> must contain at least " |
46225 | "one %<map%> clause" ); |
46226 | return true; |
46227 | } |
46228 | |
46229 | tree stmt = make_node (OMP_TARGET_ENTER_DATA); |
46230 | TREE_TYPE (stmt) = void_type_node; |
46231 | OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses; |
46232 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46233 | add_stmt (stmt); |
46234 | return true; |
46235 | } |
46236 | |
46237 | /* OpenMP 4.5: |
46238 | # pragma omp target exit data target-enter-data-clause[optseq] new-line |
46239 | structured-block */ |
46240 | |
46241 | #define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \ |
46242 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46243 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46244 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46245 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46246 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46247 | |
46248 | static bool |
46249 | cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok, |
46250 | enum pragma_context context) |
46251 | { |
46252 | bool data_seen = false; |
46253 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46254 | { |
46255 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46256 | const char *p = IDENTIFIER_POINTER (id); |
46257 | |
46258 | if (strcmp (s1: p, s2: "data" ) == 0) |
46259 | { |
46260 | cp_lexer_consume_token (lexer: parser->lexer); |
46261 | data_seen = true; |
46262 | } |
46263 | } |
46264 | if (!data_seen) |
46265 | { |
46266 | cp_parser_error (parser, gmsgid: "expected %<data%>" ); |
46267 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46268 | return false; |
46269 | } |
46270 | |
46271 | if (context == pragma_stmt) |
46272 | { |
46273 | error_at (pragma_tok->location, |
46274 | "%<#pragma %s%> may only be used in compound statements" , |
46275 | "omp target exit data" ); |
46276 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46277 | return true; |
46278 | } |
46279 | |
46280 | if (flag_openmp) |
46281 | omp_requires_mask |
46282 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46283 | |
46284 | tree clauses |
46285 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK, |
46286 | where: "#pragma omp target exit data" , pragma_tok); |
46287 | c_omp_adjust_map_clauses (clauses, false); |
46288 | int map_seen = 0; |
46289 | for (tree *pc = &clauses; *pc;) |
46290 | { |
46291 | if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP) |
46292 | switch (OMP_CLAUSE_MAP_KIND (*pc)) |
46293 | { |
46294 | case GOMP_MAP_FROM: |
46295 | case GOMP_MAP_ALWAYS_FROM: |
46296 | case GOMP_MAP_PRESENT_FROM: |
46297 | case GOMP_MAP_ALWAYS_PRESENT_FROM: |
46298 | case GOMP_MAP_RELEASE: |
46299 | case GOMP_MAP_DELETE: |
46300 | map_seen = 3; |
46301 | break; |
46302 | case GOMP_MAP_TOFROM: |
46303 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM); |
46304 | map_seen = 3; |
46305 | break; |
46306 | case GOMP_MAP_ALWAYS_TOFROM: |
46307 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM); |
46308 | map_seen = 3; |
46309 | break; |
46310 | case GOMP_MAP_PRESENT_TOFROM: |
46311 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM); |
46312 | map_seen = 3; |
46313 | break; |
46314 | case GOMP_MAP_ALWAYS_PRESENT_TOFROM: |
46315 | OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM); |
46316 | map_seen = 3; |
46317 | break; |
46318 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46319 | case GOMP_MAP_FIRSTPRIVATE_REFERENCE: |
46320 | case GOMP_MAP_ALWAYS_POINTER: |
46321 | case GOMP_MAP_ATTACH_DETACH: |
46322 | break; |
46323 | default: |
46324 | map_seen |= 1; |
46325 | error_at (OMP_CLAUSE_LOCATION (*pc), |
46326 | "%<#pragma omp target exit data%> with map-type other " |
46327 | "than %<from%>, %<tofrom%>, %<release%> or %<delete%> " |
46328 | "on %<map%> clause" ); |
46329 | *pc = OMP_CLAUSE_CHAIN (*pc); |
46330 | continue; |
46331 | } |
46332 | pc = &OMP_CLAUSE_CHAIN (*pc); |
46333 | } |
46334 | |
46335 | if (map_seen != 3) |
46336 | { |
46337 | if (map_seen == 0) |
46338 | error_at (pragma_tok->location, |
46339 | "%<#pragma omp target exit data%> must contain at least " |
46340 | "one %<map%> clause" ); |
46341 | return true; |
46342 | } |
46343 | |
46344 | tree stmt = make_node (OMP_TARGET_EXIT_DATA); |
46345 | TREE_TYPE (stmt) = void_type_node; |
46346 | OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses; |
46347 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46348 | add_stmt (stmt); |
46349 | return true; |
46350 | } |
46351 | |
46352 | /* OpenMP 4.0: |
46353 | # pragma omp target update target-update-clause[optseq] new-line */ |
46354 | |
46355 | #define OMP_TARGET_UPDATE_CLAUSE_MASK \ |
46356 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \ |
46357 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ |
46358 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46359 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46360 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46361 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) |
46362 | |
46363 | static bool |
46364 | cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok, |
46365 | enum pragma_context context) |
46366 | { |
46367 | if (context == pragma_stmt) |
46368 | { |
46369 | error_at (pragma_tok->location, |
46370 | "%<#pragma %s%> may only be used in compound statements" , |
46371 | "omp target update" ); |
46372 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46373 | return true; |
46374 | } |
46375 | |
46376 | tree clauses |
46377 | = cp_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK, |
46378 | where: "#pragma omp target update" , pragma_tok); |
46379 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE |
46380 | && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE) |
46381 | { |
46382 | error_at (pragma_tok->location, |
46383 | "%<#pragma omp target update%> must contain at least one " |
46384 | "%<from%> or %<to%> clauses" ); |
46385 | return true; |
46386 | } |
46387 | |
46388 | if (flag_openmp) |
46389 | omp_requires_mask |
46390 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46391 | |
46392 | tree stmt = make_node (OMP_TARGET_UPDATE); |
46393 | TREE_TYPE (stmt) = void_type_node; |
46394 | OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses; |
46395 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46396 | add_stmt (stmt); |
46397 | return true; |
46398 | } |
46399 | |
46400 | /* OpenMP 4.0: |
46401 | # pragma omp target target-clause[optseq] new-line |
46402 | structured-block */ |
46403 | |
46404 | #define OMP_TARGET_CLAUSE_MASK \ |
46405 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \ |
46406 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \ |
46407 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
46408 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ |
46409 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ |
46410 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
46411 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
46412 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \ |
46413 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
46414 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ |
46415 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \ |
46416 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\ |
46417 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR)) |
46418 | |
46419 | static bool |
46420 | cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, |
46421 | enum pragma_context context, bool *if_p) |
46422 | { |
46423 | if (flag_openmp) |
46424 | omp_requires_mask |
46425 | = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED); |
46426 | |
46427 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46428 | { |
46429 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
46430 | const char *p = IDENTIFIER_POINTER (id); |
46431 | enum tree_code ccode = ERROR_MARK; |
46432 | |
46433 | if (strcmp (s1: p, s2: "teams" ) == 0) |
46434 | ccode = OMP_TEAMS; |
46435 | else if (strcmp (s1: p, s2: "parallel" ) == 0) |
46436 | ccode = OMP_PARALLEL; |
46437 | else if (strcmp (s1: p, s2: "simd" ) == 0) |
46438 | ccode = OMP_SIMD; |
46439 | if (ccode != ERROR_MARK) |
46440 | { |
46441 | tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT]; |
46442 | char p_name[sizeof ("#pragma omp target teams distribute " |
46443 | "parallel for simd" )]; |
46444 | |
46445 | cp_lexer_consume_token (lexer: parser->lexer); |
46446 | strcpy (dest: p_name, src: "#pragma omp target" ); |
46447 | if (!flag_openmp) /* flag_openmp_simd */ |
46448 | { |
46449 | tree stmt; |
46450 | switch (ccode) |
46451 | { |
46452 | case OMP_TEAMS: |
46453 | stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, |
46454 | OMP_TARGET_CLAUSE_MASK, |
46455 | cclauses, if_p); |
46456 | break; |
46457 | case OMP_PARALLEL: |
46458 | stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, |
46459 | OMP_TARGET_CLAUSE_MASK, |
46460 | cclauses, if_p); |
46461 | break; |
46462 | case OMP_SIMD: |
46463 | stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, |
46464 | OMP_TARGET_CLAUSE_MASK, |
46465 | cclauses, if_p); |
46466 | break; |
46467 | default: |
46468 | gcc_unreachable (); |
46469 | } |
46470 | return stmt != NULL_TREE; |
46471 | } |
46472 | keep_next_level (true); |
46473 | tree sb = begin_omp_structured_block (), ret; |
46474 | unsigned save = cp_parser_begin_omp_structured_block (parser); |
46475 | switch (ccode) |
46476 | { |
46477 | case OMP_TEAMS: |
46478 | ret = cp_parser_omp_teams (parser, pragma_tok, p_name, |
46479 | OMP_TARGET_CLAUSE_MASK, cclauses, |
46480 | if_p); |
46481 | break; |
46482 | case OMP_PARALLEL: |
46483 | ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, |
46484 | OMP_TARGET_CLAUSE_MASK, cclauses, |
46485 | if_p); |
46486 | break; |
46487 | case OMP_SIMD: |
46488 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, |
46489 | OMP_TARGET_CLAUSE_MASK, cclauses, |
46490 | if_p); |
46491 | break; |
46492 | default: |
46493 | gcc_unreachable (); |
46494 | } |
46495 | cp_parser_end_omp_structured_block (parser, save); |
46496 | tree body = finish_omp_structured_block (sb); |
46497 | if (ret == NULL_TREE) |
46498 | return false; |
46499 | if (ccode == OMP_TEAMS && !processing_template_decl) |
46500 | /* For combined target teams, ensure the num_teams and |
46501 | thread_limit clause expressions are evaluated on the host, |
46502 | before entering the target construct. */ |
46503 | for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; |
46504 | c; c = OMP_CLAUSE_CHAIN (c)) |
46505 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS |
46506 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT) |
46507 | for (int i = 0; |
46508 | i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i) |
46509 | if (OMP_CLAUSE_OPERAND (c, i) |
46510 | && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST) |
46511 | { |
46512 | tree expr = OMP_CLAUSE_OPERAND (c, i); |
46513 | expr = force_target_expr (TREE_TYPE (expr), expr, |
46514 | tf_none); |
46515 | if (expr == error_mark_node) |
46516 | continue; |
46517 | tree tmp = TARGET_EXPR_SLOT (expr); |
46518 | add_stmt (expr); |
46519 | OMP_CLAUSE_OPERAND (c, i) = expr; |
46520 | tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c), |
46521 | OMP_CLAUSE_FIRSTPRIVATE); |
46522 | OMP_CLAUSE_DECL (tc) = tmp; |
46523 | OMP_CLAUSE_CHAIN (tc) |
46524 | = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; |
46525 | cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc; |
46526 | } |
46527 | c_omp_adjust_map_clauses (cclauses[C_OMP_CLAUSE_SPLIT_TARGET], true); |
46528 | finish_omp_target (pragma_tok->location, |
46529 | cclauses[C_OMP_CLAUSE_SPLIT_TARGET], body, true); |
46530 | return true; |
46531 | } |
46532 | else if (!flag_openmp) /* flag_openmp_simd */ |
46533 | { |
46534 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46535 | return false; |
46536 | } |
46537 | else if (strcmp (s1: p, s2: "data" ) == 0) |
46538 | { |
46539 | cp_lexer_consume_token (lexer: parser->lexer); |
46540 | cp_parser_omp_target_data (parser, pragma_tok, if_p); |
46541 | return true; |
46542 | } |
46543 | else if (strcmp (s1: p, s2: "enter" ) == 0) |
46544 | { |
46545 | cp_lexer_consume_token (lexer: parser->lexer); |
46546 | return cp_parser_omp_target_enter_data (parser, pragma_tok, context); |
46547 | } |
46548 | else if (strcmp (s1: p, s2: "exit" ) == 0) |
46549 | { |
46550 | cp_lexer_consume_token (lexer: parser->lexer); |
46551 | return cp_parser_omp_target_exit_data (parser, pragma_tok, context); |
46552 | } |
46553 | else if (strcmp (s1: p, s2: "update" ) == 0) |
46554 | { |
46555 | cp_lexer_consume_token (lexer: parser->lexer); |
46556 | return cp_parser_omp_target_update (parser, pragma_tok, context); |
46557 | } |
46558 | } |
46559 | if (!flag_openmp) /* flag_openmp_simd */ |
46560 | { |
46561 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46562 | return false; |
46563 | } |
46564 | |
46565 | tree clauses = cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK, |
46566 | where: "#pragma omp target" , pragma_tok, |
46567 | finish_p: false); |
46568 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
46569 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) |
46570 | { |
46571 | tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); |
46572 | OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c); |
46573 | OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM); |
46574 | OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c); |
46575 | OMP_CLAUSE_CHAIN (c) = nc; |
46576 | } |
46577 | clauses = finish_omp_clauses (clauses, C_ORT_OMP_TARGET); |
46578 | |
46579 | c_omp_adjust_map_clauses (clauses, true); |
46580 | keep_next_level (true); |
46581 | tree body = cp_parser_omp_structured_block (parser, if_p); |
46582 | |
46583 | finish_omp_target (pragma_tok->location, clauses, body, false); |
46584 | return true; |
46585 | } |
46586 | |
46587 | /* OpenACC 2.0: |
46588 | # pragma acc cache (variable-list) new-line |
46589 | */ |
46590 | |
46591 | static tree |
46592 | cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok) |
46593 | { |
46594 | /* Don't create location wrapper nodes within 'OMP_CLAUSE__CACHE_' |
46595 | clauses. */ |
46596 | auto_suppress_location_wrappers sentinel; |
46597 | |
46598 | tree stmt, clauses; |
46599 | |
46600 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE__CACHE_, NULL_TREE); |
46601 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
46602 | |
46603 | cp_parser_require_pragma_eol (parser, pragma_tok: cp_lexer_peek_token (lexer: parser->lexer)); |
46604 | |
46605 | stmt = make_node (OACC_CACHE); |
46606 | TREE_TYPE (stmt) = void_type_node; |
46607 | OACC_CACHE_CLAUSES (stmt) = clauses; |
46608 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46609 | add_stmt (stmt); |
46610 | |
46611 | return stmt; |
46612 | } |
46613 | |
46614 | /* OpenACC 2.0: |
46615 | # pragma acc data oacc-data-clause[optseq] new-line |
46616 | structured-block */ |
46617 | |
46618 | #define OACC_DATA_CLAUSE_MASK \ |
46619 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
46620 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
46621 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
46622 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
46623 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
46624 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
46625 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \ |
46626 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
46627 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
46628 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
46629 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) ) |
46630 | |
46631 | static tree |
46632 | cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46633 | { |
46634 | tree stmt, clauses, block; |
46635 | unsigned int save; |
46636 | |
46637 | clauses = cp_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK, |
46638 | where: "#pragma acc data" , pragma_tok); |
46639 | |
46640 | block = begin_omp_parallel (); |
46641 | save = cp_parser_begin_omp_structured_block (parser); |
46642 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
46643 | cp_parser_end_omp_structured_block (parser, save); |
46644 | stmt = finish_oacc_data (clauses, block); |
46645 | return stmt; |
46646 | } |
46647 | |
46648 | /* OpenACC 2.0: |
46649 | # pragma acc host_data <clauses> new-line |
46650 | structured-block */ |
46651 | |
46652 | #define OACC_HOST_DATA_CLAUSE_MASK \ |
46653 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \ |
46654 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
46655 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) ) |
46656 | |
46657 | static tree |
46658 | cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
46659 | { |
46660 | tree stmt, clauses, block; |
46661 | unsigned int save; |
46662 | |
46663 | clauses = cp_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK, |
46664 | where: "#pragma acc host_data" , pragma_tok, |
46665 | finish_p: false); |
46666 | if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR)) |
46667 | { |
46668 | error_at (pragma_tok->location, |
46669 | "%<host_data%> construct requires %<use_device%> clause" ); |
46670 | return error_mark_node; |
46671 | } |
46672 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
46673 | block = begin_omp_parallel (); |
46674 | save = cp_parser_begin_omp_structured_block (parser); |
46675 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
46676 | cp_parser_end_omp_structured_block (parser, save); |
46677 | stmt = finish_oacc_host_data (clauses, block); |
46678 | return stmt; |
46679 | } |
46680 | |
46681 | /* OpenACC 2.0: |
46682 | # pragma acc declare oacc-data-clause[optseq] new-line |
46683 | */ |
46684 | |
46685 | #define OACC_DECLARE_CLAUSE_MASK \ |
46686 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
46687 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
46688 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
46689 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
46690 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
46691 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \ |
46692 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \ |
46693 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) ) |
46694 | |
46695 | static tree |
46696 | cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) |
46697 | { |
46698 | tree clauses, stmt; |
46699 | bool error = false; |
46700 | bool found_in_scope = global_bindings_p (); |
46701 | |
46702 | clauses = cp_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK, |
46703 | where: "#pragma acc declare" , pragma_tok, finish_p: true); |
46704 | |
46705 | |
46706 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
46707 | { |
46708 | error_at (pragma_tok->location, |
46709 | "no valid clauses specified in %<#pragma acc declare%>" ); |
46710 | return NULL_TREE; |
46711 | } |
46712 | |
46713 | for (tree t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) |
46714 | { |
46715 | location_t loc = OMP_CLAUSE_LOCATION (t); |
46716 | tree decl = OMP_CLAUSE_DECL (t); |
46717 | if (!DECL_P (decl)) |
46718 | { |
46719 | error_at (loc, "array section in %<#pragma acc declare%>" ); |
46720 | error = true; |
46721 | continue; |
46722 | } |
46723 | gcc_assert (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_MAP); |
46724 | switch (OMP_CLAUSE_MAP_KIND (t)) |
46725 | { |
46726 | case GOMP_MAP_FIRSTPRIVATE_POINTER: |
46727 | case GOMP_MAP_ALLOC: |
46728 | case GOMP_MAP_TO: |
46729 | case GOMP_MAP_FORCE_DEVICEPTR: |
46730 | case GOMP_MAP_DEVICE_RESIDENT: |
46731 | break; |
46732 | |
46733 | case GOMP_MAP_LINK: |
46734 | if (!global_bindings_p () |
46735 | && (TREE_STATIC (decl) |
46736 | || !DECL_EXTERNAL (decl))) |
46737 | { |
46738 | error_at (loc, |
46739 | "%qD must be a global variable in " |
46740 | "%<#pragma acc declare link%>" , |
46741 | decl); |
46742 | error = true; |
46743 | continue; |
46744 | } |
46745 | break; |
46746 | |
46747 | default: |
46748 | if (global_bindings_p ()) |
46749 | { |
46750 | error_at (loc, "invalid OpenACC clause at file scope" ); |
46751 | error = true; |
46752 | continue; |
46753 | } |
46754 | if (DECL_EXTERNAL (decl)) |
46755 | { |
46756 | error_at (loc, |
46757 | "invalid use of %<extern%> variable %qD " |
46758 | "in %<#pragma acc declare%>" , decl); |
46759 | error = true; |
46760 | continue; |
46761 | } |
46762 | else if (TREE_PUBLIC (decl)) |
46763 | { |
46764 | error_at (loc, |
46765 | "invalid use of %<global%> variable %qD " |
46766 | "in %<#pragma acc declare%>" , decl); |
46767 | error = true; |
46768 | continue; |
46769 | } |
46770 | break; |
46771 | } |
46772 | |
46773 | if (!found_in_scope) |
46774 | /* This seems to ignore the existence of cleanup scopes? |
46775 | What is the meaning for local extern decls? The local |
46776 | extern is in this scope, but it is referring to a decl that |
46777 | is namespace scope. */ |
46778 | for (tree d = current_binding_level->names; d; d = TREE_CHAIN (d)) |
46779 | if (d == decl) |
46780 | { |
46781 | found_in_scope = true; |
46782 | break; |
46783 | } |
46784 | if (!found_in_scope) |
46785 | { |
46786 | error_at (loc, |
46787 | "%qD must be a variable declared in the same scope as " |
46788 | "%<#pragma acc declare%>" , decl); |
46789 | error = true; |
46790 | continue; |
46791 | } |
46792 | |
46793 | if (lookup_attribute (attr_name: "omp declare target" , DECL_ATTRIBUTES (decl)) |
46794 | || lookup_attribute (attr_name: "omp declare target link" , |
46795 | DECL_ATTRIBUTES (decl))) |
46796 | { |
46797 | error_at (loc, "variable %qD used more than once with " |
46798 | "%<#pragma acc declare%>" , decl); |
46799 | error = true; |
46800 | continue; |
46801 | } |
46802 | |
46803 | if (!error) |
46804 | { |
46805 | tree id; |
46806 | |
46807 | if (DECL_LOCAL_DECL_P (decl)) |
46808 | /* We need to mark the aliased decl, as that is the entity |
46809 | that is being referred to. This won't work for |
46810 | dependent variables, but it didn't work for them before |
46811 | DECL_LOCAL_DECL_P was a thing either. But then |
46812 | dependent local extern variable decls are as rare as |
46813 | hen's teeth. */ |
46814 | if (auto alias = DECL_LOCAL_DECL_ALIAS (decl)) |
46815 | if (alias != error_mark_node) |
46816 | decl = alias; |
46817 | |
46818 | if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK) |
46819 | id = get_identifier ("omp declare target link" ); |
46820 | else |
46821 | id = get_identifier ("omp declare target" ); |
46822 | |
46823 | DECL_ATTRIBUTES (decl) |
46824 | = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl)); |
46825 | if (current_binding_level->kind == sk_namespace) |
46826 | { |
46827 | symtab_node *node = symtab_node::get (decl); |
46828 | if (node != NULL) |
46829 | { |
46830 | node->offloadable = 1; |
46831 | if (ENABLE_OFFLOADING) |
46832 | { |
46833 | g->have_offload = true; |
46834 | if (is_a <varpool_node *> (p: node)) |
46835 | vec_safe_push (v&: offload_vars, obj: decl); |
46836 | } |
46837 | } |
46838 | } |
46839 | } |
46840 | } |
46841 | |
46842 | if (error || current_binding_level->kind == sk_namespace) |
46843 | return NULL_TREE; |
46844 | |
46845 | stmt = make_node (OACC_DECLARE); |
46846 | TREE_TYPE (stmt) = void_type_node; |
46847 | OACC_DECLARE_CLAUSES (stmt) = clauses; |
46848 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
46849 | |
46850 | add_stmt (stmt); |
46851 | |
46852 | return NULL_TREE; |
46853 | } |
46854 | |
46855 | /* OpenACC 2.0: |
46856 | # pragma acc enter data oacc-enter-data-clause[optseq] new-line |
46857 | |
46858 | or |
46859 | |
46860 | # pragma acc exit data oacc-exit-data-clause[optseq] new-line |
46861 | |
46862 | LOC is the location of the #pragma token. |
46863 | */ |
46864 | |
46865 | #define OACC_ENTER_DATA_CLAUSE_MASK \ |
46866 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
46867 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
46868 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
46869 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
46870 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
46871 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
46872 | |
46873 | #define OACC_EXIT_DATA_CLAUSE_MASK \ |
46874 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
46875 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
46876 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
46877 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \ |
46878 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \ |
46879 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \ |
46880 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
46881 | |
46882 | static tree |
46883 | cp_parser_oacc_enter_exit_data (cp_parser *parser, cp_token *pragma_tok, |
46884 | bool enter) |
46885 | { |
46886 | location_t loc = pragma_tok->location; |
46887 | tree stmt, clauses; |
46888 | const char *p = "" ; |
46889 | |
46890 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
46891 | p = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
46892 | |
46893 | if (strcmp (s1: p, s2: "data" ) != 0) |
46894 | { |
46895 | error_at (loc, "expected %<data%> after %<#pragma acc %s%>" , |
46896 | enter ? "enter" : "exit" ); |
46897 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
46898 | return NULL_TREE; |
46899 | } |
46900 | |
46901 | cp_lexer_consume_token (lexer: parser->lexer); |
46902 | |
46903 | if (enter) |
46904 | clauses = cp_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK, |
46905 | where: "#pragma acc enter data" , pragma_tok); |
46906 | else |
46907 | clauses = cp_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK, |
46908 | where: "#pragma acc exit data" , pragma_tok); |
46909 | |
46910 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
46911 | { |
46912 | error_at (loc, "%<#pragma acc %s data%> has no data movement clause" , |
46913 | enter ? "enter" : "exit" ); |
46914 | return NULL_TREE; |
46915 | } |
46916 | |
46917 | stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA); |
46918 | TREE_TYPE (stmt) = void_type_node; |
46919 | OMP_STANDALONE_CLAUSES (stmt) = clauses; |
46920 | SET_EXPR_LOCATION (stmt, loc); |
46921 | add_stmt (stmt); |
46922 | return stmt; |
46923 | } |
46924 | |
46925 | /* OpenACC 2.0: |
46926 | # pragma acc loop oacc-loop-clause[optseq] new-line |
46927 | structured-block */ |
46928 | |
46929 | #define OACC_LOOP_CLAUSE_MASK \ |
46930 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \ |
46931 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
46932 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
46933 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ |
46934 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ |
46935 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ |
46936 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \ |
46937 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \ |
46938 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ |
46939 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE)) |
46940 | |
46941 | static tree |
46942 | cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name, |
46943 | omp_clause_mask mask, tree *cclauses, bool *if_p) |
46944 | { |
46945 | bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1; |
46946 | |
46947 | strcat (dest: p_name, src: " loop" ); |
46948 | mask |= OACC_LOOP_CLAUSE_MASK; |
46949 | |
46950 | tree clauses = cp_parser_oacc_all_clauses (parser, mask, where: p_name, pragma_tok, |
46951 | finish_p: cclauses == NULL); |
46952 | if (cclauses) |
46953 | { |
46954 | clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel); |
46955 | if (*cclauses) |
46956 | *cclauses = finish_omp_clauses (*cclauses, C_ORT_ACC); |
46957 | if (clauses) |
46958 | clauses = finish_omp_clauses (clauses, C_ORT_ACC); |
46959 | } |
46960 | |
46961 | tree block = begin_omp_structured_block (); |
46962 | int save = cp_parser_begin_omp_structured_block (parser); |
46963 | tree stmt = cp_parser_omp_for_loop (parser, code: OACC_LOOP, clauses, NULL, if_p); |
46964 | cp_parser_end_omp_structured_block (parser, save); |
46965 | |
46966 | /* Later processing of combined acc loop constructs gets confused |
46967 | by an extra level of empty nested BIND_EXPRs, so flatten them. */ |
46968 | block = finish_omp_structured_block (block); |
46969 | if (TREE_CODE (block) == BIND_EXPR |
46970 | && TREE_CODE (BIND_EXPR_BODY (block)) == BIND_EXPR |
46971 | && !BIND_EXPR_VARS (block)) |
46972 | block = BIND_EXPR_BODY (block); |
46973 | add_stmt (block); |
46974 | |
46975 | return stmt; |
46976 | } |
46977 | |
46978 | /* OpenACC 2.0: |
46979 | # pragma acc kernels oacc-kernels-clause[optseq] new-line |
46980 | structured-block |
46981 | |
46982 | or |
46983 | |
46984 | # pragma acc parallel oacc-parallel-clause[optseq] new-line |
46985 | structured-block |
46986 | |
46987 | OpenACC 2.6: |
46988 | |
46989 | # pragma acc serial oacc-serial-clause[optseq] new-line |
46990 | */ |
46991 | |
46992 | #define OACC_KERNELS_CLAUSE_MASK \ |
46993 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
46994 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
46995 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
46996 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
46997 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
46998 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
46999 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47000 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47001 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47002 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47003 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
47004 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ |
47005 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47006 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47007 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ |
47008 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47009 | |
47010 | #define OACC_PARALLEL_CLAUSE_MASK \ |
47011 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47012 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47013 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47014 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47015 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47016 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47017 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47018 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47019 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \ |
47020 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47021 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47022 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \ |
47023 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \ |
47024 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47025 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
47026 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
47027 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47028 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \ |
47029 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47030 | |
47031 | #define OACC_SERIAL_CLAUSE_MASK \ |
47032 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47033 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \ |
47034 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \ |
47035 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \ |
47036 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \ |
47037 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \ |
47038 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \ |
47039 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \ |
47040 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47041 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \ |
47042 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \ |
47043 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \ |
47044 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \ |
47045 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \ |
47046 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47047 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) ) |
47048 | |
47049 | static tree |
47050 | cp_parser_oacc_compute (cp_parser *parser, cp_token *pragma_tok, |
47051 | char *p_name, bool *if_p) |
47052 | { |
47053 | omp_clause_mask mask; |
47054 | enum tree_code code; |
47055 | switch (cp_parser_pragma_kind (token: pragma_tok)) |
47056 | { |
47057 | case PRAGMA_OACC_KERNELS: |
47058 | strcat (dest: p_name, src: " kernels" ); |
47059 | mask = OACC_KERNELS_CLAUSE_MASK; |
47060 | code = OACC_KERNELS; |
47061 | break; |
47062 | case PRAGMA_OACC_PARALLEL: |
47063 | strcat (dest: p_name, src: " parallel" ); |
47064 | mask = OACC_PARALLEL_CLAUSE_MASK; |
47065 | code = OACC_PARALLEL; |
47066 | break; |
47067 | case PRAGMA_OACC_SERIAL: |
47068 | strcat (dest: p_name, src: " serial" ); |
47069 | mask = OACC_SERIAL_CLAUSE_MASK; |
47070 | code = OACC_SERIAL; |
47071 | break; |
47072 | default: |
47073 | gcc_unreachable (); |
47074 | } |
47075 | |
47076 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47077 | { |
47078 | const char *p |
47079 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47080 | if (strcmp (s1: p, s2: "loop" ) == 0) |
47081 | { |
47082 | cp_lexer_consume_token (lexer: parser->lexer); |
47083 | tree block = begin_omp_parallel (); |
47084 | tree clauses; |
47085 | tree stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, |
47086 | cclauses: &clauses, if_p); |
47087 | protected_set_expr_location (stmt, pragma_tok->location); |
47088 | return finish_omp_construct (code, block, clauses); |
47089 | } |
47090 | } |
47091 | |
47092 | tree clauses = cp_parser_oacc_all_clauses (parser, mask, where: p_name, pragma_tok); |
47093 | |
47094 | tree block = begin_omp_parallel (); |
47095 | unsigned int save = cp_parser_begin_omp_structured_block (parser); |
47096 | cp_parser_statement (parser, NULL_TREE, in_compound: false, if_p); |
47097 | cp_parser_end_omp_structured_block (parser, save); |
47098 | return finish_omp_construct (code, block, clauses); |
47099 | } |
47100 | |
47101 | /* OpenACC 2.0: |
47102 | # pragma acc update oacc-update-clause[optseq] new-line |
47103 | */ |
47104 | |
47105 | #define OACC_UPDATE_CLAUSE_MASK \ |
47106 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \ |
47107 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \ |
47108 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \ |
47109 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \ |
47110 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \ |
47111 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \ |
47112 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT)) |
47113 | |
47114 | static tree |
47115 | cp_parser_oacc_update (cp_parser *parser, cp_token *pragma_tok) |
47116 | { |
47117 | tree stmt, clauses; |
47118 | |
47119 | clauses = cp_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK, |
47120 | where: "#pragma acc update" , pragma_tok); |
47121 | |
47122 | if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE) |
47123 | { |
47124 | error_at (pragma_tok->location, |
47125 | "%<#pragma acc update%> must contain at least one " |
47126 | "%<device%> or %<host%> or %<self%> clause" ); |
47127 | return NULL_TREE; |
47128 | } |
47129 | |
47130 | stmt = make_node (OACC_UPDATE); |
47131 | TREE_TYPE (stmt) = void_type_node; |
47132 | OACC_UPDATE_CLAUSES (stmt) = clauses; |
47133 | SET_EXPR_LOCATION (stmt, pragma_tok->location); |
47134 | add_stmt (stmt); |
47135 | return stmt; |
47136 | } |
47137 | |
47138 | /* OpenACC 2.0: |
47139 | # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line |
47140 | |
47141 | LOC is the location of the #pragma token. |
47142 | */ |
47143 | |
47144 | #define OACC_WAIT_CLAUSE_MASK \ |
47145 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)) |
47146 | |
47147 | static tree |
47148 | cp_parser_oacc_wait (cp_parser *parser, cp_token *pragma_tok) |
47149 | { |
47150 | tree clauses, list = NULL_TREE, stmt = NULL_TREE; |
47151 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47152 | |
47153 | if (cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
47154 | list = cp_parser_oacc_wait_list (parser, clause_loc: loc, list); |
47155 | |
47156 | clauses = cp_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, |
47157 | where: "#pragma acc wait" , pragma_tok); |
47158 | |
47159 | stmt = c_finish_oacc_wait (loc, list, clauses); |
47160 | stmt = finish_expr_stmt (stmt); |
47161 | |
47162 | return stmt; |
47163 | } |
47164 | |
47165 | /* OpenMP 4.0: |
47166 | # pragma omp declare simd declare-simd-clauses[optseq] new-line */ |
47167 | |
47168 | #define OMP_DECLARE_SIMD_CLAUSE_MASK \ |
47169 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ |
47170 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ |
47171 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ |
47172 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ |
47173 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ |
47174 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) |
47175 | |
47176 | static void |
47177 | cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok, |
47178 | enum pragma_context context, |
47179 | bool variant_p) |
47180 | { |
47181 | bool first_p = parser->omp_declare_simd == NULL; |
47182 | cp_omp_declare_simd_data data; |
47183 | if (first_p) |
47184 | { |
47185 | data.error_seen = false; |
47186 | data.fndecl_seen = false; |
47187 | data.variant_p = variant_p; |
47188 | data.tokens = vNULL; |
47189 | data.attribs[0] = NULL; |
47190 | data.attribs[1] = NULL; |
47191 | data.loc = UNKNOWN_LOCATION; |
47192 | /* It is safe to take the address of a local variable; it will only be |
47193 | used while this scope is live. */ |
47194 | parser->omp_declare_simd = &data; |
47195 | } |
47196 | else if (parser->omp_declare_simd->variant_p != variant_p) |
47197 | { |
47198 | error_at (pragma_tok->location, |
47199 | "%<#pragma omp declare %s%> followed by " |
47200 | "%<#pragma omp declare %s%>" , |
47201 | parser->omp_declare_simd->variant_p ? "variant" : "simd" , |
47202 | parser->omp_declare_simd->variant_p ? "simd" : "variant" ); |
47203 | parser->omp_declare_simd->error_seen = true; |
47204 | } |
47205 | |
47206 | /* Store away all pragma tokens. */ |
47207 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
47208 | cp_lexer_consume_token (lexer: parser->lexer); |
47209 | cp_parser_require_pragma_eol (parser, pragma_tok); |
47210 | struct cp_token_cache *cp |
47211 | = cp_token_cache_new (first: pragma_tok, last: cp_lexer_peek_token (lexer: parser->lexer)); |
47212 | parser->omp_declare_simd->tokens.safe_push (obj: cp); |
47213 | |
47214 | if (first_p) |
47215 | { |
47216 | while (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
47217 | cp_parser_pragma (parser, context, NULL); |
47218 | switch (context) |
47219 | { |
47220 | case pragma_external: |
47221 | cp_parser_declaration (parser, NULL_TREE); |
47222 | break; |
47223 | case pragma_member: |
47224 | cp_parser_member_declaration (parser); |
47225 | break; |
47226 | case pragma_objc_icode: |
47227 | cp_parser_block_declaration (parser, /*statement_p=*/false); |
47228 | break; |
47229 | default: |
47230 | cp_parser_declaration_statement (parser); |
47231 | break; |
47232 | } |
47233 | if (parser->omp_declare_simd |
47234 | && !parser->omp_declare_simd->error_seen |
47235 | && !parser->omp_declare_simd->fndecl_seen) |
47236 | error_at (pragma_tok->location, |
47237 | "%<#pragma omp declare %s%> not immediately followed by " |
47238 | "function declaration or definition" , |
47239 | parser->omp_declare_simd->variant_p ? "variant" : "simd" ); |
47240 | data.tokens.release (); |
47241 | parser->omp_declare_simd = NULL; |
47242 | } |
47243 | } |
47244 | |
47245 | static const char *const omp_construct_selectors[] = { |
47246 | "simd" , "target" , "teams" , "parallel" , "for" , NULL }; |
47247 | static const char *const omp_device_selectors[] = { |
47248 | "kind" , "isa" , "arch" , NULL }; |
47249 | static const char *const omp_implementation_selectors[] = { |
47250 | "vendor" , "extension" , "atomic_default_mem_order" , "unified_address" , |
47251 | "unified_shared_memory" , "dynamic_allocators" , "reverse_offload" , NULL }; |
47252 | static const char *const omp_user_selectors[] = { |
47253 | "condition" , NULL }; |
47254 | |
47255 | /* OpenMP 5.0: |
47256 | |
47257 | trait-selector: |
47258 | trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])] |
47259 | |
47260 | trait-score: |
47261 | score(score-expression) */ |
47262 | |
47263 | static tree |
47264 | cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p) |
47265 | { |
47266 | tree ret = NULL_TREE; |
47267 | do |
47268 | { |
47269 | tree selector; |
47270 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
47271 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47272 | selector = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47273 | else |
47274 | { |
47275 | cp_parser_error (parser, gmsgid: "expected trait selector name" ); |
47276 | return error_mark_node; |
47277 | } |
47278 | |
47279 | tree properties = NULL_TREE; |
47280 | const char *const *selectors = NULL; |
47281 | bool allow_score = true; |
47282 | bool allow_user = false; |
47283 | int property_limit = 0; |
47284 | enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST, |
47285 | CTX_PROPERTY_ID, CTX_PROPERTY_EXPR, |
47286 | CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE; |
47287 | switch (IDENTIFIER_POINTER (set)[0]) |
47288 | { |
47289 | case 'c': /* construct */ |
47290 | selectors = omp_construct_selectors; |
47291 | allow_score = false; |
47292 | property_limit = 1; |
47293 | property_kind = CTX_PROPERTY_SIMD; |
47294 | break; |
47295 | case 'd': /* device */ |
47296 | selectors = omp_device_selectors; |
47297 | allow_score = false; |
47298 | allow_user = true; |
47299 | property_limit = 3; |
47300 | property_kind = CTX_PROPERTY_NAME_LIST; |
47301 | break; |
47302 | case 'i': /* implementation */ |
47303 | selectors = omp_implementation_selectors; |
47304 | allow_user = true; |
47305 | property_limit = 3; |
47306 | property_kind = CTX_PROPERTY_NAME_LIST; |
47307 | break; |
47308 | case 'u': /* user */ |
47309 | selectors = omp_user_selectors; |
47310 | property_limit = 1; |
47311 | property_kind = CTX_PROPERTY_EXPR; |
47312 | break; |
47313 | default: |
47314 | gcc_unreachable (); |
47315 | } |
47316 | for (int i = 0; ; i++) |
47317 | { |
47318 | if (selectors[i] == NULL) |
47319 | { |
47320 | if (allow_user) |
47321 | { |
47322 | property_kind = CTX_PROPERTY_USER; |
47323 | break; |
47324 | } |
47325 | else |
47326 | { |
47327 | error ("selector %qs not allowed for context selector " |
47328 | "set %qs" , IDENTIFIER_POINTER (selector), |
47329 | IDENTIFIER_POINTER (set)); |
47330 | cp_lexer_consume_token (lexer: parser->lexer); |
47331 | return error_mark_node; |
47332 | } |
47333 | } |
47334 | if (i == property_limit) |
47335 | property_kind = CTX_PROPERTY_NONE; |
47336 | if (strcmp (s1: selectors[i], IDENTIFIER_POINTER (selector)) == 0) |
47337 | break; |
47338 | } |
47339 | if (property_kind == CTX_PROPERTY_NAME_LIST |
47340 | && IDENTIFIER_POINTER (set)[0] == 'i' |
47341 | && strcmp (IDENTIFIER_POINTER (selector), |
47342 | s2: "atomic_default_mem_order" ) == 0) |
47343 | property_kind = CTX_PROPERTY_ID; |
47344 | |
47345 | cp_lexer_consume_token (lexer: parser->lexer); |
47346 | |
47347 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
47348 | { |
47349 | if (property_kind == CTX_PROPERTY_NONE) |
47350 | { |
47351 | error ("selector %qs does not accept any properties" , |
47352 | IDENTIFIER_POINTER (selector)); |
47353 | return error_mark_node; |
47354 | } |
47355 | |
47356 | matching_parens parens; |
47357 | parens.consume_open (parser); |
47358 | |
47359 | cp_token *token = cp_lexer_peek_token (lexer: parser->lexer); |
47360 | if (allow_score |
47361 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
47362 | && strcmp (IDENTIFIER_POINTER (token->u.value), s2: "score" ) == 0 |
47363 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_OPEN_PAREN)) |
47364 | { |
47365 | cp_lexer_save_tokens (lexer: parser->lexer); |
47366 | cp_lexer_consume_token (lexer: parser->lexer); |
47367 | cp_lexer_consume_token (lexer: parser->lexer); |
47368 | if (cp_parser_skip_to_closing_parenthesis (parser, recovering: false, or_comma: false, |
47369 | consume_paren: true) |
47370 | && cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COLON)) |
47371 | { |
47372 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
47373 | cp_lexer_consume_token (lexer: parser->lexer); |
47374 | |
47375 | matching_parens parens2; |
47376 | parens2.require_open (parser); |
47377 | tree score = cp_parser_constant_expression (parser); |
47378 | if (!parens2.require_close (parser)) |
47379 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, |
47380 | or_comma: false, consume_paren: true); |
47381 | cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON); |
47382 | if (score != error_mark_node) |
47383 | { |
47384 | score = fold_non_dependent_expr (score); |
47385 | if (value_dependent_expression_p (score)) |
47386 | properties = tree_cons (get_identifier (" score" ), |
47387 | score, properties); |
47388 | else if (!INTEGRAL_TYPE_P (TREE_TYPE (score)) |
47389 | || TREE_CODE (score) != INTEGER_CST) |
47390 | error_at (token->location, "score argument must be " |
47391 | "constant integer expression" ); |
47392 | else if (tree_int_cst_sgn (score) < 0) |
47393 | error_at (token->location, "score argument must be " |
47394 | "non-negative" ); |
47395 | else |
47396 | properties = tree_cons (get_identifier (" score" ), |
47397 | score, properties); |
47398 | } |
47399 | } |
47400 | else |
47401 | cp_lexer_rollback_tokens (lexer: parser->lexer); |
47402 | |
47403 | token = cp_lexer_peek_token (lexer: parser->lexer); |
47404 | } |
47405 | |
47406 | switch (property_kind) |
47407 | { |
47408 | tree t; |
47409 | case CTX_PROPERTY_USER: |
47410 | do |
47411 | { |
47412 | t = cp_parser_constant_expression (parser); |
47413 | if (t != error_mark_node) |
47414 | { |
47415 | t = fold_non_dependent_expr (t); |
47416 | if (TREE_CODE (t) == STRING_CST) |
47417 | properties = tree_cons (NULL_TREE, t, properties); |
47418 | else if (!value_dependent_expression_p (t) |
47419 | && (!INTEGRAL_TYPE_P (TREE_TYPE (t)) |
47420 | || !tree_fits_shwi_p (t))) |
47421 | error_at (token->location, "property must be " |
47422 | "constant integer expression or string " |
47423 | "literal" ); |
47424 | else |
47425 | properties = tree_cons (NULL_TREE, t, properties); |
47426 | } |
47427 | else |
47428 | return error_mark_node; |
47429 | |
47430 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47431 | cp_lexer_consume_token (lexer: parser->lexer); |
47432 | else |
47433 | break; |
47434 | } |
47435 | while (1); |
47436 | break; |
47437 | case CTX_PROPERTY_ID: |
47438 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
47439 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47440 | { |
47441 | tree prop = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47442 | cp_lexer_consume_token (lexer: parser->lexer); |
47443 | properties = tree_cons (prop, NULL_TREE, properties); |
47444 | } |
47445 | else |
47446 | { |
47447 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
47448 | return error_mark_node; |
47449 | } |
47450 | break; |
47451 | case CTX_PROPERTY_NAME_LIST: |
47452 | do |
47453 | { |
47454 | tree prop = NULL_TREE, value = NULL_TREE; |
47455 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_KEYWORD) |
47456 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47457 | { |
47458 | prop = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47459 | cp_lexer_consume_token (lexer: parser->lexer); |
47460 | } |
47461 | else if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_STRING)) |
47462 | value = cp_parser_string_literal (parser, |
47463 | /*translate=*/false, |
47464 | /*wide_ok=*/false); |
47465 | else |
47466 | { |
47467 | cp_parser_error (parser, gmsgid: "expected identifier or " |
47468 | "string literal" ); |
47469 | return error_mark_node; |
47470 | } |
47471 | |
47472 | properties = tree_cons (prop, value, properties); |
47473 | |
47474 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47475 | cp_lexer_consume_token (lexer: parser->lexer); |
47476 | else |
47477 | break; |
47478 | } |
47479 | while (1); |
47480 | break; |
47481 | case CTX_PROPERTY_EXPR: |
47482 | t = cp_parser_constant_expression (parser); |
47483 | if (t != error_mark_node) |
47484 | { |
47485 | t = fold_non_dependent_expr (t); |
47486 | if (!value_dependent_expression_p (t) |
47487 | && (!INTEGRAL_TYPE_P (TREE_TYPE (t)) |
47488 | || !tree_fits_shwi_p (t))) |
47489 | error_at (token->location, "property must be " |
47490 | "constant integer expression" ); |
47491 | else |
47492 | properties = tree_cons (NULL_TREE, t, properties); |
47493 | } |
47494 | else |
47495 | return error_mark_node; |
47496 | break; |
47497 | case CTX_PROPERTY_SIMD: |
47498 | if (!has_parms_p) |
47499 | { |
47500 | error_at (token->location, "properties for %<simd%> " |
47501 | "selector may not be specified in " |
47502 | "%<metadirective%>" ); |
47503 | return error_mark_node; |
47504 | } |
47505 | properties |
47506 | = cp_parser_omp_all_clauses (parser, |
47507 | OMP_DECLARE_SIMD_CLAUSE_MASK, |
47508 | where: "simd" , NULL, finish_p: true, nested: 2); |
47509 | break; |
47510 | default: |
47511 | gcc_unreachable (); |
47512 | } |
47513 | |
47514 | if (!parens.require_close (parser)) |
47515 | cp_parser_skip_to_closing_parenthesis (parser, recovering: true, or_comma: false, consume_paren: true); |
47516 | |
47517 | properties = nreverse (properties); |
47518 | } |
47519 | else if (property_kind == CTX_PROPERTY_NAME_LIST |
47520 | || property_kind == CTX_PROPERTY_ID |
47521 | || property_kind == CTX_PROPERTY_EXPR) |
47522 | { |
47523 | cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN); |
47524 | return error_mark_node; |
47525 | } |
47526 | |
47527 | ret = tree_cons (selector, properties, ret); |
47528 | |
47529 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47530 | cp_lexer_consume_token (lexer: parser->lexer); |
47531 | else |
47532 | break; |
47533 | } |
47534 | while (1); |
47535 | |
47536 | return nreverse (ret); |
47537 | } |
47538 | |
47539 | /* OpenMP 5.0: |
47540 | |
47541 | trait-set-selector[,trait-set-selector[,...]] |
47542 | |
47543 | trait-set-selector: |
47544 | trait-set-selector-name = { trait-selector[, trait-selector[, ...]] } |
47545 | |
47546 | trait-set-selector-name: |
47547 | constructor |
47548 | device |
47549 | implementation |
47550 | user */ |
47551 | |
47552 | static tree |
47553 | cp_parser_omp_context_selector_specification (cp_parser *parser, |
47554 | bool has_parms_p) |
47555 | { |
47556 | tree ret = NULL_TREE; |
47557 | do |
47558 | { |
47559 | const char *setp = "" ; |
47560 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47561 | setp |
47562 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47563 | switch (setp[0]) |
47564 | { |
47565 | case 'c': |
47566 | if (strcmp (s1: setp, s2: "construct" ) == 0) |
47567 | setp = NULL; |
47568 | break; |
47569 | case 'd': |
47570 | if (strcmp (s1: setp, s2: "device" ) == 0) |
47571 | setp = NULL; |
47572 | break; |
47573 | case 'i': |
47574 | if (strcmp (s1: setp, s2: "implementation" ) == 0) |
47575 | setp = NULL; |
47576 | break; |
47577 | case 'u': |
47578 | if (strcmp (s1: setp, s2: "user" ) == 0) |
47579 | setp = NULL; |
47580 | break; |
47581 | default: |
47582 | break; |
47583 | } |
47584 | if (setp) |
47585 | { |
47586 | cp_parser_error (parser, gmsgid: "expected %<construct%>, %<device%>, " |
47587 | "%<implementation%> or %<user%>" ); |
47588 | return error_mark_node; |
47589 | } |
47590 | |
47591 | tree set = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47592 | cp_lexer_consume_token (lexer: parser->lexer); |
47593 | |
47594 | if (!cp_parser_require (parser, type: CPP_EQ, token_desc: RT_EQ)) |
47595 | return error_mark_node; |
47596 | |
47597 | matching_braces braces; |
47598 | if (!braces.require_open (parser)) |
47599 | return error_mark_node; |
47600 | |
47601 | tree selectors |
47602 | = cp_parser_omp_context_selector (parser, set, has_parms_p); |
47603 | if (selectors == error_mark_node) |
47604 | { |
47605 | cp_parser_skip_to_closing_brace (parser); |
47606 | ret = error_mark_node; |
47607 | } |
47608 | else if (ret != error_mark_node) |
47609 | ret = tree_cons (set, selectors, ret); |
47610 | |
47611 | braces.require_close (parser); |
47612 | |
47613 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47614 | cp_lexer_consume_token (lexer: parser->lexer); |
47615 | else |
47616 | break; |
47617 | } |
47618 | while (1); |
47619 | |
47620 | if (ret == error_mark_node) |
47621 | return ret; |
47622 | return nreverse (ret); |
47623 | } |
47624 | |
47625 | /* Assumption clauses: |
47626 | OpenMP 5.1 |
47627 | absent (directive-name-list) |
47628 | contains (directive-name-list) |
47629 | holds (expression) |
47630 | no_openmp |
47631 | no_openmp_routines |
47632 | no_parallelism */ |
47633 | |
47634 | static void |
47635 | cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, |
47636 | bool is_assume) |
47637 | { |
47638 | bool no_openmp = false; |
47639 | bool no_openmp_routines = false; |
47640 | bool no_parallelism = false; |
47641 | bitmap_head absent_head, contains_head; |
47642 | |
47643 | bitmap_obstack_initialize (NULL); |
47644 | bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack); |
47645 | bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack); |
47646 | |
47647 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
47648 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
47649 | "expected at least one assumption clause" ); |
47650 | |
47651 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
47652 | { |
47653 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
47654 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
47655 | cp_lexer_consume_token (lexer: parser->lexer); |
47656 | |
47657 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47658 | break; |
47659 | |
47660 | const char *p |
47661 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47662 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47663 | |
47664 | if (!strcmp (s1: p, s2: "no_openmp" )) |
47665 | { |
47666 | cp_lexer_consume_token (lexer: parser->lexer); |
47667 | if (no_openmp) |
47668 | error_at (cloc, "too many %qs clauses" , "no_openmp" ); |
47669 | no_openmp = true; |
47670 | } |
47671 | else if (!strcmp (s1: p, s2: "no_openmp_routines" )) |
47672 | { |
47673 | cp_lexer_consume_token (lexer: parser->lexer); |
47674 | if (no_openmp_routines) |
47675 | error_at (cloc, "too many %qs clauses" , "no_openmp_routines" ); |
47676 | no_openmp_routines = true; |
47677 | } |
47678 | else if (!strcmp (s1: p, s2: "no_parallelism" )) |
47679 | { |
47680 | cp_lexer_consume_token (lexer: parser->lexer); |
47681 | if (no_parallelism) |
47682 | error_at (cloc, "too many %qs clauses" , "no_parallelism" ); |
47683 | no_parallelism = true; |
47684 | } |
47685 | else if (!strcmp (s1: p, s2: "holds" )) |
47686 | { |
47687 | cp_lexer_consume_token (lexer: parser->lexer); |
47688 | matching_parens parens; |
47689 | if (parens.require_open (parser)) |
47690 | { |
47691 | location_t eloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47692 | tree t = cp_parser_assignment_expression (parser); |
47693 | if (!type_dependent_expression_p (t)) |
47694 | t = contextual_conv_bool (t, tf_warning_or_error); |
47695 | if (is_assume && !error_operand_p (t)) |
47696 | finish_expr_stmt (build_assume_call (eloc, t)); |
47697 | if (!parens.require_close (parser)) |
47698 | cp_parser_skip_to_closing_parenthesis (parser, |
47699 | /*recovering=*/true, |
47700 | /*or_comma=*/false, |
47701 | /*consume_paren=*/true); |
47702 | } |
47703 | } |
47704 | else if (!strcmp (s1: p, s2: "absent" ) || !strcmp (s1: p, s2: "contains" )) |
47705 | { |
47706 | cp_lexer_consume_token (lexer: parser->lexer); |
47707 | matching_parens parens; |
47708 | if (parens.require_open (parser)) |
47709 | { |
47710 | do |
47711 | { |
47712 | const char *directive[3] = {}; |
47713 | int i; |
47714 | location_t dloc |
47715 | = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47716 | for (i = 0; i < 3; i++) |
47717 | { |
47718 | tree id; |
47719 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, type: CPP_NAME)) |
47720 | id = cp_lexer_peek_nth_token (lexer: parser->lexer, |
47721 | n: i + 1)->u.value; |
47722 | else if (cp_lexer_nth_token_is (lexer: parser->lexer, n: i + 1, |
47723 | type: CPP_KEYWORD)) |
47724 | { |
47725 | enum rid rid |
47726 | = cp_lexer_peek_nth_token (lexer: parser->lexer, |
47727 | n: i + 1)->keyword; |
47728 | id = ridpointers[rid]; |
47729 | } |
47730 | else |
47731 | break; |
47732 | directive[i] = IDENTIFIER_POINTER (id); |
47733 | } |
47734 | if (i == 0) |
47735 | error_at (dloc, "expected directive name" ); |
47736 | else |
47737 | { |
47738 | const struct c_omp_directive *dir |
47739 | = c_omp_categorize_directive (directive[0], |
47740 | directive[1], |
47741 | directive[2]); |
47742 | if (dir == NULL |
47743 | || dir->kind == C_OMP_DIR_DECLARATIVE |
47744 | || dir->kind == C_OMP_DIR_INFORMATIONAL |
47745 | || dir->id == PRAGMA_OMP_END |
47746 | || (!dir->second && directive[1]) |
47747 | || (!dir->third && directive[2])) |
47748 | error_at (dloc, "unknown OpenMP directive name in " |
47749 | "%qs clause argument" , p); |
47750 | else |
47751 | { |
47752 | int id = dir - c_omp_directives; |
47753 | if (bitmap_bit_p (p[0] == 'a' ? &contains_head |
47754 | : &absent_head, id)) |
47755 | error_at (dloc, "%<%s%s%s%s%s%> directive " |
47756 | "mentioned in both %<absent%> and " |
47757 | "%<contains%> clauses" , |
47758 | directive[0], |
47759 | directive[1] ? " " : "" , |
47760 | directive[1] ? directive[1] : "" , |
47761 | directive[2] ? " " : "" , |
47762 | directive[2] ? directive[2] : "" ); |
47763 | else if (!bitmap_set_bit (p[0] == 'a' |
47764 | ? &absent_head |
47765 | : &contains_head, id)) |
47766 | error_at (dloc, "%<%s%s%s%s%s%> directive " |
47767 | "mentioned multiple times in %qs " |
47768 | "clauses" , |
47769 | directive[0], |
47770 | directive[1] ? " " : "" , |
47771 | directive[1] ? directive[1] : "" , |
47772 | directive[2] ? " " : "" , |
47773 | directive[2] ? directive[2] : "" , p); |
47774 | } |
47775 | for (; i; --i) |
47776 | cp_lexer_consume_token (lexer: parser->lexer); |
47777 | } |
47778 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
47779 | cp_lexer_consume_token (lexer: parser->lexer); |
47780 | else |
47781 | break; |
47782 | } |
47783 | while (1); |
47784 | if (!parens.require_close (parser)) |
47785 | cp_parser_skip_to_closing_parenthesis (parser, |
47786 | /*recovering=*/true, |
47787 | /*or_comma=*/false, |
47788 | /*consume_paren=*/true); |
47789 | } |
47790 | } |
47791 | else if (startswith (str: p, prefix: "ext_" )) |
47792 | { |
47793 | warning_at (cloc, 0, "unknown assumption clause %qs" , p); |
47794 | cp_lexer_consume_token (lexer: parser->lexer); |
47795 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
47796 | for (size_t n = cp_parser_skip_balanced_tokens (parser, n: 1) - 1; |
47797 | n; --n) |
47798 | cp_lexer_consume_token (lexer: parser->lexer); |
47799 | } |
47800 | else |
47801 | { |
47802 | cp_lexer_consume_token (lexer: parser->lexer); |
47803 | error_at (cloc, "expected assumption clause" ); |
47804 | break; |
47805 | } |
47806 | } |
47807 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47808 | } |
47809 | |
47810 | /* OpenMP 5.1 |
47811 | # pragma omp assume clauses[optseq] new-line */ |
47812 | |
47813 | static void |
47814 | cp_parser_omp_assume (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
47815 | { |
47816 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: true); |
47817 | add_stmt (cp_parser_omp_structured_block (parser, if_p)); |
47818 | } |
47819 | |
47820 | /* OpenMP 5.1 |
47821 | # pragma omp assumes clauses[optseq] new-line */ |
47822 | |
47823 | static bool |
47824 | cp_parser_omp_assumes (cp_parser *parser, cp_token *pragma_tok) |
47825 | { |
47826 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: false); |
47827 | return false; |
47828 | } |
47829 | |
47830 | /* Finalize #pragma omp declare variant after a fndecl has been parsed, and put |
47831 | that into "omp declare variant base" attribute. */ |
47832 | |
47833 | static tree |
47834 | cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, |
47835 | tree attrs) |
47836 | { |
47837 | matching_parens parens; |
47838 | if (!parens.require_open (parser)) |
47839 | { |
47840 | fail: |
47841 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47842 | return attrs; |
47843 | } |
47844 | |
47845 | bool template_p; |
47846 | cp_id_kind idk = CP_ID_KIND_NONE; |
47847 | cp_token *varid_token = cp_lexer_peek_token (lexer: parser->lexer); |
47848 | cp_expr varid |
47849 | = cp_parser_id_expression (parser, /*template_keyword_p=*/false, |
47850 | /*check_dependency_p=*/true, |
47851 | /*template_p=*/&template_p, |
47852 | /*declarator_p=*/false, |
47853 | /*optional_p=*/false); |
47854 | parens.require_close (parser); |
47855 | |
47856 | tree variant; |
47857 | if (TREE_CODE (varid) == TEMPLATE_ID_EXPR |
47858 | || TREE_CODE (varid) == TYPE_DECL |
47859 | || varid == error_mark_node) |
47860 | variant = varid; |
47861 | else if (varid_token->type == CPP_NAME && varid_token->error_reported) |
47862 | variant = NULL_TREE; |
47863 | else |
47864 | { |
47865 | tree ambiguous_decls; |
47866 | variant = cp_parser_lookup_name (parser, name: varid, tag_type: none_type, |
47867 | is_template: template_p, /*is_namespace=*/false, |
47868 | /*check_dependency=*/true, |
47869 | ambiguous_decls: &ambiguous_decls, |
47870 | name_location: varid.get_location ()); |
47871 | if (ambiguous_decls) |
47872 | variant = NULL_TREE; |
47873 | } |
47874 | if (variant == NULL_TREE) |
47875 | variant = error_mark_node; |
47876 | else if (TREE_CODE (variant) != SCOPE_REF) |
47877 | { |
47878 | const char *error_msg; |
47879 | variant |
47880 | = finish_id_expression (varid, variant, parser->scope, |
47881 | &idk, false, true, |
47882 | &parser->non_integral_constant_expression_p, |
47883 | template_p, true, false, false, &error_msg, |
47884 | varid.get_location ()); |
47885 | if (error_msg) |
47886 | cp_parser_error (parser, gmsgid: error_msg); |
47887 | } |
47888 | location_t caret_loc = get_pure_location (loc: varid.get_location ()); |
47889 | location_t start_loc = get_start (loc: varid_token->location); |
47890 | location_t finish_loc = get_finish (loc: varid.get_location ()); |
47891 | location_t varid_loc = make_location (caret: caret_loc, start: start_loc, finish: finish_loc); |
47892 | |
47893 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
47894 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
47895 | cp_lexer_consume_token (lexer: parser->lexer); |
47896 | |
47897 | const char *clause = "" ; |
47898 | location_t match_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
47899 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
47900 | clause = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
47901 | if (strcmp (s1: clause, s2: "match" )) |
47902 | { |
47903 | cp_parser_error (parser, gmsgid: "expected %<match%>" ); |
47904 | goto fail; |
47905 | } |
47906 | |
47907 | cp_lexer_consume_token (lexer: parser->lexer); |
47908 | |
47909 | if (!parens.require_open (parser)) |
47910 | goto fail; |
47911 | |
47912 | tree ctx = cp_parser_omp_context_selector_specification (parser, has_parms_p: true); |
47913 | if (ctx == error_mark_node) |
47914 | goto fail; |
47915 | ctx = omp_check_context_selector (loc: match_loc, ctx); |
47916 | if (ctx != error_mark_node && variant != error_mark_node) |
47917 | { |
47918 | tree match_loc_node = maybe_wrap_with_location (integer_zero_node, |
47919 | match_loc); |
47920 | tree loc_node = maybe_wrap_with_location (integer_zero_node, varid_loc); |
47921 | loc_node = tree_cons (match_loc_node, |
47922 | build_int_cst (integer_type_node, idk), |
47923 | build_tree_list (loc_node, integer_zero_node)); |
47924 | attrs = tree_cons (get_identifier ("omp declare variant base" ), |
47925 | tree_cons (variant, ctx, loc_node), attrs); |
47926 | if (processing_template_decl) |
47927 | ATTR_IS_DEPENDENT (attrs) = 1; |
47928 | } |
47929 | |
47930 | parens.require_close (parser); |
47931 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
47932 | return attrs; |
47933 | } |
47934 | |
47935 | |
47936 | /* Finalize #pragma omp declare simd clauses after direct declarator has |
47937 | been parsed, and put that into "omp declare simd" attribute. */ |
47938 | |
47939 | static tree |
47940 | cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs) |
47941 | { |
47942 | struct cp_token_cache *ce; |
47943 | cp_omp_declare_simd_data *data = parser->omp_declare_simd; |
47944 | int i; |
47945 | |
47946 | if (!data->error_seen && data->fndecl_seen) |
47947 | { |
47948 | error ("%<#pragma omp declare %s%> not immediately followed by " |
47949 | "a single function declaration or definition" , |
47950 | data->variant_p ? "variant" : "simd" ); |
47951 | data->error_seen = true; |
47952 | } |
47953 | if (data->error_seen) |
47954 | return attrs; |
47955 | |
47956 | FOR_EACH_VEC_ELT (data->tokens, i, ce) |
47957 | { |
47958 | tree c, cl; |
47959 | |
47960 | cp_parser_push_lexer_for_tokens (parser, cache: ce); |
47961 | parser->lexer->in_pragma = true; |
47962 | gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA); |
47963 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
47964 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
47965 | const char *kind = IDENTIFIER_POINTER (id); |
47966 | cp_lexer_consume_token (lexer: parser->lexer); |
47967 | if (strcmp (s1: kind, s2: "simd" ) == 0) |
47968 | { |
47969 | cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, |
47970 | where: "#pragma omp declare simd" , |
47971 | pragma_tok); |
47972 | if (cl) |
47973 | cl = tree_cons (NULL_TREE, cl, NULL_TREE); |
47974 | c = build_tree_list (get_identifier ("omp declare simd" ), cl); |
47975 | TREE_CHAIN (c) = attrs; |
47976 | if (processing_template_decl) |
47977 | ATTR_IS_DEPENDENT (c) = 1; |
47978 | attrs = c; |
47979 | } |
47980 | else |
47981 | { |
47982 | gcc_assert (strcmp (kind, "variant" ) == 0); |
47983 | attrs |
47984 | = cp_finish_omp_declare_variant (parser, pragma_tok, attrs); |
47985 | } |
47986 | cp_parser_pop_lexer (parser); |
47987 | } |
47988 | |
47989 | cp_lexer *lexer = NULL; |
47990 | for (int i = 0; i < 2; i++) |
47991 | { |
47992 | if (data->attribs[i] == NULL) |
47993 | continue; |
47994 | for (tree *pa = data->attribs[i]; *pa; ) |
47995 | if (get_attribute_namespace (*pa) == omp_identifier |
47996 | && is_attribute_p (attr_name: "directive" , ident: get_attribute_name (*pa))) |
47997 | { |
47998 | for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a)) |
47999 | { |
48000 | tree d = TREE_VALUE (a); |
48001 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
48002 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
48003 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
48004 | const char *directive[3] = {}; |
48005 | for (int j = 0; j < 3; j++) |
48006 | { |
48007 | tree id = NULL_TREE; |
48008 | if (first + j == last) |
48009 | break; |
48010 | if (first[j].type == CPP_NAME) |
48011 | id = first[j].u.value; |
48012 | else if (first[j].type == CPP_KEYWORD) |
48013 | id = ridpointers[(int) first[j].keyword]; |
48014 | else |
48015 | break; |
48016 | directive[j] = IDENTIFIER_POINTER (id); |
48017 | } |
48018 | const c_omp_directive *dir = NULL; |
48019 | if (directive[0]) |
48020 | dir = c_omp_categorize_directive (directive[0], directive[1], |
48021 | directive[2]); |
48022 | if (dir == NULL) |
48023 | { |
48024 | error_at (first->location, |
48025 | "unknown OpenMP directive name in " |
48026 | "%qs attribute argument" , |
48027 | TREE_PUBLIC (d) |
48028 | ? "omp::decl" : "omp::directive" ); |
48029 | continue; |
48030 | } |
48031 | if (dir->id != PRAGMA_OMP_DECLARE |
48032 | || (strcmp (s1: directive[1], s2: "simd" ) != 0 |
48033 | && strcmp (s1: directive[1], s2: "variant" ) != 0)) |
48034 | { |
48035 | error_at (first->location, |
48036 | "OpenMP directive other than %<declare simd%> " |
48037 | "or %<declare variant%> appertains to a " |
48038 | "declaration" ); |
48039 | continue; |
48040 | } |
48041 | |
48042 | if (parser->omp_attrs_forbidden_p) |
48043 | { |
48044 | error_at (first->location, |
48045 | "mixing OpenMP directives with attribute and " |
48046 | "pragma syntax on the same statement" ); |
48047 | parser->omp_attrs_forbidden_p = false; |
48048 | } |
48049 | |
48050 | if (!flag_openmp && strcmp (s1: directive[1], s2: "simd" ) != 0) |
48051 | continue; |
48052 | if (lexer == NULL) |
48053 | { |
48054 | lexer = cp_lexer_alloc (); |
48055 | lexer->debugging_p = parser->lexer->debugging_p; |
48056 | } |
48057 | vec_safe_reserve (v&: lexer->buffer, nelems: (last - first) + 2); |
48058 | cp_token tok = {}; |
48059 | tok.type = CPP_PRAGMA; |
48060 | tok.keyword = RID_MAX; |
48061 | tok.u.value = build_int_cst (NULL, PRAGMA_OMP_DECLARE); |
48062 | tok.location = first->location; |
48063 | lexer->buffer->quick_push (obj: tok); |
48064 | while (++first < last) |
48065 | lexer->buffer->quick_push (obj: *first); |
48066 | tok = {}; |
48067 | tok.type = CPP_PRAGMA_EOL; |
48068 | tok.keyword = RID_MAX; |
48069 | tok.location = last->location; |
48070 | lexer->buffer->quick_push (obj: tok); |
48071 | tok = {}; |
48072 | tok.type = CPP_EOF; |
48073 | tok.keyword = RID_MAX; |
48074 | tok.location = last->location; |
48075 | lexer->buffer->quick_push (obj: tok); |
48076 | lexer->next = parser->lexer; |
48077 | lexer->next_token = lexer->buffer->address (); |
48078 | lexer->last_token = lexer->next_token |
48079 | + lexer->buffer->length () |
48080 | - 1; |
48081 | lexer->in_omp_attribute_pragma = true; |
48082 | parser->lexer = lexer; |
48083 | /* Move the current source position to that of the first token |
48084 | in the new lexer. */ |
48085 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
48086 | |
48087 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
48088 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48089 | const char *kind = IDENTIFIER_POINTER (id); |
48090 | cp_lexer_consume_token (lexer: parser->lexer); |
48091 | |
48092 | tree c, cl; |
48093 | if (strcmp (s1: kind, s2: "simd" ) == 0) |
48094 | { |
48095 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48096 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
48097 | cp_lexer_consume_token (lexer: parser->lexer); |
48098 | |
48099 | omp_clause_mask mask = OMP_DECLARE_SIMD_CLAUSE_MASK; |
48100 | cl = cp_parser_omp_all_clauses (parser, mask, |
48101 | where: "#pragma omp declare simd" , |
48102 | pragma_tok); |
48103 | if (cl) |
48104 | cl = tree_cons (NULL_TREE, cl, NULL_TREE); |
48105 | c = build_tree_list (get_identifier ("omp declare simd" ), |
48106 | cl); |
48107 | TREE_CHAIN (c) = attrs; |
48108 | if (processing_template_decl) |
48109 | ATTR_IS_DEPENDENT (c) = 1; |
48110 | attrs = c; |
48111 | } |
48112 | else |
48113 | { |
48114 | gcc_assert (strcmp (kind, "variant" ) == 0); |
48115 | attrs |
48116 | = cp_finish_omp_declare_variant (parser, pragma_tok, |
48117 | attrs); |
48118 | } |
48119 | gcc_assert (parser->lexer != lexer); |
48120 | vec_safe_truncate (v: lexer->buffer, size: 0); |
48121 | } |
48122 | *pa = TREE_CHAIN (*pa); |
48123 | } |
48124 | else |
48125 | pa = &TREE_CHAIN (*pa); |
48126 | } |
48127 | if (lexer) |
48128 | cp_lexer_destroy (lexer); |
48129 | |
48130 | data->fndecl_seen = true; |
48131 | return attrs; |
48132 | } |
48133 | |
48134 | /* D should be DEFERRED_PARSE from omp::decl attribute. If it contains |
48135 | a threadprivate, groupprivate, allocate or declare target directive, |
48136 | return true and parse it for DECL. */ |
48137 | |
48138 | bool |
48139 | cp_maybe_parse_omp_decl (tree decl, tree d) |
48140 | { |
48141 | gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); |
48142 | cp_token *first = DEFPARSE_TOKENS (d)->first; |
48143 | cp_token *last = DEFPARSE_TOKENS (d)->last; |
48144 | const char *directive[3] = {}; |
48145 | for (int j = 0; j < 3; j++) |
48146 | { |
48147 | tree id = NULL_TREE; |
48148 | if (first + j == last) |
48149 | break; |
48150 | if (first[j].type == CPP_NAME) |
48151 | id = first[j].u.value; |
48152 | else if (first[j].type == CPP_KEYWORD) |
48153 | id = ridpointers[(int) first[j].keyword]; |
48154 | else |
48155 | break; |
48156 | directive[j] = IDENTIFIER_POINTER (id); |
48157 | } |
48158 | const c_omp_directive *dir = NULL; |
48159 | if (directive[0]) |
48160 | dir = c_omp_categorize_directive (directive[0], directive[1], |
48161 | directive[2]); |
48162 | if (dir == NULL) |
48163 | { |
48164 | error_at (first->location, |
48165 | "unknown OpenMP directive name in " |
48166 | "%qs attribute argument" , "omp::decl" ); |
48167 | return false; |
48168 | } |
48169 | if (dir->id != PRAGMA_OMP_THREADPRIVATE |
48170 | /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */ |
48171 | && dir->id != PRAGMA_OMP_ALLOCATE |
48172 | && (dir->id != PRAGMA_OMP_DECLARE |
48173 | || strcmp (s1: directive[1], s2: "target" ) != 0)) |
48174 | return false; |
48175 | |
48176 | if (!flag_openmp && !dir->simd) |
48177 | return true; |
48178 | |
48179 | cp_parser *parser = the_parser; |
48180 | cp_lexer *lexer = cp_lexer_alloc (); |
48181 | lexer->debugging_p = parser->lexer->debugging_p; |
48182 | lexer->in_omp_decl_attribute = decl; |
48183 | vec_safe_reserve (v&: lexer->buffer, nelems: last - first + 3, exact: true); |
48184 | cp_token tok = {}; |
48185 | tok.type = CPP_PRAGMA; |
48186 | tok.keyword = RID_MAX; |
48187 | tok.u.value = build_int_cst (NULL, dir->id); |
48188 | tok.location = first->location; |
48189 | lexer->buffer->quick_push (obj: tok); |
48190 | while (++first < last) |
48191 | lexer->buffer->quick_push (obj: *first); |
48192 | tok = {}; |
48193 | tok.type = CPP_PRAGMA_EOL; |
48194 | tok.keyword = RID_MAX; |
48195 | tok.location = last->location; |
48196 | lexer->buffer->quick_push (obj: tok); |
48197 | tok = {}; |
48198 | tok.type = CPP_EOF; |
48199 | tok.keyword = RID_MAX; |
48200 | tok.location = last->location; |
48201 | lexer->buffer->quick_push (obj: tok); |
48202 | lexer->next = parser->lexer; |
48203 | lexer->next_token = lexer->buffer->address (); |
48204 | lexer->last_token = lexer->next_token |
48205 | + lexer->buffer->length () |
48206 | - 1; |
48207 | lexer->in_omp_attribute_pragma = true; |
48208 | parser->lexer = lexer; |
48209 | /* Move the current source position to that of the first token in the |
48210 | new lexer. */ |
48211 | cp_lexer_set_source_position_from_token (token: lexer->next_token); |
48212 | cp_parser_pragma (parser, pragma_external, NULL); |
48213 | |
48214 | return true; |
48215 | } |
48216 | |
48217 | /* Helper for cp_parser_omp_declare_target, handle one to or link clause |
48218 | on #pragma omp declare target. Return false if errors were reported. */ |
48219 | |
48220 | static bool |
48221 | handle_omp_declare_target_clause (tree c, tree t, int device_type, |
48222 | bool indirect) |
48223 | { |
48224 | tree at1 = lookup_attribute (attr_name: "omp declare target" , DECL_ATTRIBUTES (t)); |
48225 | tree at2 = lookup_attribute (attr_name: "omp declare target link" , DECL_ATTRIBUTES (t)); |
48226 | tree id; |
48227 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK) |
48228 | { |
48229 | id = get_identifier ("omp declare target link" ); |
48230 | std::swap (a&: at1, b&: at2); |
48231 | } |
48232 | else |
48233 | id = get_identifier ("omp declare target" ); |
48234 | if (at2) |
48235 | { |
48236 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER) |
48237 | error_at (OMP_CLAUSE_LOCATION (c), |
48238 | "%qD specified both in declare target %<link%> and %qs" |
48239 | " clauses" , t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter" ); |
48240 | else |
48241 | error_at (OMP_CLAUSE_LOCATION (c), |
48242 | "%qD specified both in declare target %<link%> and " |
48243 | "%<to%> or %<enter%> clauses" , t); |
48244 | return false; |
48245 | } |
48246 | if (!at1) |
48247 | { |
48248 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48249 | if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t)) |
48250 | return true; |
48251 | |
48252 | symtab_node *node = symtab_node::get (decl: t); |
48253 | if (node != NULL) |
48254 | { |
48255 | node->offloadable = 1; |
48256 | if (ENABLE_OFFLOADING) |
48257 | { |
48258 | g->have_offload = true; |
48259 | if (is_a <varpool_node *> (p: node)) |
48260 | vec_safe_push (v&: offload_vars, obj: t); |
48261 | } |
48262 | } |
48263 | } |
48264 | if (TREE_CODE (t) != FUNCTION_DECL) |
48265 | return true; |
48266 | if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0) |
48267 | { |
48268 | tree at3 = lookup_attribute (attr_name: "omp declare target host" , |
48269 | DECL_ATTRIBUTES (t)); |
48270 | if (at3 == NULL_TREE) |
48271 | { |
48272 | id = get_identifier ("omp declare target host" ); |
48273 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48274 | } |
48275 | } |
48276 | if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0) |
48277 | { |
48278 | tree at3 = lookup_attribute (attr_name: "omp declare target nohost" , |
48279 | DECL_ATTRIBUTES (t)); |
48280 | if (at3 == NULL_TREE) |
48281 | { |
48282 | id = get_identifier ("omp declare target nohost" ); |
48283 | DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48284 | } |
48285 | } |
48286 | if (indirect) |
48287 | { |
48288 | tree at4 = lookup_attribute (attr_name: "omp declare target indirect" , |
48289 | DECL_ATTRIBUTES (t)); |
48290 | if (at4 == NULL_TREE) |
48291 | { |
48292 | id = get_identifier ("omp declare target indirect" ); |
48293 | DECL_ATTRIBUTES (t) |
48294 | = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t)); |
48295 | } |
48296 | } |
48297 | return true; |
48298 | } |
48299 | |
48300 | /* OpenMP 4.0: |
48301 | # pragma omp declare target new-line |
48302 | declarations and definitions |
48303 | # pragma omp end declare target new-line |
48304 | |
48305 | OpenMP 4.5: |
48306 | # pragma omp declare target ( extended-list ) new-line |
48307 | |
48308 | # pragma omp declare target declare-target-clauses[seq] new-line */ |
48309 | |
48310 | #define OMP_DECLARE_TARGET_CLAUSE_MASK \ |
48311 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \ |
48312 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \ |
48313 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \ |
48314 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ |
48315 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT)) |
48316 | |
48317 | static void |
48318 | cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) |
48319 | { |
48320 | tree clauses = NULL_TREE; |
48321 | int device_type = 0; |
48322 | bool indirect = false; |
48323 | bool only_device_type_or_indirect = true; |
48324 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME) |
48325 | || (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48326 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME))) |
48327 | clauses |
48328 | = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK, |
48329 | where: "#pragma omp declare target" , pragma_tok); |
48330 | else if (parser->lexer->in_omp_decl_attribute |
48331 | || cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
48332 | { |
48333 | clauses = cp_parser_omp_var_list (parser, kind: OMP_CLAUSE_ENTER, |
48334 | list: clauses); |
48335 | clauses = finish_omp_clauses (clauses, C_ORT_OMP); |
48336 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48337 | } |
48338 | else |
48339 | { |
48340 | cp_omp_declare_target_attr a |
48341 | = { .attr_syntax: parser->lexer->in_omp_attribute_pragma, .device_type: -1, .indirect: false }; |
48342 | vec_safe_push (v&: scope_chain->omp_declare_target_attribute, obj: a); |
48343 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48344 | return; |
48345 | } |
48346 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48347 | { |
48348 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE) |
48349 | device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c); |
48350 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48351 | indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c)); |
48352 | } |
48353 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48354 | { |
48355 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE |
48356 | || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48357 | continue; |
48358 | tree t = OMP_CLAUSE_DECL (c); |
48359 | only_device_type_or_indirect = false; |
48360 | if (!handle_omp_declare_target_clause (c, t, device_type, indirect)) |
48361 | continue; |
48362 | if (VAR_OR_FUNCTION_DECL_P (t) |
48363 | && DECL_LOCAL_DECL_P (t) |
48364 | && DECL_LANG_SPECIFIC (t) |
48365 | && DECL_LOCAL_DECL_ALIAS (t) |
48366 | && DECL_LOCAL_DECL_ALIAS (t) != error_mark_node) |
48367 | handle_omp_declare_target_clause (c, DECL_LOCAL_DECL_ALIAS (t), |
48368 | device_type, indirect); |
48369 | } |
48370 | if ((device_type || indirect) && only_device_type_or_indirect) |
48371 | error_at (OMP_CLAUSE_LOCATION (clauses), |
48372 | "directive with only %<device_type%> or %<indirect%> clauses" ); |
48373 | if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY) |
48374 | error_at (OMP_CLAUSE_LOCATION (clauses), |
48375 | "%<device_type%> clause must specify 'any' when used with " |
48376 | "an %<indirect%> clause" ); |
48377 | } |
48378 | |
48379 | /* OpenMP 5.1 |
48380 | # pragma omp begin assumes clauses[optseq] new-line |
48381 | |
48382 | # pragma omp begin declare target clauses[optseq] new-line */ |
48383 | |
48384 | #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \ |
48385 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ |
48386 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT)) |
48387 | |
48388 | static void |
48389 | cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) |
48390 | { |
48391 | const char *p = "" ; |
48392 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
48393 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48394 | { |
48395 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48396 | p = IDENTIFIER_POINTER (id); |
48397 | } |
48398 | if (strcmp (s1: p, s2: "declare" ) == 0) |
48399 | { |
48400 | cp_lexer_consume_token (lexer: parser->lexer); |
48401 | p = "" ; |
48402 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48403 | { |
48404 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48405 | p = IDENTIFIER_POINTER (id); |
48406 | } |
48407 | if (strcmp (s1: p, s2: "target" ) == 0) |
48408 | { |
48409 | cp_lexer_consume_token (lexer: parser->lexer); |
48410 | tree clauses |
48411 | = cp_parser_omp_all_clauses (parser, |
48412 | OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK, |
48413 | where: "#pragma omp begin declare target" , |
48414 | pragma_tok); |
48415 | int device_type = 0; |
48416 | bool indirect = 0; |
48417 | for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) |
48418 | { |
48419 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE) |
48420 | device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c); |
48421 | if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT) |
48422 | indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c)); |
48423 | } |
48424 | cp_omp_declare_target_attr a |
48425 | = { .attr_syntax: in_omp_attribute_pragma, .device_type: device_type, .indirect: indirect }; |
48426 | vec_safe_push (v&: scope_chain->omp_declare_target_attribute, obj: a); |
48427 | } |
48428 | else |
48429 | { |
48430 | cp_parser_error (parser, gmsgid: "expected %<target%>" ); |
48431 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48432 | } |
48433 | } |
48434 | else if (strcmp (s1: p, s2: "assumes" ) == 0) |
48435 | { |
48436 | cp_lexer_consume_token (lexer: parser->lexer); |
48437 | cp_parser_omp_assumption_clauses (parser, pragma_tok, is_assume: false); |
48438 | cp_omp_begin_assumes_data a = { .attr_syntax: in_omp_attribute_pragma }; |
48439 | vec_safe_push (v&: scope_chain->omp_begin_assumes, obj: a); |
48440 | } |
48441 | else |
48442 | { |
48443 | cp_parser_error (parser, gmsgid: "expected %<declare target%> or %<assumes%>" ); |
48444 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48445 | } |
48446 | } |
48447 | |
48448 | /* OpenMP 4.0: |
48449 | # pragma omp end declare target new-line |
48450 | |
48451 | OpenMP 5.1: |
48452 | # pragma omp end assumes new-line */ |
48453 | |
48454 | static void |
48455 | cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok) |
48456 | { |
48457 | const char *p = "" ; |
48458 | bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; |
48459 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48460 | { |
48461 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48462 | p = IDENTIFIER_POINTER (id); |
48463 | } |
48464 | if (strcmp (s1: p, s2: "declare" ) == 0) |
48465 | { |
48466 | cp_lexer_consume_token (lexer: parser->lexer); |
48467 | p = "" ; |
48468 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48469 | { |
48470 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48471 | p = IDENTIFIER_POINTER (id); |
48472 | } |
48473 | if (strcmp (s1: p, s2: "target" ) == 0) |
48474 | cp_lexer_consume_token (lexer: parser->lexer); |
48475 | else |
48476 | { |
48477 | cp_parser_error (parser, gmsgid: "expected %<target%>" ); |
48478 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48479 | return; |
48480 | } |
48481 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48482 | if (!vec_safe_length (v: scope_chain->omp_declare_target_attribute)) |
48483 | error_at (pragma_tok->location, |
48484 | "%<#pragma omp end declare target%> without corresponding " |
48485 | "%<#pragma omp declare target%> or " |
48486 | "%<#pragma omp begin declare target%>" ); |
48487 | else |
48488 | { |
48489 | cp_omp_declare_target_attr |
48490 | a = scope_chain->omp_declare_target_attribute->pop (); |
48491 | if (a.attr_syntax != in_omp_attribute_pragma) |
48492 | { |
48493 | if (a.attr_syntax) |
48494 | error_at (pragma_tok->location, |
48495 | "%qs in attribute syntax terminated " |
48496 | "with %qs in pragma syntax" , |
48497 | a.device_type >= 0 ? "begin declare target" |
48498 | : "declare target" , |
48499 | "end declare target" ); |
48500 | else |
48501 | error_at (pragma_tok->location, |
48502 | "%qs in pragma syntax terminated " |
48503 | "with %qs in attribute syntax" , |
48504 | a.device_type >= 0 ? "begin declare target" |
48505 | : "declare target" , |
48506 | "end declare target" ); |
48507 | } |
48508 | } |
48509 | } |
48510 | else if (strcmp (s1: p, s2: "assumes" ) == 0) |
48511 | { |
48512 | cp_lexer_consume_token (lexer: parser->lexer); |
48513 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48514 | if (!vec_safe_length (v: scope_chain->omp_begin_assumes)) |
48515 | error_at (pragma_tok->location, |
48516 | "%qs without corresponding %qs" , |
48517 | "#pragma omp end assumes" , "#pragma omp begin assumes" ); |
48518 | else |
48519 | { |
48520 | cp_omp_begin_assumes_data |
48521 | a = scope_chain->omp_begin_assumes->pop (); |
48522 | if (a.attr_syntax != in_omp_attribute_pragma) |
48523 | { |
48524 | if (a.attr_syntax) |
48525 | error_at (pragma_tok->location, |
48526 | "%qs in attribute syntax terminated " |
48527 | "with %qs in pragma syntax" , |
48528 | "begin assumes" , "end assumes" ); |
48529 | else |
48530 | error_at (pragma_tok->location, |
48531 | "%qs in pragma syntax terminated " |
48532 | "with %qs in attribute syntax" , |
48533 | "begin assumes" , "end assumes" ); |
48534 | } |
48535 | } |
48536 | } |
48537 | else |
48538 | { |
48539 | cp_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>" ); |
48540 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48541 | return; |
48542 | } |
48543 | } |
48544 | |
48545 | /* Helper function of cp_parser_omp_declare_reduction. Parse the combiner |
48546 | expression and optional initializer clause of |
48547 | #pragma omp declare reduction. We store the expression(s) as |
48548 | either 3, 6 or 7 special statements inside of the artificial function's |
48549 | body. The first two statements are DECL_EXPRs for the artificial |
48550 | OMP_OUT resp. OMP_IN variables, followed by a statement with the combiner |
48551 | expression that uses those variables. |
48552 | If there was any INITIALIZER clause, this is followed by further statements, |
48553 | the fourth and fifth statements are DECL_EXPRs for the artificial |
48554 | OMP_PRIV resp. OMP_ORIG variables. If the INITIALIZER clause wasn't the |
48555 | constructor variant (first token after open paren is not omp_priv), |
48556 | then the sixth statement is a statement with the function call expression |
48557 | that uses the OMP_PRIV and optionally OMP_ORIG variable. |
48558 | Otherwise, the sixth statement is whatever statement cp_finish_decl emits |
48559 | to initialize the OMP_PRIV artificial variable and there is seventh |
48560 | statement, a DECL_EXPR of the OMP_PRIV statement again. */ |
48561 | |
48562 | static bool |
48563 | cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) |
48564 | { |
48565 | tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); |
48566 | gcc_assert (TYPE_REF_P (type)); |
48567 | type = TREE_TYPE (type); |
48568 | tree omp_out = build_lang_decl (VAR_DECL, get_identifier ("omp_out" ), type); |
48569 | DECL_ARTIFICIAL (omp_out) = 1; |
48570 | pushdecl (omp_out); |
48571 | add_decl_expr (omp_out); |
48572 | tree omp_in = build_lang_decl (VAR_DECL, get_identifier ("omp_in" ), type); |
48573 | DECL_ARTIFICIAL (omp_in) = 1; |
48574 | pushdecl (omp_in); |
48575 | add_decl_expr (omp_in); |
48576 | tree combiner; |
48577 | tree omp_priv = NULL_TREE, omp_orig = NULL_TREE, initializer = NULL_TREE; |
48578 | |
48579 | keep_next_level (true); |
48580 | tree block = begin_omp_structured_block (); |
48581 | combiner = cp_parser_expression (parser); |
48582 | finish_expr_stmt (combiner); |
48583 | block = finish_omp_structured_block (block); |
48584 | if (processing_template_decl) |
48585 | block = build_stmt (input_location, EXPR_STMT, block); |
48586 | add_stmt (block); |
48587 | |
48588 | if (!cp_parser_require (parser, type: CPP_CLOSE_PAREN, token_desc: RT_CLOSE_PAREN)) |
48589 | return false; |
48590 | |
48591 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
48592 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
48593 | cp_lexer_consume_token (lexer: parser->lexer); |
48594 | |
48595 | const char *p = "" ; |
48596 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48597 | { |
48598 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48599 | p = IDENTIFIER_POINTER (id); |
48600 | } |
48601 | |
48602 | if (strcmp (s1: p, s2: "initializer" ) == 0) |
48603 | { |
48604 | cp_lexer_consume_token (lexer: parser->lexer); |
48605 | matching_parens parens; |
48606 | if (!parens.require_open (parser)) |
48607 | return false; |
48608 | |
48609 | p = "" ; |
48610 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48611 | { |
48612 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48613 | p = IDENTIFIER_POINTER (id); |
48614 | } |
48615 | |
48616 | omp_priv = build_lang_decl (VAR_DECL, get_identifier ("omp_priv" ), type); |
48617 | DECL_ARTIFICIAL (omp_priv) = 1; |
48618 | pushdecl (omp_priv); |
48619 | add_decl_expr (omp_priv); |
48620 | omp_orig = build_lang_decl (VAR_DECL, get_identifier ("omp_orig" ), type); |
48621 | DECL_ARTIFICIAL (omp_orig) = 1; |
48622 | pushdecl (omp_orig); |
48623 | add_decl_expr (omp_orig); |
48624 | |
48625 | keep_next_level (true); |
48626 | block = begin_omp_structured_block (); |
48627 | |
48628 | bool ctor = false; |
48629 | if (strcmp (s1: p, s2: "omp_priv" ) == 0) |
48630 | { |
48631 | bool is_non_constant_init; |
48632 | ctor = true; |
48633 | cp_lexer_consume_token (lexer: parser->lexer); |
48634 | /* Reject initializer (omp_priv) and initializer (omp_priv ()). */ |
48635 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_CLOSE_PAREN) |
48636 | || (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
48637 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)->type |
48638 | == CPP_CLOSE_PAREN |
48639 | && cp_lexer_peek_nth_token (lexer: parser->lexer, n: 3)->type |
48640 | == CPP_CLOSE_PAREN)) |
48641 | { |
48642 | finish_omp_structured_block (block); |
48643 | error ("invalid initializer clause" ); |
48644 | return false; |
48645 | } |
48646 | initializer = cp_parser_initializer (parser, |
48647 | /*is_direct_init=*/nullptr, |
48648 | non_constant_p: &is_non_constant_init); |
48649 | cp_finish_decl (omp_priv, initializer, !is_non_constant_init, |
48650 | NULL_TREE, LOOKUP_ONLYCONVERTING); |
48651 | } |
48652 | else |
48653 | { |
48654 | cp_parser_parse_tentatively (parser); |
48655 | /* Don't create location wrapper nodes here. */ |
48656 | auto_suppress_location_wrappers sentinel; |
48657 | tree fn_name = cp_parser_id_expression (parser, /*template_p=*/template_keyword_p: false, |
48658 | /*check_dependency_p=*/true, |
48659 | /*template_p=*/NULL, |
48660 | /*declarator_p=*/false, |
48661 | /*optional_p=*/false); |
48662 | vec<tree, va_gc> *args; |
48663 | if (fn_name == error_mark_node |
48664 | || cp_parser_error_occurred (parser) |
48665 | || !cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN) |
48666 | || ((args = cp_parser_parenthesized_expression_list |
48667 | (parser, is_attribute_list: non_attr, /*cast_p=*/false, |
48668 | /*allow_expansion_p=*/true, |
48669 | /*non_constant_p=*/NULL)), |
48670 | cp_parser_error_occurred (parser))) |
48671 | { |
48672 | finish_omp_structured_block (block); |
48673 | cp_parser_abort_tentative_parse (parser); |
48674 | cp_parser_error (parser, gmsgid: "expected id-expression (arguments)" ); |
48675 | return false; |
48676 | } |
48677 | unsigned int i; |
48678 | tree arg; |
48679 | FOR_EACH_VEC_SAFE_ELT (args, i, arg) |
48680 | if (arg == omp_priv |
48681 | || (TREE_CODE (arg) == ADDR_EXPR |
48682 | && TREE_OPERAND (arg, 0) == omp_priv)) |
48683 | break; |
48684 | cp_parser_abort_tentative_parse (parser); |
48685 | if (arg == NULL_TREE) |
48686 | error ("one of the initializer call arguments should be %<omp_priv%>" |
48687 | " or %<&omp_priv%>" ); |
48688 | initializer = cp_parser_postfix_expression (parser, address_p: false, cast_p: false, member_access_only_p: false, |
48689 | decltype_p: false, NULL); |
48690 | finish_expr_stmt (initializer); |
48691 | } |
48692 | |
48693 | block = finish_omp_structured_block (block); |
48694 | cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL); |
48695 | if (processing_template_decl) |
48696 | block = build_stmt (input_location, EXPR_STMT, block); |
48697 | add_stmt (block); |
48698 | |
48699 | if (ctor) |
48700 | add_decl_expr (omp_orig); |
48701 | |
48702 | if (!parens.require_close (parser)) |
48703 | return false; |
48704 | } |
48705 | |
48706 | if (!cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
48707 | cp_parser_required_error (parser, token_desc: RT_PRAGMA_EOL, /*keyword=*/false, |
48708 | UNKNOWN_LOCATION); |
48709 | |
48710 | return true; |
48711 | } |
48712 | |
48713 | /* OpenMP 4.0 |
48714 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ |
48715 | initializer-clause[opt] new-line |
48716 | |
48717 | initializer-clause: |
48718 | initializer (omp_priv initializer) |
48719 | initializer (function-name (argument-list)) */ |
48720 | |
48721 | static void |
48722 | cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, |
48723 | enum pragma_context) |
48724 | { |
48725 | auto_vec<tree> types; |
48726 | enum tree_code reduc_code = ERROR_MARK; |
48727 | tree reduc_id = NULL_TREE, orig_reduc_id = NULL_TREE, type; |
48728 | unsigned int i; |
48729 | cp_token *first_token; |
48730 | cp_token_cache *cp; |
48731 | int errs; |
48732 | void *p; |
48733 | |
48734 | /* Get the high-water mark for the DECLARATOR_OBSTACK. */ |
48735 | p = obstack_alloc (&declarator_obstack, 0); |
48736 | |
48737 | if (!cp_parser_require (parser, type: CPP_OPEN_PAREN, token_desc: RT_OPEN_PAREN)) |
48738 | goto fail; |
48739 | |
48740 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
48741 | { |
48742 | case CPP_PLUS: |
48743 | reduc_code = PLUS_EXPR; |
48744 | break; |
48745 | case CPP_MULT: |
48746 | reduc_code = MULT_EXPR; |
48747 | break; |
48748 | case CPP_MINUS: |
48749 | reduc_code = MINUS_EXPR; |
48750 | break; |
48751 | case CPP_AND: |
48752 | reduc_code = BIT_AND_EXPR; |
48753 | break; |
48754 | case CPP_XOR: |
48755 | reduc_code = BIT_XOR_EXPR; |
48756 | break; |
48757 | case CPP_OR: |
48758 | reduc_code = BIT_IOR_EXPR; |
48759 | break; |
48760 | case CPP_AND_AND: |
48761 | reduc_code = TRUTH_ANDIF_EXPR; |
48762 | break; |
48763 | case CPP_OR_OR: |
48764 | reduc_code = TRUTH_ORIF_EXPR; |
48765 | break; |
48766 | case CPP_NAME: |
48767 | reduc_id = orig_reduc_id = cp_parser_identifier (parser); |
48768 | break; |
48769 | default: |
48770 | cp_parser_error (parser, gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, " |
48771 | "%<|%>, %<&&%>, %<||%> or identifier" ); |
48772 | goto fail; |
48773 | } |
48774 | |
48775 | if (reduc_code != ERROR_MARK) |
48776 | cp_lexer_consume_token (lexer: parser->lexer); |
48777 | |
48778 | reduc_id = omp_reduction_id (reduc_code, reduc_id, NULL_TREE); |
48779 | if (reduc_id == error_mark_node) |
48780 | goto fail; |
48781 | |
48782 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON)) |
48783 | goto fail; |
48784 | |
48785 | /* Types may not be defined in declare reduction type list. */ |
48786 | const char *saved_message; |
48787 | saved_message = parser->type_definition_forbidden_message; |
48788 | parser->type_definition_forbidden_message |
48789 | = G_("types may not be defined in declare reduction type list" ); |
48790 | bool saved_colon_corrects_to_scope_p; |
48791 | saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; |
48792 | parser->colon_corrects_to_scope_p = false; |
48793 | bool saved_colon_doesnt_start_class_def_p; |
48794 | saved_colon_doesnt_start_class_def_p |
48795 | = parser->colon_doesnt_start_class_def_p; |
48796 | parser->colon_doesnt_start_class_def_p = true; |
48797 | |
48798 | while (true) |
48799 | { |
48800 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
48801 | type = cp_parser_type_id (parser); |
48802 | if (type == error_mark_node) |
48803 | ; |
48804 | else if (ARITHMETIC_TYPE_P (type) |
48805 | && (orig_reduc_id == NULL_TREE |
48806 | || (TREE_CODE (type) != COMPLEX_TYPE |
48807 | && (id_equal (id: orig_reduc_id, str: "min" ) |
48808 | || id_equal (id: orig_reduc_id, str: "max" ))))) |
48809 | error_at (loc, "predeclared arithmetic type %qT in " |
48810 | "%<#pragma omp declare reduction%>" , type); |
48811 | else if (FUNC_OR_METHOD_TYPE_P (type) |
48812 | || TREE_CODE (type) == ARRAY_TYPE) |
48813 | error_at (loc, "function or array type %qT in " |
48814 | "%<#pragma omp declare reduction%>" , type); |
48815 | else if (TYPE_REF_P (type)) |
48816 | error_at (loc, "reference type %qT in " |
48817 | "%<#pragma omp declare reduction%>" , type); |
48818 | else if (TYPE_QUALS_NO_ADDR_SPACE (type)) |
48819 | error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified " |
48820 | "type %qT in %<#pragma omp declare reduction%>" , type); |
48821 | else |
48822 | types.safe_push (obj: type); |
48823 | |
48824 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA)) |
48825 | cp_lexer_consume_token (lexer: parser->lexer); |
48826 | else |
48827 | break; |
48828 | } |
48829 | |
48830 | /* Restore the saved message. */ |
48831 | parser->type_definition_forbidden_message = saved_message; |
48832 | parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; |
48833 | parser->colon_doesnt_start_class_def_p |
48834 | = saved_colon_doesnt_start_class_def_p; |
48835 | |
48836 | if (!cp_parser_require (parser, type: CPP_COLON, token_desc: RT_COLON) |
48837 | || types.is_empty ()) |
48838 | { |
48839 | fail: |
48840 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
48841 | goto done; |
48842 | } |
48843 | |
48844 | first_token = cp_lexer_peek_token (lexer: parser->lexer); |
48845 | cp = NULL; |
48846 | errs = errorcount; |
48847 | FOR_EACH_VEC_ELT (types, i, type) |
48848 | { |
48849 | tree fntype |
48850 | = build_function_type_list (void_type_node, |
48851 | cp_build_reference_type (type, false), |
48852 | NULL_TREE); |
48853 | tree this_reduc_id = reduc_id; |
48854 | if (!dependent_type_p (type)) |
48855 | this_reduc_id = omp_reduction_id (ERROR_MARK, reduc_id, type); |
48856 | tree fndecl = build_lang_decl (FUNCTION_DECL, this_reduc_id, fntype); |
48857 | DECL_SOURCE_LOCATION (fndecl) = pragma_tok->location; |
48858 | DECL_ARTIFICIAL (fndecl) = 1; |
48859 | DECL_EXTERNAL (fndecl) = 1; |
48860 | DECL_DECLARED_INLINE_P (fndecl) = 1; |
48861 | DECL_IGNORED_P (fndecl) = 1; |
48862 | DECL_OMP_DECLARE_REDUCTION_P (fndecl) = 1; |
48863 | SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier ("<udr>" )); |
48864 | DECL_ATTRIBUTES (fndecl) |
48865 | = tree_cons (get_identifier ("gnu_inline" ), NULL_TREE, |
48866 | DECL_ATTRIBUTES (fndecl)); |
48867 | bool block_scope = false; |
48868 | if (current_function_decl) |
48869 | { |
48870 | block_scope = true; |
48871 | DECL_CONTEXT (fndecl) = current_function_decl; |
48872 | DECL_LOCAL_DECL_P (fndecl) = true; |
48873 | } |
48874 | |
48875 | if (processing_template_decl) |
48876 | fndecl = push_template_decl (fndecl); |
48877 | |
48878 | if (block_scope) |
48879 | { |
48880 | if (!processing_template_decl) |
48881 | pushdecl (fndecl); |
48882 | } |
48883 | else if (current_class_type) |
48884 | { |
48885 | if (cp == NULL) |
48886 | { |
48887 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
48888 | cp_lexer_consume_token (lexer: parser->lexer); |
48889 | cp = cp_token_cache_new (first: first_token, |
48890 | last: cp_lexer_peek_nth_token (lexer: parser->lexer, |
48891 | n: 2)); |
48892 | } |
48893 | DECL_STATIC_FUNCTION_P (fndecl) = 1; |
48894 | finish_member_declaration (fndecl); |
48895 | DECL_PENDING_INLINE_INFO (fndecl) = cp; |
48896 | DECL_PENDING_INLINE_P (fndecl) = 1; |
48897 | vec_safe_push (unparsed_funs_with_definitions, obj: fndecl); |
48898 | continue; |
48899 | } |
48900 | else |
48901 | { |
48902 | DECL_CONTEXT (fndecl) = current_namespace; |
48903 | tree d = pushdecl (fndecl); |
48904 | /* We should never meet a matched duplicate decl. */ |
48905 | gcc_checking_assert (d == error_mark_node || d == fndecl); |
48906 | } |
48907 | |
48908 | tree block = NULL_TREE; |
48909 | if (!block_scope) |
48910 | start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED); |
48911 | else |
48912 | block = begin_omp_structured_block (); |
48913 | if (cp) |
48914 | { |
48915 | cp_parser_push_lexer_for_tokens (parser, cache: cp); |
48916 | parser->lexer->in_pragma = true; |
48917 | } |
48918 | |
48919 | bool ok = cp_parser_omp_declare_reduction_exprs (fndecl, parser); |
48920 | |
48921 | if (cp) |
48922 | cp_parser_pop_lexer (parser); |
48923 | if (!block_scope) |
48924 | finish_function (/*inline_p=*/false); |
48925 | else |
48926 | { |
48927 | DECL_CONTEXT (fndecl) = current_function_decl; |
48928 | if (DECL_TEMPLATE_INFO (fndecl)) |
48929 | DECL_CONTEXT (DECL_TI_TEMPLATE (fndecl)) = current_function_decl; |
48930 | } |
48931 | if (!ok) |
48932 | goto fail; |
48933 | |
48934 | if (block_scope) |
48935 | { |
48936 | block = finish_omp_structured_block (block); |
48937 | if (TREE_CODE (block) == BIND_EXPR) |
48938 | DECL_SAVED_TREE (fndecl) = BIND_EXPR_BODY (block); |
48939 | else if (TREE_CODE (block) == STATEMENT_LIST) |
48940 | DECL_SAVED_TREE (fndecl) = block; |
48941 | if (processing_template_decl) |
48942 | add_decl_expr (fndecl); |
48943 | } |
48944 | |
48945 | cp_check_omp_declare_reduction (fndecl); |
48946 | if (cp == NULL && types.length () > 1) |
48947 | cp = cp_token_cache_new (first: first_token, |
48948 | last: cp_lexer_peek_nth_token (lexer: parser->lexer, n: 2)); |
48949 | if (errs != errorcount) |
48950 | break; |
48951 | } |
48952 | |
48953 | cp_parser_require_pragma_eol (parser, pragma_tok); |
48954 | |
48955 | done: |
48956 | /* Free any declarators allocated. */ |
48957 | obstack_free (&declarator_obstack, p); |
48958 | } |
48959 | |
48960 | /* OpenMP 4.0 |
48961 | #pragma omp declare simd declare-simd-clauses[optseq] new-line |
48962 | #pragma omp declare reduction (reduction-id : typename-list : expression) \ |
48963 | initializer-clause[opt] new-line |
48964 | #pragma omp declare target new-line |
48965 | |
48966 | OpenMP 5.0 |
48967 | #pragma omp declare variant (identifier) match (context-selector) */ |
48968 | |
48969 | static bool |
48970 | cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok, |
48971 | enum pragma_context context) |
48972 | { |
48973 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
48974 | { |
48975 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
48976 | const char *p = IDENTIFIER_POINTER (id); |
48977 | |
48978 | if (strcmp (s1: p, s2: "simd" ) == 0) |
48979 | { |
48980 | cp_lexer_consume_token (lexer: parser->lexer); |
48981 | cp_parser_omp_declare_simd (parser, pragma_tok, |
48982 | context, variant_p: false); |
48983 | return true; |
48984 | } |
48985 | if (flag_openmp && strcmp (s1: p, s2: "variant" ) == 0) |
48986 | { |
48987 | cp_lexer_consume_token (lexer: parser->lexer); |
48988 | cp_parser_omp_declare_simd (parser, pragma_tok, |
48989 | context, variant_p: true); |
48990 | return true; |
48991 | } |
48992 | cp_ensure_no_omp_declare_simd (parser); |
48993 | if (strcmp (s1: p, s2: "reduction" ) == 0) |
48994 | { |
48995 | cp_lexer_consume_token (lexer: parser->lexer); |
48996 | cp_parser_omp_declare_reduction (parser, pragma_tok, |
48997 | context); |
48998 | return false; |
48999 | } |
49000 | if (!flag_openmp) /* flag_openmp_simd */ |
49001 | { |
49002 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49003 | return false; |
49004 | } |
49005 | if (strcmp (s1: p, s2: "target" ) == 0) |
49006 | { |
49007 | cp_lexer_consume_token (lexer: parser->lexer); |
49008 | cp_parser_omp_declare_target (parser, pragma_tok); |
49009 | return false; |
49010 | } |
49011 | } |
49012 | cp_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, " |
49013 | "%<target%> or %<variant%>" ); |
49014 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49015 | return false; |
49016 | } |
49017 | |
49018 | /* OpenMP 5.0 |
49019 | #pragma omp requires clauses[optseq] new-line */ |
49020 | |
49021 | static bool |
49022 | cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) |
49023 | { |
49024 | enum omp_requires new_req = (enum omp_requires) 0; |
49025 | |
49026 | location_t loc = pragma_tok->location; |
49027 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49028 | { |
49029 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
49030 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
49031 | cp_lexer_consume_token (lexer: parser->lexer); |
49032 | |
49033 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49034 | { |
49035 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49036 | const char *p = IDENTIFIER_POINTER (id); |
49037 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49038 | enum omp_requires this_req = (enum omp_requires) 0; |
49039 | |
49040 | if (!strcmp (s1: p, s2: "unified_address" )) |
49041 | this_req = OMP_REQUIRES_UNIFIED_ADDRESS; |
49042 | else if (!strcmp (s1: p, s2: "unified_shared_memory" )) |
49043 | this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY; |
49044 | else if (!strcmp (s1: p, s2: "dynamic_allocators" )) |
49045 | this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS; |
49046 | else if (!strcmp (s1: p, s2: "reverse_offload" )) |
49047 | this_req = OMP_REQUIRES_REVERSE_OFFLOAD; |
49048 | else if (!strcmp (s1: p, s2: "atomic_default_mem_order" )) |
49049 | { |
49050 | cp_lexer_consume_token (lexer: parser->lexer); |
49051 | |
49052 | matching_parens parens; |
49053 | if (parens.require_open (parser)) |
49054 | { |
49055 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49056 | { |
49057 | id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49058 | p = IDENTIFIER_POINTER (id); |
49059 | |
49060 | if (!strcmp (s1: p, s2: "seq_cst" )) |
49061 | this_req |
49062 | = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST; |
49063 | else if (!strcmp (s1: p, s2: "relaxed" )) |
49064 | this_req |
49065 | = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED; |
49066 | else if (!strcmp (s1: p, s2: "acq_rel" )) |
49067 | this_req |
49068 | = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL; |
49069 | } |
49070 | if (this_req == 0) |
49071 | { |
49072 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
49073 | "expected %<seq_cst%>, %<relaxed%> or " |
49074 | "%<acq_rel%>" ); |
49075 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
49076 | { |
49077 | case CPP_EOF: |
49078 | case CPP_PRAGMA_EOL: |
49079 | case CPP_CLOSE_PAREN: |
49080 | break; |
49081 | default: |
49082 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
49083 | type: CPP_CLOSE_PAREN)) |
49084 | cp_lexer_consume_token (lexer: parser->lexer); |
49085 | break; |
49086 | } |
49087 | } |
49088 | else |
49089 | cp_lexer_consume_token (lexer: parser->lexer); |
49090 | |
49091 | if (!parens.require_close (parser)) |
49092 | cp_parser_skip_to_closing_parenthesis (parser, |
49093 | /*recovering=*/true, |
49094 | /*or_comma=*/false, |
49095 | /*consume_paren=*/ |
49096 | true); |
49097 | |
49098 | if (this_req == 0) |
49099 | { |
49100 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49101 | return false; |
49102 | } |
49103 | } |
49104 | p = NULL; |
49105 | } |
49106 | else |
49107 | { |
49108 | error_at (cloc, "expected %<unified_address%>, " |
49109 | "%<unified_shared_memory%>, " |
49110 | "%<dynamic_allocators%>, " |
49111 | "%<reverse_offload%> " |
49112 | "or %<atomic_default_mem_order%> clause" ); |
49113 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49114 | return false; |
49115 | } |
49116 | if (p) |
49117 | cp_lexer_consume_token (lexer: parser->lexer); |
49118 | if (this_req) |
49119 | { |
49120 | if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49121 | { |
49122 | if ((this_req & new_req) != 0) |
49123 | error_at (cloc, "too many %qs clauses" , p); |
49124 | if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS |
49125 | && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0) |
49126 | error_at (cloc, "%qs clause used lexically after first " |
49127 | "target construct or offloading API" , p); |
49128 | } |
49129 | else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49130 | { |
49131 | error_at (cloc, "too many %qs clauses" , |
49132 | "atomic_default_mem_order" ); |
49133 | this_req = (enum omp_requires) 0; |
49134 | } |
49135 | else if ((omp_requires_mask |
49136 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0) |
49137 | { |
49138 | error_at (cloc, "more than one %<atomic_default_mem_order%>" |
49139 | " clause in a single compilation unit" ); |
49140 | this_req |
49141 | = (enum omp_requires) |
49142 | (omp_requires_mask |
49143 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER); |
49144 | } |
49145 | else if ((omp_requires_mask |
49146 | & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0) |
49147 | error_at (cloc, "%<atomic_default_mem_order%> clause used " |
49148 | "lexically after first %<atomic%> construct " |
49149 | "without memory order clause" ); |
49150 | new_req = (enum omp_requires) (new_req | this_req); |
49151 | omp_requires_mask |
49152 | = (enum omp_requires) (omp_requires_mask | this_req); |
49153 | continue; |
49154 | } |
49155 | } |
49156 | break; |
49157 | } |
49158 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49159 | |
49160 | if (new_req == 0) |
49161 | error_at (loc, "%<pragma omp requires%> requires at least one clause" ); |
49162 | return false; |
49163 | } |
49164 | |
49165 | |
49166 | /* OpenMP 5.1: |
49167 | #pragma omp nothing new-line */ |
49168 | |
49169 | static void |
49170 | cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok) |
49171 | { |
49172 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49173 | } |
49174 | |
49175 | |
49176 | /* OpenMP 5.1 |
49177 | #pragma omp error clauses[optseq] new-line */ |
49178 | |
49179 | static bool |
49180 | cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, |
49181 | enum pragma_context context) |
49182 | { |
49183 | int at_compilation = -1; |
49184 | int severity_fatal = -1; |
49185 | tree message = NULL_TREE; |
49186 | bool bad = false; |
49187 | location_t loc = pragma_tok->location; |
49188 | |
49189 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49190 | { |
49191 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_COMMA) |
49192 | && cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, type: CPP_NAME)) |
49193 | cp_lexer_consume_token (lexer: parser->lexer); |
49194 | |
49195 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_NAME)) |
49196 | break; |
49197 | |
49198 | const char *p |
49199 | = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); |
49200 | location_t cloc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49201 | static const char *args[] = { |
49202 | "execution" , "compilation" , "warning" , "fatal" |
49203 | }; |
49204 | int *v = NULL; |
49205 | int idx = 0, n = -1; |
49206 | tree m = NULL_TREE; |
49207 | |
49208 | if (!strcmp (s1: p, s2: "at" )) |
49209 | v = &at_compilation; |
49210 | else if (!strcmp (s1: p, s2: "severity" )) |
49211 | { |
49212 | v = &severity_fatal; |
49213 | idx += 2; |
49214 | } |
49215 | else if (strcmp (s1: p, s2: "message" )) |
49216 | { |
49217 | error_at (cloc, |
49218 | "expected %<at%>, %<severity%> or %<message%> clause" ); |
49219 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49220 | return false; |
49221 | } |
49222 | |
49223 | cp_lexer_consume_token (lexer: parser->lexer); |
49224 | |
49225 | matching_parens parens; |
49226 | if (parens.require_open (parser)) |
49227 | { |
49228 | if (v == NULL) |
49229 | { |
49230 | m = cp_parser_assignment_expression (parser); |
49231 | if (type_dependent_expression_p (m)) |
49232 | m = build1 (IMPLICIT_CONV_EXPR, const_string_type_node, m); |
49233 | else |
49234 | m = perform_implicit_conversion_flags (const_string_type_node, m, |
49235 | tf_warning_or_error, |
49236 | LOOKUP_NORMAL); |
49237 | } |
49238 | else |
49239 | { |
49240 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49241 | { |
49242 | tree val = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49243 | const char *q = IDENTIFIER_POINTER (val); |
49244 | |
49245 | if (!strcmp (s1: q, s2: args[idx])) |
49246 | n = 0; |
49247 | else if (!strcmp (s1: q, s2: args[idx + 1])) |
49248 | n = 1; |
49249 | } |
49250 | if (n == -1) |
49251 | { |
49252 | error_at (cp_lexer_peek_token (lexer: parser->lexer)->location, |
49253 | "expected %qs or %qs" , args[idx], args[idx + 1]); |
49254 | bad = true; |
49255 | switch (cp_lexer_peek_token (lexer: parser->lexer)->type) |
49256 | { |
49257 | case CPP_EOF: |
49258 | case CPP_PRAGMA_EOL: |
49259 | case CPP_CLOSE_PAREN: |
49260 | break; |
49261 | default: |
49262 | if (cp_lexer_nth_token_is (lexer: parser->lexer, n: 2, |
49263 | type: CPP_CLOSE_PAREN)) |
49264 | cp_lexer_consume_token (lexer: parser->lexer); |
49265 | break; |
49266 | } |
49267 | } |
49268 | else |
49269 | cp_lexer_consume_token (lexer: parser->lexer); |
49270 | } |
49271 | |
49272 | if (!parens.require_close (parser)) |
49273 | cp_parser_skip_to_closing_parenthesis (parser, |
49274 | /*recovering=*/true, |
49275 | /*or_comma=*/false, |
49276 | /*consume_paren=*/ |
49277 | true); |
49278 | |
49279 | if (v == NULL) |
49280 | { |
49281 | if (message) |
49282 | { |
49283 | error_at (cloc, "too many %qs clauses" , p); |
49284 | bad = true; |
49285 | } |
49286 | else |
49287 | message = m; |
49288 | } |
49289 | else if (n != -1) |
49290 | { |
49291 | if (*v != -1) |
49292 | { |
49293 | error_at (cloc, "too many %qs clauses" , p); |
49294 | bad = true; |
49295 | } |
49296 | else |
49297 | *v = n; |
49298 | } |
49299 | } |
49300 | else |
49301 | bad = true; |
49302 | } |
49303 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49304 | if (bad) |
49305 | return true; |
49306 | |
49307 | if (at_compilation == -1) |
49308 | at_compilation = 1; |
49309 | if (severity_fatal == -1) |
49310 | severity_fatal = 1; |
49311 | if (!at_compilation) |
49312 | { |
49313 | if (context != pragma_compound) |
49314 | { |
49315 | error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause " |
49316 | "may only be used in compound statements" ); |
49317 | return true; |
49318 | } |
49319 | tree fndecl |
49320 | = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR |
49321 | : BUILT_IN_GOMP_WARNING); |
49322 | if (!message) |
49323 | message = build_zero_cst (const_string_type_node); |
49324 | tree stmt = build_call_expr_loc (loc, fndecl, 2, message, |
49325 | build_all_ones_cst (size_type_node)); |
49326 | add_stmt (stmt); |
49327 | return true; |
49328 | } |
49329 | |
49330 | if (in_discarded_stmt) |
49331 | return false; |
49332 | |
49333 | const char *msg = NULL; |
49334 | if (message) |
49335 | { |
49336 | msg = c_getstr (fold_for_warn (message)); |
49337 | if (msg == NULL) |
49338 | msg = _("<message unknown at compile time>" ); |
49339 | } |
49340 | if (msg) |
49341 | emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, |
49342 | "%<pragma omp error%> encountered: %s" , msg); |
49343 | else |
49344 | emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, |
49345 | "%<pragma omp error%> encountered" ); |
49346 | return false; |
49347 | } |
49348 | |
49349 | /* OpenMP 4.5: |
49350 | #pragma omp taskloop taskloop-clause[optseq] new-line |
49351 | for-loop |
49352 | |
49353 | #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line |
49354 | for-loop */ |
49355 | |
49356 | #define OMP_TASKLOOP_CLAUSE_MASK \ |
49357 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \ |
49358 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ |
49359 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ |
49360 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ |
49361 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \ |
49362 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \ |
49363 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \ |
49364 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ |
49365 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ |
49366 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ |
49367 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ |
49368 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ |
49369 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \ |
49370 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ |
49371 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ |
49372 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ |
49373 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION)) |
49374 | |
49375 | static tree |
49376 | cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok, |
49377 | char *p_name, omp_clause_mask mask, tree *cclauses, |
49378 | bool *if_p) |
49379 | { |
49380 | tree clauses, sb, ret; |
49381 | unsigned int save; |
49382 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49383 | |
49384 | strcat (dest: p_name, src: " taskloop" ); |
49385 | mask |= OMP_TASKLOOP_CLAUSE_MASK; |
49386 | /* #pragma omp parallel master taskloop{, simd} disallow in_reduction |
49387 | clause. */ |
49388 | if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) |
49389 | mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION); |
49390 | |
49391 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_NAME)) |
49392 | { |
49393 | tree id = cp_lexer_peek_token (lexer: parser->lexer)->u.value; |
49394 | const char *p = IDENTIFIER_POINTER (id); |
49395 | |
49396 | if (strcmp (s1: p, s2: "simd" ) == 0) |
49397 | { |
49398 | tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; |
49399 | if (cclauses == NULL) |
49400 | cclauses = cclauses_buf; |
49401 | |
49402 | cp_lexer_consume_token (lexer: parser->lexer); |
49403 | if (!flag_openmp) /* flag_openmp_simd */ |
49404 | return cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
49405 | cclauses, if_p); |
49406 | sb = begin_omp_structured_block (); |
49407 | save = cp_parser_begin_omp_structured_block (parser); |
49408 | ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, |
49409 | cclauses, if_p); |
49410 | cp_parser_end_omp_structured_block (parser, save); |
49411 | tree body = finish_omp_structured_block (sb); |
49412 | if (ret == NULL) |
49413 | return ret; |
49414 | ret = make_node (OMP_TASKLOOP); |
49415 | TREE_TYPE (ret) = void_type_node; |
49416 | OMP_FOR_BODY (ret) = body; |
49417 | OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; |
49418 | SET_EXPR_LOCATION (ret, loc); |
49419 | add_stmt (ret); |
49420 | return ret; |
49421 | } |
49422 | } |
49423 | if (!flag_openmp) /* flag_openmp_simd */ |
49424 | { |
49425 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49426 | return NULL_TREE; |
49427 | } |
49428 | |
49429 | clauses = cp_parser_omp_all_clauses (parser, mask, where: p_name, pragma_tok, |
49430 | finish_p: cclauses == NULL); |
49431 | if (cclauses) |
49432 | { |
49433 | cp_omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses); |
49434 | clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; |
49435 | } |
49436 | |
49437 | keep_next_level (true); |
49438 | sb = begin_omp_structured_block (); |
49439 | save = cp_parser_begin_omp_structured_block (parser); |
49440 | |
49441 | ret = cp_parser_omp_for_loop (parser, code: OMP_TASKLOOP, clauses, cclauses, |
49442 | if_p); |
49443 | |
49444 | cp_parser_end_omp_structured_block (parser, save); |
49445 | add_stmt (finish_omp_structured_block (sb)); |
49446 | |
49447 | return ret; |
49448 | } |
49449 | |
49450 | |
49451 | /* OpenACC 2.0: |
49452 | # pragma acc routine oacc-routine-clause[optseq] new-line |
49453 | function-definition |
49454 | |
49455 | # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line |
49456 | */ |
49457 | |
49458 | #define OACC_ROUTINE_CLAUSE_MASK \ |
49459 | ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \ |
49460 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \ |
49461 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \ |
49462 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \ |
49463 | | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) ) |
49464 | |
49465 | /* Parse the OpenACC routine pragma. This has an optional '( name )' |
49466 | component, which must resolve to a declared namespace-scope |
49467 | function. The clauses are either processed directly (for a named |
49468 | function), or defered until the immediatley following declaration |
49469 | is parsed. */ |
49470 | |
49471 | static void |
49472 | cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok, |
49473 | enum pragma_context context) |
49474 | { |
49475 | gcc_checking_assert (context == pragma_external); |
49476 | /* The checking for "another pragma following this one" in the "no optional |
49477 | '( name )'" case makes sure that we dont re-enter. */ |
49478 | gcc_checking_assert (parser->oacc_routine == NULL); |
49479 | |
49480 | cp_oacc_routine_data data; |
49481 | data.error_seen = false; |
49482 | data.fndecl_seen = false; |
49483 | data.tokens = vNULL; |
49484 | data.clauses = NULL_TREE; |
49485 | data.loc = pragma_tok->location; |
49486 | /* It is safe to take the address of a local variable; it will only be |
49487 | used while this scope is live. */ |
49488 | parser->oacc_routine = &data; |
49489 | |
49490 | /* Look for optional '( name )'. */ |
49491 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_OPEN_PAREN)) |
49492 | { |
49493 | matching_parens parens; |
49494 | parens.consume_open (parser); /* '(' */ |
49495 | |
49496 | /* We parse the name as an id-expression. If it resolves to |
49497 | anything other than a non-overloaded function at namespace |
49498 | scope, it's an error. */ |
49499 | location_t name_loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49500 | tree name = cp_parser_id_expression (parser, |
49501 | /*template_keyword_p=*/false, |
49502 | /*check_dependency_p=*/false, |
49503 | /*template_p=*/NULL, |
49504 | /*declarator_p=*/false, |
49505 | /*optional_p=*/false); |
49506 | tree decl = (identifier_p (t: name) |
49507 | ? cp_parser_lookup_name_simple (parser, name, location: name_loc) |
49508 | : name); |
49509 | if (name != error_mark_node && decl == error_mark_node) |
49510 | cp_parser_name_lookup_error (parser, name, decl, desired: NLE_NULL, location: name_loc); |
49511 | |
49512 | if (decl == error_mark_node |
49513 | || !parens.require_close (parser)) |
49514 | { |
49515 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
49516 | parser->oacc_routine = NULL; |
49517 | return; |
49518 | } |
49519 | |
49520 | data.clauses |
49521 | = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, |
49522 | where: "#pragma acc routine" , |
49523 | pragma_tok: cp_lexer_peek_token (lexer: parser->lexer)); |
49524 | /* The clauses are in reverse order; fix that to make later diagnostic |
49525 | emission easier. */ |
49526 | data.clauses = nreverse (data.clauses); |
49527 | |
49528 | if (decl && is_overloaded_fn (decl) |
49529 | && (TREE_CODE (decl) != FUNCTION_DECL |
49530 | || DECL_FUNCTION_TEMPLATE_P (decl))) |
49531 | { |
49532 | error_at (name_loc, |
49533 | "%<#pragma acc routine%> names a set of overloads" ); |
49534 | parser->oacc_routine = NULL; |
49535 | return; |
49536 | } |
49537 | |
49538 | /* Perhaps we should use the same rule as declarations in different |
49539 | namespaces? */ |
49540 | if (!DECL_NAMESPACE_SCOPE_P (decl)) |
49541 | { |
49542 | error_at (name_loc, |
49543 | "%qD does not refer to a namespace scope function" , decl); |
49544 | parser->oacc_routine = NULL; |
49545 | return; |
49546 | } |
49547 | |
49548 | if (TREE_CODE (decl) != FUNCTION_DECL) |
49549 | { |
49550 | error_at (name_loc, "%qD does not refer to a function" , decl); |
49551 | parser->oacc_routine = NULL; |
49552 | return; |
49553 | } |
49554 | |
49555 | cp_finalize_oacc_routine (parser, decl, false); |
49556 | parser->oacc_routine = NULL; |
49557 | } |
49558 | else /* No optional '( name )'. */ |
49559 | { |
49560 | /* Store away all pragma tokens. */ |
49561 | while (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_PRAGMA_EOL)) |
49562 | cp_lexer_consume_token (lexer: parser->lexer); |
49563 | cp_parser_require_pragma_eol (parser, pragma_tok); |
49564 | struct cp_token_cache *cp |
49565 | = cp_token_cache_new (first: pragma_tok, last: cp_lexer_peek_token (lexer: parser->lexer)); |
49566 | parser->oacc_routine->tokens.safe_push (obj: cp); |
49567 | |
49568 | /* Emit a helpful diagnostic if there's another pragma following this |
49569 | one. */ |
49570 | if (cp_lexer_next_token_is (lexer: parser->lexer, type: CPP_PRAGMA)) |
49571 | { |
49572 | cp_ensure_no_oacc_routine (parser); |
49573 | data.tokens.release (); |
49574 | /* ..., and then just keep going. */ |
49575 | return; |
49576 | } |
49577 | |
49578 | /* We only have to consider the pragma_external case here. */ |
49579 | cp_parser_declaration (parser, NULL_TREE); |
49580 | if (parser->oacc_routine |
49581 | && !parser->oacc_routine->fndecl_seen) |
49582 | cp_ensure_no_oacc_routine (parser); |
49583 | else |
49584 | parser->oacc_routine = NULL; |
49585 | data.tokens.release (); |
49586 | } |
49587 | } |
49588 | |
49589 | /* Finalize #pragma acc routine clauses after direct declarator has |
49590 | been parsed. */ |
49591 | |
49592 | static tree |
49593 | cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs) |
49594 | { |
49595 | struct cp_token_cache *ce; |
49596 | cp_oacc_routine_data *data = parser->oacc_routine; |
49597 | |
49598 | if (!data->error_seen && data->fndecl_seen) |
49599 | { |
49600 | error_at (data->loc, |
49601 | "%<#pragma acc routine%> not immediately followed by " |
49602 | "a single function declaration or definition" ); |
49603 | data->error_seen = true; |
49604 | } |
49605 | if (data->error_seen) |
49606 | return attrs; |
49607 | |
49608 | gcc_checking_assert (data->tokens.length () == 1); |
49609 | ce = data->tokens[0]; |
49610 | |
49611 | cp_parser_push_lexer_for_tokens (parser, cache: ce); |
49612 | parser->lexer->in_pragma = true; |
49613 | gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA); |
49614 | |
49615 | cp_token *pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
49616 | gcc_checking_assert (parser->oacc_routine->clauses == NULL_TREE); |
49617 | parser->oacc_routine->clauses |
49618 | = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, |
49619 | where: "#pragma acc routine" , pragma_tok); |
49620 | /* The clauses are in reverse order; fix that to make later diagnostic |
49621 | emission easier. */ |
49622 | parser->oacc_routine->clauses = nreverse (parser->oacc_routine->clauses); |
49623 | cp_parser_pop_lexer (parser); |
49624 | /* Later, cp_finalize_oacc_routine will process the clauses. */ |
49625 | parser->oacc_routine->fndecl_seen = true; |
49626 | |
49627 | return attrs; |
49628 | } |
49629 | |
49630 | /* Apply any saved OpenACC routine clauses to a just-parsed |
49631 | declaration. */ |
49632 | |
49633 | static void |
49634 | cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn) |
49635 | { |
49636 | if (UNLIKELY (parser->oacc_routine != NULL)) |
49637 | { |
49638 | /* Keep going if we're in error reporting mode. */ |
49639 | if (parser->oacc_routine->error_seen |
49640 | || fndecl == error_mark_node) |
49641 | return; |
49642 | |
49643 | if (TREE_CODE (fndecl) != FUNCTION_DECL) |
49644 | { |
49645 | if (parser->oacc_routine->fndecl_seen) |
49646 | { |
49647 | error_at (parser->oacc_routine->loc, |
49648 | "%<#pragma acc routine%> not immediately followed by" |
49649 | " a single function declaration or definition" ); |
49650 | parser->oacc_routine = NULL; |
49651 | return; |
49652 | } |
49653 | |
49654 | cp_ensure_no_oacc_routine (parser); |
49655 | return; |
49656 | } |
49657 | |
49658 | int compatible |
49659 | = oacc_verify_routine_clauses (fndecl, &parser->oacc_routine->clauses, |
49660 | parser->oacc_routine->loc, |
49661 | "#pragma acc routine" ); |
49662 | if (compatible < 0) |
49663 | { |
49664 | parser->oacc_routine = NULL; |
49665 | return; |
49666 | } |
49667 | if (compatible > 0) |
49668 | { |
49669 | } |
49670 | else |
49671 | { |
49672 | if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl))) |
49673 | { |
49674 | error_at (parser->oacc_routine->loc, |
49675 | TREE_USED (fndecl) |
49676 | ? G_("%<#pragma acc routine%> must be applied before" |
49677 | " use" ) |
49678 | : G_("%<#pragma acc routine%> must be applied before" |
49679 | " definition" )); |
49680 | parser->oacc_routine = NULL; |
49681 | return; |
49682 | } |
49683 | |
49684 | /* Set the routine's level of parallelism. */ |
49685 | tree dims = oacc_build_routine_dims (clauses: parser->oacc_routine->clauses); |
49686 | oacc_replace_fn_attrib (fn: fndecl, dims); |
49687 | |
49688 | /* Add an "omp declare target" attribute. */ |
49689 | DECL_ATTRIBUTES (fndecl) |
49690 | = tree_cons (get_identifier ("omp declare target" ), |
49691 | parser->oacc_routine->clauses, |
49692 | DECL_ATTRIBUTES (fndecl)); |
49693 | } |
49694 | } |
49695 | } |
49696 | |
49697 | /* Main entry point to OpenMP statement pragmas. */ |
49698 | |
49699 | static void |
49700 | cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) |
49701 | { |
49702 | tree stmt; |
49703 | char p_name[sizeof "#pragma omp teams distribute parallel for simd" ]; |
49704 | omp_clause_mask mask (0); |
49705 | |
49706 | switch (cp_parser_pragma_kind (token: pragma_tok)) |
49707 | { |
49708 | case PRAGMA_OACC_ATOMIC: |
49709 | cp_parser_omp_atomic (parser, pragma_tok, openacc: true); |
49710 | return; |
49711 | case PRAGMA_OACC_CACHE: |
49712 | stmt = cp_parser_oacc_cache (parser, pragma_tok); |
49713 | break; |
49714 | case PRAGMA_OACC_DATA: |
49715 | stmt = cp_parser_oacc_data (parser, pragma_tok, if_p); |
49716 | break; |
49717 | case PRAGMA_OACC_ENTER_DATA: |
49718 | stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, enter: true); |
49719 | break; |
49720 | case PRAGMA_OACC_EXIT_DATA: |
49721 | stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, enter: false); |
49722 | break; |
49723 | case PRAGMA_OACC_HOST_DATA: |
49724 | stmt = cp_parser_oacc_host_data (parser, pragma_tok, if_p); |
49725 | break; |
49726 | case PRAGMA_OACC_KERNELS: |
49727 | case PRAGMA_OACC_PARALLEL: |
49728 | case PRAGMA_OACC_SERIAL: |
49729 | strcpy (dest: p_name, src: "#pragma acc" ); |
49730 | stmt = cp_parser_oacc_compute (parser, pragma_tok, p_name, if_p); |
49731 | break; |
49732 | case PRAGMA_OACC_LOOP: |
49733 | strcpy (dest: p_name, src: "#pragma acc" ); |
49734 | stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL, |
49735 | if_p); |
49736 | break; |
49737 | case PRAGMA_OACC_UPDATE: |
49738 | stmt = cp_parser_oacc_update (parser, pragma_tok); |
49739 | break; |
49740 | case PRAGMA_OACC_WAIT: |
49741 | stmt = cp_parser_oacc_wait (parser, pragma_tok); |
49742 | break; |
49743 | case PRAGMA_OMP_ALLOCATE: |
49744 | cp_parser_omp_allocate (parser, pragma_tok); |
49745 | return; |
49746 | case PRAGMA_OMP_ATOMIC: |
49747 | cp_parser_omp_atomic (parser, pragma_tok, openacc: false); |
49748 | return; |
49749 | case PRAGMA_OMP_CRITICAL: |
49750 | stmt = cp_parser_omp_critical (parser, pragma_tok, if_p); |
49751 | break; |
49752 | case PRAGMA_OMP_DISTRIBUTE: |
49753 | strcpy (dest: p_name, src: "#pragma omp" ); |
49754 | stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL, |
49755 | if_p); |
49756 | break; |
49757 | case PRAGMA_OMP_FOR: |
49758 | strcpy (dest: p_name, src: "#pragma omp" ); |
49759 | stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL, |
49760 | if_p); |
49761 | break; |
49762 | case PRAGMA_OMP_LOOP: |
49763 | strcpy (dest: p_name, src: "#pragma omp" ); |
49764 | stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL, |
49765 | if_p); |
49766 | break; |
49767 | case PRAGMA_OMP_MASKED: |
49768 | strcpy (dest: p_name, src: "#pragma omp" ); |
49769 | stmt = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, NULL, |
49770 | if_p); |
49771 | break; |
49772 | case PRAGMA_OMP_MASTER: |
49773 | strcpy (dest: p_name, src: "#pragma omp" ); |
49774 | stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, |
49775 | if_p); |
49776 | break; |
49777 | case PRAGMA_OMP_PARALLEL: |
49778 | strcpy (dest: p_name, src: "#pragma omp" ); |
49779 | stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL, |
49780 | if_p); |
49781 | break; |
49782 | case PRAGMA_OMP_SCOPE: |
49783 | stmt = cp_parser_omp_scope (parser, pragma_tok, if_p); |
49784 | break; |
49785 | case PRAGMA_OMP_SECTIONS: |
49786 | strcpy (dest: p_name, src: "#pragma omp" ); |
49787 | stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL); |
49788 | break; |
49789 | case PRAGMA_OMP_SIMD: |
49790 | strcpy (dest: p_name, src: "#pragma omp" ); |
49791 | stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL, |
49792 | if_p); |
49793 | break; |
49794 | case PRAGMA_OMP_SINGLE: |
49795 | stmt = cp_parser_omp_single (parser, pragma_tok, if_p); |
49796 | break; |
49797 | case PRAGMA_OMP_TASK: |
49798 | stmt = cp_parser_omp_task (parser, pragma_tok, if_p); |
49799 | break; |
49800 | case PRAGMA_OMP_TASKGROUP: |
49801 | stmt = cp_parser_omp_taskgroup (parser, pragma_tok, if_p); |
49802 | break; |
49803 | case PRAGMA_OMP_TASKLOOP: |
49804 | strcpy (dest: p_name, src: "#pragma omp" ); |
49805 | stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL, |
49806 | if_p); |
49807 | break; |
49808 | case PRAGMA_OMP_TEAMS: |
49809 | strcpy (dest: p_name, src: "#pragma omp" ); |
49810 | stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL, |
49811 | if_p); |
49812 | break; |
49813 | case PRAGMA_OMP_ASSUME: |
49814 | cp_parser_omp_assume (parser, pragma_tok, if_p); |
49815 | return; |
49816 | default: |
49817 | gcc_unreachable (); |
49818 | } |
49819 | |
49820 | protected_set_expr_location (stmt, pragma_tok->location); |
49821 | } |
49822 | |
49823 | /* Transactional Memory parsing routines. */ |
49824 | |
49825 | /* Parse a transaction attribute. |
49826 | |
49827 | txn-attribute: |
49828 | attribute |
49829 | [ [ identifier ] ] |
49830 | |
49831 | We use this instead of cp_parser_attributes_opt for transactions to avoid |
49832 | the pedwarn in C++98 mode. */ |
49833 | |
49834 | static tree |
49835 | cp_parser_txn_attribute_opt (cp_parser *parser) |
49836 | { |
49837 | cp_token *token; |
49838 | tree attr_name, attr = NULL; |
49839 | |
49840 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_ATTRIBUTE)) |
49841 | return cp_parser_attributes_opt (parser); |
49842 | |
49843 | if (cp_lexer_next_token_is_not (lexer: parser->lexer, type: CPP_OPEN_SQUARE)) |
49844 | return NULL_TREE; |
49845 | cp_lexer_consume_token (lexer: parser->lexer); |
49846 | if (!cp_parser_require (parser, type: CPP_OPEN_SQUARE, token_desc: RT_OPEN_SQUARE)) |
49847 | goto error1; |
49848 | |
49849 | token = cp_lexer_peek_token (lexer: parser->lexer); |
49850 | if (token->type == CPP_NAME || token->type == CPP_KEYWORD) |
49851 | { |
49852 | token = cp_lexer_consume_token (lexer: parser->lexer); |
49853 | |
49854 | attr_name = (token->type == CPP_KEYWORD |
49855 | /* For keywords, use the canonical spelling, |
49856 | not the parsed identifier. */ |
49857 | ? ridpointers[(int) token->keyword] |
49858 | : token->u.value); |
49859 | attr = build_tree_list (attr_name, NULL_TREE); |
49860 | } |
49861 | else |
49862 | cp_parser_error (parser, gmsgid: "expected identifier" ); |
49863 | |
49864 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
49865 | error1: |
49866 | cp_parser_require (parser, type: CPP_CLOSE_SQUARE, token_desc: RT_CLOSE_SQUARE); |
49867 | return attr; |
49868 | } |
49869 | |
49870 | /* Parse a __transaction_atomic or __transaction_relaxed statement. |
49871 | |
49872 | transaction-statement: |
49873 | __transaction_atomic txn-attribute[opt] txn-noexcept-spec[opt] |
49874 | compound-statement |
49875 | __transaction_relaxed txn-noexcept-spec[opt] compound-statement |
49876 | */ |
49877 | |
49878 | static tree |
49879 | cp_parser_transaction (cp_parser *parser, cp_token *token) |
49880 | { |
49881 | unsigned char old_in = parser->in_transaction; |
49882 | unsigned char this_in = 1, new_in; |
49883 | enum rid keyword = token->keyword; |
49884 | tree stmt, attrs, noex; |
49885 | |
49886 | cp_lexer_consume_token (lexer: parser->lexer); |
49887 | |
49888 | if (keyword == RID_TRANSACTION_RELAXED |
49889 | || keyword == RID_SYNCHRONIZED) |
49890 | this_in |= TM_STMT_ATTR_RELAXED; |
49891 | else |
49892 | { |
49893 | attrs = cp_parser_txn_attribute_opt (parser); |
49894 | if (attrs) |
49895 | this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); |
49896 | } |
49897 | |
49898 | /* Parse a noexcept specification. */ |
49899 | if (keyword == RID_ATOMIC_NOEXCEPT) |
49900 | noex = boolean_true_node; |
49901 | else if (keyword == RID_ATOMIC_CANCEL) |
49902 | { |
49903 | /* cancel-and-throw is unimplemented. */ |
49904 | sorry ("%<atomic_cancel%>" ); |
49905 | noex = NULL_TREE; |
49906 | } |
49907 | else |
49908 | noex = cp_parser_noexcept_specification_opt (parser, |
49909 | flags: CP_PARSER_FLAGS_NONE, |
49910 | /*require_constexpr=*/true, |
49911 | /*consumed_expr=*/NULL, |
49912 | /*return_cond=*/true); |
49913 | |
49914 | /* Keep track if we're in the lexical scope of an outer transaction. */ |
49915 | new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); |
49916 | |
49917 | stmt = begin_transaction_stmt (token->location, NULL, this_in); |
49918 | |
49919 | parser->in_transaction = new_in; |
49920 | cp_parser_compound_statement (parser, NULL, bcs_flags: BCS_TRANSACTION, function_body: false); |
49921 | parser->in_transaction = old_in; |
49922 | |
49923 | finish_transaction_stmt (stmt, NULL, this_in, noex); |
49924 | |
49925 | return stmt; |
49926 | } |
49927 | |
49928 | /* Parse a __transaction_atomic or __transaction_relaxed expression. |
49929 | |
49930 | transaction-expression: |
49931 | __transaction_atomic txn-noexcept-spec[opt] ( expression ) |
49932 | __transaction_relaxed txn-noexcept-spec[opt] ( expression ) |
49933 | */ |
49934 | |
49935 | static tree |
49936 | cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) |
49937 | { |
49938 | unsigned char old_in = parser->in_transaction; |
49939 | unsigned char this_in = 1; |
49940 | cp_token *token; |
49941 | tree expr, noex; |
49942 | bool noex_expr; |
49943 | location_t loc = cp_lexer_peek_token (lexer: parser->lexer)->location; |
49944 | |
49945 | gcc_assert (keyword == RID_TRANSACTION_ATOMIC |
49946 | || keyword == RID_TRANSACTION_RELAXED); |
49947 | |
49948 | if (!flag_tm) |
49949 | error_at (loc, |
49950 | keyword == RID_TRANSACTION_RELAXED |
49951 | ? G_("%<__transaction_relaxed%> without transactional memory " |
49952 | "support enabled" ) |
49953 | : G_("%<__transaction_atomic%> without transactional memory " |
49954 | "support enabled" )); |
49955 | |
49956 | token = cp_parser_require_keyword (parser, keyword, |
49957 | token_desc: (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC |
49958 | : RT_TRANSACTION_RELAXED)); |
49959 | gcc_assert (token != NULL); |
49960 | |
49961 | if (keyword == RID_TRANSACTION_RELAXED) |
49962 | this_in |= TM_STMT_ATTR_RELAXED; |
49963 | |
49964 | /* Set this early. This might mean that we allow transaction_cancel in |
49965 | an expression that we find out later actually has to be a constexpr. |
49966 | However, we expect that cxx_constant_value will be able to deal with |
49967 | this; also, if the noexcept has no constexpr, then what we parse next |
49968 | really is a transaction's body. */ |
49969 | parser->in_transaction = this_in; |
49970 | |
49971 | /* Parse a noexcept specification. */ |
49972 | noex = cp_parser_noexcept_specification_opt (parser, |
49973 | flags: CP_PARSER_FLAGS_NONE, |
49974 | /*require_constexpr=*/false, |
49975 | consumed_expr: &noex_expr, |
49976 | /*return_cond=*/true); |
49977 | |
49978 | if (!noex || !noex_expr |
49979 | || cp_lexer_peek_token (lexer: parser->lexer)->type == CPP_OPEN_PAREN) |
49980 | { |
49981 | matching_parens parens; |
49982 | parens.require_open (parser); |
49983 | |
49984 | expr = cp_parser_expression (parser); |
49985 | expr = finish_parenthesized_expr (expr); |
49986 | |
49987 | parens.require_close (parser); |
49988 | } |
49989 | else |
49990 | { |
49991 | /* The only expression that is available got parsed for the noexcept |
49992 | already. noexcept is true then. */ |
49993 | expr = noex; |
49994 | noex = boolean_true_node; |
49995 | } |
49996 | |
49997 | expr = build_transaction_expr (token->location, expr, this_in, noex); |
49998 | parser->in_transaction = old_in; |
49999 | |
50000 | if (cp_parser_non_integral_constant_expression (parser, thing: NIC_TRANSACTION)) |
50001 | return error_mark_node; |
50002 | |
50003 | return (flag_tm ? expr : error_mark_node); |
50004 | } |
50005 | |
50006 | /* Parse a function-transaction-block. |
50007 | |
50008 | function-transaction-block: |
50009 | __transaction_atomic txn-attribute[opt] ctor-initializer[opt] |
50010 | function-body |
50011 | __transaction_atomic txn-attribute[opt] function-try-block |
50012 | __transaction_relaxed ctor-initializer[opt] function-body |
50013 | __transaction_relaxed function-try-block |
50014 | */ |
50015 | |
50016 | static void |
50017 | cp_parser_function_transaction (cp_parser *parser, enum rid keyword) |
50018 | { |
50019 | unsigned char old_in = parser->in_transaction; |
50020 | unsigned char new_in = 1; |
50021 | tree compound_stmt, stmt, attrs; |
50022 | cp_token *token; |
50023 | |
50024 | gcc_assert (keyword == RID_TRANSACTION_ATOMIC |
50025 | || keyword == RID_TRANSACTION_RELAXED); |
50026 | token = cp_parser_require_keyword (parser, keyword, |
50027 | token_desc: (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC |
50028 | : RT_TRANSACTION_RELAXED)); |
50029 | gcc_assert (token != NULL); |
50030 | |
50031 | if (keyword == RID_TRANSACTION_RELAXED) |
50032 | new_in |= TM_STMT_ATTR_RELAXED; |
50033 | else |
50034 | { |
50035 | attrs = cp_parser_txn_attribute_opt (parser); |
50036 | if (attrs) |
50037 | new_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); |
50038 | } |
50039 | |
50040 | stmt = begin_transaction_stmt (token->location, &compound_stmt, new_in); |
50041 | |
50042 | parser->in_transaction = new_in; |
50043 | |
50044 | if (cp_lexer_next_token_is_keyword (lexer: parser->lexer, keyword: RID_TRY)) |
50045 | cp_parser_function_try_block (parser); |
50046 | else |
50047 | cp_parser_ctor_initializer_opt_and_function_body |
50048 | (parser, /*in_function_try_block=*/false); |
50049 | |
50050 | parser->in_transaction = old_in; |
50051 | |
50052 | finish_transaction_stmt (stmt, compound_stmt, new_in, NULL_TREE); |
50053 | } |
50054 | |
50055 | /* Parse a __transaction_cancel statement. |
50056 | |
50057 | cancel-statement: |
50058 | __transaction_cancel txn-attribute[opt] ; |
50059 | __transaction_cancel txn-attribute[opt] throw-expression ; |
50060 | |
50061 | ??? Cancel and throw is not yet implemented. */ |
50062 | |
50063 | static tree |
50064 | cp_parser_transaction_cancel (cp_parser *parser) |
50065 | { |
50066 | cp_token *token; |
50067 | bool is_outer = false; |
50068 | tree stmt, attrs; |
50069 | |
50070 | token = cp_parser_require_keyword (parser, keyword: RID_TRANSACTION_CANCEL, |
50071 | token_desc: RT_TRANSACTION_CANCEL); |
50072 | gcc_assert (token != NULL); |
50073 | |
50074 | attrs = cp_parser_txn_attribute_opt (parser); |
50075 | if (attrs) |
50076 | is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0); |
50077 | |
50078 | /* ??? Parse cancel-and-throw here. */ |
50079 | |
50080 | cp_parser_require (parser, type: CPP_SEMICOLON, token_desc: RT_SEMICOLON); |
50081 | |
50082 | if (!flag_tm) |
50083 | { |
50084 | error_at (token->location, "%<__transaction_cancel%> without " |
50085 | "transactional memory support enabled" ); |
50086 | return error_mark_node; |
50087 | } |
50088 | else if (parser->in_transaction & TM_STMT_ATTR_RELAXED) |
50089 | { |
50090 | error_at (token->location, "%<__transaction_cancel%> within a " |
50091 | "%<__transaction_relaxed%>" ); |
50092 | return error_mark_node; |
50093 | } |
50094 | else if (is_outer) |
50095 | { |
50096 | if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0 |
50097 | && !is_tm_may_cancel_outer (current_function_decl)) |
50098 | { |
50099 | error_at (token->location, "outer %<__transaction_cancel%> not " |
50100 | "within outer %<__transaction_atomic%>" ); |
50101 | error_at (token->location, |
50102 | " or a %<transaction_may_cancel_outer%> function" ); |
50103 | return error_mark_node; |
50104 | } |
50105 | } |
50106 | else if (parser->in_transaction == 0) |
50107 | { |
50108 | error_at (token->location, "%<__transaction_cancel%> not within " |
50109 | "%<__transaction_atomic%>" ); |
50110 | return error_mark_node; |
50111 | } |
50112 | |
50113 | stmt = build_tm_abort_call (token->location, is_outer); |
50114 | add_stmt (stmt); |
50115 | |
50116 | return stmt; |
50117 | } |
50118 | |
50119 | |
50120 | /* Special handling for the first token or line in the file. The first |
50121 | thing in the file might be #pragma GCC pch_preprocess, which loads a |
50122 | PCH file, which is a GC collection point. So we need to handle this |
50123 | first pragma without benefit of an existing lexer structure. |
50124 | |
50125 | Always returns one token to the caller in *FIRST_TOKEN. This is |
50126 | either the true first token of the file, or the first token after |
50127 | the initial pragma. */ |
50128 | |
50129 | static void |
50130 | cp_parser_initial_pragma (cp_token *first_token) |
50131 | { |
50132 | if (cp_parser_pragma_kind (token: first_token) != PRAGMA_GCC_PCH_PREPROCESS) |
50133 | return; |
50134 | |
50135 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50136 | |
50137 | tree name = NULL; |
50138 | if (first_token->type == CPP_STRING) |
50139 | { |
50140 | name = first_token->u.value; |
50141 | |
50142 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50143 | } |
50144 | |
50145 | /* Skip to the end of the pragma. */ |
50146 | if (first_token->type != CPP_PRAGMA_EOL) |
50147 | { |
50148 | error_at (first_token->location, |
50149 | "malformed %<#pragma GCC pch_preprocess%>" ); |
50150 | do |
50151 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50152 | while (first_token->type != CPP_PRAGMA_EOL); |
50153 | } |
50154 | |
50155 | /* Now actually load the PCH file. */ |
50156 | if (name) |
50157 | c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name)); |
50158 | |
50159 | /* Read one more token to return to our caller. We have to do this |
50160 | after reading the PCH file in, since its pointers have to be |
50161 | live. */ |
50162 | cp_lexer_get_preprocessor_token (flags: 0, token: first_token); |
50163 | } |
50164 | |
50165 | /* Parse a pragma GCC ivdep. */ |
50166 | |
50167 | static bool |
50168 | cp_parser_pragma_ivdep (cp_parser *parser, cp_token *pragma_tok) |
50169 | { |
50170 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50171 | return true; |
50172 | } |
50173 | |
50174 | /* Parse a pragma GCC unroll. */ |
50175 | |
50176 | static unsigned short |
50177 | cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok) |
50178 | { |
50179 | location_t location = cp_lexer_peek_token (lexer: parser->lexer)->location; |
50180 | tree expr = cp_parser_constant_expression (parser); |
50181 | unsigned short unroll; |
50182 | expr = maybe_constant_value (expr); |
50183 | HOST_WIDE_INT lunroll = 0; |
50184 | if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) |
50185 | || TREE_CODE (expr) != INTEGER_CST |
50186 | || (lunroll = tree_to_shwi (expr)) < 0 |
50187 | || lunroll >= USHRT_MAX) |
50188 | { |
50189 | error_at (location, "%<#pragma GCC unroll%> requires an" |
50190 | " assignment-expression that evaluates to a non-negative" |
50191 | " integral constant less than %u" , USHRT_MAX); |
50192 | unroll = 0; |
50193 | } |
50194 | else |
50195 | { |
50196 | unroll = (unsigned short)lunroll; |
50197 | if (unroll == 0) |
50198 | unroll = 1; |
50199 | } |
50200 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50201 | return unroll; |
50202 | } |
50203 | |
50204 | /* Parse a pragma GCC novector. */ |
50205 | |
50206 | static bool |
50207 | cp_parser_pragma_novector (cp_parser *parser, cp_token *pragma_tok) |
50208 | { |
50209 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50210 | return true; |
50211 | } |
50212 | |
50213 | /* Normal parsing of a pragma token. Here we can (and must) use the |
50214 | regular lexer. */ |
50215 | |
50216 | static bool |
50217 | cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) |
50218 | { |
50219 | cp_token *pragma_tok; |
50220 | unsigned int id; |
50221 | tree stmt; |
50222 | bool ret = false; |
50223 | |
50224 | pragma_tok = cp_lexer_consume_token (lexer: parser->lexer); |
50225 | gcc_assert (pragma_tok->type == CPP_PRAGMA); |
50226 | parser->lexer->in_pragma = true; |
50227 | |
50228 | id = cp_parser_pragma_kind (token: pragma_tok); |
50229 | if (parser->omp_for_parse_state |
50230 | && parser->omp_for_parse_state->in_intervening_code |
50231 | && id >= PRAGMA_OMP__START_ |
50232 | && id <= PRAGMA_OMP__LAST_) |
50233 | { |
50234 | error_at (pragma_tok->location, |
50235 | "intervening code must not contain OpenMP directives" ); |
50236 | parser->omp_for_parse_state->fail = true; |
50237 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50238 | return false; |
50239 | } |
50240 | if (id != PRAGMA_OMP_DECLARE && id != PRAGMA_OACC_ROUTINE) |
50241 | cp_ensure_no_omp_declare_simd (parser); |
50242 | switch (id) |
50243 | { |
50244 | case PRAGMA_GCC_PCH_PREPROCESS: |
50245 | error_at (pragma_tok->location, |
50246 | "%<#pragma GCC pch_preprocess%> must be first" ); |
50247 | break; |
50248 | |
50249 | case PRAGMA_OMP_BARRIER: |
50250 | switch (context) |
50251 | { |
50252 | case pragma_compound: |
50253 | cp_parser_omp_barrier (parser, pragma_tok); |
50254 | return false; |
50255 | case pragma_stmt: |
50256 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50257 | "used in compound statements" , "omp barrier" ); |
50258 | ret = true; |
50259 | break; |
50260 | default: |
50261 | goto bad_stmt; |
50262 | } |
50263 | break; |
50264 | |
50265 | case PRAGMA_OMP_DEPOBJ: |
50266 | switch (context) |
50267 | { |
50268 | case pragma_compound: |
50269 | cp_parser_omp_depobj (parser, pragma_tok); |
50270 | return false; |
50271 | case pragma_stmt: |
50272 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50273 | "used in compound statements" , "omp depobj" ); |
50274 | ret = true; |
50275 | break; |
50276 | default: |
50277 | goto bad_stmt; |
50278 | } |
50279 | break; |
50280 | |
50281 | case PRAGMA_OMP_FLUSH: |
50282 | switch (context) |
50283 | { |
50284 | case pragma_compound: |
50285 | cp_parser_omp_flush (parser, pragma_tok); |
50286 | return false; |
50287 | case pragma_stmt: |
50288 | error_at (pragma_tok->location, "%<#pragma %s%> may only be " |
50289 | "used in compound statements" , "omp flush" ); |
50290 | ret = true; |
50291 | break; |
50292 | default: |
50293 | goto bad_stmt; |
50294 | } |
50295 | break; |
50296 | |
50297 | case PRAGMA_OMP_TASKWAIT: |
50298 | switch (context) |
50299 | { |
50300 | case pragma_compound: |
50301 | cp_parser_omp_taskwait (parser, pragma_tok); |
50302 | return false; |
50303 | case pragma_stmt: |
50304 | error_at (pragma_tok->location, |
50305 | "%<#pragma %s%> may only be used in compound statements" , |
50306 | "omp taskwait" ); |
50307 | ret = true; |
50308 | break; |
50309 | default: |
50310 | goto bad_stmt; |
50311 | } |
50312 | break; |
50313 | |
50314 | case PRAGMA_OMP_TASKYIELD: |
50315 | switch (context) |
50316 | { |
50317 | case pragma_compound: |
50318 | cp_parser_omp_taskyield (parser, pragma_tok); |
50319 | return false; |
50320 | case pragma_stmt: |
50321 | error_at (pragma_tok->location, |
50322 | "%<#pragma %s%> may only be used in compound statements" , |
50323 | "omp taskyield" ); |
50324 | ret = true; |
50325 | break; |
50326 | default: |
50327 | goto bad_stmt; |
50328 | } |
50329 | break; |
50330 | |
50331 | case PRAGMA_OMP_CANCEL: |
50332 | switch (context) |
50333 | { |
50334 | case pragma_compound: |
50335 | cp_parser_omp_cancel (parser, pragma_tok); |
50336 | return false; |
50337 | case pragma_stmt: |
50338 | error_at (pragma_tok->location, |
50339 | "%<#pragma %s%> may only be used in compound statements" , |
50340 | "omp cancel" ); |
50341 | ret = true; |
50342 | break; |
50343 | default: |
50344 | goto bad_stmt; |
50345 | } |
50346 | break; |
50347 | |
50348 | case PRAGMA_OMP_CANCELLATION_POINT: |
50349 | return cp_parser_omp_cancellation_point (parser, pragma_tok, context); |
50350 | |
50351 | case PRAGMA_OMP_THREADPRIVATE: |
50352 | cp_parser_omp_threadprivate (parser, pragma_tok); |
50353 | return false; |
50354 | |
50355 | case PRAGMA_OMP_DECLARE: |
50356 | return cp_parser_omp_declare (parser, pragma_tok, context); |
50357 | |
50358 | case PRAGMA_OACC_DECLARE: |
50359 | cp_parser_oacc_declare (parser, pragma_tok); |
50360 | return false; |
50361 | |
50362 | case PRAGMA_OACC_ENTER_DATA: |
50363 | if (context == pragma_stmt) |
50364 | { |
50365 | error_at (pragma_tok->location, |
50366 | "%<#pragma %s%> may only be used in compound statements" , |
50367 | "acc enter data" ); |
50368 | ret = true; |
50369 | break; |
50370 | } |
50371 | else if (context != pragma_compound) |
50372 | goto bad_stmt; |
50373 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50374 | return true; |
50375 | |
50376 | case PRAGMA_OACC_EXIT_DATA: |
50377 | if (context == pragma_stmt) |
50378 | { |
50379 | error_at (pragma_tok->location, |
50380 | "%<#pragma %s%> may only be used in compound statements" , |
50381 | "acc exit data" ); |
50382 | ret = true; |
50383 | break; |
50384 | } |
50385 | else if (context != pragma_compound) |
50386 | goto bad_stmt; |
50387 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50388 | return true; |
50389 | |
50390 | case PRAGMA_OACC_ROUTINE: |
50391 | if (context != pragma_external) |
50392 | { |
50393 | error_at (pragma_tok->location, |
50394 | "%<#pragma acc routine%> must be at file scope" ); |
50395 | ret = true; |
50396 | break; |
50397 | } |
50398 | cp_parser_oacc_routine (parser, pragma_tok, context); |
50399 | return false; |
50400 | |
50401 | case PRAGMA_OACC_UPDATE: |
50402 | if (context == pragma_stmt) |
50403 | { |
50404 | error_at (pragma_tok->location, |
50405 | "%<#pragma %s%> may only be used in compound statements" , |
50406 | "acc update" ); |
50407 | ret = true; |
50408 | break; |
50409 | } |
50410 | else if (context != pragma_compound) |
50411 | goto bad_stmt; |
50412 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50413 | return true; |
50414 | |
50415 | case PRAGMA_OACC_WAIT: |
50416 | if (context == pragma_stmt) |
50417 | { |
50418 | error_at (pragma_tok->location, |
50419 | "%<#pragma %s%> may only be used in compound statements" , |
50420 | "acc wait" ); |
50421 | ret = true; |
50422 | break; |
50423 | } |
50424 | else if (context != pragma_compound) |
50425 | goto bad_stmt; |
50426 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50427 | return true; |
50428 | case PRAGMA_OMP_ALLOCATE: |
50429 | cp_parser_omp_allocate (parser, pragma_tok); |
50430 | return false; |
50431 | case PRAGMA_OACC_ATOMIC: |
50432 | case PRAGMA_OACC_CACHE: |
50433 | case PRAGMA_OACC_DATA: |
50434 | case PRAGMA_OACC_HOST_DATA: |
50435 | case PRAGMA_OACC_KERNELS: |
50436 | case PRAGMA_OACC_LOOP: |
50437 | case PRAGMA_OACC_PARALLEL: |
50438 | case PRAGMA_OACC_SERIAL: |
50439 | case PRAGMA_OMP_ASSUME: |
50440 | case PRAGMA_OMP_ATOMIC: |
50441 | case PRAGMA_OMP_CRITICAL: |
50442 | case PRAGMA_OMP_DISTRIBUTE: |
50443 | case PRAGMA_OMP_FOR: |
50444 | case PRAGMA_OMP_LOOP: |
50445 | case PRAGMA_OMP_MASKED: |
50446 | case PRAGMA_OMP_MASTER: |
50447 | case PRAGMA_OMP_PARALLEL: |
50448 | case PRAGMA_OMP_SCOPE: |
50449 | case PRAGMA_OMP_SECTIONS: |
50450 | case PRAGMA_OMP_SIMD: |
50451 | case PRAGMA_OMP_SINGLE: |
50452 | case PRAGMA_OMP_TASK: |
50453 | case PRAGMA_OMP_TASKGROUP: |
50454 | case PRAGMA_OMP_TASKLOOP: |
50455 | case PRAGMA_OMP_TEAMS: |
50456 | if (context != pragma_stmt && context != pragma_compound) |
50457 | goto bad_stmt; |
50458 | stmt = push_omp_privatization_clauses (false); |
50459 | cp_parser_omp_construct (parser, pragma_tok, if_p); |
50460 | pop_omp_privatization_clauses (stmt); |
50461 | return true; |
50462 | |
50463 | case PRAGMA_OMP_REQUIRES: |
50464 | if (context != pragma_external) |
50465 | { |
50466 | error_at (pragma_tok->location, |
50467 | "%<#pragma omp requires%> may only be used at file or " |
50468 | "namespace scope" ); |
50469 | ret = true; |
50470 | break; |
50471 | } |
50472 | return cp_parser_omp_requires (parser, pragma_tok); |
50473 | |
50474 | case PRAGMA_OMP_ASSUMES: |
50475 | if (context != pragma_external) |
50476 | { |
50477 | error_at (pragma_tok->location, |
50478 | "%<#pragma omp assumes%> may only be used at file or " |
50479 | "namespace scope" ); |
50480 | ret = true; |
50481 | break; |
50482 | } |
50483 | return cp_parser_omp_assumes (parser, pragma_tok); |
50484 | |
50485 | case PRAGMA_OMP_NOTHING: |
50486 | cp_parser_omp_nothing (parser, pragma_tok); |
50487 | return false; |
50488 | |
50489 | case PRAGMA_OMP_ERROR: |
50490 | return cp_parser_omp_error (parser, pragma_tok, context); |
50491 | |
50492 | case PRAGMA_OMP_ORDERED: |
50493 | if (context != pragma_stmt && context != pragma_compound) |
50494 | goto bad_stmt; |
50495 | stmt = push_omp_privatization_clauses (false); |
50496 | ret = cp_parser_omp_ordered (parser, pragma_tok, context, if_p); |
50497 | pop_omp_privatization_clauses (stmt); |
50498 | return ret; |
50499 | |
50500 | case PRAGMA_OMP_TARGET: |
50501 | if (context != pragma_stmt && context != pragma_compound) |
50502 | goto bad_stmt; |
50503 | stmt = push_omp_privatization_clauses (false); |
50504 | ret = cp_parser_omp_target (parser, pragma_tok, context, if_p); |
50505 | pop_omp_privatization_clauses (stmt); |
50506 | return ret; |
50507 | |
50508 | case PRAGMA_OMP_BEGIN: |
50509 | cp_parser_omp_begin (parser, pragma_tok); |
50510 | return false; |
50511 | |
50512 | case PRAGMA_OMP_END: |
50513 | cp_parser_omp_end (parser, pragma_tok); |
50514 | return false; |
50515 | |
50516 | case PRAGMA_OMP_SCAN: |
50517 | error_at (pragma_tok->location, |
50518 | "%<#pragma omp scan%> may only be used in " |
50519 | "a loop construct with %<inscan%> %<reduction%> clause" ); |
50520 | break; |
50521 | |
50522 | case PRAGMA_OMP_SECTION: |
50523 | error_at (pragma_tok->location, |
50524 | "%<#pragma omp section%> may only be used in " |
50525 | "%<#pragma omp sections%> construct" ); |
50526 | break; |
50527 | |
50528 | case PRAGMA_IVDEP: |
50529 | case PRAGMA_UNROLL: |
50530 | case PRAGMA_NOVECTOR: |
50531 | { |
50532 | bool ivdep; |
50533 | unsigned short unroll = 0; |
50534 | bool novector = false; |
50535 | const char *pragma_str; |
50536 | |
50537 | switch (id) |
50538 | { |
50539 | case PRAGMA_IVDEP: |
50540 | pragma_str = "ivdep" ; |
50541 | break; |
50542 | case PRAGMA_UNROLL: |
50543 | pragma_str = "unroll" ; |
50544 | break; |
50545 | case PRAGMA_NOVECTOR: |
50546 | pragma_str = "novector" ; |
50547 | break; |
50548 | default: |
50549 | gcc_unreachable (); |
50550 | } |
50551 | |
50552 | if (context == pragma_external) |
50553 | { |
50554 | error_at (pragma_tok->location, |
50555 | "%<#pragma GCC %s%> must be inside a function" , |
50556 | pragma_str); |
50557 | break; |
50558 | } |
50559 | |
50560 | cp_token *tok = pragma_tok; |
50561 | bool has_more = true; |
50562 | do |
50563 | { |
50564 | switch (cp_parser_pragma_kind (token: tok)) |
50565 | { |
50566 | case PRAGMA_IVDEP: |
50567 | { |
50568 | if (tok != pragma_tok) |
50569 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
50570 | ivdep = cp_parser_pragma_ivdep (parser, pragma_tok: tok); |
50571 | break; |
50572 | } |
50573 | case PRAGMA_UNROLL: |
50574 | { |
50575 | if (tok != pragma_tok) |
50576 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
50577 | unroll = cp_parser_pragma_unroll (parser, pragma_tok: tok); |
50578 | break; |
50579 | } |
50580 | case PRAGMA_NOVECTOR: |
50581 | { |
50582 | if (tok != pragma_tok) |
50583 | tok = cp_lexer_consume_token (lexer: parser->lexer); |
50584 | novector = cp_parser_pragma_novector (parser, pragma_tok: tok); |
50585 | break; |
50586 | } |
50587 | default: |
50588 | has_more = false; |
50589 | break; |
50590 | } |
50591 | tok = cp_lexer_peek_token (lexer: the_parser->lexer); |
50592 | has_more = has_more && tok->type == CPP_PRAGMA; |
50593 | } |
50594 | while (has_more); |
50595 | |
50596 | if (tok->type != CPP_KEYWORD |
50597 | || (tok->keyword != RID_FOR |
50598 | && tok->keyword != RID_WHILE |
50599 | && tok->keyword != RID_DO)) |
50600 | { |
50601 | cp_parser_error (parser, gmsgid: "for, while or do statement expected" ); |
50602 | return false; |
50603 | } |
50604 | cp_parser_iteration_statement (parser, if_p, ivdep, unroll, novector); |
50605 | return true; |
50606 | } |
50607 | |
50608 | default: |
50609 | gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); |
50610 | c_invoke_pragma_handler (id); |
50611 | break; |
50612 | |
50613 | bad_stmt: |
50614 | cp_parser_error (parser, gmsgid: "expected declaration specifiers" ); |
50615 | break; |
50616 | } |
50617 | |
50618 | cp_parser_skip_to_pragma_eol (parser, pragma_tok); |
50619 | return ret; |
50620 | } |
50621 | |
50622 | /* Helper for pragma_lex in preprocess-only mode; in this mode, we have not |
50623 | populated the lexer with any tokens (the tokens rather being read by |
50624 | c-ppoutput.c's machinery), so we need to read enough tokens now to handle |
50625 | a pragma. */ |
50626 | static void |
50627 | maybe_read_tokens_for_pragma_lex () |
50628 | { |
50629 | const auto lexer = the_parser->lexer; |
50630 | if (!lexer->buffer->is_empty ()) |
50631 | return; |
50632 | |
50633 | /* Read the rest of the tokens comprising the pragma line. */ |
50634 | cp_token *tok; |
50635 | do |
50636 | { |
50637 | tok = vec_safe_push (v&: lexer->buffer, obj: cp_token ()); |
50638 | cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, token: tok); |
50639 | gcc_assert (tok->type != CPP_EOF); |
50640 | } while (tok->type != CPP_PRAGMA_EOL); |
50641 | lexer->next_token = lexer->buffer->address (); |
50642 | lexer->last_token = lexer->next_token + lexer->buffer->length () - 1; |
50643 | } |
50644 | |
50645 | /* The interface the pragma parsers have to the lexer. */ |
50646 | |
50647 | enum cpp_ttype |
50648 | pragma_lex (tree *value, location_t *loc) |
50649 | { |
50650 | if (flag_preprocess_only) |
50651 | maybe_read_tokens_for_pragma_lex (); |
50652 | |
50653 | cp_token *tok = cp_lexer_peek_token (lexer: the_parser->lexer); |
50654 | enum cpp_ttype ret = tok->type; |
50655 | |
50656 | *value = tok->u.value; |
50657 | if (loc) |
50658 | *loc = tok->location; |
50659 | |
50660 | if (ret == CPP_PRAGMA_EOL) |
50661 | ret = CPP_EOF; |
50662 | else if (ret == CPP_STRING) |
50663 | *value = cp_parser_string_literal (parser: the_parser, /*translate=*/false, |
50664 | /*wide_ok=*/false); |
50665 | else |
50666 | { |
50667 | if (ret == CPP_KEYWORD) |
50668 | ret = CPP_NAME; |
50669 | cp_lexer_consume_token (lexer: the_parser->lexer); |
50670 | } |
50671 | |
50672 | return ret; |
50673 | } |
50674 | |
50675 | void |
50676 | pragma_lex_discard_to_eol () |
50677 | { |
50678 | /* We have already read all the tokens, so we just need to discard |
50679 | them here. */ |
50680 | const auto lexer = the_parser->lexer; |
50681 | lexer->next_token = lexer->last_token; |
50682 | lexer->buffer->truncate (size: 0); |
50683 | } |
50684 | |
50685 | |
50686 | /* External interface. */ |
50687 | |
50688 | /* Parse one entire translation unit. */ |
50689 | |
50690 | void |
50691 | c_parse_file (void) |
50692 | { |
50693 | static bool already_called = false; |
50694 | |
50695 | if (already_called) |
50696 | fatal_error (input_location, |
50697 | "multi-source compilation not implemented for C++" ); |
50698 | already_called = true; |
50699 | |
50700 | /* cp_lexer_new_main is called before doing any GC allocation |
50701 | because tokenization might load a PCH file. */ |
50702 | cp_lexer_new_main (); |
50703 | |
50704 | cp_parser_translation_unit (parser: the_parser); |
50705 | class_decl_loc_t::diag_mismatched_tags (); |
50706 | |
50707 | the_parser = NULL; |
50708 | |
50709 | finish_translation_unit (); |
50710 | } |
50711 | |
50712 | /* Create an identifier for a generic parameter type (a synthesized |
50713 | template parameter implied by `auto' or a concept identifier). */ |
50714 | |
50715 | static GTY(()) int generic_parm_count; |
50716 | static tree |
50717 | make_generic_type_name () |
50718 | { |
50719 | char buf[32]; |
50720 | sprintf (s: buf, format: "auto:%d" , ++generic_parm_count); |
50721 | return get_identifier (buf); |
50722 | } |
50723 | |
50724 | /* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS |
50725 | (creating a new template parameter list if necessary). Returns the newly |
50726 | created template type parm. */ |
50727 | |
50728 | static tree |
50729 | synthesize_implicit_template_parm (cp_parser *parser, tree constr) |
50730 | { |
50731 | /* A requires-clause is not a function and cannot have placeholders. */ |
50732 | if (current_binding_level->requires_expression) |
50733 | { |
50734 | error ("placeholder type not allowed in this context" ); |
50735 | return error_mark_node; |
50736 | } |
50737 | |
50738 | gcc_assert (current_binding_level->kind == sk_function_parms); |
50739 | |
50740 | /* We are either continuing a function template that already contains implicit |
50741 | template parameters, creating a new fully-implicit function template, or |
50742 | extending an existing explicit function template with implicit template |
50743 | parameters. */ |
50744 | |
50745 | cp_binding_level *const entry_scope = current_binding_level; |
50746 | |
50747 | bool become_template = false; |
50748 | cp_binding_level *parent_scope = 0; |
50749 | |
50750 | if (parser->implicit_template_scope) |
50751 | { |
50752 | gcc_assert (parser->implicit_template_parms); |
50753 | |
50754 | current_binding_level = parser->implicit_template_scope; |
50755 | } |
50756 | else |
50757 | { |
50758 | /* Roll back to the existing template parameter scope (in the case of |
50759 | extending an explicit function template) or introduce a new template |
50760 | parameter scope ahead of the function parameter scope (or class scope |
50761 | in the case of out-of-line member definitions). The function scope is |
50762 | added back after template parameter synthesis below. */ |
50763 | |
50764 | cp_binding_level *scope = entry_scope; |
50765 | |
50766 | while (scope->kind == sk_function_parms) |
50767 | { |
50768 | parent_scope = scope; |
50769 | scope = scope->level_chain; |
50770 | } |
50771 | if (current_class_type && !LAMBDA_TYPE_P (current_class_type)) |
50772 | { |
50773 | /* If not defining a class, then any class scope is a scope level in |
50774 | an out-of-line member definition. In this case simply wind back |
50775 | beyond the first such scope to inject the template parameter list. |
50776 | Otherwise wind back to the class being defined. The latter can |
50777 | occur in class member friend declarations such as: |
50778 | |
50779 | class A { |
50780 | void foo (auto); |
50781 | }; |
50782 | class B { |
50783 | friend void A::foo (auto); |
50784 | }; |
50785 | |
50786 | The template parameter list synthesized for the friend declaration |
50787 | must be injected in the scope of 'B'. This can also occur in |
50788 | erroneous cases such as: |
50789 | |
50790 | struct A { |
50791 | struct B { |
50792 | void foo (auto); |
50793 | }; |
50794 | void B::foo (auto) {} |
50795 | }; |
50796 | |
50797 | Here the attempted definition of 'B::foo' within 'A' is ill-formed |
50798 | but, nevertheless, the template parameter list synthesized for the |
50799 | declarator should be injected into the scope of 'A' as if the |
50800 | ill-formed template was specified explicitly. */ |
50801 | |
50802 | while (scope->kind == sk_class && !scope->defining_class_p) |
50803 | { |
50804 | parent_scope = scope; |
50805 | scope = scope->level_chain; |
50806 | } |
50807 | } |
50808 | |
50809 | current_binding_level = scope; |
50810 | |
50811 | if (scope->kind != sk_template_parms |
50812 | || !function_being_declared_is_template_p (parser)) |
50813 | { |
50814 | /* Introduce a new template parameter list for implicit template |
50815 | parameters. */ |
50816 | |
50817 | become_template = true; |
50818 | |
50819 | parser->implicit_template_scope |
50820 | = begin_scope (sk_template_parms, NULL); |
50821 | |
50822 | ++processing_template_decl; |
50823 | |
50824 | parser->fully_implicit_function_template_p = true; |
50825 | ++parser->num_template_parameter_lists; |
50826 | } |
50827 | else |
50828 | { |
50829 | /* Synthesize implicit template parameters at the end of the explicit |
50830 | template parameter list. */ |
50831 | |
50832 | gcc_assert (current_template_parms); |
50833 | |
50834 | parser->implicit_template_scope = scope; |
50835 | |
50836 | tree v = INNERMOST_TEMPLATE_PARMS (current_template_parms); |
50837 | parser->implicit_template_parms |
50838 | = TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1); |
50839 | } |
50840 | } |
50841 | |
50842 | /* Synthesize a new template parameter and track the current template |
50843 | parameter chain with implicit_template_parms. */ |
50844 | |
50845 | tree proto = constr ? DECL_INITIAL (constr) : NULL_TREE; |
50846 | tree synth_id = make_generic_type_name (); |
50847 | bool non_type = false; |
50848 | |
50849 | /* Synthesize the type template parameter. */ |
50850 | gcc_assert(!proto || TREE_CODE (proto) == TYPE_DECL); |
50851 | tree synth_tmpl_parm = finish_template_type_parm (class_type_node, synth_id); |
50852 | |
50853 | if (become_template) |
50854 | current_template_parms = tree_cons (size_int (current_template_depth + 1), |
50855 | NULL_TREE, current_template_parms); |
50856 | |
50857 | /* Attach the constraint to the parm before processing. */ |
50858 | tree node = build_tree_list (NULL_TREE, synth_tmpl_parm); |
50859 | TREE_TYPE (node) = constr; |
50860 | tree new_parm |
50861 | = process_template_parm (parser->implicit_template_parms, |
50862 | input_location, |
50863 | node, |
50864 | /*non_type=*/non_type, |
50865 | /*param_pack=*/false); |
50866 | // Process_template_parm returns the list of parms, and |
50867 | // parser->implicit_template_parms holds the final node of the parm |
50868 | // list. We really want to manipulate the newly appended element. |
50869 | gcc_checking_assert (!parser->implicit_template_parms |
50870 | || parser->implicit_template_parms == new_parm); |
50871 | if (parser->implicit_template_parms) |
50872 | new_parm = TREE_CHAIN (new_parm); |
50873 | gcc_checking_assert (!TREE_CHAIN (new_parm)); |
50874 | |
50875 | // Record the last implicit parm node |
50876 | parser->implicit_template_parms = new_parm; |
50877 | |
50878 | /* Mark the synthetic declaration "virtual". This is used when |
50879 | comparing template-heads to determine if whether an abbreviated |
50880 | function template is equivalent to an explicit template. |
50881 | |
50882 | Note that DECL_ARTIFICIAL is used elsewhere for template |
50883 | parameters. */ |
50884 | if (TREE_VALUE (new_parm) != error_mark_node) |
50885 | DECL_VIRTUAL_P (TREE_VALUE (new_parm)) = true; |
50886 | |
50887 | tree new_decl = get_local_decls (); |
50888 | if (non_type) |
50889 | /* Return the TEMPLATE_PARM_INDEX, not the PARM_DECL. */ |
50890 | new_decl = DECL_INITIAL (new_decl); |
50891 | |
50892 | /* If creating a fully implicit function template, start the new implicit |
50893 | template parameter list with this synthesized type, otherwise grow the |
50894 | current template parameter list. */ |
50895 | |
50896 | if (become_template) |
50897 | { |
50898 | parent_scope->level_chain = current_binding_level; |
50899 | |
50900 | tree new_parms = make_tree_vec (1); |
50901 | TREE_VEC_ELT (new_parms, 0) = parser->implicit_template_parms; |
50902 | TREE_VALUE (current_template_parms) = new_parms; |
50903 | } |
50904 | else |
50905 | { |
50906 | tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); |
50907 | int new_parm_idx = TREE_VEC_LENGTH (new_parms); |
50908 | new_parms = grow_tree_vec (v: new_parms, new_parm_idx + 1); |
50909 | TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms; |
50910 | } |
50911 | |
50912 | /* If the new parameter was constrained, we need to add that to the |
50913 | constraints in the template parameter list. */ |
50914 | if (tree req = TEMPLATE_PARM_CONSTRAINTS (new_parm)) |
50915 | { |
50916 | tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); |
50917 | reqs = combine_constraint_expressions (reqs, req); |
50918 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs; |
50919 | } |
50920 | |
50921 | current_binding_level = entry_scope; |
50922 | |
50923 | return new_decl; |
50924 | } |
50925 | |
50926 | /* Finish the declaration of a fully implicit function template. Such a |
50927 | template has no explicit template parameter list so has not been through the |
50928 | normal template head and tail processing. synthesize_implicit_template_parm |
50929 | tries to do the head; this tries to do the tail. MEMBER_DECL_OPT should be |
50930 | provided if the declaration is a class member such that its template |
50931 | declaration can be completed. If MEMBER_DECL_OPT is provided the finished |
50932 | form is returned. Otherwise NULL_TREE is returned. */ |
50933 | |
50934 | static tree |
50935 | finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt) |
50936 | { |
50937 | gcc_assert (parser->fully_implicit_function_template_p); |
50938 | |
50939 | if (member_decl_opt && member_decl_opt != error_mark_node |
50940 | && DECL_VIRTUAL_P (member_decl_opt)) |
50941 | { |
50942 | error_at (DECL_SOURCE_LOCATION (member_decl_opt), |
50943 | "implicit templates may not be %<virtual%>" ); |
50944 | DECL_VIRTUAL_P (member_decl_opt) = false; |
50945 | } |
50946 | |
50947 | if (member_decl_opt) |
50948 | member_decl_opt = finish_member_template_decl (member_decl_opt); |
50949 | end_template_decl (); |
50950 | |
50951 | parser->fully_implicit_function_template_p = false; |
50952 | parser->implicit_template_parms = 0; |
50953 | parser->implicit_template_scope = 0; |
50954 | --parser->num_template_parameter_lists; |
50955 | |
50956 | return member_decl_opt; |
50957 | } |
50958 | |
50959 | /* Like finish_fully_implicit_template, but to be used in error |
50960 | recovery, rearranging scopes so that we restore the state we had |
50961 | before synthesize_implicit_template_parm inserted the implement |
50962 | template parms scope. */ |
50963 | |
50964 | static void |
50965 | abort_fully_implicit_template (cp_parser *parser) |
50966 | { |
50967 | cp_binding_level *return_to_scope = current_binding_level; |
50968 | |
50969 | if (parser->implicit_template_scope |
50970 | && return_to_scope != parser->implicit_template_scope) |
50971 | { |
50972 | cp_binding_level *child = return_to_scope; |
50973 | for (cp_binding_level *scope = child->level_chain; |
50974 | scope != parser->implicit_template_scope; |
50975 | scope = child->level_chain) |
50976 | child = scope; |
50977 | child->level_chain = parser->implicit_template_scope->level_chain; |
50978 | parser->implicit_template_scope->level_chain = return_to_scope; |
50979 | current_binding_level = parser->implicit_template_scope; |
50980 | } |
50981 | else |
50982 | return_to_scope = return_to_scope->level_chain; |
50983 | |
50984 | finish_fully_implicit_template (parser, NULL); |
50985 | |
50986 | gcc_assert (current_binding_level == return_to_scope); |
50987 | } |
50988 | |
50989 | /* Helper function for diagnostics that have complained about things |
50990 | being used with 'extern "C"' linkage. |
50991 | |
50992 | Attempt to issue a note showing where the 'extern "C"' linkage began. */ |
50993 | |
50994 | void |
50995 | maybe_show_extern_c_location (void) |
50996 | { |
50997 | if (the_parser->innermost_linkage_specification_location != UNKNOWN_LOCATION) |
50998 | inform (the_parser->innermost_linkage_specification_location, |
50999 | "%<extern \"C\"%> linkage started here" ); |
51000 | } |
51001 | |
51002 | #include "gt-cp-parser.h" |
51003 | |