1/* Parser for C and Objective-C.
2 Copyright (C) 1987-2025 Free Software Foundation, Inc.
3
4 Parser actions based on the old Bison parser; structure somewhat
5 influenced by and fragments based on the C++ parser.
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
22
23/* TODO:
24
25 Make sure all relevant comments, and all relevant code from all
26 actions, brought over from old parser. Verify exact correspondence
27 of syntax accepted.
28
29 Add testcases covering every input symbol in every state in old and
30 new parsers.
31
32 Include full syntax for GNU C, including erroneous cases accepted
33 with error messages, in syntax productions in comments.
34
35 Make more diagnostics in the front end generally take an explicit
36 location rather than implicitly using input_location. */
37
38#include "config.h"
39#define INCLUDE_STRING
40#include "system.h"
41#include "coretypes.h"
42#include "target.h"
43#include "function.h"
44#include "c-tree.h"
45#include "timevar.h"
46#include "stringpool.h"
47#include "cgraph.h"
48#include "attribs.h"
49#include "stor-layout.h"
50#include "varasm.h"
51#include "trans-mem.h"
52#include "c-family/c-pragma.h"
53#include "c-lang.h"
54#include "c-family/c-objc.h"
55#include "plugin.h"
56#include "omp-general.h"
57#include "omp-offload.h"
58#include "builtins.h"
59#include "gomp-constants.h"
60#include "c-family/c-indentation.h"
61#include "gimple-expr.h"
62#include "context.h"
63#include "gcc-rich-location.h"
64#include "c-parser.h"
65#include "gimple-parser.h"
66#include "read-rtl-function.h"
67#include "run-rtl-passes.h"
68#include "intl.h"
69#include "c-family/name-hint.h"
70#include "tree-iterator.h"
71#include "tree-pretty-print.h"
72#include "memmodel.h"
73#include "c-family/known-headers.h"
74#include "bitmap.h"
75#include "analyzer/analyzer-language.h"
76#include "toplev.h"
77#include "asan.h"
78#include "c-family/c-ubsan.h"
79#include "gcc-urlifier.h"
80
81/* We need to walk over decls with incomplete struct/union/enum types
82 after parsing the whole translation unit.
83 In finish_decl(), if the decl is static, has incomplete
84 struct/union/enum type, it is appended to incomplete_record_decls.
85 In c_parser_translation_unit(), we iterate over incomplete_record_decls
86 and report error if any of the decls are still incomplete. */
87
88vec<tree> incomplete_record_decls;
89
90void
91set_c_expr_source_range (c_expr *expr,
92 location_t start, location_t finish)
93{
94 expr->src_range.m_start = start;
95 expr->src_range.m_finish = finish;
96 if (expr->value)
97 set_source_range (expr: expr->value, start, finish);
98}
99
100void
101set_c_expr_source_range (c_expr *expr,
102 source_range src_range)
103{
104 expr->src_range = src_range;
105 if (expr->value)
106 set_source_range (expr: expr->value, src_range);
107}
108
109
110/* Initialization routine for this file. */
111
112void
113c_parse_init (void)
114{
115 /* The only initialization required is of the reserved word
116 identifiers. */
117 unsigned int i;
118 tree id;
119 int mask = 0;
120
121 /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
122 the c_token structure. */
123 gcc_assert (RID_MAX <= 255);
124
125 mask |= D_CXXONLY;
126 if (!flag_isoc99)
127 mask |= D_C99;
128 if (!flag_isoc23)
129 mask |= D_C23;
130 if (flag_no_asm)
131 {
132 mask |= D_ASM | D_EXT;
133 if (!flag_isoc99)
134 mask |= D_EXT89;
135 if (!flag_isoc23)
136 mask |= D_EXT11;
137 }
138 if (!c_dialect_objc ())
139 mask |= D_OBJC | D_CXX_OBJC;
140
141 ridpointers = ggc_cleared_vec_alloc<tree> (c: (int) RID_MAX);
142 for (i = 0; i < num_c_common_reswords; i++)
143 {
144 /* If a keyword is disabled, do not enter it into the table
145 and so create a canonical spelling that isn't a keyword. */
146 if (c_common_reswords[i].disable & mask)
147 {
148 if (warn_cxx_compat
149 && (c_common_reswords[i].disable & D_CXXWARN))
150 {
151 id = get_identifier (c_common_reswords[i].word);
152 C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
153 C_IS_RESERVED_WORD (id) = 1;
154 }
155 continue;
156 }
157
158 id = get_identifier (c_common_reswords[i].word);
159 C_SET_RID_CODE (id, c_common_reswords[i].rid);
160 C_IS_RESERVED_WORD (id) = 1;
161 ridpointers [(int) c_common_reswords[i].rid] = id;
162 }
163
164 for (i = 0; i < NUM_INT_N_ENTS; i++)
165 {
166 /* We always create the symbols but they aren't always supported. */
167 char name[50];
168 sprintf (s: name, format: "__int%d", int_n_data[i].bitsize);
169 id = get_identifier (name);
170 C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
171 C_IS_RESERVED_WORD (id) = 1;
172
173 sprintf (s: name, format: "__int%d__", int_n_data[i].bitsize);
174 id = get_identifier (name);
175 C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
176 C_IS_RESERVED_WORD (id) = 1;
177 }
178
179 if (flag_openmp)
180 {
181 id = get_identifier ("omp_all_memory");
182 C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
183 C_IS_RESERVED_WORD (id) = 1;
184 ridpointers [RID_OMP_ALL_MEMORY] = id;
185 }
186}
187
188/* A parser structure recording information about the state and
189 context of parsing. Includes lexer information with up to two
190 tokens of look-ahead; more are not needed for C. */
191struct GTY(()) c_parser {
192 /* The look-ahead tokens. */
193 c_token * GTY((skip)) tokens;
194 /* Buffer for look-ahead tokens. */
195 c_token tokens_buf[4];
196 /* How many look-ahead tokens are available (0 - 4, or
197 more if parsing from pre-lexed tokens). */
198 unsigned int tokens_avail;
199 /* Raw look-ahead tokens, used only for checking in Objective-C
200 whether '[[' starts attributes. */
201 vec<c_token, va_gc> *raw_tokens;
202 /* The number of raw look-ahead tokens that have since been fully
203 lexed. */
204 unsigned int raw_tokens_used;
205 /* True if a syntax error is being recovered from; false otherwise.
206 c_parser_error sets this flag. It should clear this flag when
207 enough tokens have been consumed to recover from the error. */
208 BOOL_BITFIELD error : 1;
209 /* True if we're processing a pragma, and shouldn't automatically
210 consume CPP_PRAGMA_EOL. */
211 BOOL_BITFIELD in_pragma : 1;
212 /* True if we're parsing the outermost block of an if statement. */
213 BOOL_BITFIELD in_if_block : 1;
214 /* True if we want to lex a translated, joined string (for an
215 initial #pragma pch_preprocess). Otherwise the parser is
216 responsible for concatenating strings and translating to the
217 execution character set as needed. */
218 BOOL_BITFIELD lex_joined_string : 1;
219 /* True if, when the parser is concatenating string literals, it
220 should translate them to the execution character set (false
221 inside attributes). */
222 BOOL_BITFIELD translate_strings_p : 1;
223
224 /* Objective-C specific parser/lexer information. */
225
226 /* True if we are in a context where the Objective-C "PQ" keywords
227 are considered keywords. */
228 BOOL_BITFIELD objc_pq_context : 1;
229 /* True if we are parsing a (potential) Objective-C foreach
230 statement. This is set to true after we parsed 'for (' and while
231 we wait for 'in' or ';' to decide if it's a standard C for loop or an
232 Objective-C foreach loop. */
233 BOOL_BITFIELD objc_could_be_foreach_context : 1;
234 /* The following flag is needed to contextualize Objective-C lexical
235 analysis. In some cases (e.g., 'int NSObject;'), it is
236 undesirable to bind an identifier to an Objective-C class, even
237 if a class with that name exists. */
238 BOOL_BITFIELD objc_need_raw_identifier : 1;
239 /* Nonzero if we're processing a __transaction statement. The value
240 is 1 | TM_STMT_ATTR_*. */
241 unsigned int in_transaction : 4;
242 /* True if we are in a context where the Objective-C "Property attribute"
243 keywords are valid. */
244 BOOL_BITFIELD objc_property_attr_context : 1;
245
246 /* Whether we have just seen/constructed a string-literal. Set when
247 returning a string-literal from c_parser_string_literal. Reset
248 in consume_token. Useful when we get a parse error and see an
249 unknown token, which could have been a string-literal constant
250 macro. */
251 BOOL_BITFIELD seen_string_literal : 1;
252
253 /* TRUE if omp::directive, omp::decl or omp::sequence attributes may not
254 appear. */
255 BOOL_BITFIELD omp_attrs_forbidden_p : 1;
256
257 /* Location of the last consumed token. */
258 location_t last_token_location;
259
260 /* Holds state for parsing collapsed OMP_FOR loops. Managed by
261 c_parser_omp_for_loop. */
262 struct omp_for_parse_data * GTY((skip)) omp_for_parse_state;
263
264 /* If we're in the context of OpenMP directives written as C23
265 attributes turned into pragma, the tokens field is temporarily
266 redirected. This holds data needed to restore state afterwards.
267 It's NULL otherwise. */
268 struct omp_attribute_pragma_state *in_omp_attribute_pragma;
269
270 /* Set for omp::decl attribute parsing to the decl to which it
271 appertains. */
272 tree in_omp_decl_attribute;
273
274 /* Non-null only when parsing the body of an OpenMP metadirective.
275 Managed by c_parser_omp_metadirective. */
276 struct omp_metadirective_parse_data * GTY((skip))
277 omp_metadirective_state;
278};
279
280/* Holds data needed to restore the token stream to its previous state
281 after parsing an OpenMP attribute-syntax pragma. */
282struct GTY(()) omp_attribute_pragma_state
283{
284 vec<c_token, va_gc> *token_vec;
285 c_token * GTY((skip)) save_tokens;
286 unsigned int save_tokens_avail;
287};
288
289/* Return a pointer to the Nth token in PARSERs tokens_buf. */
290
291c_token *
292c_parser_tokens_buf (c_parser *parser, unsigned n)
293{
294 return &parser->tokens_buf[n];
295}
296
297/* Return the error state of PARSER. */
298
299bool
300c_parser_error (c_parser *parser)
301{
302 return parser->error;
303}
304
305/* Set the error state of PARSER to ERR. */
306
307void
308c_parser_set_error (c_parser *parser, bool err)
309{
310 parser->error = err;
311}
312
313
314/* The actual parser and external interface. ??? Does this need to be
315 garbage-collected? */
316
317static GTY (()) c_parser *the_parser;
318
319/* Read in and lex a single token, storing it in *TOKEN. If RAW,
320 context-sensitive postprocessing of the token is not done. */
321
322static void
323c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
324{
325 timevar_push (tv: TV_LEX);
326
327 if (raw || vec_safe_length (v: parser->raw_tokens) == 0)
328 {
329 token->type = c_lex_with_flags (&token->value, &token->location,
330 &token->flags,
331 (parser->lex_joined_string
332 ? 0 : C_LEX_STRING_NO_JOIN));
333 token->id_kind = C_ID_NONE;
334 token->keyword = RID_MAX;
335 token->pragma_kind = PRAGMA_NONE;
336 }
337 else
338 {
339 /* Use a token previously lexed as a raw look-ahead token, and
340 complete the processing on it. */
341 *token = (*parser->raw_tokens)[parser->raw_tokens_used];
342 ++parser->raw_tokens_used;
343 if (parser->raw_tokens_used == vec_safe_length (v: parser->raw_tokens))
344 {
345 vec_free (v&: parser->raw_tokens);
346 parser->raw_tokens_used = 0;
347 }
348 }
349
350 if (raw)
351 goto out;
352
353 switch (token->type)
354 {
355 case CPP_NAME:
356 {
357 tree decl;
358
359 bool objc_force_identifier = parser->objc_need_raw_identifier;
360 if (c_dialect_objc ())
361 parser->objc_need_raw_identifier = false;
362
363 if (C_IS_RESERVED_WORD (token->value))
364 {
365 enum rid rid_code = C_RID_CODE (token->value);
366
367 if (rid_code == RID_CXX_COMPAT_WARN)
368 {
369 warning_at (token->location,
370 OPT_Wc___compat,
371 "identifier %qE conflicts with C++ keyword",
372 token->value);
373 }
374 else if (rid_code >= RID_FIRST_ADDR_SPACE
375 && rid_code <= RID_LAST_ADDR_SPACE)
376 {
377 addr_space_t as;
378 as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
379 targetm.addr_space.diagnose_usage (as, token->location);
380 token->id_kind = C_ID_ADDRSPACE;
381 token->keyword = rid_code;
382 break;
383 }
384 else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
385 {
386 /* We found an Objective-C "pq" keyword (in, out,
387 inout, bycopy, byref, oneway). They need special
388 care because the interpretation depends on the
389 context. */
390 if (parser->objc_pq_context)
391 {
392 token->type = CPP_KEYWORD;
393 token->keyword = rid_code;
394 break;
395 }
396 else if (parser->objc_could_be_foreach_context
397 && rid_code == RID_IN)
398 {
399 /* We are in Objective-C, inside a (potential)
400 foreach context (which means after having
401 parsed 'for (', but before having parsed ';'),
402 and we found 'in'. We consider it the keyword
403 which terminates the declaration at the
404 beginning of a foreach-statement. Note that
405 this means you can't use 'in' for anything else
406 in that context; in particular, in Objective-C
407 you can't use 'in' as the name of the running
408 variable in a C for loop. We could potentially
409 try to add code here to disambiguate, but it
410 seems a reasonable limitation. */
411 token->type = CPP_KEYWORD;
412 token->keyword = rid_code;
413 break;
414 }
415 /* Else, "pq" keywords outside of the "pq" context are
416 not keywords, and we fall through to the code for
417 normal tokens. */
418 }
419 else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
420 {
421 /* We found an Objective-C "property attribute"
422 keyword (getter, setter, readonly, etc). These are
423 only valid in the property context. */
424 if (parser->objc_property_attr_context)
425 {
426 token->type = CPP_KEYWORD;
427 token->keyword = rid_code;
428 break;
429 }
430 /* Else they are not special keywords.
431 */
432 }
433 else if (c_dialect_objc ()
434 && (OBJC_IS_AT_KEYWORD (rid_code)
435 || OBJC_IS_CXX_KEYWORD (rid_code)))
436 {
437 /* We found one of the Objective-C "@" keywords (defs,
438 selector, synchronized, etc) or one of the
439 Objective-C "cxx" keywords (class, private,
440 protected, public, try, catch, throw) without a
441 preceding '@' sign. Do nothing and fall through to
442 the code for normal tokens (in C++ we would still
443 consider the CXX ones keywords, but not in C). */
444 ;
445 }
446 else
447 {
448 token->type = CPP_KEYWORD;
449 token->keyword = rid_code;
450 break;
451 }
452 }
453
454 decl = lookup_name (token->value);
455 if (decl)
456 {
457 if (TREE_CODE (decl) == TYPE_DECL)
458 {
459 token->id_kind = C_ID_TYPENAME;
460 break;
461 }
462 }
463 else if (c_dialect_objc ())
464 {
465 tree objc_interface_decl = objc_is_class_name (token->value);
466 /* Objective-C class names are in the same namespace as
467 variables and typedefs, and hence are shadowed by local
468 declarations. */
469 if (objc_interface_decl
470 && (!objc_force_identifier || global_bindings_p ()))
471 {
472 token->value = objc_interface_decl;
473 token->id_kind = C_ID_CLASSNAME;
474 break;
475 }
476 }
477 token->id_kind = C_ID_ID;
478 }
479 break;
480 case CPP_AT_NAME:
481 /* This only happens in Objective-C; it must be a keyword. */
482 token->type = CPP_KEYWORD;
483 switch (C_RID_CODE (token->value))
484 {
485 /* Replace 'class' with '@class', 'private' with '@private',
486 etc. This prevents confusion with the C++ keyword
487 'class', and makes the tokens consistent with other
488 Objective-C 'AT' keywords. For example '@class' is
489 reported as RID_AT_CLASS which is consistent with
490 '@synchronized', which is reported as
491 RID_AT_SYNCHRONIZED.
492 */
493 case RID_CLASS: token->keyword = RID_AT_CLASS; break;
494 case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
495 case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
496 case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
497 case RID_THROW: token->keyword = RID_AT_THROW; break;
498 case RID_TRY: token->keyword = RID_AT_TRY; break;
499 case RID_CATCH: token->keyword = RID_AT_CATCH; break;
500 case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
501 default: token->keyword = C_RID_CODE (token->value);
502 }
503 break;
504 case CPP_COLON:
505 case CPP_COMMA:
506 case CPP_CLOSE_PAREN:
507 case CPP_SEMICOLON:
508 /* These tokens may affect the interpretation of any identifiers
509 following, if doing Objective-C. */
510 if (c_dialect_objc ())
511 parser->objc_need_raw_identifier = false;
512 break;
513 case CPP_PRAGMA:
514 /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
515 token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
516 token->value = NULL;
517 break;
518 default:
519 break;
520 }
521 out:
522 timevar_pop (tv: TV_LEX);
523}
524
525/* Return a pointer to the next token from PARSER, reading it in if
526 necessary. */
527
528c_token *
529c_parser_peek_token (c_parser *parser)
530{
531 if (parser->tokens_avail == 0)
532 {
533 c_lex_one_token (parser, token: &parser->tokens[0]);
534 parser->tokens_avail = 1;
535 }
536 return &parser->tokens[0];
537}
538
539/* Return a pointer to the next-but-one token from PARSER, reading it
540 in if necessary. The next token is already read in. */
541
542c_token *
543c_parser_peek_2nd_token (c_parser *parser)
544{
545 if (parser->tokens_avail >= 2)
546 return &parser->tokens[1];
547 gcc_assert (parser->tokens_avail == 1);
548 gcc_assert (parser->tokens[0].type != CPP_EOF);
549 gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
550 c_lex_one_token (parser, token: &parser->tokens[1]);
551 parser->tokens_avail = 2;
552 return &parser->tokens[1];
553}
554
555/* Return a pointer to the Nth token from PARSER, reading it
556 in if necessary. The N-1th token is already read in. */
557
558c_token *
559c_parser_peek_nth_token (c_parser *parser, unsigned int n)
560{
561 /* N is 1-based, not zero-based. */
562 gcc_assert (n > 0);
563
564 if (parser->tokens_avail >= n)
565 return &parser->tokens[n - 1];
566 gcc_assert (parser->tokens_avail == n - 1);
567 c_lex_one_token (parser, token: &parser->tokens[n - 1]);
568 parser->tokens_avail = n;
569 return &parser->tokens[n - 1];
570}
571
572/* Return a pointer to the Nth token from PARSER, reading it in as a
573 raw look-ahead token if necessary. The N-1th token is already read
574 in. Raw look-ahead tokens remain available for when the non-raw
575 functions above are called. */
576
577c_token *
578c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
579{
580 /* N is 1-based, not zero-based. */
581 gcc_assert (n > 0);
582
583 if (parser->tokens_avail >= n)
584 return &parser->tokens[n - 1];
585 unsigned int raw_len = vec_safe_length (v: parser->raw_tokens);
586 unsigned int raw_avail
587 = parser->tokens_avail + raw_len - parser->raw_tokens_used;
588 gcc_assert (raw_avail >= n - 1);
589 if (raw_avail >= n)
590 return &(*parser->raw_tokens)[parser->raw_tokens_used
591 + n - 1 - parser->tokens_avail];
592 vec_safe_reserve (v&: parser->raw_tokens, nelems: 1);
593 parser->raw_tokens->quick_grow (len: raw_len + 1);
594 c_lex_one_token (parser, token: &(*parser->raw_tokens)[raw_len], raw: true);
595 return &(*parser->raw_tokens)[raw_len];
596}
597
598bool
599c_keyword_starts_typename (enum rid keyword)
600{
601 switch (keyword)
602 {
603 case RID_UNSIGNED:
604 case RID_LONG:
605 case RID_SHORT:
606 case RID_SIGNED:
607 case RID_COMPLEX:
608 case RID_INT:
609 case RID_CHAR:
610 case RID_FLOAT:
611 case RID_DOUBLE:
612 case RID_VOID:
613 case RID_DFLOAT32:
614 case RID_DFLOAT64:
615 case RID_DFLOAT128:
616 case RID_DFLOAT64X:
617 CASE_RID_FLOATN_NX:
618 case RID_BOOL:
619 case RID_BITINT:
620 case RID_ENUM:
621 case RID_STRUCT:
622 case RID_UNION:
623 case RID_TYPEOF:
624 case RID_TYPEOF_UNQUAL:
625 case RID_CONST:
626 case RID_ATOMIC:
627 case RID_VOLATILE:
628 case RID_RESTRICT:
629 case RID_ATTRIBUTE:
630 case RID_FRACT:
631 case RID_ACCUM:
632 case RID_SAT:
633 case RID_AUTO_TYPE:
634 case RID_ALIGNAS:
635 return true;
636 default:
637 if (keyword >= RID_FIRST_INT_N
638 && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
639 && int_n_enabled_p[keyword - RID_FIRST_INT_N])
640 return true;
641 return false;
642 }
643}
644
645/* Return true if TOKEN can start a type name,
646 false otherwise. */
647bool
648c_token_starts_typename (c_token *token)
649{
650 switch (token->type)
651 {
652 case CPP_NAME:
653 switch (token->id_kind)
654 {
655 case C_ID_ID:
656 return false;
657 case C_ID_ADDRSPACE:
658 return true;
659 case C_ID_TYPENAME:
660 return true;
661 case C_ID_CLASSNAME:
662 gcc_assert (c_dialect_objc ());
663 return true;
664 default:
665 gcc_unreachable ();
666 }
667 case CPP_KEYWORD:
668 return c_keyword_starts_typename (keyword: token->keyword);
669 case CPP_LESS:
670 if (c_dialect_objc ())
671 return true;
672 return false;
673 default:
674 return false;
675 }
676}
677
678/* Return true if the next token from PARSER can start a type name,
679 false otherwise. LA specifies how to do lookahead in order to
680 detect unknown type names. If unsure, pick CLA_PREFER_ID. */
681
682static inline bool
683c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
684{
685 c_token *token = c_parser_peek_token (parser);
686 if (c_token_starts_typename (token))
687 return true;
688
689 /* Try a bit harder to detect an unknown typename. */
690 if (la != cla_prefer_id
691 && token->type == CPP_NAME
692 && token->id_kind == C_ID_ID
693
694 /* Do not try too hard when we could have "object in array". */
695 && !parser->objc_could_be_foreach_context
696
697 && (la == cla_prefer_type
698 || c_parser_peek_2nd_token (parser)->type == CPP_NAME
699 || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
700
701 /* Only unknown identifiers. */
702 && !lookup_name (token->value))
703 return true;
704
705 return false;
706}
707
708/* Return true if TOKEN, after an open parenthesis, can start a
709 compound literal (either a storage class specifier allowed in that
710 context, or a type name), false otherwise. */
711static bool
712c_token_starts_compound_literal (c_token *token)
713{
714 switch (token->type)
715 {
716 case CPP_KEYWORD:
717 switch (token->keyword)
718 {
719 case RID_CONSTEXPR:
720 case RID_REGISTER:
721 case RID_STATIC:
722 case RID_THREAD:
723 return true;
724 default:
725 break;
726 }
727 /* Fall through. */
728 default:
729 return c_token_starts_typename (token);
730 }
731}
732
733/* Return true if TOKEN is a type qualifier, false otherwise. */
734static bool
735c_token_is_qualifier (c_token *token)
736{
737 switch (token->type)
738 {
739 case CPP_NAME:
740 switch (token->id_kind)
741 {
742 case C_ID_ADDRSPACE:
743 return true;
744 default:
745 return false;
746 }
747 case CPP_KEYWORD:
748 switch (token->keyword)
749 {
750 case RID_CONST:
751 case RID_VOLATILE:
752 case RID_RESTRICT:
753 case RID_ATTRIBUTE:
754 case RID_ATOMIC:
755 return true;
756 default:
757 return false;
758 }
759 case CPP_LESS:
760 return false;
761 default:
762 gcc_unreachable ();
763 }
764}
765
766/* Return true if the next token from PARSER is a type qualifier,
767 false otherwise. */
768static inline bool
769c_parser_next_token_is_qualifier (c_parser *parser)
770{
771 c_token *token = c_parser_peek_token (parser);
772 return c_token_is_qualifier (token);
773}
774
775/* Return true if TOKEN can start declaration specifiers (not
776 including standard attributes), false otherwise. */
777static bool
778c_token_starts_declspecs (c_token *token)
779{
780 switch (token->type)
781 {
782 case CPP_NAME:
783 switch (token->id_kind)
784 {
785 case C_ID_ID:
786 return false;
787 case C_ID_ADDRSPACE:
788 return true;
789 case C_ID_TYPENAME:
790 return true;
791 case C_ID_CLASSNAME:
792 gcc_assert (c_dialect_objc ());
793 return true;
794 default:
795 gcc_unreachable ();
796 }
797 case CPP_KEYWORD:
798 switch (token->keyword)
799 {
800 case RID_STATIC:
801 case RID_EXTERN:
802 case RID_REGISTER:
803 case RID_TYPEDEF:
804 case RID_INLINE:
805 case RID_NORETURN:
806 case RID_AUTO:
807 case RID_THREAD:
808 case RID_UNSIGNED:
809 case RID_LONG:
810 case RID_SHORT:
811 case RID_SIGNED:
812 case RID_COMPLEX:
813 case RID_INT:
814 case RID_CHAR:
815 case RID_FLOAT:
816 case RID_DOUBLE:
817 case RID_VOID:
818 case RID_DFLOAT32:
819 case RID_DFLOAT64:
820 case RID_DFLOAT128:
821 case RID_DFLOAT64X:
822 CASE_RID_FLOATN_NX:
823 case RID_BOOL:
824 case RID_BITINT:
825 case RID_ENUM:
826 case RID_STRUCT:
827 case RID_UNION:
828 case RID_TYPEOF:
829 case RID_TYPEOF_UNQUAL:
830 case RID_CONST:
831 case RID_VOLATILE:
832 case RID_RESTRICT:
833 case RID_ATTRIBUTE:
834 case RID_FRACT:
835 case RID_ACCUM:
836 case RID_SAT:
837 case RID_ALIGNAS:
838 case RID_ATOMIC:
839 case RID_AUTO_TYPE:
840 case RID_CONSTEXPR:
841 return true;
842 default:
843 if (token->keyword >= RID_FIRST_INT_N
844 && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
845 && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
846 return true;
847 return false;
848 }
849 case CPP_LESS:
850 if (c_dialect_objc ())
851 return true;
852 return false;
853 default:
854 return false;
855 }
856}
857
858
859/* Return true if TOKEN can start declaration specifiers (not
860 including standard attributes) or a static assertion, false
861 otherwise. */
862static bool
863c_token_starts_declaration (c_token *token)
864{
865 if (c_token_starts_declspecs (token)
866 || token->keyword == RID_STATIC_ASSERT)
867 return true;
868 else
869 return false;
870}
871
872/* Return true if the next token from PARSER can start declaration
873 specifiers (not including standard attributes), false
874 otherwise. */
875bool
876c_parser_next_token_starts_declspecs (c_parser *parser)
877{
878 c_token *token = c_parser_peek_token (parser);
879
880 /* In Objective-C, a classname normally starts a declspecs unless it
881 is immediately followed by a dot. In that case, it is the
882 Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
883 setter/getter on the class. c_token_starts_declspecs() can't
884 differentiate between the two cases because it only checks the
885 current token, so we have a special check here. */
886 if (c_dialect_objc ()
887 && token->type == CPP_NAME
888 && token->id_kind == C_ID_CLASSNAME
889 && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
890 return false;
891
892 return c_token_starts_declspecs (token);
893}
894
895/* Return true if the next tokens from PARSER can start declaration
896 specifiers (not including standard attributes) or a static
897 assertion, false otherwise. */
898bool
899c_parser_next_tokens_start_declaration (c_parser *parser)
900{
901 c_token *token = c_parser_peek_token (parser);
902
903 /* Same as above. */
904 if (c_dialect_objc ()
905 && token->type == CPP_NAME
906 && token->id_kind == C_ID_CLASSNAME
907 && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
908 return false;
909
910 /* Labels do not start declarations. */
911 if (token->type == CPP_NAME
912 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
913 return false;
914
915 if (c_token_starts_declaration (token))
916 return true;
917
918 if (c_parser_next_tokens_start_typename (parser, la: cla_nonabstract_decl))
919 return true;
920
921 return false;
922}
923
924/* Consume the next token from PARSER. */
925
926void
927c_parser_consume_token (c_parser *parser)
928{
929 gcc_assert (parser->tokens_avail >= 1);
930 gcc_assert (parser->tokens[0].type != CPP_EOF);
931 gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
932 gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
933 parser->last_token_location = parser->tokens[0].location;
934 if (parser->tokens != &parser->tokens_buf[0])
935 parser->tokens++;
936 else if (parser->tokens_avail >= 2)
937 {
938 parser->tokens[0] = parser->tokens[1];
939 if (parser->tokens_avail >= 3)
940 {
941 parser->tokens[1] = parser->tokens[2];
942 if (parser->tokens_avail >= 4)
943 parser->tokens[2] = parser->tokens[3];
944 }
945 }
946 parser->tokens_avail--;
947 parser->seen_string_literal = false;
948}
949
950/* Expect the current token to be a #pragma. Consume it and remember
951 that we've begun parsing a pragma. */
952
953static void
954c_parser_consume_pragma (c_parser *parser)
955{
956 gcc_assert (!parser->in_pragma);
957 gcc_assert (parser->tokens_avail >= 1);
958 gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
959 if (parser->tokens != &parser->tokens_buf[0])
960 parser->tokens++;
961 else if (parser->tokens_avail >= 2)
962 {
963 parser->tokens[0] = parser->tokens[1];
964 if (parser->tokens_avail >= 3)
965 parser->tokens[1] = parser->tokens[2];
966 }
967 parser->tokens_avail--;
968 parser->in_pragma = true;
969}
970
971/* Update the global input_location from TOKEN. */
972static inline void
973c_parser_set_source_position_from_token (c_token *token)
974{
975 if (token->type != CPP_EOF)
976 {
977 input_location = token->location;
978 }
979}
980
981/* Helper function for c_parser_error.
982 Having peeked a token of kind TOK1_KIND that might signify
983 a conflict marker, peek successor tokens to determine
984 if we actually do have a conflict marker.
985 Specifically, we consider a run of 7 '<', '=' or '>' characters
986 at the start of a line as a conflict marker.
987 These come through the lexer as three pairs and a single,
988 e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
989 If it returns true, *OUT_LOC is written to with the location/range
990 of the marker. */
991
992static bool
993c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
994 location_t *out_loc)
995{
996 c_token *token2 = c_parser_peek_2nd_token (parser);
997 if (token2->type != tok1_kind)
998 return false;
999 c_token *token3 = c_parser_peek_nth_token (parser, n: 3);
1000 if (token3->type != tok1_kind)
1001 return false;
1002 c_token *token4 = c_parser_peek_nth_token (parser, n: 4);
1003 if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
1004 return false;
1005
1006 /* It must be at the start of the line. */
1007 location_t start_loc = c_parser_peek_token (parser)->location;
1008 if (LOCATION_COLUMN (start_loc) != 1)
1009 return false;
1010
1011 /* We have a conflict marker. Construct a location of the form:
1012 <<<<<<<
1013 ^~~~~~~
1014 with start == caret, finishing at the end of the marker. */
1015 location_t finish_loc = get_finish (loc: token4->location);
1016 *out_loc = make_location (caret: start_loc, start: start_loc, finish: finish_loc);
1017
1018 return true;
1019}
1020
1021/* Issue a diagnostic of the form
1022 FILE:LINE: MESSAGE before TOKEN
1023 where TOKEN is the next token in the input stream of PARSER.
1024 MESSAGE (specified by the caller) is usually of the form "expected
1025 OTHER-TOKEN".
1026
1027 Use RICHLOC as the location of the diagnostic.
1028
1029 Do not issue a diagnostic if still recovering from an error.
1030
1031 Return true iff an error was actually emitted.
1032
1033 ??? This is taken from the C++ parser, but building up messages in
1034 this way is not i18n-friendly and some other approach should be
1035 used. */
1036
1037static bool
1038c_parser_error_richloc (c_parser *parser, const char *gmsgid,
1039 rich_location *richloc)
1040{
1041 c_token *token = c_parser_peek_token (parser);
1042 if (parser->error)
1043 return false;
1044 parser->error = true;
1045 if (!gmsgid)
1046 return false;
1047
1048 /* If this is actually a conflict marker, report it as such. */
1049 if (token->type == CPP_LSHIFT
1050 || token->type == CPP_RSHIFT
1051 || token->type == CPP_EQ_EQ)
1052 {
1053 location_t loc;
1054 if (c_parser_peek_conflict_marker (parser, tok1_kind: token->type, out_loc: &loc))
1055 {
1056 error_at (loc, "version control conflict marker in file");
1057 return true;
1058 }
1059 }
1060
1061 /* If we were parsing a string-literal and there is an unknown name
1062 token right after, then check to see if that could also have been
1063 a literal string by checking the name against a list of known
1064 standard string literal constants defined in header files. If
1065 there is one, then add that as an hint to the error message. */
1066 auto_diagnostic_group d;
1067 name_hint h;
1068 if (parser->seen_string_literal && token->type == CPP_NAME)
1069 {
1070 tree name = token->value;
1071 const char *token_name = IDENTIFIER_POINTER (name);
1072 const char *header_hint
1073 = get_c_stdlib_header_for_string_macro_name (n: token_name);
1074 if (header_hint != NULL)
1075 h = name_hint (nullptr,
1076 std::make_unique<suggest_missing_header>
1077 (args&: token->location,
1078 args&: token_name,
1079 args&: header_hint));
1080 }
1081
1082 c_parse_error (gmsgid,
1083 /* Because c_parse_error does not understand
1084 CPP_KEYWORD, keywords are treated like
1085 identifiers. */
1086 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
1087 /* ??? The C parser does not save the cpp flags of a
1088 token, we need to pass 0 here and we will not get
1089 the source spelling of some tokens but rather the
1090 canonical spelling. */
1091 token->value, /*flags=*/0, richloc);
1092 return true;
1093}
1094
1095/* As c_parser_error_richloc, but issue the message at the
1096 location of PARSER's next token, or at input_location
1097 if the next token is EOF. */
1098
1099bool
1100c_parser_error (c_parser *parser, const char *gmsgid)
1101{
1102 c_token *token = c_parser_peek_token (parser);
1103 c_parser_set_source_position_from_token (token);
1104 rich_location richloc (line_table, input_location);
1105 return c_parser_error_richloc (parser, gmsgid, richloc: &richloc);
1106}
1107
1108/* Some tokens naturally come in pairs e.g.'(' and ')'.
1109 This class is for tracking such a matching pair of symbols.
1110 In particular, it tracks the location of the first token,
1111 so that if the second token is missing, we can highlight the
1112 location of the first token when notifying the user about the
1113 problem. */
1114
1115template <typename traits_t>
1116class token_pair
1117{
1118 public:
1119 /* token_pair's ctor. */
1120 token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
1121
1122 /* If the next token is the opening symbol for this pair, consume it and
1123 return true.
1124 Otherwise, issue an error and return false.
1125 In either case, record the location of the opening token. */
1126
1127 bool require_open (c_parser *parser)
1128 {
1129 c_token *token = c_parser_peek_token (parser);
1130 if (token)
1131 m_open_loc = token->location;
1132
1133 return c_parser_require (parser, traits_t::open_token_type,
1134 traits_t::open_gmsgid);
1135 }
1136
1137 /* Consume the next token from PARSER, recording its location as
1138 that of the opening token within the pair. */
1139
1140 void consume_open (c_parser *parser)
1141 {
1142 c_token *token = c_parser_peek_token (parser);
1143 gcc_assert (token->type == traits_t::open_token_type);
1144 m_open_loc = token->location;
1145 c_parser_consume_token (parser);
1146 }
1147
1148 /* If the next token is the closing symbol for this pair, consume it
1149 and return true.
1150 Otherwise, issue an error, highlighting the location of the
1151 corresponding opening token, and return false. */
1152
1153 bool require_close (c_parser *parser) const
1154 {
1155 return c_parser_require (parser, traits_t::close_token_type,
1156 traits_t::close_gmsgid, m_open_loc);
1157 }
1158
1159 /* Like token_pair::require_close, except that tokens will be skipped
1160 until the desired token is found. An error message is still produced
1161 if the next token is not as expected. */
1162
1163 void skip_until_found_close (c_parser *parser) const
1164 {
1165 c_parser_skip_until_found (parser, traits_t::close_token_type,
1166 traits_t::close_gmsgid, m_open_loc);
1167 }
1168
1169 private:
1170 location_t m_open_loc;
1171};
1172
1173/* Traits for token_pair<T> for tracking matching pairs of parentheses. */
1174
1175struct matching_paren_traits
1176{
1177 static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
1178 static const char * const open_gmsgid;
1179 static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
1180 static const char * const close_gmsgid;
1181};
1182
1183const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
1184const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
1185
1186/* "matching_parens" is a token_pair<T> class for tracking matching
1187 pairs of parentheses. */
1188
1189typedef token_pair<matching_paren_traits> matching_parens;
1190
1191/* Traits for token_pair<T> for tracking matching pairs of braces. */
1192
1193struct matching_brace_traits
1194{
1195 static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
1196 static const char * const open_gmsgid;
1197 static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
1198 static const char * const close_gmsgid;
1199};
1200
1201const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
1202const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
1203
1204/* "matching_braces" is a token_pair<T> class for tracking matching
1205 pairs of braces. */
1206
1207typedef token_pair<matching_brace_traits> matching_braces;
1208
1209/* Get a description of the matching symbol to TYPE e.g. "(" for
1210 CPP_CLOSE_PAREN. */
1211
1212static const char *
1213get_matching_symbol (enum cpp_ttype type)
1214{
1215 switch (type)
1216 {
1217 default:
1218 gcc_unreachable ();
1219 case CPP_CLOSE_PAREN:
1220 return "(";
1221 case CPP_CLOSE_BRACE:
1222 return "{";
1223 }
1224}
1225
1226/* If the next token is of the indicated TYPE, consume it. Otherwise,
1227 issue the error MSGID. If MSGID is NULL then a message has already
1228 been produced and no message will be produced this time. Returns
1229 true if found, false otherwise.
1230
1231 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1232 within any error as the location of an "opening" token matching
1233 the close token TYPE (e.g. the location of the '(' when TYPE is
1234 CPP_CLOSE_PAREN).
1235
1236 If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
1237 one type (e.g. "expected %<)%>") and thus it may be reasonable to
1238 attempt to generate a fix-it hint for the problem.
1239 Otherwise msgid describes multiple token types (e.g.
1240 "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
1241 generate a fix-it hint. */
1242
1243bool
1244c_parser_require (c_parser *parser,
1245 enum cpp_ttype type,
1246 const char *msgid,
1247 location_t matching_location,
1248 bool type_is_unique)
1249{
1250 if (c_parser_next_token_is (parser, type))
1251 {
1252 c_parser_consume_token (parser);
1253 return true;
1254 }
1255 else
1256 {
1257 location_t next_token_loc = c_parser_peek_token (parser)->location;
1258 gcc_rich_location richloc (next_token_loc);
1259
1260 /* Potentially supply a fix-it hint, suggesting to add the
1261 missing token immediately after the *previous* token.
1262 This may move the primary location within richloc. */
1263 if (!parser->error && type_is_unique)
1264 maybe_suggest_missing_token_insertion (richloc: &richloc, token_type: type,
1265 prev_token_loc: parser->last_token_location);
1266
1267 /* If matching_location != UNKNOWN_LOCATION, highlight it.
1268 Attempt to consolidate diagnostics by printing it as a
1269 secondary range within the main diagnostic. */
1270 bool added_matching_location = false;
1271 if (matching_location != UNKNOWN_LOCATION)
1272 added_matching_location
1273 = richloc.add_location_if_nearby (dc: *global_dc, loc: matching_location);
1274
1275 if (c_parser_error_richloc (parser, gmsgid: msgid, richloc: &richloc))
1276 /* If we weren't able to consolidate matching_location, then
1277 print it as a secondary diagnostic. */
1278 if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
1279 inform (matching_location, "to match this %qs",
1280 get_matching_symbol (type));
1281
1282 return false;
1283 }
1284}
1285
1286/* If the next token is the indicated keyword, consume it. Otherwise,
1287 issue the error MSGID. Returns true if found, false otherwise. */
1288
1289static bool
1290c_parser_require_keyword (c_parser *parser,
1291 enum rid keyword,
1292 const char *msgid)
1293{
1294 if (c_parser_next_token_is_keyword (parser, keyword))
1295 {
1296 c_parser_consume_token (parser);
1297 return true;
1298 }
1299 else
1300 {
1301 c_parser_error (parser, gmsgid: msgid);
1302 return false;
1303 }
1304}
1305
1306/* Like c_parser_require, except that tokens will be skipped until the
1307 desired token is found. An error message is still produced if the
1308 next token is not as expected. If MSGID is NULL then a message has
1309 already been produced and no message will be produced this
1310 time.
1311
1312 If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
1313 within any error as the location of an "opening" token matching
1314 the close token TYPE (e.g. the location of the '(' when TYPE is
1315 CPP_CLOSE_PAREN). */
1316
1317void
1318c_parser_skip_until_found (c_parser *parser,
1319 enum cpp_ttype type,
1320 const char *msgid,
1321 location_t matching_location)
1322{
1323 unsigned nesting_depth = 0;
1324
1325 if (c_parser_require (parser, type, msgid, matching_location))
1326 {
1327 if (UNLIKELY (type == CPP_PRAGMA_EOL) && parser->in_omp_attribute_pragma)
1328 {
1329 c_token *token = c_parser_peek_token (parser);
1330 if (token->type == CPP_EOF)
1331 {
1332 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1333 parser->tokens_avail
1334 = parser->in_omp_attribute_pragma->save_tokens_avail;
1335 parser->in_omp_attribute_pragma = NULL;
1336 }
1337 }
1338 return;
1339 }
1340
1341 /* Skip tokens until the desired token is found. */
1342 while (true)
1343 {
1344 /* Peek at the next token. */
1345 c_token *token = c_parser_peek_token (parser);
1346 /* If we've reached the token we want, consume it and stop. */
1347 if (token->type == type && !nesting_depth)
1348 {
1349 c_parser_consume_token (parser);
1350 if (UNLIKELY (type == CPP_PRAGMA_EOL)
1351 && parser->in_omp_attribute_pragma)
1352 {
1353 c_token *token = c_parser_peek_token (parser);
1354 if (token->type == CPP_EOF)
1355 {
1356 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1357 parser->tokens_avail
1358 = parser->in_omp_attribute_pragma->save_tokens_avail;
1359 parser->in_omp_attribute_pragma = NULL;
1360 }
1361 }
1362 break;
1363 }
1364
1365 /* If we've run out of tokens, stop. */
1366 if (token->type == CPP_EOF)
1367 return;
1368 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1369 return;
1370 if (token->type == CPP_OPEN_BRACE
1371 || token->type == CPP_OPEN_PAREN
1372 || token->type == CPP_OPEN_SQUARE)
1373 ++nesting_depth;
1374 else if (token->type == CPP_CLOSE_BRACE
1375 || token->type == CPP_CLOSE_PAREN
1376 || token->type == CPP_CLOSE_SQUARE)
1377 {
1378 if (nesting_depth-- == 0)
1379 break;
1380 }
1381 /* Consume this token. */
1382 c_parser_consume_token (parser);
1383 }
1384 parser->error = false;
1385}
1386
1387/* Skip tokens until the end of a parameter is found, but do not
1388 consume the comma, semicolon or closing delimiter. */
1389
1390static void
1391c_parser_skip_to_end_of_parameter (c_parser *parser)
1392{
1393 unsigned nesting_depth = 0;
1394
1395 while (true)
1396 {
1397 c_token *token = c_parser_peek_token (parser);
1398 if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
1399 && !nesting_depth)
1400 break;
1401 /* If we've run out of tokens, stop. */
1402 if (token->type == CPP_EOF)
1403 return;
1404 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
1405 return;
1406 if (token->type == CPP_OPEN_BRACE
1407 || token->type == CPP_OPEN_PAREN
1408 || token->type == CPP_OPEN_SQUARE)
1409 ++nesting_depth;
1410 else if (token->type == CPP_CLOSE_BRACE
1411 || token->type == CPP_CLOSE_PAREN
1412 || token->type == CPP_CLOSE_SQUARE)
1413 {
1414 if (nesting_depth-- == 0)
1415 break;
1416 }
1417 /* Consume this token. */
1418 c_parser_consume_token (parser);
1419 }
1420 parser->error = false;
1421}
1422
1423/* Skip tokens until a non-nested closing curly brace is the next
1424 token, or there are no more tokens. Return true in the first case,
1425 false otherwise. */
1426
1427static bool
1428c_parser_skip_to_closing_brace (c_parser *parser)
1429{
1430 unsigned nesting_depth = 0;
1431
1432 while (true)
1433 {
1434 c_token *token = c_parser_peek_token (parser);
1435
1436 switch (token->type)
1437 {
1438 case CPP_PRAGMA_EOL:
1439 if (!parser->in_pragma)
1440 break;
1441 /* FALLTHRU */
1442 case CPP_EOF:
1443 /* If we've run out of tokens, stop. */
1444 return false;
1445
1446 case CPP_CLOSE_BRACE:
1447 /* If the next token is a non-nested `}', then we have reached
1448 the end of the current block. */
1449 if (nesting_depth-- == 0)
1450 return true;
1451 break;
1452
1453 case CPP_OPEN_BRACE:
1454 /* If it the next token is a `{', then we are entering a new
1455 block. Consume the entire block. */
1456 ++nesting_depth;
1457 break;
1458
1459 default:
1460 break;
1461 }
1462
1463 /* Consume the token. */
1464 c_parser_consume_token (parser);
1465 }
1466}
1467
1468/* Expect to be at the end of the pragma directive and consume an
1469 end of line marker. */
1470
1471static void
1472c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
1473{
1474 gcc_assert (parser->in_pragma);
1475 parser->in_pragma = false;
1476
1477 if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
1478 c_parser_error (parser, gmsgid: "expected end of line");
1479
1480 cpp_ttype token_type;
1481 do
1482 {
1483 c_token *token = c_parser_peek_token (parser);
1484 token_type = token->type;
1485 if (token_type == CPP_EOF)
1486 break;
1487 c_parser_consume_token (parser);
1488 }
1489 while (token_type != CPP_PRAGMA_EOL);
1490
1491 if (parser->in_omp_attribute_pragma)
1492 {
1493 c_token *token = c_parser_peek_token (parser);
1494 if (token->type == CPP_EOF)
1495 {
1496 parser->tokens = parser->in_omp_attribute_pragma->save_tokens;
1497 parser->tokens_avail
1498 = parser->in_omp_attribute_pragma->save_tokens_avail;
1499 parser->in_omp_attribute_pragma = NULL;
1500 }
1501 }
1502
1503 parser->error = false;
1504}
1505
1506/* Skip tokens until we have consumed an entire block, or until we
1507 have consumed a non-nested ';'. */
1508
1509static void
1510c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
1511 bool metadirective_p = false)
1512{
1513 unsigned nesting_depth = 0;
1514 int bracket_depth = 0;
1515 bool save_error = parser->error;
1516
1517 while (true)
1518 {
1519 c_token *token;
1520
1521 /* Peek at the next token. */
1522 token = c_parser_peek_token (parser);
1523
1524 switch (token->type)
1525 {
1526 case CPP_EOF:
1527 return;
1528
1529 case CPP_PRAGMA_EOL:
1530 if (parser->in_pragma)
1531 return;
1532 break;
1533
1534 case CPP_SEMICOLON:
1535 /* If the next token is a ';', we have reached the
1536 end of the statement. */
1537 if (!nesting_depth && (!metadirective_p || bracket_depth <= 0))
1538 {
1539 /* Consume the ';'. */
1540 c_parser_consume_token (parser);
1541 goto finished;
1542 }
1543 break;
1544
1545 case CPP_CLOSE_BRACE:
1546 /* If the next token is a non-nested '}', then we have
1547 reached the end of the current block. */
1548 if ((nesting_depth == 0 || --nesting_depth == 0)
1549 && (!metadirective_p || bracket_depth <= 0))
1550 {
1551 c_parser_consume_token (parser);
1552 goto finished;
1553 }
1554 break;
1555
1556 case CPP_OPEN_BRACE:
1557 /* If it the next token is a '{', then we are entering a new
1558 block. Consume the entire block. */
1559 ++nesting_depth;
1560 break;
1561
1562 case CPP_OPEN_PAREN:
1563 /* Track parentheses in case the statement is a standalone 'for'
1564 statement - we want to skip over the semicolons separating the
1565 operands. */
1566 if (metadirective_p && nesting_depth == 0)
1567 ++bracket_depth;
1568 break;
1569
1570 case CPP_CLOSE_PAREN:
1571 if (metadirective_p && nesting_depth == 0)
1572 --bracket_depth;
1573 break;
1574
1575 case CPP_PRAGMA:
1576 /* If we see a pragma, consume the whole thing at once. We
1577 have some safeguards against consuming pragmas willy-nilly.
1578 Normally, we'd expect to be here with parser->error set,
1579 which disables these safeguards. But it's possible to get
1580 here for secondary error recovery, after parser->error has
1581 been cleared. */
1582 c_parser_consume_pragma (parser);
1583 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
1584 parser->error = save_error;
1585 continue;
1586
1587 default:
1588 break;
1589 }
1590
1591 c_parser_consume_token (parser);
1592 }
1593
1594 finished:
1595 parser->error = false;
1596}
1597
1598/* CPP's options (initialized by c-opts.cc). */
1599extern cpp_options *cpp_opts;
1600
1601/* Save the warning flags which are controlled by __extension__. */
1602
1603static inline int
1604disable_extension_diagnostics (void)
1605{
1606 int ret = (pedantic
1607 | (warn_pointer_arith << 1)
1608 | (warn_traditional << 2)
1609 | (flag_iso << 3)
1610 | (warn_long_long << 4)
1611 | (warn_cxx_compat << 5)
1612 | (warn_overlength_strings << 6)
1613 /* warn_c90_c99_compat has three states: -1/0/1, so we must
1614 play tricks to properly restore it. */
1615 | ((warn_c90_c99_compat == 1) << 7)
1616 | ((warn_c90_c99_compat == -1) << 8)
1617 /* Similarly for warn_c99_c11_compat. */
1618 | ((warn_c99_c11_compat == 1) << 9)
1619 | ((warn_c99_c11_compat == -1) << 10)
1620 /* Similarly for warn_c11_c23_compat. */
1621 | ((warn_c11_c23_compat == 1) << 11)
1622 | ((warn_c11_c23_compat == -1) << 12)
1623 /* Similarly for warn_c23_c2y_compat. */
1624 | ((warn_c23_c2y_compat == 1) << 13)
1625 | ((warn_c23_c2y_compat == -1) << 14)
1626 );
1627 cpp_opts->cpp_pedantic = pedantic = 0;
1628 warn_pointer_arith = 0;
1629 cpp_opts->cpp_warn_traditional = warn_traditional = 0;
1630 flag_iso = 0;
1631 cpp_opts->cpp_warn_long_long = warn_long_long = 0;
1632 warn_cxx_compat = 0;
1633 warn_overlength_strings = 0;
1634 warn_c90_c99_compat = 0;
1635 warn_c99_c11_compat = 0;
1636 warn_c11_c23_compat = 0;
1637 warn_c23_c2y_compat = 0;
1638 return ret;
1639}
1640
1641/* Restore the warning flags which are controlled by __extension__.
1642 FLAGS is the return value from disable_extension_diagnostics. */
1643
1644static inline void
1645restore_extension_diagnostics (int flags)
1646{
1647 cpp_opts->cpp_pedantic = pedantic = flags & 1;
1648 warn_pointer_arith = (flags >> 1) & 1;
1649 cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
1650 flag_iso = (flags >> 3) & 1;
1651 cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
1652 warn_cxx_compat = (flags >> 5) & 1;
1653 warn_overlength_strings = (flags >> 6) & 1;
1654 /* See above for why is this needed. */
1655 warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
1656 warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
1657 warn_c11_c23_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
1658 warn_c23_c2y_compat = (flags >> 13) & 1 ? 1 : ((flags >> 14) & 1 ? -1 : 0);
1659}
1660
1661/* Helper data structure for parsing #pragma acc routine. */
1662struct oacc_routine_data {
1663 bool error_seen; /* Set if error has been reported. */
1664 bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
1665 tree clauses;
1666 location_t loc;
1667};
1668
1669/* Used for parsing objc foreach statements. */
1670static tree objc_foreach_break_label, objc_foreach_continue_label;
1671
1672/* Used for parsing OMP for loops.
1673
1674 Some notes on flags used for context:
1675 parser->omp_for_parse_state is non-null anywhere inside the OMP FOR
1676 construct, except for the final-loop-body.
1677 The want_nested_loop flag is true if inside a {} sequence where
1678 a loop-nest (or another {} sequence containing a loop-nest) is expected,
1679 but has not yet been seen. It's false when parsing intervening code
1680 statements or their substatements that cannot contain a loop-nest.
1681 The in_intervening_code flag is true when parsing any intervening code,
1682 including substatements, and whether or not want_nested_loop is true.
1683
1684 And, about error handling:
1685 The saw_intervening_code flag is set if the loop is not perfectly
1686 nested, even in the usual case where this is not an error.
1687 perfect_nesting_fail is set if an error has been diagnosed because an
1688 imperfectly-nested loop was found where a perfectly-nested one is
1689 required (we diagnose this only once).
1690 fail is set if any kind of structural error in the loop nest
1691 has been found and diagnosed.
1692 */
1693struct omp_for_parse_data {
1694 enum tree_code code;
1695 tree declv, condv, incrv, initv;
1696 tree pre_body;
1697 tree bindings;
1698 int count; /* Expected nesting depth. */
1699 int depth; /* Current nesting depth. */
1700 location_t for_loc;
1701 bool ordered : 1;
1702 bool inscan : 1;
1703 bool want_nested_loop : 1;
1704 bool in_intervening_code : 1;
1705 bool saw_intervening_code: 1;
1706 bool perfect_nesting_fail : 1;
1707 bool fail : 1;
1708};
1709
1710struct attr_state
1711{
1712 /* True if we parsed a musttail attribute for return. */
1713 bool musttail_p;
1714};
1715
1716static bool c_parser_nth_token_starts_std_attributes (c_parser *,
1717 unsigned int);
1718static tree c_parser_std_attribute_specifier_sequence (c_parser *);
1719static void c_parser_external_declaration (c_parser *);
1720static void c_parser_asm_definition (c_parser *);
1721static tree c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
1722 bool, bool, bool, tree * = NULL,
1723 vec<c_token> * = NULL,
1724 bool have_attrs = false,
1725 tree attrs = NULL,
1726 struct oacc_routine_data * = NULL,
1727 bool * = NULL);
1728static bool c_parser_handle_statement_omp_attributes (c_parser *, tree &,
1729 bool *);
1730static void c_parser_static_assert_declaration_no_semi (c_parser *);
1731static void c_parser_static_assert_declaration (c_parser *);
1732static struct c_typespec c_parser_enum_specifier (c_parser *);
1733static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
1734static tree c_parser_struct_declaration (c_parser *, tree *);
1735static struct c_typespec c_parser_typeof_specifier (c_parser *);
1736static tree c_parser_alignas_specifier (c_parser *);
1737static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
1738 c_dtr_syn, bool *);
1739static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
1740 bool,
1741 struct c_declarator *);
1742static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
1743 bool);
1744static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
1745 tree, bool);
1746static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
1747static tree c_parser_asm_string_literal (c_parser *);
1748static tree c_parser_simple_asm_expr (c_parser *);
1749static tree c_parser_gnu_attributes (c_parser *);
1750static struct c_expr c_parser_initializer (c_parser *, tree);
1751static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
1752 struct obstack *, tree);
1753static void c_parser_initelt (c_parser *, struct obstack *);
1754static void c_parser_initval (c_parser *, struct c_expr *,
1755 struct obstack *);
1756static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
1757static location_t c_parser_compound_statement_nostart (c_parser *);
1758static void c_parser_label (c_parser *, tree);
1759static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
1760static void c_parser_statement_after_labels (c_parser *, bool *, tree,
1761 vec<tree> * = NULL,
1762 attr_state = {});
1763static tree c_parser_c99_block_statement (c_parser *, bool *,
1764 location_t * = NULL);
1765static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
1766static void c_parser_switch_statement (c_parser *, bool *, tree);
1767static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
1768 bool *, tree);
1769static void c_parser_do_statement (c_parser *, bool, unsigned short, bool,
1770 tree);
1771static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
1772 bool *, tree);
1773static tree c_parser_asm_statement (c_parser *);
1774static tree c_parser_asm_operands (c_parser *);
1775static tree c_parser_asm_goto_operands (c_parser *);
1776static tree c_parser_asm_clobbers (c_parser *);
1777static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
1778 tree = NULL_TREE);
1779static struct c_expr c_parser_conditional_expression (c_parser *,
1780 struct c_expr *, tree);
1781static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
1782 tree);
1783static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
1784static struct c_expr c_parser_unary_expression (c_parser *);
1785static inline struct c_expr c_parser_sizeof_expression (c_parser *);
1786static inline struct c_expr c_parser_countof_expression (c_parser *);
1787static struct c_expr c_parser_sizeof_or_countof_expression (c_parser *,
1788 enum rid);
1789static struct c_expr c_parser_alignof_expression (c_parser *);
1790static struct c_expr c_parser_postfix_expression (c_parser *);
1791static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
1792 struct c_declspecs *,
1793 struct c_type_name *,
1794 location_t);
1795static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
1796 location_t loc,
1797 struct c_expr);
1798static tree c_parser_transaction (c_parser *, enum rid);
1799static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
1800static tree c_parser_transaction_cancel (c_parser *);
1801static struct c_expr c_parser_expression (c_parser *);
1802static struct c_expr c_parser_expression_conv (c_parser *);
1803static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
1804 vec<tree, va_gc> **, location_t *,
1805 tree *, vec<location_t> *,
1806 unsigned int * = NULL);
1807static struct c_expr c_parser_has_attribute_expression (c_parser *);
1808
1809static void c_parser_oacc_declare (c_parser *);
1810static void c_parser_oacc_enter_exit_data (c_parser *, bool);
1811static void c_parser_oacc_update (c_parser *);
1812static void c_parser_omp_construct (c_parser *, bool *);
1813static void c_parser_omp_threadprivate (c_parser *);
1814static void c_parser_omp_barrier (c_parser *);
1815static void c_parser_omp_depobj (c_parser *);
1816static void c_parser_omp_flush (c_parser *);
1817static bool c_parser_omp_next_tokens_can_be_canon_loop (c_parser *,
1818 enum tree_code, bool);
1819static tree c_parser_omp_loop_nest (c_parser *, bool *);
1820static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
1821 tree, tree *, bool *);
1822static void c_parser_omp_taskwait (c_parser *);
1823static void c_parser_omp_taskyield (c_parser *);
1824static void c_parser_omp_cancel (c_parser *);
1825static void c_parser_omp_nothing (c_parser *);
1826static void c_parser_omp_metadirective (c_parser *, bool *);
1827
1828enum pragma_context { pragma_external, pragma_struct, pragma_param,
1829 pragma_stmt, pragma_compound };
1830static bool c_parser_pragma (c_parser *, enum pragma_context, bool *, tree);
1831static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
1832static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
1833static void c_parser_omp_begin (c_parser *);
1834static void c_parser_omp_end (c_parser *);
1835static bool c_parser_omp_declare (c_parser *, enum pragma_context);
1836static void c_parser_omp_requires (c_parser *);
1837static bool c_parser_omp_error (c_parser *, enum pragma_context);
1838static void c_parser_omp_assumption_clauses (c_parser *, bool);
1839static void c_parser_omp_allocate (c_parser *);
1840static void c_parser_omp_assumes (c_parser *);
1841static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
1842static tree c_parser_omp_dispatch (location_t, c_parser *);
1843static void c_parser_omp_interop (c_parser *);
1844static void c_parser_oacc_routine (c_parser *, enum pragma_context);
1845
1846/* These Objective-C parser functions are only ever called when
1847 compiling Objective-C. */
1848static void c_parser_objc_class_definition (c_parser *, tree);
1849static void c_parser_objc_class_instance_variables (c_parser *);
1850static void c_parser_objc_class_declaration (c_parser *);
1851static void c_parser_objc_alias_declaration (c_parser *);
1852static void c_parser_objc_protocol_definition (c_parser *, tree);
1853static bool c_parser_objc_method_type (c_parser *);
1854static void c_parser_objc_method_definition (c_parser *);
1855static void c_parser_objc_methodprotolist (c_parser *);
1856static void c_parser_objc_methodproto (c_parser *);
1857static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
1858static tree c_parser_objc_type_name (c_parser *);
1859static tree c_parser_objc_protocol_refs (c_parser *);
1860static void c_parser_objc_try_catch_finally_statement (c_parser *);
1861static void c_parser_objc_synchronized_statement (c_parser *);
1862static tree c_parser_objc_selector (c_parser *);
1863static tree c_parser_objc_selector_arg (c_parser *);
1864static tree c_parser_objc_receiver (c_parser *);
1865static tree c_parser_objc_message_args (c_parser *);
1866static tree c_parser_objc_keywordexpr (c_parser *);
1867static void c_parser_objc_at_property_declaration (c_parser *);
1868static void c_parser_objc_at_synthesize_declaration (c_parser *);
1869static void c_parser_objc_at_dynamic_declaration (c_parser *);
1870static bool c_parser_objc_diagnose_bad_element_prefix
1871 (c_parser *, struct c_declspecs *);
1872static location_t c_parser_parse_rtl_body (c_parser *, char *);
1873static tree c_parser_handle_musttail (c_parser *, tree, attr_state &);
1874
1875#if ENABLE_ANALYZER
1876
1877namespace ana {
1878
1879/* Concrete implementation of ana::translation_unit for the C frontend. */
1880
1881class c_translation_unit : public translation_unit
1882{
1883public:
1884 /* Implementation of translation_unit::lookup_constant_by_id for use by the
1885 analyzer to look up named constants in the user's source code. */
1886 tree lookup_constant_by_id (tree id) const final override
1887 {
1888 /* Consider decls. */
1889 if (tree decl = lookup_name (id))
1890 if (TREE_CODE (decl) == CONST_DECL)
1891 if (tree value = DECL_INITIAL (decl))
1892 if (TREE_CODE (value) == INTEGER_CST)
1893 return value;
1894
1895 /* Consider macros. */
1896 cpp_hashnode *hashnode = C_CPP_HASHNODE (id);
1897 if (cpp_macro_p (node: hashnode))
1898 if (tree value = consider_macro (macro: hashnode->value.macro))
1899 return value;
1900
1901 return NULL_TREE;
1902 }
1903
1904 tree
1905 lookup_type_by_id (tree id) const final override
1906 {
1907 if (tree type_decl = lookup_name (id))
1908 if (TREE_CODE (type_decl) == TYPE_DECL)
1909 {
1910 tree record_type = TREE_TYPE (type_decl);
1911 if (TREE_CODE (record_type) == RECORD_TYPE)
1912 return record_type;
1913 }
1914
1915 return NULL_TREE;
1916 }
1917
1918 tree
1919 lookup_global_var_by_id (tree id) const final override
1920 {
1921 if (tree var_decl = lookup_name (id))
1922 if (TREE_CODE (var_decl) == VAR_DECL)
1923 return var_decl;
1924
1925 return NULL_TREE;
1926 }
1927
1928private:
1929 /* Attempt to get an INTEGER_CST from MACRO.
1930 Only handle the simplest cases: where MACRO's definition is a single
1931 token containing a number, by lexing the number again.
1932 This will handle e.g.
1933 #define NAME 42
1934 and other bases but not negative numbers, parentheses or e.g.
1935 #define NAME 1 << 7
1936 as doing so would require a parser. */
1937 tree consider_macro (cpp_macro *macro) const
1938 {
1939 if (macro->paramc > 0)
1940 return NULL_TREE;
1941 if (macro->kind != cmk_macro)
1942 return NULL_TREE;
1943 if (macro->count != 1)
1944 return NULL_TREE;
1945 const cpp_token &tok = macro->exp.tokens[0];
1946 if (tok.type != CPP_NUMBER)
1947 return NULL_TREE;
1948
1949 cpp_reader *old_parse_in = parse_in;
1950 parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
1951
1952 pretty_printer pp;
1953 pp_string (&pp, (const char *) tok.val.str.text);
1954 pp_newline (&pp);
1955 cpp_push_buffer (parse_in,
1956 (const unsigned char *) pp_formatted_text (&pp),
1957 strlen (s: pp_formatted_text (&pp)),
1958 0);
1959
1960 tree value;
1961 location_t loc;
1962 unsigned char cpp_flags;
1963 c_lex_with_flags (&value, &loc, &cpp_flags, 0);
1964
1965 cpp_destroy (parse_in);
1966 parse_in = old_parse_in;
1967
1968 if (value && TREE_CODE (value) == INTEGER_CST)
1969 return value;
1970
1971 return NULL_TREE;
1972 }
1973};
1974
1975} // namespace ana
1976
1977#endif /* #if ENABLE_ANALYZER */
1978
1979/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
1980
1981 translation-unit:
1982 external-declarations
1983
1984 external-declarations:
1985 external-declaration
1986 external-declarations external-declaration
1987
1988 GNU extensions:
1989
1990 translation-unit:
1991 empty
1992*/
1993
1994static void
1995c_parser_translation_unit (c_parser *parser)
1996{
1997 if (c_parser_next_token_is (parser, type: CPP_EOF))
1998 {
1999 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2000 "ISO C forbids an empty translation unit");
2001 }
2002 else
2003 {
2004 void *obstack_position = obstack_alloc (&parser_obstack, 0);
2005 mark_valid_location_for_stdc_pragma (false);
2006 do
2007 {
2008 ggc_collect ();
2009 c_parser_external_declaration (parser);
2010 obstack_free (&parser_obstack, obstack_position);
2011 }
2012 while (c_parser_next_token_is_not (parser, type: CPP_EOF));
2013 }
2014
2015 unsigned int i;
2016 tree decl;
2017 FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
2018 if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
2019 error ("storage size of %q+D isn%'t known", decl);
2020
2021 if (vec_safe_length (v: current_omp_declare_target_attribute))
2022 {
2023 c_omp_declare_target_attr
2024 a = current_omp_declare_target_attribute->pop ();
2025 if (!errorcount)
2026 error ("%qs without corresponding %qs",
2027 a.device_type >= 0 ? "#pragma omp begin declare target"
2028 : "#pragma omp declare target",
2029 "#pragma omp end declare target");
2030 vec_safe_truncate (v: current_omp_declare_target_attribute, size: 0);
2031 }
2032 if (vec_safe_length (v: current_omp_begin_assumes))
2033 {
2034 if (!errorcount)
2035 error ("%qs without corresponding %qs",
2036 "#pragma omp begin assumes", "#pragma omp end assumes");
2037 vec_safe_truncate (v: current_omp_begin_assumes, size: 0);
2038 }
2039
2040#if ENABLE_ANALYZER
2041 if (flag_analyzer)
2042 {
2043 ana::c_translation_unit tu;
2044 ana::on_finish_translation_unit (tu);
2045 }
2046#endif
2047}
2048
2049/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
2050
2051 external-declaration:
2052 function-definition
2053 declaration
2054
2055 GNU extensions:
2056
2057 external-declaration:
2058 asm-definition
2059 ;
2060 __extension__ external-declaration
2061
2062 Objective-C:
2063
2064 external-declaration:
2065 objc-class-definition
2066 objc-class-declaration
2067 objc-alias-declaration
2068 objc-protocol-definition
2069 objc-method-definition
2070 @end
2071*/
2072
2073static void
2074c_parser_external_declaration (c_parser *parser)
2075{
2076 int ext;
2077 switch (c_parser_peek_token (parser)->type)
2078 {
2079 case CPP_KEYWORD:
2080 switch (c_parser_peek_token (parser)->keyword)
2081 {
2082 case RID_EXTENSION:
2083 ext = disable_extension_diagnostics ();
2084 c_parser_consume_token (parser);
2085 c_parser_external_declaration (parser);
2086 restore_extension_diagnostics (flags: ext);
2087 break;
2088 case RID_ASM:
2089 c_parser_asm_definition (parser);
2090 break;
2091 case RID_AT_INTERFACE:
2092 case RID_AT_IMPLEMENTATION:
2093 gcc_assert (c_dialect_objc ());
2094 c_parser_objc_class_definition (parser, NULL_TREE);
2095 break;
2096 case RID_AT_CLASS:
2097 gcc_assert (c_dialect_objc ());
2098 c_parser_objc_class_declaration (parser);
2099 break;
2100 case RID_AT_ALIAS:
2101 gcc_assert (c_dialect_objc ());
2102 c_parser_objc_alias_declaration (parser);
2103 break;
2104 case RID_AT_PROTOCOL:
2105 gcc_assert (c_dialect_objc ());
2106 c_parser_objc_protocol_definition (parser, NULL_TREE);
2107 break;
2108 case RID_AT_PROPERTY:
2109 gcc_assert (c_dialect_objc ());
2110 c_parser_objc_at_property_declaration (parser);
2111 break;
2112 case RID_AT_SYNTHESIZE:
2113 gcc_assert (c_dialect_objc ());
2114 c_parser_objc_at_synthesize_declaration (parser);
2115 break;
2116 case RID_AT_DYNAMIC:
2117 gcc_assert (c_dialect_objc ());
2118 c_parser_objc_at_dynamic_declaration (parser);
2119 break;
2120 case RID_AT_END:
2121 gcc_assert (c_dialect_objc ());
2122 c_parser_consume_token (parser);
2123 objc_finish_implementation ();
2124 break;
2125 default:
2126 goto decl_or_fndef;
2127 }
2128 break;
2129 case CPP_SEMICOLON:
2130 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
2131 "ISO C does not allow extra %<;%> outside of a function");
2132 c_parser_consume_token (parser);
2133 break;
2134 case CPP_PRAGMA:
2135 mark_valid_location_for_stdc_pragma (true);
2136 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2137 mark_valid_location_for_stdc_pragma (false);
2138 break;
2139 case CPP_PLUS:
2140 case CPP_MINUS:
2141 if (c_dialect_objc ())
2142 {
2143 c_parser_objc_method_definition (parser);
2144 break;
2145 }
2146 /* Else fall through, and yield a syntax error trying to parse
2147 as a declaration or function definition. */
2148 /* FALLTHRU */
2149 default:
2150 decl_or_fndef:
2151 /* A declaration or a function definition (or, in Objective-C,
2152 an @interface or @protocol with prefix attributes). We can
2153 only tell which after parsing the declaration specifiers, if
2154 any, and the first declarator. */
2155 c_parser_declaration_or_fndef (parser, true, true, true, false, true,
2156 false);
2157 break;
2158 }
2159}
2160
2161static void c_parser_handle_directive_omp_attributes (tree &, vec<c_token> *&,
2162 vec<c_token> *);
2163static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
2164static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
2165
2166/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
2167
2168static void
2169add_debug_begin_stmt (location_t loc)
2170{
2171 /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
2172 if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
2173 return;
2174
2175 tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
2176 SET_EXPR_LOCATION (stmt, loc);
2177 add_stmt (stmt);
2178}
2179
2180/* Helper function for c_parser_declaration_or_fndef and
2181 Handle assume attribute(s). */
2182
2183static tree
2184handle_assume_attribute (location_t here, tree attrs, bool nested)
2185{
2186 if (nested)
2187 for (tree attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: attrs); attr;
2188 attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", TREE_CHAIN (attr)))
2189 {
2190 tree args = TREE_VALUE (attr);
2191 int nargs = list_length (args);
2192 if (nargs != 1)
2193 {
2194 error_at (here, "wrong number of arguments specified "
2195 "for %qE attribute",
2196 get_attribute_name (attr));
2197 inform (here, "expected %i, found %i", 1, nargs);
2198 }
2199 else
2200 {
2201 tree arg = TREE_VALUE (args);
2202 arg = c_objc_common_truthvalue_conversion (here, arg);
2203 arg = c_fully_fold (arg, false, NULL);
2204 if (arg != error_mark_node)
2205 {
2206 tree fn = build_call_expr_internal_loc (here, IFN_ASSUME,
2207 void_type_node, 1,
2208 arg);
2209 add_stmt (fn);
2210 }
2211 }
2212 }
2213 else
2214 pedwarn (here, OPT_Wattributes,
2215 "%<assume%> attribute at top level");
2216
2217 return remove_attribute ("gnu", "assume", attrs);
2218}
2219
2220/* We might need to reclassify any previously-lexed identifier, e.g.
2221 when we've left a for loop with an if-statement without else in the
2222 body - we might have used a wrong scope for the token. See PR67784. */
2223
2224static void
2225c_parser_maybe_reclassify_token (c_parser *parser)
2226{
2227 if (c_parser_next_token_is (parser, type: CPP_NAME))
2228 {
2229 c_token *token = c_parser_peek_token (parser);
2230
2231 if (token->id_kind != C_ID_CLASSNAME)
2232 {
2233 tree decl = lookup_name (token->value);
2234
2235 token->id_kind = C_ID_ID;
2236 if (decl)
2237 {
2238 if (TREE_CODE (decl) == TYPE_DECL)
2239 token->id_kind = C_ID_TYPENAME;
2240 }
2241 else if (c_dialect_objc ())
2242 {
2243 tree objc_interface_decl = objc_is_class_name (token->value);
2244 /* Objective-C class names are in the same namespace as
2245 variables and typedefs, and hence are shadowed by local
2246 declarations. */
2247 if (objc_interface_decl)
2248 {
2249 token->value = objc_interface_decl;
2250 token->id_kind = C_ID_CLASSNAME;
2251 }
2252 }
2253 }
2254 }
2255}
2256
2257/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
2258 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
2259 is accepted; otherwise (old-style parameter declarations) only other
2260 declarations are accepted. If STATIC_ASSERT_OK is true, a static
2261 assertion is accepted; otherwise (old-style parameter declarations)
2262 it is not. If NESTED is true, we are inside a function or parsing
2263 old-style parameter declarations; any functions encountered are
2264 nested functions and declaration specifiers are required; otherwise
2265 we are at top level and functions are normal functions and
2266 declaration specifiers may be optional. If EMPTY_OK is true, empty
2267 declarations are OK (subject to all other constraints); otherwise
2268 (old-style parameter declarations) they are diagnosed. If
2269 START_ATTR_OK is true, the declaration specifiers may start with
2270 attributes (GNU or standard); otherwise they may not.
2271 OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
2272 declaration when parsing an Objective-C foreach statement.
2273 FALLTHRU_ATTR_P is used to signal whether this function parsed
2274 "__attribute__((fallthrough));". ATTRS are any standard attributes
2275 parsed in the caller (in contexts where such attributes had to be
2276 parsed to determine whether what follows is a declaration or a
2277 statement); HAVE_ATTRS says whether there were any such attributes
2278 (even empty). If SIMPLE_OK, the construct can be a simple-declaration;
2279 in that case, the ';' is not consumed (left to the caller so that it
2280 can figure out if there was a simple-declaration or not), there must
2281 be an initializer, and only one object may be declared. When SIMPLE_OK
2282 is true we are called from c_parser_selection_header.
2283
2284 Returns the resulting declaration, if there was any with an initializer.
2285
2286 declaration:
2287 declaration-specifiers init-declarator-list[opt] ;
2288 static_assert-declaration
2289
2290 function-definition:
2291 declaration-specifiers[opt] declarator declaration-list[opt]
2292 compound-statement
2293
2294 declaration-list:
2295 declaration
2296 declaration-list declaration
2297
2298 init-declarator-list:
2299 init-declarator
2300 init-declarator-list , init-declarator
2301
2302 init-declarator:
2303 declarator simple-asm-expr[opt] gnu-attributes[opt]
2304 declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
2305
2306 simple-declaration:
2307 attribute-specifier-sequence[opt] declaration-specifiers declarator
2308 = initializer
2309
2310 GNU extensions:
2311
2312 nested-function-definition:
2313 declaration-specifiers declarator declaration-list[opt]
2314 compound-statement
2315
2316 attribute ;
2317
2318 Objective-C:
2319 gnu-attributes objc-class-definition
2320 gnu-attributes objc-category-definition
2321 gnu-attributes objc-protocol-definition
2322
2323 The simple-asm-expr and gnu-attributes are GNU extensions.
2324
2325 This function does not handle __extension__; that is handled in its
2326 callers. ??? Following the old parser, __extension__ may start
2327 external declarations, declarations in functions and declarations
2328 at the start of "for" loops, but not old-style parameter
2329 declarations.
2330
2331 C99 requires declaration specifiers in a function definition; the
2332 absence is diagnosed through the diagnosis of implicit int. In GNU
2333 C we also allow but diagnose declarations without declaration
2334 specifiers, but only at top level (elsewhere they conflict with
2335 other syntax).
2336
2337 In Objective-C, declarations of the looping variable in a foreach
2338 statement are exceptionally terminated by 'in' (for example, 'for
2339 (NSObject *object in array) { ... }').
2340
2341 OpenMP:
2342
2343 declaration:
2344 threadprivate-directive
2345
2346 GIMPLE:
2347
2348 gimple-function-definition:
2349 declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
2350 declaration-list[opt] compound-statement
2351
2352 rtl-function-definition:
2353 declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
2354 declaration-list[opt] compound-statement */
2355
2356static tree
2357c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
2358 bool static_assert_ok, bool empty_ok,
2359 bool nested, bool start_attr_ok,
2360 bool simple_ok,
2361 tree *objc_foreach_object_declaration
2362 /* = NULL */,
2363 vec<c_token> *omp_declare_simd_clauses
2364 /* = NULL */,
2365 bool have_attrs /* = false */,
2366 tree attrs /* = NULL_TREE */,
2367 struct oacc_routine_data *oacc_routine_data
2368 /* = NULL */,
2369 bool *fallthru_attr_p /* = NULL */)
2370{
2371 struct c_declspecs *specs;
2372 tree prefix_attrs;
2373 tree all_prefix_attrs;
2374 bool diagnosed_no_specs = false;
2375 location_t here = c_parser_peek_token (parser)->location;
2376 tree result = NULL_TREE;
2377
2378 add_debug_begin_stmt (loc: c_parser_peek_token (parser)->location);
2379
2380 if (static_assert_ok
2381 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
2382 {
2383 c_parser_static_assert_declaration (parser);
2384 return result;
2385 }
2386 specs = build_null_declspecs ();
2387
2388 /* Handle any standard attributes parsed in the caller. */
2389 if (have_attrs)
2390 {
2391 declspecs_add_attrs (here, specs, attrs);
2392 specs->non_std_attrs_seen_p = false;
2393 }
2394
2395 /* Try to detect an unknown type name when we have "A B" or "A *B". */
2396 if (c_parser_peek_token (parser)->type == CPP_NAME
2397 && c_parser_peek_token (parser)->id_kind == C_ID_ID
2398 && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
2399 || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
2400 && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
2401 {
2402 tree name = c_parser_peek_token (parser)->value;
2403
2404 /* Issue a warning about NAME being an unknown type name, perhaps
2405 with some kind of hint.
2406 If the user forgot a "struct" etc, suggest inserting
2407 it. Otherwise, attempt to look for misspellings. */
2408 gcc_rich_location richloc (here);
2409 if (tag_exists_p (RECORD_TYPE, name))
2410 {
2411 /* This is not C++ with its implicit typedef. */
2412 richloc.add_fixit_insert_before (new_content: "struct ");
2413 error_at (&richloc,
2414 "unknown type name %qE;"
2415 " use %<struct%> keyword to refer to the type",
2416 name);
2417 }
2418 else if (tag_exists_p (UNION_TYPE, name))
2419 {
2420 richloc.add_fixit_insert_before (new_content: "union ");
2421 error_at (&richloc,
2422 "unknown type name %qE;"
2423 " use %<union%> keyword to refer to the type",
2424 name);
2425 }
2426 else if (tag_exists_p (ENUMERAL_TYPE, name))
2427 {
2428 richloc.add_fixit_insert_before (new_content: "enum ");
2429 error_at (&richloc,
2430 "unknown type name %qE;"
2431 " use %<enum%> keyword to refer to the type",
2432 name);
2433 }
2434 else
2435 {
2436 auto_diagnostic_group d;
2437 name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
2438 here);
2439 if (const char *suggestion = hint.suggestion ())
2440 {
2441 richloc.add_fixit_replace (new_content: suggestion);
2442 error_at (&richloc,
2443 "unknown type name %qE; did you mean %qs?",
2444 name, suggestion);
2445 }
2446 else
2447 error_at (here, "unknown type name %qE", name);
2448 }
2449
2450 /* Parse declspecs normally to get a correct pointer type, but avoid
2451 a further "fails to be a type name" error. Refuse nested functions
2452 since it is not how the user likely wants us to recover. */
2453 c_parser_peek_token (parser)->type = CPP_KEYWORD;
2454 c_parser_peek_token (parser)->keyword = RID_VOID;
2455 c_parser_peek_token (parser)->value = error_mark_node;
2456 fndef_ok = !nested;
2457 }
2458
2459 /* When there are standard attributes at the start of the
2460 declaration (to apply to the entity being declared), an
2461 init-declarator-list or function definition must be present. */
2462 if (c_parser_nth_token_starts_std_attributes (parser, 1))
2463 have_attrs = true;
2464
2465 c_parser_declspecs (parser, specs, true, true, start_attr_ok,
2466 true, true, start_attr_ok, true, cla_nonabstract_decl);
2467 if (parser->error)
2468 {
2469 c_parser_skip_to_end_of_block_or_statement (parser);
2470 return result;
2471 }
2472 if (nested && !specs->declspecs_seen_p)
2473 {
2474 c_parser_error (parser, gmsgid: "expected declaration specifiers");
2475 c_parser_skip_to_end_of_block_or_statement (parser);
2476 return result;
2477 }
2478
2479 finish_declspecs (specs);
2480 bool gnu_auto_type_p = specs->typespec_word == cts_auto_type;
2481 bool std_auto_type_p = specs->c23_auto_p;
2482 bool any_auto_type_p = gnu_auto_type_p || std_auto_type_p;
2483 gcc_assert (!(gnu_auto_type_p && std_auto_type_p));
2484 const char *auto_type_keyword = gnu_auto_type_p ? "__auto_type" : "auto";
2485 if (specs->constexpr_p)
2486 {
2487 /* An underspecified declaration may not declare tags or members
2488 or structures or unions; it is undefined behavior to declare
2489 the members of an enumeration. Where the structure, union or
2490 enumeration type is declared within an initializer, this is
2491 diagnosed elsewhere. Diagnose here the case of declaring
2492 such a type in the type specifiers of a constexpr
2493 declaration. */
2494 switch (specs->typespec_kind)
2495 {
2496 case ctsk_tagfirstref:
2497 case ctsk_tagfirstref_attrs:
2498 error_at (here, "%qT declared in underspecified object declaration",
2499 specs->type);
2500 break;
2501
2502 case ctsk_tagdef:
2503 error_at (here, "%qT defined in underspecified object declaration",
2504 specs->type);
2505 break;
2506
2507 default:
2508 break;
2509 }
2510 }
2511
2512 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
2513 {
2514 bool handled_assume = false;
2515 if (specs->attrs
2516 && !nested
2517 && specs->typespec_kind == ctsk_none
2518 && c_parser_handle_statement_omp_attributes (parser, specs->attrs,
2519 NULL))
2520 {
2521 if (specs->attrs)
2522 c_warn_unused_attributes (specs->attrs);
2523 while (parser->in_omp_attribute_pragma)
2524 {
2525 gcc_assert (c_parser_next_token_is (parser, CPP_PRAGMA));
2526 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
2527 }
2528 c_parser_consume_token (parser);
2529 return result;
2530 }
2531 if (specs->typespec_kind == ctsk_none
2532 && lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2533 {
2534 handled_assume = true;
2535 specs->attrs
2536 = handle_assume_attribute (here, attrs: specs->attrs, nested);
2537 }
2538 if (any_auto_type_p)
2539 error_at (here, "%qs in empty declaration", auto_type_keyword);
2540 else if (specs->typespec_kind == ctsk_none
2541 && attribute_fallthrough_p (specs->attrs))
2542 {
2543 if (fallthru_attr_p != NULL)
2544 *fallthru_attr_p = true;
2545 if (nested)
2546 {
2547 tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
2548 void_type_node, 0);
2549 add_stmt (fn);
2550 }
2551 else
2552 pedwarn (here, OPT_Wattributes,
2553 "%<fallthrough%> attribute at top level");
2554 }
2555 else if (empty_ok
2556 && !(have_attrs && specs->non_std_attrs_seen_p)
2557 && !handled_assume)
2558 shadow_tag (specs);
2559 else
2560 {
2561 shadow_tag_warned (specs, 1);
2562 if (!handled_assume)
2563 pedwarn (here, 0, "empty declaration");
2564 }
2565 /* We still have to evaluate size expressions. */
2566 if (specs->expr)
2567 add_stmt (fold_convert (void_type_node, specs->expr));
2568 c_parser_consume_token (parser);
2569 if (oacc_routine_data)
2570 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2571 return result;
2572 }
2573 else if (specs->typespec_kind == ctsk_none
2574 && nested
2575 /* Only parse __attribute__((musttail)) when called from
2576 c_parser_compound_statement_nostart. This certainly isn't
2577 a declaration in that case, but we don't do tentative parsing
2578 of GNU attributes right now. */
2579 && fallthru_attr_p
2580 && c_parser_next_token_is_keyword (parser, keyword: RID_RETURN))
2581 {
2582 attr_state astate = {};
2583 specs->attrs = c_parser_handle_musttail (parser, specs->attrs, astate);
2584 if (astate.musttail_p)
2585 {
2586 if (specs->attrs)
2587 {
2588 auto_urlify_attributes sentinel;
2589 warning_at (c_parser_peek_token (parser)->location,
2590 OPT_Wattributes,
2591 "attribute %<musttail%> mixed with other attributes "
2592 "on %<return%> statement");
2593 }
2594 c_parser_statement_after_labels (parser, NULL, NULL_TREE, NULL,
2595 astate);
2596 return result;
2597 }
2598 }
2599
2600 /* Provide better error recovery. Note that a type name here is usually
2601 better diagnosed as a redeclaration. */
2602 if (empty_ok
2603 && specs->typespec_kind == ctsk_tagdef
2604 && c_parser_next_token_starts_declspecs (parser)
2605 && !c_parser_next_token_is (parser, type: CPP_NAME))
2606 {
2607 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
2608 parser->error = false;
2609 shadow_tag_warned (specs, 1);
2610 return result;
2611 }
2612 else if (c_dialect_objc () && !any_auto_type_p)
2613 {
2614 /* Prefix attributes are an error on method decls. */
2615 switch (c_parser_peek_token (parser)->type)
2616 {
2617 case CPP_PLUS:
2618 case CPP_MINUS:
2619 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2620 return result;
2621 if (specs->attrs)
2622 {
2623 warning_at (c_parser_peek_token (parser)->location,
2624 OPT_Wattributes,
2625 "prefix attributes are ignored for methods");
2626 specs->attrs = NULL_TREE;
2627 }
2628 if (fndef_ok)
2629 c_parser_objc_method_definition (parser);
2630 else
2631 c_parser_objc_methodproto (parser);
2632 return result;
2633 break;
2634 default:
2635 break;
2636 }
2637 /* This is where we parse 'attributes @interface ...',
2638 'attributes @implementation ...', 'attributes @protocol ...'
2639 (where attributes could be, for example, __attribute__
2640 ((deprecated)).
2641 */
2642 switch (c_parser_peek_token (parser)->keyword)
2643 {
2644 case RID_AT_INTERFACE:
2645 {
2646 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2647 return result;
2648 c_parser_objc_class_definition (parser, specs->attrs);
2649 return result;
2650 }
2651 break;
2652 case RID_AT_IMPLEMENTATION:
2653 {
2654 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2655 return result;
2656 if (specs->attrs)
2657 {
2658 warning_at (c_parser_peek_token (parser)->location,
2659 OPT_Wattributes,
2660 "prefix attributes are ignored for implementations");
2661 specs->attrs = NULL_TREE;
2662 }
2663 c_parser_objc_class_definition (parser, NULL_TREE);
2664 return result;
2665 }
2666 break;
2667 case RID_AT_PROTOCOL:
2668 {
2669 if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
2670 return result;
2671 c_parser_objc_protocol_definition (parser, specs->attrs);
2672 return result;
2673 }
2674 break;
2675 case RID_AT_ALIAS:
2676 case RID_AT_CLASS:
2677 case RID_AT_END:
2678 case RID_AT_PROPERTY:
2679 if (specs->attrs)
2680 {
2681 c_parser_error (parser, gmsgid: "unexpected attribute");
2682 specs->attrs = NULL;
2683 }
2684 break;
2685 default:
2686 break;
2687 }
2688 }
2689 else if (attribute_fallthrough_p (specs->attrs))
2690 warning_at (here, OPT_Wattributes,
2691 "%<fallthrough%> attribute not followed by %<;%>");
2692 else if (lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: specs->attrs))
2693 warning_at (here, OPT_Wattributes,
2694 "%<assume%> attribute not followed by %<;%>");
2695
2696 auto_vec<c_token> omp_declare_simd_attr_clauses;
2697 c_parser_handle_directive_omp_attributes (specs->attrs,
2698 omp_declare_simd_clauses,
2699 &omp_declare_simd_attr_clauses);
2700 pending_xref_error ();
2701 prefix_attrs = specs->attrs;
2702 all_prefix_attrs = prefix_attrs;
2703 specs->attrs = NULL_TREE;
2704 bool more_than_one_decl = false;
2705 while (true)
2706 {
2707 struct c_declarator *declarator;
2708 bool dummy = false;
2709 timevar_id_t tv;
2710 tree fnbody = NULL_TREE;
2711 tree underspec_name = NULL_TREE;
2712 auto_vec<c_token> omp_dsimd_idattr_clauses;
2713 /* Declaring either one or more declarators (in which case we
2714 should diagnose if there were no declaration specifiers) or a
2715 function definition (in which case the diagnostic for
2716 implicit int suffices). */
2717 declarator = c_parser_declarator (parser,
2718 type_seen_p: specs->typespec_kind != ctsk_none,
2719 kind: C_DTR_NORMAL, seen_id: &dummy);
2720 if (declarator == NULL)
2721 {
2722 if (omp_declare_simd_clauses)
2723 c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
2724 omp_declare_simd_clauses);
2725 if (oacc_routine_data)
2726 c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
2727 /* This check is here purely to improve the diagnostic. */
2728 if (!simple_ok)
2729 c_parser_skip_to_end_of_block_or_statement (parser);
2730 return result;
2731 }
2732 if (flag_openmp || flag_openmp_simd)
2733 {
2734 struct c_declarator *d = declarator;
2735 while (d->kind != cdk_id)
2736 d = d->declarator;
2737 vec<c_token> *dummy = NULL;
2738 c_parser_handle_directive_omp_attributes (d->u.id.attrs, dummy,
2739 &omp_dsimd_idattr_clauses);
2740 }
2741 if (gnu_auto_type_p && declarator->kind != cdk_id)
2742 {
2743 error_at (here,
2744 "%<__auto_type%> requires a plain identifier"
2745 " as declarator");
2746 c_parser_skip_to_end_of_block_or_statement (parser);
2747 return result;
2748 }
2749 if (std_auto_type_p)
2750 {
2751 struct c_declarator *d = declarator;
2752 while (d->kind == cdk_attrs)
2753 d = d->declarator;
2754 if (d->kind != cdk_id)
2755 {
2756 error_at (here,
2757 "%<auto%> requires a plain identifier, possibly with"
2758 " attributes, as declarator");
2759 c_parser_skip_to_end_of_block_or_statement (parser);
2760 return result;
2761 }
2762 underspec_name = d->u.id.id;
2763 }
2764 else if (specs->constexpr_p)
2765 {
2766 struct c_declarator *d = declarator;
2767 while (d->kind != cdk_id)
2768 d = d->declarator;
2769 underspec_name = d->u.id.id;
2770 }
2771 if (c_parser_next_token_is (parser, type: CPP_EQ)
2772 || c_parser_next_token_is (parser, type: CPP_COMMA)
2773 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
2774 || c_parser_next_token_is_keyword (parser, keyword: RID_ASM)
2775 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE)
2776 || c_parser_next_token_is_keyword (parser, keyword: RID_IN))
2777 {
2778 tree asm_name = NULL_TREE;
2779 tree postfix_attrs = NULL_TREE;
2780 if (!diagnosed_no_specs && !specs->declspecs_seen_p)
2781 {
2782 diagnosed_no_specs = true;
2783 pedwarn (here, 0, "data definition has no type or storage class");
2784 }
2785 /* Having seen a data definition, there cannot now be a
2786 function definition. */
2787 fndef_ok = false;
2788 if (c_parser_next_token_is_keyword (parser, keyword: RID_ASM))
2789 asm_name = c_parser_simple_asm_expr (parser);
2790 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
2791 {
2792 postfix_attrs = c_parser_gnu_attributes (parser);
2793 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
2794 {
2795 /* This means there is an attribute specifier after
2796 the declarator in a function definition. Provide
2797 some more information for the user. */
2798 error_at (here, "attributes should be specified before the "
2799 "declarator in a function definition");
2800 c_parser_skip_to_end_of_block_or_statement (parser);
2801 return result;
2802 }
2803 }
2804 if (c_parser_next_token_is (parser, type: CPP_EQ))
2805 {
2806 tree d;
2807 struct c_expr init;
2808 location_t init_loc;
2809 c_parser_consume_token (parser);
2810 if (any_auto_type_p)
2811 {
2812 init_loc = c_parser_peek_token (parser)->location;
2813 rich_location richloc (line_table, init_loc);
2814 unsigned int underspec_state = 0;
2815 if (std_auto_type_p)
2816 underspec_state =
2817 start_underspecified_init (init_loc, underspec_name);
2818 start_init (NULL_TREE, asm_name,
2819 (global_bindings_p ()
2820 || specs->storage_class == csc_static
2821 || specs->constexpr_p),
2822 specs->constexpr_p, &richloc);
2823 /* A parameter is initialized, which is invalid. Don't
2824 attempt to instrument the initializer. */
2825 int flag_sanitize_save = flag_sanitize;
2826 if (nested && !empty_ok)
2827 flag_sanitize = 0;
2828 init = c_parser_expr_no_commas (parser, NULL);
2829 if (std_auto_type_p)
2830 finish_underspecified_init (underspec_name,
2831 underspec_state);
2832 flag_sanitize = flag_sanitize_save;
2833 if (gnu_auto_type_p
2834 && TREE_CODE (init.value) == COMPONENT_REF
2835 && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
2836 error_at (here,
2837 "%<__auto_type%> used with a bit-field"
2838 " initializer");
2839 init = convert_lvalue_to_rvalue (init_loc, init, true, true,
2840 true);
2841 tree init_type = TREE_TYPE (init.value);
2842 bool vm_type = c_type_variably_modified_p (t: init_type);
2843 if (vm_type)
2844 init.value = save_expr (init.value);
2845 finish_init ();
2846 specs->typespec_kind = ctsk_typeof;
2847 specs->locations[cdw_typedef] = init_loc;
2848 specs->typedef_p = true;
2849 specs->type = init_type;
2850 if (specs->postfix_attrs)
2851 {
2852 /* Postfix [[]] attributes are valid with C23
2853 auto, although not with __auto_type, and
2854 modify the type given by the initializer. */
2855 specs->postfix_attrs
2856 = c_warn_type_attributes (specs->type,
2857 specs->postfix_attrs);
2858 decl_attributes (&specs->type, specs->postfix_attrs, 0);
2859 specs->postfix_attrs = NULL_TREE;
2860 }
2861 if (vm_type)
2862 {
2863 bool maybe_const = true;
2864 tree type_expr = c_fully_fold (init.value, false,
2865 &maybe_const);
2866 specs->expr_const_operands &= maybe_const;
2867 if (specs->expr)
2868 specs->expr = build2 (COMPOUND_EXPR,
2869 TREE_TYPE (type_expr),
2870 specs->expr, type_expr);
2871 else
2872 specs->expr = type_expr;
2873 }
2874 d = start_decl (declarator, specs, true,
2875 chainon (postfix_attrs, all_prefix_attrs));
2876 if (!d)
2877 d = error_mark_node;
2878 if (omp_declare_simd_clauses)
2879 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2880 omp_declare_simd_clauses);
2881 if (!omp_dsimd_idattr_clauses.is_empty ())
2882 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2883 &omp_dsimd_idattr_clauses);
2884 }
2885 else
2886 {
2887 /* The declaration of the variable is in effect while
2888 its initializer is parsed, except for a constexpr
2889 variable. */
2890 init_loc = c_parser_peek_token (parser)->location;
2891 rich_location richloc (line_table, init_loc);
2892 unsigned int underspec_state = 0;
2893 if (specs->constexpr_p)
2894 underspec_state =
2895 start_underspecified_init (init_loc, underspec_name);
2896 d = start_decl (declarator, specs, true,
2897 chainon (postfix_attrs,
2898 all_prefix_attrs),
2899 !specs->constexpr_p);
2900 if (!d)
2901 d = error_mark_node;
2902 if (!specs->constexpr_p && omp_declare_simd_clauses)
2903 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2904 omp_declare_simd_clauses);
2905 if (!specs->constexpr_p
2906 && !omp_dsimd_idattr_clauses.is_empty ())
2907 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2908 &omp_dsimd_idattr_clauses);
2909 start_init (d, asm_name,
2910 TREE_STATIC (d) || specs->constexpr_p,
2911 specs->constexpr_p, &richloc);
2912 /* A parameter is initialized, which is invalid. Don't
2913 attempt to instrument the initializer. */
2914 int flag_sanitize_save = flag_sanitize;
2915 if (TREE_CODE (d) == PARM_DECL)
2916 flag_sanitize = 0;
2917 init = c_parser_initializer (parser, d);
2918 flag_sanitize = flag_sanitize_save;
2919 if (specs->constexpr_p)
2920 {
2921 finish_underspecified_init (underspec_name,
2922 underspec_state);
2923 d = pushdecl (d);
2924 if (omp_declare_simd_clauses)
2925 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2926 omp_declare_simd_clauses);
2927 if (!specs->constexpr_p
2928 && !omp_dsimd_idattr_clauses.is_empty ())
2929 c_finish_omp_declare_simd (parser, d, NULL_TREE,
2930 &omp_dsimd_idattr_clauses);
2931 }
2932 finish_init ();
2933 }
2934 if (oacc_routine_data)
2935 c_finish_oacc_routine (oacc_routine_data, d, false);
2936 if (d != error_mark_node)
2937 {
2938 maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
2939 finish_decl (d, init_loc, init.value,
2940 init.original_type, asm_name);
2941 result = d;
2942 }
2943 }
2944 else
2945 {
2946 if (any_auto_type_p || specs->constexpr_p)
2947 {
2948 error_at (here,
2949 "%qs requires an initialized data declaration",
2950 any_auto_type_p ? auto_type_keyword : "constexpr");
2951 c_parser_skip_to_end_of_block_or_statement (parser);
2952 return result;
2953 }
2954
2955 location_t lastloc = UNKNOWN_LOCATION;
2956 tree attrs = chainon (postfix_attrs, all_prefix_attrs);
2957 tree d = start_decl (declarator, specs, false, attrs, true,
2958 &lastloc);
2959 if (d && TREE_CODE (d) == FUNCTION_DECL)
2960 {
2961 /* Find the innermost declarator that is neither cdk_id
2962 nor cdk_attrs. */
2963 const struct c_declarator *decl = declarator;
2964 const struct c_declarator *last_non_id_attrs = NULL;
2965
2966 while (decl)
2967 switch (decl->kind)
2968 {
2969 case cdk_array:
2970 case cdk_function:
2971 case cdk_pointer:
2972 last_non_id_attrs = decl;
2973 decl = decl->declarator;
2974 break;
2975
2976 case cdk_attrs:
2977 decl = decl->declarator;
2978 break;
2979
2980 case cdk_id:
2981 decl = 0;
2982 break;
2983
2984 default:
2985 gcc_unreachable ();
2986 }
2987
2988 /* If it exists and is cdk_function declaration whose
2989 arguments have not been set yet, use its arguments. */
2990 if (last_non_id_attrs
2991 && last_non_id_attrs->kind == cdk_function)
2992 {
2993 tree parms = last_non_id_attrs->u.arg_info->parms;
2994 if (DECL_ARGUMENTS (d) == NULL_TREE
2995 && DECL_INITIAL (d) == NULL_TREE)
2996 DECL_ARGUMENTS (d) = parms;
2997
2998 warn_parm_array_mismatch (lastloc, d, parms);
2999 }
3000 }
3001 if (omp_declare_simd_clauses
3002 || !omp_dsimd_idattr_clauses.is_empty ())
3003 {
3004 tree parms = NULL_TREE;
3005 if (d && TREE_CODE (d) == FUNCTION_DECL)
3006 {
3007 struct c_declarator *ce = declarator;
3008 while (ce != NULL)
3009 if (ce->kind == cdk_function)
3010 {
3011 parms = ce->u.arg_info->parms;
3012 break;
3013 }
3014 else
3015 ce = ce->declarator;
3016 }
3017 if (parms)
3018 temp_store_parm_decls (d, parms);
3019 if (omp_declare_simd_clauses)
3020 c_finish_omp_declare_simd (parser, d, parms,
3021 omp_declare_simd_clauses);
3022 if (!specs->constexpr_p
3023 && !omp_dsimd_idattr_clauses.is_empty ())
3024 c_finish_omp_declare_simd (parser, d, parms,
3025 &omp_dsimd_idattr_clauses);
3026 if (parms)
3027 temp_pop_parm_decls ();
3028 }
3029 if (oacc_routine_data)
3030 c_finish_oacc_routine (oacc_routine_data, d, false);
3031 if (d)
3032 finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
3033 NULL_TREE, asm_name);
3034
3035 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
3036 {
3037 if (d)
3038 *objc_foreach_object_declaration = d;
3039 else
3040 *objc_foreach_object_declaration = error_mark_node;
3041 }
3042 }
3043 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3044 {
3045 more_than_one_decl = true;
3046 if (any_auto_type_p || specs->constexpr_p)
3047 {
3048 error_at (here,
3049 "%qs may only be used with a single declarator",
3050 any_auto_type_p ? auto_type_keyword : "constexpr");
3051 c_parser_skip_to_end_of_block_or_statement (parser);
3052 return result;
3053 }
3054 c_parser_consume_token (parser);
3055 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
3056 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
3057 prefix_attrs);
3058 else
3059 all_prefix_attrs = prefix_attrs;
3060 continue;
3061 }
3062 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
3063 {
3064 if (!simple_ok)
3065 c_parser_consume_token (parser);
3066 return result;
3067 }
3068 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
3069 {
3070 /* This can only happen in Objective-C: we found the
3071 'in' that terminates the declaration inside an
3072 Objective-C foreach statement. Do not consume the
3073 token, so that the caller can use it to determine
3074 that this indeed is a foreach context. */
3075 return result;
3076 }
3077 else
3078 {
3079 if (!simple_ok)
3080 {
3081 c_parser_error (parser, gmsgid: "expected %<,%> or %<;%>");
3082 c_parser_skip_to_end_of_block_or_statement (parser);
3083 }
3084 /* It's not valid to use if (int i = 2, j = 3). */
3085 else if (more_than_one_decl)
3086 error_at (here, "declaration in condition can only declare "
3087 "a single object");
3088 return result;
3089 }
3090 }
3091 else if (any_auto_type_p || specs->constexpr_p)
3092 {
3093 error_at (here,
3094 "%qs requires an initialized data declaration",
3095 any_auto_type_p ? auto_type_keyword : "constexpr");
3096 c_parser_skip_to_end_of_block_or_statement (parser);
3097 return result;
3098 }
3099 else if (!fndef_ok)
3100 {
3101 if (simple_ok && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3102 /* Let c_parser_selection_header emit the error. */;
3103 else
3104 {
3105 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, "
3106 "%<asm%> or %<__attribute__%>");
3107 c_parser_skip_to_end_of_block_or_statement (parser);
3108 }
3109 return result;
3110 }
3111 /* Function definition (nested or otherwise). */
3112 if (nested)
3113 {
3114 pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
3115 c_push_function_context ();
3116 }
3117 if (!start_function (specs, declarator, all_prefix_attrs))
3118 {
3119 /* At this point we've consumed:
3120 declaration-specifiers declarator
3121 and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
3122 RID_ASM, RID_ATTRIBUTE, or RID_IN,
3123 but the
3124 declaration-specifiers declarator
3125 aren't grokkable as a function definition, so we have
3126 an error. */
3127 gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
3128 if (c_parser_next_token_starts_declspecs (parser))
3129 {
3130 /* If we have
3131 declaration-specifiers declarator decl-specs
3132 then assume we have a missing semicolon, which would
3133 give us:
3134 declaration-specifiers declarator decl-specs
3135 ^
3136 ;
3137 <~~~~~~~~~ declaration ~~~~~~~~~~>
3138 Use c_parser_require to get an error with a fix-it hint. */
3139 c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
3140 parser->error = false;
3141 }
3142 else
3143 {
3144 /* This can appear in many cases looking nothing like a
3145 function definition, so we don't give a more specific
3146 error suggesting there was one. */
3147 c_parser_error (parser, gmsgid: "expected %<=%>, %<,%>, %<;%>, %<asm%> "
3148 "or %<__attribute__%>");
3149 }
3150 if (nested)
3151 c_pop_function_context ();
3152 break;
3153 }
3154
3155 if (DECL_DECLARED_INLINE_P (current_function_decl))
3156 tv = TV_PARSE_INLINE;
3157 else
3158 tv = TV_PARSE_FUNC;
3159 auto_timevar at (g_timer, tv);
3160
3161 /* Parse old-style parameter declarations. ??? Attributes are
3162 not allowed to start declaration specifiers here because of a
3163 syntax conflict between a function declaration with attribute
3164 suffix and a function definition with an attribute prefix on
3165 first old-style parameter declaration. Following the old
3166 parser, they are not accepted on subsequent old-style
3167 parameter declarations either. However, there is no
3168 ambiguity after the first declaration, nor indeed on the
3169 first as long as we don't allow postfix attributes after a
3170 declarator with a nonempty identifier list in a definition;
3171 and postfix attributes have never been accepted here in
3172 function definitions either. */
3173 int save_debug_nonbind_markers_p = debug_nonbind_markers_p;
3174 debug_nonbind_markers_p = 0;
3175 c_parser_maybe_reclassify_token (parser);
3176 while (c_parser_next_token_is_not (parser, type: CPP_EOF)
3177 && c_parser_next_token_is_not (parser, type: CPP_OPEN_BRACE))
3178 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: false,
3179 nested: true, start_attr_ok: false, simple_ok: false);
3180 debug_nonbind_markers_p = save_debug_nonbind_markers_p;
3181 store_parm_decls ();
3182 if (omp_declare_simd_clauses)
3183 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3184 omp_declare_simd_clauses);
3185 if (!omp_dsimd_idattr_clauses.is_empty ())
3186 c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
3187 &omp_dsimd_idattr_clauses);
3188 if (oacc_routine_data)
3189 c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
3190 location_t startloc = c_parser_peek_token (parser)->location;
3191 DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
3192 = startloc;
3193 location_t endloc = startloc;
3194
3195 /* If the definition was marked with __RTL, use the RTL parser now,
3196 consuming the function body. */
3197 if (specs->declspec_il == cdil_rtl)
3198 {
3199 endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
3200
3201 /* Normally, store_parm_decls sets next_is_function_body,
3202 anticipating a function body. We need a push_scope/pop_scope
3203 pair to flush out this state, or subsequent function parsing
3204 will go wrong. */
3205 push_scope ();
3206 pop_scope ();
3207
3208 finish_function (endloc);
3209 return result;
3210 }
3211 /* If the definition was marked with __GIMPLE then parse the
3212 function body as GIMPLE. */
3213 else if (specs->declspec_il != cdil_none)
3214 {
3215 bool saved = in_late_binary_op;
3216 in_late_binary_op = true;
3217 c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
3218 specs->declspec_il,
3219 specs->entry_bb_count);
3220 in_late_binary_op = saved;
3221 }
3222 else
3223 fnbody = c_parser_compound_statement (parser, &endloc);
3224 tree fndecl = current_function_decl;
3225 if (nested)
3226 {
3227 tree decl = current_function_decl;
3228 /* Mark nested functions as needing static-chain initially.
3229 lower_nested_functions will recompute it but the
3230 DECL_STATIC_CHAIN flag is also used before that happens,
3231 by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
3232 DECL_STATIC_CHAIN (decl) = 1;
3233 add_stmt (fnbody);
3234 finish_function (endloc);
3235 c_pop_function_context ();
3236 add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
3237 }
3238 else
3239 {
3240 if (fnbody)
3241 add_stmt (fnbody);
3242 finish_function (endloc);
3243 }
3244 /* Get rid of the empty stmt list for GIMPLE/RTL. */
3245 if (specs->declspec_il != cdil_none)
3246 DECL_SAVED_TREE (fndecl) = NULL_TREE;
3247
3248 break;
3249 }
3250
3251 return result;
3252}
3253
3254/* Parse an asm-definition (asm() outside a function body). This is a
3255 GNU extension.
3256
3257 asm-definition:
3258 simple-asm-expr ;
3259 asm ( toplevel-asm-argument ) ;
3260
3261 toplevel-asm-argument:
3262 asm-string-literal
3263 asm-string-literal : asm-operands[opt]
3264 asm-string-literal : asm-operands[opt] : asm-operands[opt]
3265
3266 The :: token is considered equivalent to two consecutive : tokens. */
3267
3268static void
3269c_parser_asm_definition (c_parser *parser)
3270{
3271 location_t asm_loc = c_parser_peek_token (parser)->location;
3272 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
3273 c_parser_consume_token (parser);
3274 matching_parens parens;
3275 tree asm_str = NULL_TREE;
3276 tree outputs = NULL_TREE, inputs = NULL_TREE;
3277 if (!parens.require_open (parser))
3278 goto done;
3279 asm_str = c_parser_asm_string_literal (parser);
3280 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3281 {
3282 parens.require_close (parser);
3283 goto done;
3284 }
3285 for (int section = 0; section < 2; ++section)
3286 {
3287 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
3288 {
3289 ++section;
3290 if (section == 2)
3291 {
3292 c_parser_error (parser, gmsgid: "expected %<)%>");
3293 error_close_paren:
3294 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
3295 asm_str = NULL_TREE;
3296 goto done;
3297 }
3298 c_parser_consume_token (parser);
3299 }
3300 else if (!c_parser_require (parser, type: CPP_COLON,
3301 msgid: "expected %<:%> or %<)%>",
3302 UNKNOWN_LOCATION, type_is_unique: false))
3303 goto error_close_paren;
3304 if (!c_parser_next_token_is (parser, type: CPP_COLON)
3305 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
3306 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3307 {
3308 if (section)
3309 inputs = c_parser_asm_operands (parser);
3310 else
3311 outputs = c_parser_asm_operands (parser);
3312 }
3313 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
3314 break;
3315 }
3316
3317 if (!parens.require_close (parser))
3318 {
3319 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
3320 asm_str = NULL_TREE;
3321 }
3322
3323 if (asm_str)
3324 asm_str = build_asm_expr (asm_loc, asm_str, outputs, inputs,
3325 NULL_TREE, NULL_TREE, false, false);
3326done:
3327 if (asm_str)
3328 symtab->finalize_toplevel_asm (asm_str);
3329 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
3330}
3331
3332/* Parse a static assertion (C11 6.7.10).
3333
3334 static_assert-declaration:
3335 static_assert-declaration-no-semi ;
3336*/
3337
3338static void
3339c_parser_static_assert_declaration (c_parser *parser)
3340{
3341 c_parser_static_assert_declaration_no_semi (parser);
3342 if (parser->error
3343 || !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
3344 c_parser_skip_to_end_of_block_or_statement (parser);
3345}
3346
3347/* Parse a static assertion (C11 6.7.10), without the trailing
3348 semicolon.
3349
3350 static_assert-declaration-no-semi:
3351 _Static_assert ( constant-expression , string-literal )
3352
3353 C23:
3354 static_assert-declaration-no-semi:
3355 _Static_assert ( constant-expression )
3356*/
3357
3358static void
3359c_parser_static_assert_declaration_no_semi (c_parser *parser)
3360{
3361 location_t assert_loc, value_loc;
3362 tree value;
3363 tree string = NULL_TREE;
3364
3365 gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
3366 tree spelling = c_parser_peek_token (parser)->value;
3367 assert_loc = c_parser_peek_token (parser)->location;
3368 if (flag_isoc99)
3369 pedwarn_c99 (assert_loc, OPT_Wpedantic,
3370 "ISO C99 does not support %qE", spelling);
3371 else
3372 pedwarn_c99 (assert_loc, OPT_Wpedantic,
3373 "ISO C90 does not support %qE", spelling);
3374 c_parser_consume_token (parser);
3375 matching_parens parens;
3376 if (!parens.require_open (parser))
3377 return;
3378 location_t value_tok_loc = c_parser_peek_token (parser)->location;
3379 value = convert_lvalue_to_rvalue (value_tok_loc,
3380 c_parser_expr_no_commas (parser, NULL),
3381 true, true).value;
3382 value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
3383 if (c_parser_next_token_is (parser, type: CPP_COMMA))
3384 {
3385 c_parser_consume_token (parser);
3386 switch (c_parser_peek_token (parser)->type)
3387 {
3388 case CPP_STRING:
3389 case CPP_STRING16:
3390 case CPP_STRING32:
3391 case CPP_WSTRING:
3392 case CPP_UTF8STRING:
3393 string = c_parser_string_literal (parser, false, true).value;
3394 break;
3395 default:
3396 c_parser_error (parser, gmsgid: "expected string literal");
3397 return;
3398 }
3399 }
3400 else if (flag_isoc11)
3401 /* If pedantic for pre-C11, the use of _Static_assert itself will
3402 have been diagnosed, so do not also diagnose the use of this
3403 new C23 feature of _Static_assert. */
3404 pedwarn_c11 (assert_loc, OPT_Wpedantic,
3405 "ISO C11 does not support omitting the string in "
3406 "%qE", spelling);
3407 parens.require_close (parser);
3408
3409 if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
3410 {
3411 error_at (value_loc, "expression in static assertion is not an integer");
3412 return;
3413 }
3414 if (TREE_CODE (value) != INTEGER_CST)
3415 {
3416 value = c_fully_fold (value, false, NULL);
3417 /* Strip no-op conversions. */
3418 STRIP_TYPE_NOPS (value);
3419 if (TREE_CODE (value) == INTEGER_CST)
3420 pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
3421 "is not an integer constant expression");
3422 }
3423 if (TREE_CODE (value) != INTEGER_CST)
3424 {
3425 error_at (value_loc, "expression in static assertion is not constant");
3426 return;
3427 }
3428 constant_expression_warning (value);
3429 if (integer_zerop (value))
3430 {
3431 if (string)
3432 error_at (assert_loc, "static assertion failed: %E", string);
3433 else
3434 error_at (assert_loc, "static assertion failed");
3435 }
3436}
3437
3438/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
3439 6.7, C11 6.7), adding them to SPECS (which may already include some).
3440 Storage class specifiers are accepted iff SCSPEC_OK; type
3441 specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
3442 accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
3443 iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
3444 addition to the syntax shown, standard attributes are accepted at
3445 the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
3446 unlike gnu-attributes, they are not accepted in the middle of the
3447 list. (This combines various different syntax productions in the C
3448 standard, and in some cases gnu-attributes and standard attributes
3449 at the start may already have been parsed before this function is
3450 called.)
3451
3452 declaration-specifiers:
3453 storage-class-specifier declaration-specifiers[opt]
3454 type-specifier declaration-specifiers[opt]
3455 type-qualifier declaration-specifiers[opt]
3456 function-specifier declaration-specifiers[opt]
3457 alignment-specifier declaration-specifiers[opt]
3458
3459 Function specifiers (inline) are from C99, and are currently
3460 handled as storage class specifiers, as is __thread. Alignment
3461 specifiers are from C11.
3462
3463 C90 6.5.1, C99 6.7.1, C11 6.7.1:
3464 storage-class-specifier:
3465 typedef
3466 extern
3467 static
3468 auto
3469 register
3470 _Thread_local
3471
3472 (_Thread_local is new in C11.)
3473
3474 C99 6.7.4, C11 6.7.4:
3475 function-specifier:
3476 inline
3477 _Noreturn
3478
3479 (_Noreturn is new in C11.)
3480
3481 C90 6.5.2, C99 6.7.2, C11 6.7.2:
3482 type-specifier:
3483 void
3484 char
3485 short
3486 int
3487 long
3488 float
3489 double
3490 signed
3491 unsigned
3492 _Bool
3493 _Complex
3494 [_Imaginary removed in C99 TC2]
3495 _BitInt ( constant-expression )
3496 struct-or-union-specifier
3497 enum-specifier
3498 typedef-name
3499 atomic-type-specifier
3500
3501 (_Bool and _Complex are new in C99.)
3502 (atomic-type-specifier is new in C11.)
3503 (_BitInt is new in C23.)
3504
3505 C90 6.5.3, C99 6.7.3, C11 6.7.3:
3506
3507 type-qualifier:
3508 const
3509 restrict
3510 volatile
3511 address-space-qualifier
3512 _Atomic
3513
3514 (restrict is new in C99.)
3515 (_Atomic is new in C11.)
3516
3517 GNU extensions:
3518
3519 declaration-specifiers:
3520 gnu-attributes declaration-specifiers[opt]
3521
3522 type-qualifier:
3523 address-space
3524
3525 address-space:
3526 identifier recognized by the target
3527
3528 storage-class-specifier:
3529 __thread
3530
3531 type-specifier:
3532 typeof-specifier
3533 __auto_type
3534 __intN
3535 _Decimal32
3536 _Decimal64
3537 _Decimal128
3538 _Fract
3539 _Accum
3540 _Sat
3541
3542 (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
3543 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
3544
3545 atomic-type-specifier
3546 _Atomic ( type-name )
3547
3548 Objective-C:
3549
3550 type-specifier:
3551 class-name objc-protocol-refs[opt]
3552 typedef-name objc-protocol-refs
3553 objc-protocol-refs
3554*/
3555
3556void
3557c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
3558 bool scspec_ok, bool typespec_ok, bool start_attr_ok,
3559 bool alignspec_ok, bool auto_type_ok,
3560 bool start_std_attr_ok, bool end_std_attr_ok,
3561 enum c_lookahead_kind la)
3562{
3563 bool attrs_ok = start_attr_ok;
3564 bool seen_type = specs->typespec_kind != ctsk_none;
3565
3566 if (!typespec_ok)
3567 gcc_assert (la == cla_prefer_id);
3568
3569 if (start_std_attr_ok
3570 && c_parser_nth_token_starts_std_attributes (parser, 1))
3571 {
3572 gcc_assert (!specs->non_std_attrs_seen_p);
3573 location_t loc = c_parser_peek_token (parser)->location;
3574 tree attrs = c_parser_std_attribute_specifier_sequence (parser);
3575 declspecs_add_attrs (loc, specs, attrs);
3576 specs->non_std_attrs_seen_p = false;
3577 }
3578
3579 while (c_parser_next_token_is (parser, type: CPP_NAME)
3580 || c_parser_next_token_is (parser, type: CPP_KEYWORD)
3581 || (c_dialect_objc () && c_parser_next_token_is (parser, type: CPP_LESS)))
3582 {
3583 struct c_typespec t;
3584 tree attrs;
3585 tree align;
3586 location_t loc = c_parser_peek_token (parser)->location;
3587
3588 /* If we cannot accept a type, exit if the next token must start
3589 one. Also, if we already have seen a tagged definition,
3590 a typename would be an error anyway and likely the user
3591 has simply forgotten a semicolon, so we exit. */
3592 if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
3593 && c_parser_next_tokens_start_typename (parser, la)
3594 && !c_parser_next_token_is_qualifier (parser)
3595 && !c_parser_next_token_is_keyword (parser, keyword: RID_ALIGNAS))
3596 break;
3597
3598 if (c_parser_next_token_is (parser, type: CPP_NAME))
3599 {
3600 c_token *name_token = c_parser_peek_token (parser);
3601 tree value = name_token->value;
3602 c_id_kind kind = name_token->id_kind;
3603
3604 if (kind == C_ID_ADDRSPACE)
3605 {
3606 addr_space_t as
3607 = name_token->keyword - RID_FIRST_ADDR_SPACE;
3608 declspecs_add_addrspace (name_token->location, specs, as);
3609 c_parser_consume_token (parser);
3610 attrs_ok = true;
3611 continue;
3612 }
3613
3614 gcc_assert (!c_parser_next_token_is_qualifier (parser));
3615
3616 /* If we cannot accept a type, and the next token must start one,
3617 exit. Do the same if we already have seen a tagged definition,
3618 since it would be an error anyway and likely the user has simply
3619 forgotten a semicolon. */
3620 if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
3621 break;
3622
3623 /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
3624 a C_ID_CLASSNAME. */
3625 c_parser_consume_token (parser);
3626 seen_type = true;
3627 attrs_ok = true;
3628 if (kind == C_ID_ID)
3629 {
3630 auto_diagnostic_group d;
3631 name_hint hint = lookup_name_fuzzy (value, FUZZY_LOOKUP_TYPENAME,
3632 loc);
3633 if (const char *suggestion = hint.suggestion ())
3634 {
3635 gcc_rich_location richloc (loc);
3636 richloc.add_fixit_replace (new_content: suggestion);
3637 error_at (&richloc,
3638 "unknown type name %qE; did you mean %qs?",
3639 value, suggestion);
3640 }
3641 else
3642 error_at (loc, "unknown type name %qE", value);
3643 t.kind = ctsk_typedef;
3644 t.spec = error_mark_node;
3645 }
3646 else if (kind == C_ID_TYPENAME
3647 && (!c_dialect_objc ()
3648 || c_parser_next_token_is_not (parser, type: CPP_LESS)))
3649 {
3650 t.kind = ctsk_typedef;
3651 /* For a typedef name, record the meaning, not the name.
3652 In case of 'foo foo, bar;'. */
3653 t.spec = lookup_name (value);
3654 }
3655 else
3656 {
3657 tree proto = NULL_TREE;
3658 gcc_assert (c_dialect_objc ());
3659 t.kind = ctsk_objc;
3660 if (c_parser_next_token_is (parser, type: CPP_LESS))
3661 proto = c_parser_objc_protocol_refs (parser);
3662 t.spec = objc_get_protocol_qualified_type (value, proto);
3663 }
3664 t.expr = NULL_TREE;
3665 t.expr_const_operands = true;
3666 t.has_enum_type_specifier = false;
3667 declspecs_add_type (name_token->location, specs, t);
3668 continue;
3669 }
3670 if (c_parser_next_token_is (parser, type: CPP_LESS))
3671 {
3672 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
3673 nisse@lysator.liu.se. */
3674 tree proto;
3675 gcc_assert (c_dialect_objc ());
3676 if (!typespec_ok || seen_type)
3677 break;
3678 proto = c_parser_objc_protocol_refs (parser);
3679 t.kind = ctsk_objc;
3680 t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
3681 t.expr = NULL_TREE;
3682 t.expr_const_operands = true;
3683 t.has_enum_type_specifier = false;
3684 declspecs_add_type (loc, specs, t);
3685 continue;
3686 }
3687 gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
3688 switch (c_parser_peek_token (parser)->keyword)
3689 {
3690 case RID_STATIC:
3691 case RID_EXTERN:
3692 case RID_REGISTER:
3693 case RID_TYPEDEF:
3694 case RID_INLINE:
3695 case RID_NORETURN:
3696 case RID_AUTO:
3697 case RID_THREAD:
3698 case RID_CONSTEXPR:
3699 if (!scspec_ok)
3700 goto out;
3701 attrs_ok = true;
3702 /* TODO: Distinguish between function specifiers (inline, noreturn)
3703 and storage class specifiers, either here or in
3704 declspecs_add_scspec. */
3705 declspecs_add_scspec (loc, specs,
3706 c_parser_peek_token (parser)->value);
3707 c_parser_consume_token (parser);
3708 break;
3709 case RID_AUTO_TYPE:
3710 if (!auto_type_ok)
3711 goto out;
3712 /* Fall through. */
3713 case RID_UNSIGNED:
3714 case RID_LONG:
3715 case RID_SHORT:
3716 case RID_SIGNED:
3717 case RID_COMPLEX:
3718 case RID_INT:
3719 case RID_CHAR:
3720 case RID_FLOAT:
3721 case RID_DOUBLE:
3722 case RID_VOID:
3723 case RID_DFLOAT32:
3724 case RID_DFLOAT64:
3725 case RID_DFLOAT128:
3726 case RID_DFLOAT64X:
3727 CASE_RID_FLOATN_NX:
3728 case RID_BOOL:
3729 case RID_FRACT:
3730 case RID_ACCUM:
3731 case RID_SAT:
3732 case RID_INT_N_0:
3733 case RID_INT_N_1:
3734 case RID_INT_N_2:
3735 case RID_INT_N_3:
3736 if (!typespec_ok)
3737 goto out;
3738 attrs_ok = true;
3739 seen_type = true;
3740 if (c_dialect_objc ())
3741 parser->objc_need_raw_identifier = true;
3742 t.kind = ctsk_resword;
3743 t.spec = c_parser_peek_token (parser)->value;
3744 t.expr = NULL_TREE;
3745 t.expr_const_operands = true;
3746 t.has_enum_type_specifier = false;
3747 declspecs_add_type (loc, specs, t);
3748 c_parser_consume_token (parser);
3749 break;
3750 case RID_ENUM:
3751 if (!typespec_ok)
3752 goto out;
3753 attrs_ok = true;
3754 seen_type = true;
3755 t = c_parser_enum_specifier (parser);
3756 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3757 declspecs_add_type (loc, specs, t);
3758 break;
3759 case RID_STRUCT:
3760 case RID_UNION:
3761 if (!typespec_ok)
3762 goto out;
3763 attrs_ok = true;
3764 seen_type = true;
3765 t = c_parser_struct_or_union_specifier (parser);
3766 invoke_plugin_callbacks (event: PLUGIN_FINISH_TYPE, gcc_data: t.spec);
3767 declspecs_add_type (loc, specs, t);
3768 break;
3769 case RID_TYPEOF:
3770 case RID_TYPEOF_UNQUAL:
3771 /* ??? The old parser rejected typeof after other type
3772 specifiers, but is a syntax error the best way of
3773 handling this? */
3774 if (!typespec_ok || seen_type)
3775 goto out;
3776 attrs_ok = true;
3777 seen_type = true;
3778 t = c_parser_typeof_specifier (parser);
3779 declspecs_add_type (loc, specs, t);
3780 break;
3781 case RID_BITINT:
3782 if (!typespec_ok)
3783 goto out;
3784 else
3785 {
3786 attrs_ok = true;
3787 seen_type = true;
3788 t.kind = ctsk_resword;
3789 t.spec = c_parser_peek_token (parser)->value;
3790 t.expr = error_mark_node;
3791 t.expr_const_operands = true;
3792 t.has_enum_type_specifier = false;
3793 c_parser_consume_token (parser);
3794 matching_parens parens;
3795 if (parens.require_open (parser))
3796 {
3797 c_expr expr = c_parser_expr_no_commas (parser, NULL);
3798 t.expr = convert_lvalue_to_rvalue (loc, expr, true,
3799 true).value;
3800 parens.skip_until_found_close (parser);
3801 }
3802 declspecs_add_type (loc, specs, t);
3803 }
3804 break;
3805 case RID_ATOMIC:
3806 /* C parser handling of Objective-C constructs needs
3807 checking for correct lvalue-to-rvalue conversions, and
3808 the code in build_modify_expr handling various
3809 Objective-C cases, and that in build_unary_op handling
3810 Objective-C cases for increment / decrement, also needs
3811 updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
3812 and objc_types_are_equivalent may also need updates. */
3813 if (c_dialect_objc ())
3814 sorry ("%<_Atomic%> in Objective-C");
3815 if (flag_isoc99)
3816 pedwarn_c99 (loc, OPT_Wpedantic,
3817 "ISO C99 does not support the %<_Atomic%> qualifier");
3818 else
3819 pedwarn_c99 (loc, OPT_Wpedantic,
3820 "ISO C90 does not support the %<_Atomic%> qualifier");
3821 attrs_ok = true;
3822 tree value;
3823 value = c_parser_peek_token (parser)->value;
3824 c_parser_consume_token (parser);
3825 if (typespec_ok && c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
3826 {
3827 /* _Atomic ( type-name ). */
3828 seen_type = true;
3829 c_parser_consume_token (parser);
3830 struct c_type_name *type = c_parser_type_name (parser);
3831 t.kind = ctsk_typeof;
3832 t.spec = error_mark_node;
3833 t.expr = NULL_TREE;
3834 t.expr_const_operands = true;
3835 t.has_enum_type_specifier = false;
3836 if (type != NULL)
3837 t.spec = groktypename (type, &t.expr,
3838 &t.expr_const_operands);
3839 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
3840 msgid: "expected %<)%>");
3841 if (t.spec != error_mark_node)
3842 {
3843 if (TREE_CODE (t.spec) == ARRAY_TYPE)
3844 error_at (loc, "%<_Atomic%>-qualified array type");
3845 else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
3846 error_at (loc, "%<_Atomic%>-qualified function type");
3847 else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
3848 error_at (loc, "%<_Atomic%> applied to a qualified type");
3849 else
3850 t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
3851 }
3852 declspecs_add_type (loc, specs, t);
3853 }
3854 else
3855 declspecs_add_qual (loc, specs, value);
3856 break;
3857 case RID_CONST:
3858 case RID_VOLATILE:
3859 case RID_RESTRICT:
3860 attrs_ok = true;
3861 declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
3862 c_parser_consume_token (parser);
3863 break;
3864 case RID_ATTRIBUTE:
3865 if (!attrs_ok)
3866 goto out;
3867 attrs = c_parser_gnu_attributes (parser);
3868 declspecs_add_attrs (loc, specs, attrs);
3869 break;
3870 case RID_ALIGNAS:
3871 if (!alignspec_ok)
3872 goto out;
3873 align = c_parser_alignas_specifier (parser);
3874 declspecs_add_alignas (loc, specs, align);
3875 break;
3876 case RID_GIMPLE:
3877 if (! flag_gimple)
3878 error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
3879 c_parser_consume_token (parser);
3880 specs->declspec_il = cdil_gimple;
3881 specs->locations[cdw_gimple] = loc;
3882 c_parser_gimple_or_rtl_pass_list (parser, specs);
3883 break;
3884 case RID_RTL:
3885 c_parser_consume_token (parser);
3886 specs->declspec_il = cdil_rtl;
3887 specs->locations[cdw_rtl] = loc;
3888 c_parser_gimple_or_rtl_pass_list (parser, specs);
3889 break;
3890 default:
3891 goto out;
3892 }
3893 }
3894 out:
3895 if (end_std_attr_ok
3896 && c_parser_nth_token_starts_std_attributes (parser, 1))
3897 specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
3898}
3899
3900/* Complain about a non-CPP_NAME within an enumerator list. */
3901
3902static void
3903report_bad_enum_name (c_parser *parser)
3904{
3905 if (!parser->error)
3906 {
3907 c_token *token = c_parser_peek_token (parser);
3908 switch (token->type)
3909 {
3910 default:
3911 break;
3912 case CPP_CLOSE_BRACE:
3913 /* Give a nicer error for "enum {}". */
3914 error_at (token->location,
3915 "empty enum is invalid");
3916 parser->error = true;
3917 return;
3918 case CPP_KEYWORD:
3919 /* Give a nicer error for attempts to use "true" and "false"
3920 in enums with C23 onwards. */
3921 if (token->keyword == RID_FALSE
3922 || token->keyword == RID_TRUE)
3923 {
3924 auto_diagnostic_group d;
3925 error_at (token->location,
3926 "cannot use keyword %qs as enumeration constant",
3927 IDENTIFIER_POINTER (token->value));
3928 add_note_about_new_keyword (loc: token->location,
3929 keyword_id: token->value);
3930 parser->error = true;
3931 return;
3932 }
3933 break;
3934 }
3935 }
3936
3937 /* Otherwise, a more generic error message. */
3938 c_parser_error (parser, gmsgid: "expected identifier");
3939}
3940
3941/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
3942
3943 enum-specifier:
3944 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3945 { enumerator-list } gnu-attributes[opt]
3946 enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
3947 { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
3948 enum gnu-attributes[opt] identifier
3949
3950 The form with trailing comma is new in C99; enum-type-specifiers
3951 are new in C23. The forms with gnu-attributes are GNU extensions.
3952 In GNU C, we accept any expression without commas in the syntax
3953 (assignment expressions, not just conditional expressions);
3954 assignment expressions will be diagnosed as non-constant.
3955
3956 enum-type-specifier:
3957 : specifier-qualifier-list
3958
3959 enumerator-list:
3960 enumerator
3961 enumerator-list , enumerator
3962
3963 enumerator:
3964 enumeration-constant attribute-specifier-sequence[opt]
3965 enumeration-constant attribute-specifier-sequence[opt]
3966 = constant-expression
3967
3968 GNU Extensions:
3969
3970 enumerator:
3971 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3972 enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
3973 = constant-expression
3974
3975*/
3976
3977static struct c_typespec
3978c_parser_enum_specifier (c_parser *parser)
3979{
3980 struct c_typespec ret;
3981 bool have_std_attrs;
3982 bool potential_nesting_p = false;
3983 tree std_attrs = NULL_TREE;
3984 tree attrs;
3985 tree ident = NULL_TREE;
3986 tree fixed_underlying_type = NULL_TREE;
3987 location_t enum_loc;
3988 location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
3989 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
3990 c_parser_consume_token (parser);
3991 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
3992 if (have_std_attrs)
3993 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
3994 attrs = c_parser_gnu_attributes (parser);
3995 enum_loc = c_parser_peek_token (parser)->location;
3996 /* Set the location in case we create a decl now. */
3997 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
3998 if (c_parser_next_token_is (parser, type: CPP_NAME))
3999 {
4000 ident = c_parser_peek_token (parser)->value;
4001 ident_loc = c_parser_peek_token (parser)->location;
4002 enum_loc = ident_loc;
4003 c_parser_consume_token (parser);
4004 }
4005 if (c_parser_next_token_is (parser, type: CPP_COLON)
4006 /* Distinguish an enum-type-specifier from a bit-field
4007 declaration of the form "enum e : constant-expression;". */
4008 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
4009 {
4010 pedwarn_c11 (enum_loc, OPT_Wpedantic,
4011 "ISO C does not support specifying %<enum%> underlying "
4012 "types before C23");
4013 if (ident)
4014 {
4015 /* The tag is in scope during the enum-type-specifier (which
4016 may refer to the tag inside typeof). */
4017 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
4018 have_std_attrs, std_attrs, true);
4019 if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
4020 error_at (enum_loc, "%<enum%> declared both with and without "
4021 "fixed underlying type");
4022 potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
4023 }
4024 else
4025 {
4026 /* There must be an enum definition, so this initialization
4027 (to avoid possible warnings about uninitialized data)
4028 will be replaced later (either with the results of that
4029 definition, or with the results of error handling for the
4030 case of no tag and no definition). */
4031 ret.spec = NULL_TREE;
4032 ret.kind = ctsk_tagdef;
4033 ret.expr = NULL_TREE;
4034 ret.expr_const_operands = true;
4035 ret.has_enum_type_specifier = true;
4036 }
4037 c_parser_consume_token (parser);
4038 struct c_declspecs *specs = build_null_declspecs ();
4039 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: false, alignspec_ok: false, auto_type_ok: false,
4040 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_id);
4041 finish_declspecs (specs);
4042 if (specs->default_int_p)
4043 error_at (enum_loc, "no %<enum%> underlying type specified");
4044 else if (TREE_CODE (specs->type) != INTEGER_TYPE
4045 && TREE_CODE (specs->type) != BOOLEAN_TYPE)
4046 {
4047 error_at (enum_loc, "invalid %<enum%> underlying type");
4048 specs->type = integer_type_node;
4049 }
4050 else if (specs->restrict_p)
4051 error_at (enum_loc, "invalid use of %<restrict%>");
4052 fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
4053 if (ident)
4054 {
4055 /* The type specified must be consistent with any previously
4056 specified underlying type. If this is a newly declared
4057 type, it is now a complete type. */
4058 if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4059 && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
4060 {
4061 TYPE_MIN_VALUE (ret.spec) =
4062 TYPE_MIN_VALUE (fixed_underlying_type);
4063 TYPE_MAX_VALUE (ret.spec) =
4064 TYPE_MAX_VALUE (fixed_underlying_type);
4065 TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
4066 SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
4067 TYPE_SIZE (ret.spec) = NULL_TREE;
4068 TYPE_PRECISION (ret.spec) =
4069 TYPE_PRECISION (fixed_underlying_type);
4070 ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
4071 layout_type (ret.spec);
4072 }
4073 else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
4074 && !comptypes (fixed_underlying_type,
4075 ENUM_UNDERLYING_TYPE (ret.spec)))
4076 {
4077 error_at (enum_loc, "%<enum%> underlying type incompatible with "
4078 "previous declaration");
4079 fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
4080 }
4081 }
4082 }
4083 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
4084 {
4085 /* Parse an enum definition. */
4086 struct c_enum_contents the_enum;
4087 tree type;
4088 tree postfix_attrs;
4089 /* We chain the enumerators in reverse order, then put them in
4090 forward order at the end. */
4091 tree values;
4092 timevar_push (tv: TV_PARSE_ENUM);
4093 type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
4094 potential_nesting_p);
4095 values = NULL_TREE;
4096 c_parser_consume_token (parser);
4097 while (true)
4098 {
4099 tree enum_id;
4100 tree enum_value;
4101 tree enum_decl;
4102 bool seen_comma;
4103 c_token *token;
4104 location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
4105 location_t decl_loc, value_loc;
4106 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
4107 {
4108 report_bad_enum_name (parser);
4109 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4110 values = error_mark_node;
4111 break;
4112 }
4113 token = c_parser_peek_token (parser);
4114 enum_id = token->value;
4115 /* Set the location in case we create a decl now. */
4116 c_parser_set_source_position_from_token (token);
4117 decl_loc = value_loc = token->location;
4118 c_parser_consume_token (parser);
4119 /* Parse any specified attributes. */
4120 tree std_attrs = NULL_TREE;
4121 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4122 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4123 tree enum_attrs = chainon (std_attrs,
4124 c_parser_gnu_attributes (parser));
4125 if (c_parser_next_token_is (parser, type: CPP_EQ))
4126 {
4127 c_parser_consume_token (parser);
4128 value_loc = c_parser_peek_token (parser)->location;
4129 enum_value = convert_lvalue_to_rvalue (value_loc,
4130 (c_parser_expr_no_commas
4131 (parser, NULL)),
4132 true, true).value;
4133 }
4134 else
4135 enum_value = NULL_TREE;
4136 enum_decl = build_enumerator (decl_loc, value_loc,
4137 &the_enum, enum_id, enum_value);
4138 if (enum_attrs)
4139 decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
4140 TREE_CHAIN (enum_decl) = values;
4141 values = enum_decl;
4142 seen_comma = false;
4143 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4144 {
4145 comma_loc = c_parser_peek_token (parser)->location;
4146 seen_comma = true;
4147 c_parser_consume_token (parser);
4148 }
4149 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4150 {
4151 if (seen_comma)
4152 pedwarn_c90 (comma_loc, OPT_Wpedantic,
4153 "comma at end of enumerator list");
4154 c_parser_consume_token (parser);
4155 break;
4156 }
4157 if (!seen_comma)
4158 {
4159 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
4160 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4161 values = error_mark_node;
4162 break;
4163 }
4164 }
4165 postfix_attrs = c_parser_gnu_attributes (parser);
4166 ret.spec = finish_enum (type, nreverse (values),
4167 chainon (std_attrs,
4168 chainon (attrs, postfix_attrs)));
4169 ret.kind = ctsk_tagdef;
4170 ret.expr = NULL_TREE;
4171 ret.expr_const_operands = true;
4172 ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
4173 timevar_pop (tv: TV_PARSE_ENUM);
4174 return ret;
4175 }
4176 else if (!ident)
4177 {
4178 c_parser_error (parser, gmsgid: "expected %<{%>");
4179 ret.spec = error_mark_node;
4180 ret.kind = ctsk_tagref;
4181 ret.expr = NULL_TREE;
4182 ret.expr_const_operands = true;
4183 ret.has_enum_type_specifier = false;
4184 return ret;
4185 }
4186 /* Attributes may only appear when the members are defined or in
4187 certain forward declarations (treat enum forward declarations in
4188 GNU C analogously to struct and union forward declarations in
4189 standard C). */
4190 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4191 c_parser_error (parser, gmsgid: "expected %<;%>");
4192 if (fixed_underlying_type == NULL_TREE)
4193 {
4194 ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
4195 std_attrs, false);
4196 /* In ISO C, enumerated types without a fixed underlying type
4197 can be referred to only if already defined. */
4198 if (pedantic && !COMPLETE_TYPE_P (ret.spec))
4199 {
4200 gcc_assert (ident);
4201 pedwarn (enum_loc, OPT_Wpedantic,
4202 "ISO C forbids forward references to %<enum%> types");
4203 }
4204 }
4205 return ret;
4206}
4207
4208/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
4209
4210 struct-or-union-specifier:
4211 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4212 identifier[opt] { struct-contents } gnu-attributes[opt]
4213 struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
4214 identifier
4215
4216 struct-contents:
4217 struct-declaration-list
4218
4219 struct-declaration-list:
4220 struct-declaration ;
4221 struct-declaration-list struct-declaration ;
4222
4223 GNU extensions:
4224
4225 struct-contents:
4226 empty
4227 struct-declaration
4228 struct-declaration-list struct-declaration
4229
4230 struct-declaration-list:
4231 struct-declaration-list ;
4232 ;
4233
4234 (Note that in the syntax here, unlike that in ISO C, the semicolons
4235 are included here rather than in struct-declaration, in order to
4236 describe the syntax with extra semicolons and missing semicolon at
4237 end.)
4238
4239 Objective-C:
4240
4241 struct-declaration-list:
4242 @defs ( class-name )
4243
4244 (Note this does not include a trailing semicolon, but can be
4245 followed by further declarations, and gets a pedwarn-if-pedantic
4246 when followed by a semicolon.) */
4247
4248static struct c_typespec
4249c_parser_struct_or_union_specifier (c_parser *parser)
4250{
4251 struct c_typespec ret;
4252 bool have_std_attrs;
4253 tree std_attrs = NULL_TREE;
4254 tree attrs;
4255 tree ident = NULL_TREE;
4256 location_t struct_loc;
4257 location_t ident_loc = UNKNOWN_LOCATION;
4258 enum tree_code code;
4259 switch (c_parser_peek_token (parser)->keyword)
4260 {
4261 case RID_STRUCT:
4262 code = RECORD_TYPE;
4263 break;
4264 case RID_UNION:
4265 code = UNION_TYPE;
4266 break;
4267 default:
4268 gcc_unreachable ();
4269 }
4270 struct_loc = c_parser_peek_token (parser)->location;
4271 c_parser_consume_token (parser);
4272 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
4273 if (have_std_attrs)
4274 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
4275 attrs = c_parser_gnu_attributes (parser);
4276
4277 /* Set the location in case we create a decl now. */
4278 c_parser_set_source_position_from_token (token: c_parser_peek_token (parser));
4279
4280 if (c_parser_next_token_is (parser, type: CPP_NAME))
4281 {
4282 ident = c_parser_peek_token (parser)->value;
4283 ident_loc = c_parser_peek_token (parser)->location;
4284 struct_loc = ident_loc;
4285 c_parser_consume_token (parser);
4286 }
4287 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
4288 {
4289 /* Parse a struct or union definition. Start the scope of the
4290 tag before parsing components. */
4291 class c_struct_parse_info *struct_info;
4292 tree type = start_struct (struct_loc, code, ident, &struct_info);
4293 tree postfix_attrs;
4294 /* We chain the components in reverse order, then put them in
4295 forward order at the end. Each struct-declaration may
4296 declare multiple components (comma-separated), so we must use
4297 chainon to join them, although when parsing each
4298 struct-declaration we can use TREE_CHAIN directly.
4299
4300 The theory behind all this is that there will be more
4301 semicolon separated fields than comma separated fields, and
4302 so we'll be minimizing the number of node traversals required
4303 by chainon. */
4304 tree contents;
4305 tree expr = NULL;
4306 timevar_push (tv: TV_PARSE_STRUCT);
4307 contents = NULL_TREE;
4308 c_parser_consume_token (parser);
4309 /* Handle the Objective-C @defs construct,
4310 e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
4311 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_DEFS))
4312 {
4313 tree name;
4314 gcc_assert (c_dialect_objc ());
4315 c_parser_consume_token (parser);
4316 matching_parens parens;
4317 if (!parens.require_open (parser))
4318 goto end_at_defs;
4319 if (c_parser_next_token_is (parser, type: CPP_NAME)
4320 && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
4321 {
4322 name = c_parser_peek_token (parser)->value;
4323 c_parser_consume_token (parser);
4324 }
4325 else
4326 {
4327 c_parser_error (parser, gmsgid: "expected class name");
4328 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
4329 goto end_at_defs;
4330 }
4331 parens.skip_until_found_close (parser);
4332 contents = nreverse (objc_get_class_ivars (name));
4333 }
4334 end_at_defs:
4335 /* Parse the struct-declarations and semicolons. Problems with
4336 semicolons are diagnosed here; empty structures are diagnosed
4337 elsewhere. */
4338 while (true)
4339 {
4340 tree decls;
4341 /* Parse any stray semicolon. */
4342 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4343 {
4344 location_t semicolon_loc
4345 = c_parser_peek_token (parser)->location;
4346 gcc_rich_location richloc (semicolon_loc);
4347 richloc.add_fixit_remove ();
4348 pedwarn (&richloc, OPT_Wpedantic,
4349 "extra semicolon in struct or union specified");
4350 c_parser_consume_token (parser);
4351 continue;
4352 }
4353 /* Stop if at the end of the struct or union contents. */
4354 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4355 {
4356 c_parser_consume_token (parser);
4357 break;
4358 }
4359 /* Accept #pragmas at struct scope. */
4360 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
4361 {
4362 c_parser_pragma (parser, pragma_struct, NULL, NULL_TREE);
4363 continue;
4364 }
4365 /* Parse some comma-separated declarations, but not the
4366 trailing semicolon if any. */
4367 decls = c_parser_struct_declaration (parser, &expr);
4368 contents = chainon (decls, contents);
4369 /* If no semicolon follows, either we have a parse error or
4370 are at the end of the struct or union and should
4371 pedwarn. */
4372 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
4373 c_parser_consume_token (parser);
4374 else
4375 {
4376 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4377 pedwarn (c_parser_peek_token (parser)->location, 0,
4378 "no semicolon at end of struct or union");
4379 else if (parser->error
4380 || !c_parser_next_token_starts_declspecs (parser))
4381 {
4382 c_parser_error (parser, gmsgid: "expected %<;%>");
4383 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
4384 break;
4385 }
4386
4387 /* If we come here, we have already emitted an error
4388 for an expected `;', identifier or `(', and we also
4389 recovered already. Go on with the next field. */
4390 }
4391 }
4392 postfix_attrs = c_parser_gnu_attributes (parser);
4393 ret.spec = finish_struct (struct_loc, type, nreverse (contents),
4394 chainon (std_attrs,
4395 chainon (attrs, postfix_attrs)),
4396 struct_info, expr: &expr);
4397 ret.kind = ctsk_tagdef;
4398 ret.expr = expr;
4399 ret.expr_const_operands = true;
4400 ret.has_enum_type_specifier = false;
4401 timevar_pop (tv: TV_PARSE_STRUCT);
4402 return ret;
4403 }
4404 else if (!ident)
4405 {
4406 c_parser_error (parser, gmsgid: "expected %<{%>");
4407 ret.spec = error_mark_node;
4408 ret.kind = ctsk_tagref;
4409 ret.expr = NULL_TREE;
4410 ret.expr_const_operands = true;
4411 ret.has_enum_type_specifier = false;
4412 return ret;
4413 }
4414 /* Attributes may only appear when the members are defined or in
4415 certain forward declarations. */
4416 if (have_std_attrs && c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
4417 c_parser_error (parser, gmsgid: "expected %<;%>");
4418 /* ??? Existing practice is that GNU attributes are ignored after
4419 the struct or union keyword when not defining the members. */
4420 ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
4421 false);
4422 return ret;
4423}
4424
4425/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
4426 *without* the trailing semicolon.
4427
4428 struct-declaration:
4429 attribute-specifier-sequence[opt] specifier-qualifier-list
4430 attribute-specifier-sequence[opt] struct-declarator-list
4431 static_assert-declaration-no-semi
4432
4433 specifier-qualifier-list:
4434 type-specifier specifier-qualifier-list[opt]
4435 type-qualifier specifier-qualifier-list[opt]
4436 alignment-specifier specifier-qualifier-list[opt]
4437 gnu-attributes specifier-qualifier-list[opt]
4438
4439 struct-declarator-list:
4440 struct-declarator
4441 struct-declarator-list , gnu-attributes[opt] struct-declarator
4442
4443 struct-declarator:
4444 declarator gnu-attributes[opt]
4445 declarator[opt] : constant-expression gnu-attributes[opt]
4446
4447 GNU extensions:
4448
4449 struct-declaration:
4450 __extension__ struct-declaration
4451 specifier-qualifier-list
4452
4453 Unlike the ISO C syntax, semicolons are handled elsewhere. The use
4454 of gnu-attributes where shown is a GNU extension. In GNU C, we accept
4455 any expression without commas in the syntax (assignment
4456 expressions, not just conditional expressions); assignment
4457 expressions will be diagnosed as non-constant. */
4458
4459static tree
4460c_parser_struct_declaration (c_parser *parser, tree *expr)
4461{
4462 struct c_declspecs *specs;
4463 tree prefix_attrs;
4464 tree all_prefix_attrs;
4465 tree decls;
4466 location_t decl_loc;
4467 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
4468 {
4469 int ext;
4470 tree decl;
4471 ext = disable_extension_diagnostics ();
4472 c_parser_consume_token (parser);
4473 decl = c_parser_struct_declaration (parser, expr);
4474 restore_extension_diagnostics (flags: ext);
4475 return decl;
4476 }
4477 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
4478 {
4479 c_parser_static_assert_declaration_no_semi (parser);
4480 return NULL_TREE;
4481 }
4482 specs = build_null_declspecs ();
4483 decl_loc = c_parser_peek_token (parser)->location;
4484 /* Strictly by the standard, we shouldn't allow _Alignas here,
4485 but it appears to have been intended to allow it there, so
4486 we're keeping it as it is until WG14 reaches a conclusion
4487 of N1731.
4488 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
4489 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true,
4490 alignspec_ok: true, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: true, la: cla_nonabstract_decl);
4491 if (parser->error)
4492 return NULL_TREE;
4493 if (!specs->declspecs_seen_p)
4494 {
4495 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
4496 return NULL_TREE;
4497 }
4498 finish_declspecs (specs);
4499 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4500 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4501 {
4502 tree ret;
4503 if (specs->typespec_kind == ctsk_none)
4504 {
4505 pedwarn (decl_loc, OPT_Wpedantic,
4506 "ISO C forbids member declarations with no members");
4507 shadow_tag_warned (specs, pedantic);
4508 ret = NULL_TREE;
4509 }
4510 else
4511 {
4512 /* Support for unnamed structs or unions as members of
4513 structs or unions (which is [a] useful and [b] supports
4514 MS P-SDK). */
4515 tree attrs = NULL;
4516
4517 ret = grokfield (c_parser_peek_token (parser)->location,
4518 build_id_declarator (NULL_TREE), specs,
4519 NULL_TREE, &attrs, expr);
4520 if (ret)
4521 decl_attributes (&ret, attrs, 0);
4522 }
4523 return ret;
4524 }
4525
4526 /* Provide better error recovery. Note that a type name here is valid,
4527 and will be treated as a field name. */
4528 if (specs->typespec_kind == ctsk_tagdef
4529 && TREE_CODE (specs->type) != ENUMERAL_TYPE
4530 && c_parser_next_token_starts_declspecs (parser)
4531 && !c_parser_next_token_is (parser, type: CPP_NAME))
4532 {
4533 c_parser_error (parser, gmsgid: "expected %<;%>, identifier or %<(%>");
4534 parser->error = false;
4535 return NULL_TREE;
4536 }
4537
4538 pending_xref_error ();
4539 prefix_attrs = specs->attrs;
4540 all_prefix_attrs = prefix_attrs;
4541 specs->attrs = NULL_TREE;
4542 decls = NULL_TREE;
4543 while (true)
4544 {
4545 /* Declaring one or more declarators or un-named bit-fields. */
4546 struct c_declarator *declarator;
4547 bool dummy = false;
4548 if (c_parser_next_token_is (parser, type: CPP_COLON))
4549 declarator = build_id_declarator (NULL_TREE);
4550 else
4551 declarator = c_parser_declarator (parser,
4552 type_seen_p: specs->typespec_kind != ctsk_none,
4553 kind: C_DTR_NORMAL, seen_id: &dummy);
4554 if (declarator == NULL)
4555 {
4556 c_parser_skip_to_end_of_block_or_statement (parser);
4557 break;
4558 }
4559 if (c_parser_next_token_is (parser, type: CPP_COLON)
4560 || c_parser_next_token_is (parser, type: CPP_COMMA)
4561 || c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4562 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE)
4563 || c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4564 {
4565 tree postfix_attrs = NULL_TREE;
4566 tree width = NULL_TREE;
4567 tree d;
4568 if (c_parser_next_token_is (parser, type: CPP_COLON))
4569 {
4570 c_parser_consume_token (parser);
4571 location_t loc = c_parser_peek_token (parser)->location;
4572 width = convert_lvalue_to_rvalue (loc,
4573 (c_parser_expr_no_commas
4574 (parser, NULL)),
4575 true, true).value;
4576 }
4577 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4578 postfix_attrs = c_parser_gnu_attributes (parser);
4579 d = grokfield (c_parser_peek_token (parser)->location,
4580 declarator, specs, width, &all_prefix_attrs, expr);
4581 decl_attributes (&d, chainon (postfix_attrs,
4582 all_prefix_attrs), 0);
4583 DECL_CHAIN (d) = decls;
4584 decls = d;
4585 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
4586 all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
4587 prefix_attrs);
4588 else
4589 all_prefix_attrs = prefix_attrs;
4590 if (c_parser_next_token_is (parser, type: CPP_COMMA))
4591 c_parser_consume_token (parser);
4592 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
4593 || c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
4594 {
4595 /* Semicolon consumed in caller. */
4596 break;
4597 }
4598 else
4599 {
4600 c_parser_error (parser, gmsgid: "expected %<,%>, %<;%> or %<}%>");
4601 break;
4602 }
4603 }
4604 else
4605 {
4606 c_parser_error (parser,
4607 gmsgid: "expected %<:%>, %<,%>, %<;%>, %<}%> or "
4608 "%<__attribute__%>");
4609 break;
4610 }
4611 }
4612 return decls;
4613}
4614
4615/* Parse a typeof specifier (a GNU extension adopted in C23).
4616
4617 typeof-specifier:
4618 typeof ( expression )
4619 typeof ( type-name )
4620 typeof_unqual ( expression )
4621 typeof_unqual ( type-name )
4622*/
4623
4624static struct c_typespec
4625c_parser_typeof_specifier (c_parser *parser)
4626{
4627 bool is_unqual;
4628 bool is_std;
4629 struct c_typespec ret;
4630 ret.kind = ctsk_typeof;
4631 ret.spec = error_mark_node;
4632 ret.expr = NULL_TREE;
4633 ret.expr_const_operands = true;
4634 ret.has_enum_type_specifier = false;
4635 if (c_parser_next_token_is_keyword (parser, keyword: RID_TYPEOF))
4636 {
4637 is_unqual = false;
4638 tree spelling = c_parser_peek_token (parser)->value;
4639 is_std = (flag_isoc23
4640 && strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof") == 0);
4641 }
4642 else
4643 {
4644 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL));
4645 is_unqual = true;
4646 tree spelling = c_parser_peek_token (parser)->value;
4647 is_std = strcmp (IDENTIFIER_POINTER (spelling), s2: "typeof_unqual") == 0;
4648 }
4649 c_parser_consume_token (parser);
4650 c_inhibit_evaluation_warnings++;
4651 in_typeof++;
4652 matching_parens parens;
4653 if (!parens.require_open (parser))
4654 {
4655 c_inhibit_evaluation_warnings--;
4656 in_typeof--;
4657 return ret;
4658 }
4659 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4660 {
4661 struct c_type_name *type = c_parser_type_name (parser);
4662 c_inhibit_evaluation_warnings--;
4663 in_typeof--;
4664 if (type != NULL)
4665 {
4666 ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
4667 pop_maybe_used (c_type_variably_modified_p (t: ret.spec));
4668 }
4669 }
4670 else
4671 {
4672 bool was_vm;
4673 location_t here = c_parser_peek_token (parser)->location;
4674 struct c_expr expr = c_parser_expression (parser);
4675 c_inhibit_evaluation_warnings--;
4676 in_typeof--;
4677 if (TREE_CODE (expr.value) == COMPONENT_REF
4678 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
4679 error_at (here, "%<typeof%> applied to a bit-field");
4680 mark_exp_read (expr.value);
4681 ret.spec = TREE_TYPE (expr.value);
4682 was_vm = c_type_variably_modified_p (t: ret.spec);
4683 /* This is returned with the type so that when the type is
4684 evaluated, this can be evaluated. */
4685 if (was_vm)
4686 ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
4687 pop_maybe_used (was_vm);
4688 }
4689 parens.skip_until_found_close (parser);
4690 if (ret.spec != error_mark_node)
4691 {
4692 if (is_unqual)
4693 {
4694 bool is_array = TREE_CODE (ret.spec) == ARRAY_TYPE;
4695 int quals = TYPE_QUALS (strip_array_types (ret.spec));
4696 if ((is_array ? quals & ~TYPE_QUAL_ATOMIC : quals)
4697 != TYPE_UNQUALIFIED)
4698 {
4699 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4700 if (quals & TYPE_QUAL_ATOMIC && is_array)
4701 ret.spec = c_build_qualified_type (ret.spec,
4702 TYPE_QUAL_ATOMIC);
4703 }
4704 }
4705 if (is_std)
4706 {
4707 /* In ISO C terms, _Noreturn is not part of the type of
4708 expressions such as &abort, but in GCC it is represented
4709 internally as a type qualifier. */
4710 if (TREE_CODE (ret.spec) == FUNCTION_TYPE
4711 && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED)
4712 ret.spec = TYPE_MAIN_VARIANT (ret.spec);
4713 else if (FUNCTION_POINTER_TYPE_P (ret.spec)
4714 && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
4715 ret.spec
4716 = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
4717 }
4718 }
4719 return ret;
4720}
4721
4722/* Parse an alignment-specifier.
4723
4724 C11 6.7.5:
4725
4726 alignment-specifier:
4727 _Alignas ( type-name )
4728 _Alignas ( constant-expression )
4729*/
4730
4731static tree
4732c_parser_alignas_specifier (c_parser * parser)
4733{
4734 tree ret = error_mark_node;
4735 location_t loc = c_parser_peek_token (parser)->location;
4736 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
4737 tree spelling = c_parser_peek_token (parser)->value;
4738 c_parser_consume_token (parser);
4739 if (flag_isoc99)
4740 pedwarn_c99 (loc, OPT_Wpedantic,
4741 "ISO C99 does not support %qE", spelling);
4742 else
4743 pedwarn_c99 (loc, OPT_Wpedantic,
4744 "ISO C90 does not support %qE", spelling);
4745 matching_parens parens;
4746 if (!parens.require_open (parser))
4747 return ret;
4748 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
4749 {
4750 struct c_type_name *type = c_parser_type_name (parser);
4751 if (type != NULL)
4752 ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
4753 false, true, 1);
4754 }
4755 else
4756 ret = convert_lvalue_to_rvalue (loc,
4757 c_parser_expr_no_commas (parser, NULL),
4758 true, true).value;
4759 parens.skip_until_found_close (parser);
4760 return ret;
4761}
4762
4763/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
4764 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
4765 a typedef name may be redeclared; otherwise it may not. KIND
4766 indicates which kind of declarator is wanted. Returns a valid
4767 declarator except in the case of a syntax error in which case NULL is
4768 returned. *SEEN_ID is set to true if an identifier being declared is
4769 seen; this is used to diagnose bad forms of abstract array declarators
4770 and to determine whether an identifier list is syntactically permitted.
4771
4772 declarator:
4773 pointer[opt] direct-declarator
4774
4775 direct-declarator:
4776 identifier
4777 ( gnu-attributes[opt] declarator )
4778 direct-declarator array-declarator
4779 direct-declarator ( parameter-type-list )
4780 direct-declarator ( identifier-list[opt] )
4781
4782 pointer:
4783 * type-qualifier-list[opt]
4784 * type-qualifier-list[opt] pointer
4785
4786 type-qualifier-list:
4787 type-qualifier
4788 gnu-attributes
4789 type-qualifier-list type-qualifier
4790 type-qualifier-list gnu-attributes
4791
4792 array-declarator:
4793 [ type-qualifier-list[opt] assignment-expression[opt] ]
4794 [ static type-qualifier-list[opt] assignment-expression ]
4795 [ type-qualifier-list static assignment-expression ]
4796 [ type-qualifier-list[opt] * ]
4797
4798 parameter-type-list:
4799 parameter-list
4800 parameter-list , ...
4801
4802 parameter-list:
4803 parameter-declaration
4804 parameter-list , parameter-declaration
4805
4806 parameter-declaration:
4807 declaration-specifiers declarator gnu-attributes[opt]
4808 declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
4809
4810 identifier-list:
4811 identifier
4812 identifier-list , identifier
4813
4814 abstract-declarator:
4815 pointer
4816 pointer[opt] direct-abstract-declarator
4817
4818 direct-abstract-declarator:
4819 ( gnu-attributes[opt] abstract-declarator )
4820 direct-abstract-declarator[opt] array-declarator
4821 direct-abstract-declarator[opt] ( parameter-type-list[opt] )
4822
4823 GNU extensions:
4824
4825 direct-declarator:
4826 direct-declarator ( parameter-forward-declarations
4827 parameter-type-list[opt] )
4828
4829 direct-abstract-declarator:
4830 direct-abstract-declarator[opt] ( parameter-forward-declarations
4831 parameter-type-list[opt] )
4832
4833 parameter-forward-declarations:
4834 parameter-list ;
4835 parameter-forward-declarations parameter-list ;
4836
4837 The uses of gnu-attributes shown above are GNU extensions.
4838
4839 Some forms of array declarator are not included in C99 in the
4840 syntax for abstract declarators; these are disallowed elsewhere.
4841 This may be a defect (DR#289).
4842
4843 This function also accepts an omitted abstract declarator as being
4844 an abstract declarator, although not part of the formal syntax. */
4845
4846struct c_declarator *
4847c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4848 bool *seen_id)
4849{
4850 /* Parse any initial pointer part. */
4851 if (c_parser_next_token_is (parser, type: CPP_MULT))
4852 {
4853 struct c_declspecs *quals_attrs = build_null_declspecs ();
4854 struct c_declarator *inner;
4855 c_parser_consume_token (parser);
4856 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
4857 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: true, end_std_attr_ok: false, la: cla_prefer_id);
4858 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4859 if (inner == NULL)
4860 return NULL;
4861 else
4862 return make_pointer_declarator (quals_attrs, inner);
4863 }
4864 /* Now we have a direct declarator, direct abstract declarator or
4865 nothing (which counts as a direct abstract declarator here). */
4866 return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
4867}
4868
4869/* Parse a direct declarator or direct abstract declarator; arguments
4870 as c_parser_declarator. */
4871
4872static struct c_declarator *
4873c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
4874 bool *seen_id)
4875{
4876 /* The direct declarator must start with an identifier (possibly
4877 omitted) or a parenthesized declarator (possibly abstract). In
4878 an ordinary declarator, initial parentheses must start a
4879 parenthesized declarator. In an abstract declarator or parameter
4880 declarator, they could start a parenthesized declarator or a
4881 parameter list. To tell which, the open parenthesis and any
4882 following gnu-attributes must be read. If a declaration
4883 specifier or standard attributes follow, then it is a parameter
4884 list; if the specifier is a typedef name, there might be an
4885 ambiguity about redeclaring it, which is resolved in the
4886 direction of treating it as a typedef name. If a close
4887 parenthesis follows, it is also an empty parameter list, as the
4888 syntax does not permit empty abstract declarators. Otherwise, it
4889 is a parenthesized declarator (in which case the analysis may be
4890 repeated inside it, recursively).
4891
4892 ??? There is an ambiguity in a parameter declaration "int
4893 (__attribute__((foo)) x)", where x is not a typedef name: it
4894 could be an abstract declarator for a function, or declare x with
4895 parentheses. The proper resolution of this ambiguity needs
4896 documenting. At present we follow an accident of the old
4897 parser's implementation, whereby the first parameter must have
4898 some declaration specifiers other than just gnu-attributes. Thus as
4899 a parameter declaration it is treated as a parenthesized
4900 parameter named x, and as an abstract declarator it is
4901 rejected.
4902
4903 ??? Also following the old parser, gnu-attributes inside an empty
4904 parameter list are ignored, making it a list not yielding a
4905 prototype, rather than giving an error or making it have one
4906 parameter with implicit type int.
4907
4908 ??? Also following the old parser, typedef names may be
4909 redeclared in declarators, but not Objective-C class names. */
4910
4911 if (kind != C_DTR_ABSTRACT
4912 && c_parser_next_token_is (parser, type: CPP_NAME)
4913 && ((type_seen_p
4914 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
4915 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
4916 || c_parser_peek_token (parser)->id_kind == C_ID_ID))
4917 {
4918 struct c_declarator *inner
4919 = build_id_declarator (c_parser_peek_token (parser)->value);
4920 *seen_id = true;
4921 inner->id_loc = c_parser_peek_token (parser)->location;
4922 c_parser_consume_token (parser);
4923 if (c_parser_nth_token_starts_std_attributes (parser, 1))
4924 inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
4925 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4926 }
4927
4928 if (kind != C_DTR_NORMAL
4929 && c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
4930 && !c_parser_nth_token_starts_std_attributes (parser, 1))
4931 {
4932 struct c_declarator *inner = build_id_declarator (NULL_TREE);
4933 inner->id_loc = c_parser_peek_token (parser)->location;
4934 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4935 }
4936
4937 /* Either we are at the end of an abstract declarator, or we have
4938 parentheses. */
4939
4940 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
4941 {
4942 tree attrs;
4943 struct c_declarator *inner;
4944 c_parser_consume_token (parser);
4945 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
4946 keyword: RID_ATTRIBUTE);
4947 attrs = c_parser_gnu_attributes (parser);
4948 if (kind != C_DTR_NORMAL
4949 && (c_parser_next_token_starts_declspecs (parser)
4950 || (!have_gnu_attrs
4951 && (c_parser_nth_token_starts_std_attributes (parser, 1)
4952 || c_parser_next_token_is (parser, type: CPP_ELLIPSIS)))
4953 || c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN)))
4954 {
4955 struct c_arg_info *args
4956 = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
4957 attrs, have_gnu_attrs);
4958 if (args == NULL)
4959 return NULL;
4960 else
4961 {
4962 inner = build_id_declarator (NULL_TREE);
4963 if (!(args->types
4964 && args->types != error_mark_node
4965 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
4966 && c_parser_nth_token_starts_std_attributes (parser, 1))
4967 {
4968 tree std_attrs
4969 = c_parser_std_attribute_specifier_sequence (parser);
4970 if (std_attrs)
4971 inner = build_attrs_declarator (std_attrs, inner);
4972 }
4973 inner = build_function_declarator (args, inner);
4974 return c_parser_direct_declarator_inner (parser, *seen_id,
4975 inner);
4976 }
4977 }
4978 /* A parenthesized declarator. */
4979 inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
4980 if (inner != NULL && attrs != NULL)
4981 inner = build_attrs_declarator (attrs, inner);
4982 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
4983 {
4984 c_parser_consume_token (parser);
4985 if (inner == NULL)
4986 return NULL;
4987 else
4988 return c_parser_direct_declarator_inner (parser, *seen_id, inner);
4989 }
4990 else
4991 {
4992 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
4993 msgid: "expected %<)%>");
4994 return NULL;
4995 }
4996 }
4997 else
4998 {
4999 if (kind == C_DTR_NORMAL)
5000 {
5001 c_parser_error (parser, gmsgid: "expected identifier or %<(%>");
5002 return NULL;
5003 }
5004 else
5005 return build_id_declarator (NULL_TREE);
5006 }
5007}
5008
5009/* Parse part of a direct declarator or direct abstract declarator,
5010 given that some (in INNER) has already been parsed; ID_PRESENT is
5011 true if an identifier is present, false for an abstract
5012 declarator. */
5013
5014static struct c_declarator *
5015c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
5016 struct c_declarator *inner)
5017{
5018 /* Parse a sequence of array declarators and parameter lists. */
5019 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
5020 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5021 {
5022 location_t brace_loc = c_parser_peek_token (parser)->location;
5023 struct c_declarator *declarator;
5024 struct c_declspecs *quals_attrs = build_null_declspecs ();
5025 struct c_expr dimen;
5026 dimen.value = NULL_TREE;
5027 dimen.original_code = ERROR_MARK;
5028 dimen.original_type = NULL_TREE;
5029 c_parser_consume_token (parser);
5030 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
5031 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
5032
5033 location_t static_loc = UNKNOWN_LOCATION;
5034 if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
5035 {
5036 static_loc = c_parser_peek_token (parser)->location;
5037 c_parser_consume_token (parser);
5038 if (!quals_attrs->declspecs_seen_p)
5039 c_parser_declspecs (parser, specs: quals_attrs, scspec_ok: false, typespec_ok: false, start_attr_ok: true,
5040 alignspec_ok: false, auto_type_ok: false, start_std_attr_ok: false, end_std_attr_ok: false, la: cla_prefer_id);
5041 }
5042 if (!quals_attrs->declspecs_seen_p)
5043 quals_attrs = NULL;
5044 /* If "static" is present, there must be an array dimension.
5045 Otherwise, there may be a dimension, "*", or no
5046 dimension. */
5047 const bool static_seen = (static_loc != UNKNOWN_LOCATION);
5048 bool star_seen = false;
5049 if (c_parser_next_token_is (parser, type: CPP_MULT)
5050 && c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
5051 {
5052 star_seen = true;
5053 c_parser_consume_token (parser);
5054 }
5055 else if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
5056 dimen = c_parser_expr_no_commas (parser, NULL);
5057
5058 if (static_seen)
5059 {
5060 if (star_seen)
5061 {
5062 error_at (static_loc,
5063 "%<static%> may not be used with an unspecified "
5064 "variable length array size");
5065 /* Prevent further errors. */
5066 star_seen = false;
5067 dimen.value = error_mark_node;
5068 }
5069 else if (!dimen.value)
5070 error_at (static_loc,
5071 "%<static%> may not be used without an array size");
5072 }
5073
5074 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
5075 c_parser_consume_token (parser);
5076 else
5077 {
5078 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
5079 msgid: "expected %<]%>");
5080 return NULL;
5081 }
5082 if (dimen.value)
5083 dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
5084 declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
5085 static_seen, star_seen);
5086 if (declarator == NULL)
5087 return NULL;
5088 if (c_parser_nth_token_starts_std_attributes (parser, 1))
5089 {
5090 tree std_attrs
5091 = c_parser_std_attribute_specifier_sequence (parser);
5092 if (std_attrs)
5093 inner = build_attrs_declarator (std_attrs, inner);
5094 }
5095 inner = set_array_declarator_inner (declarator, inner);
5096 return c_parser_direct_declarator_inner (parser, id_present, inner);
5097 }
5098 else if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
5099 {
5100 tree attrs;
5101 struct c_arg_info *args;
5102 c_parser_consume_token (parser);
5103 bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
5104 keyword: RID_ATTRIBUTE);
5105 attrs = c_parser_gnu_attributes (parser);
5106 args = c_parser_parms_declarator (parser, id_present, attrs,
5107 have_gnu_attrs);
5108 if (args == NULL)
5109 return NULL;
5110 else
5111 {
5112 if (!(args->types
5113 && args->types != error_mark_node
5114 && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
5115 && c_parser_nth_token_starts_std_attributes (parser, 1))
5116 {
5117 tree std_attrs
5118 = c_parser_std_attribute_specifier_sequence (parser);
5119 if (std_attrs)
5120 inner = build_attrs_declarator (std_attrs, inner);
5121 }
5122 inner = build_function_declarator (args, inner);
5123 return c_parser_direct_declarator_inner (parser, id_present, inner);
5124 }
5125 }
5126 return inner;
5127}
5128
5129/* Parse a parameter list or identifier list, including the closing
5130 parenthesis but not the opening one. ATTRS are the gnu-attributes
5131 at the start of the list. ID_LIST_OK is true if an identifier list
5132 is acceptable; such a list must not have attributes at the start.
5133 HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
5134 attributes) were present (in which case standard attributes cannot
5135 occur). */
5136
5137static struct c_arg_info *
5138c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
5139 bool have_gnu_attrs)
5140{
5141 push_scope ();
5142 declare_parm_level ();
5143 /* If the list starts with an identifier, it is an identifier list.
5144 Otherwise, it is either a prototype list or an empty list. */
5145 if (id_list_ok
5146 && !attrs
5147 && c_parser_next_token_is (parser, type: CPP_NAME)
5148 && c_parser_peek_token (parser)->id_kind == C_ID_ID
5149
5150 /* Look ahead to detect typos in type names. */
5151 && c_parser_peek_2nd_token (parser)->type != CPP_NAME
5152 && c_parser_peek_2nd_token (parser)->type != CPP_MULT
5153 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
5154 && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
5155 && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
5156 {
5157 tree list = NULL_TREE, *nextp = &list;
5158 while (c_parser_next_token_is (parser, type: CPP_NAME)
5159 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
5160 {
5161 *nextp = build_tree_list (NULL_TREE,
5162 c_parser_peek_token (parser)->value);
5163 nextp = & TREE_CHAIN (*nextp);
5164 c_parser_consume_token (parser);
5165 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5166 break;
5167 c_parser_consume_token (parser);
5168 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5169 {
5170 c_parser_error (parser, gmsgid: "expected identifier");
5171 break;
5172 }
5173 }
5174 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5175 {
5176 struct c_arg_info *ret = build_arg_info ();
5177 ret->types = list;
5178 c_parser_consume_token (parser);
5179 pop_scope ();
5180 return ret;
5181 }
5182 else
5183 {
5184 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5185 msgid: "expected %<)%>");
5186 pop_scope ();
5187 return NULL;
5188 }
5189 }
5190 else
5191 {
5192 struct c_arg_info *ret
5193 = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
5194 pop_scope ();
5195 return ret;
5196 }
5197}
5198
5199/* Parse a parameter list (possibly empty), including the closing
5200 parenthesis but not the opening one. ATTRS are the gnu-attributes
5201 at the start of the list; if HAVE_GNU_ATTRS, there were some such
5202 attributes (possibly empty, in which case ATTRS is NULL_TREE),
5203 which means standard attributes cannot start the list. EXPR is
5204 NULL or an expression that needs to be evaluated for the side
5205 effects of array size expressions in the parameters. */
5206
5207static struct c_arg_info *
5208c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
5209 bool have_gnu_attrs)
5210{
5211 bool bad_parm = false;
5212
5213 /* ??? Following the old parser, forward parameter declarations may
5214 use abstract declarators, and if no real parameter declarations
5215 follow the forward declarations then this is not diagnosed. Also
5216 note as above that gnu-attributes are ignored as the only contents of
5217 the parentheses, or as the only contents after forward
5218 declarations. */
5219 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5220 {
5221 struct c_arg_info *ret = build_arg_info ();
5222 c_parser_consume_token (parser);
5223 return ret;
5224 }
5225 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS) && !have_gnu_attrs)
5226 {
5227 struct c_arg_info *ret = build_arg_info ();
5228
5229 ret->types = NULL_TREE;
5230 pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
5231 "ISO C requires a named argument before %<...%> "
5232 "before C23");
5233 c_parser_consume_token (parser);
5234 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5235 {
5236 ret->no_named_args_stdarg_p = true;
5237 c_parser_consume_token (parser);
5238 return ret;
5239 }
5240 else
5241 {
5242 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5243 msgid: "expected %<)%>");
5244 return NULL;
5245 }
5246 }
5247 /* Nonempty list of parameters, either terminated with semicolon
5248 (forward declarations; recurse) or with close parenthesis (normal
5249 function) or with ", ... )" (variadic function). */
5250 while (true)
5251 {
5252 /* Parse a parameter. */
5253 struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
5254 have_gnu_attrs);
5255 attrs = NULL_TREE;
5256 have_gnu_attrs = false;
5257 if (parm == NULL)
5258 bad_parm = true;
5259 else
5260 push_parm_decl (parm, &expr);
5261 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
5262 {
5263 tree new_attrs;
5264 c_parser_consume_token (parser);
5265 mark_forward_parm_decls ();
5266 bool new_have_gnu_attrs
5267 = c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE);
5268 new_attrs = c_parser_gnu_attributes (parser);
5269 return c_parser_parms_list_declarator (parser, attrs: new_attrs, expr,
5270 have_gnu_attrs: new_have_gnu_attrs);
5271 }
5272 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5273 {
5274 c_parser_consume_token (parser);
5275 if (bad_parm)
5276 return NULL;
5277 else
5278 return get_parm_info (false, expr);
5279 }
5280 if (!c_parser_require (parser, type: CPP_COMMA,
5281 msgid: "expected %<;%>, %<,%> or %<)%>",
5282 UNKNOWN_LOCATION, type_is_unique: false))
5283 {
5284 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5285 return NULL;
5286 }
5287 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
5288 {
5289 c_parser_consume_token (parser);
5290 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5291 {
5292 c_parser_consume_token (parser);
5293 if (bad_parm)
5294 return NULL;
5295 else
5296 return get_parm_info (true, expr);
5297 }
5298 else
5299 {
5300 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5301 msgid: "expected %<)%>");
5302 return NULL;
5303 }
5304 }
5305 }
5306}
5307
5308/* Parse a parameter declaration. ATTRS are the gnu-attributes at the
5309 start of the declaration if it is the first parameter;
5310 HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
5311 empty) there. */
5312
5313static struct c_parm *
5314c_parser_parameter_declaration (c_parser *parser, tree attrs,
5315 bool have_gnu_attrs)
5316{
5317 struct c_declspecs *specs;
5318 struct c_declarator *declarator;
5319 tree prefix_attrs;
5320 tree postfix_attrs = NULL_TREE;
5321 bool dummy = false;
5322
5323 /* Accept #pragmas between parameter declarations. */
5324 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
5325 c_parser_pragma (parser, pragma_param, NULL, NULL_TREE);
5326
5327 if (!c_parser_next_token_starts_declspecs (parser)
5328 && !c_parser_nth_token_starts_std_attributes (parser, 1))
5329 {
5330 c_token *token = c_parser_peek_token (parser);
5331 if (parser->error)
5332 return NULL;
5333 c_parser_set_source_position_from_token (token);
5334 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
5335 {
5336 auto_diagnostic_group d;
5337 name_hint hint = lookup_name_fuzzy (token->value,
5338 FUZZY_LOOKUP_TYPENAME,
5339 token->location);
5340 if (const char *suggestion = hint.suggestion ())
5341 {
5342 gcc_rich_location richloc (token->location);
5343 richloc.add_fixit_replace (new_content: suggestion);
5344 error_at (&richloc,
5345 "unknown type name %qE; did you mean %qs?",
5346 token->value, suggestion);
5347 }
5348 else
5349 error_at (token->location, "unknown type name %qE", token->value);
5350 parser->error = true;
5351 }
5352 /* ??? In some Objective-C cases '...' isn't applicable so there
5353 should be a different message. */
5354 else
5355 c_parser_error (parser,
5356 gmsgid: "expected declaration specifiers or %<...%>");
5357 c_parser_skip_to_end_of_parameter (parser);
5358 return NULL;
5359 }
5360
5361 location_t start_loc = c_parser_peek_token (parser)->location;
5362
5363 specs = build_null_declspecs ();
5364 if (attrs)
5365 {
5366 declspecs_add_attrs (input_location, specs, attrs);
5367 attrs = NULL_TREE;
5368 }
5369 c_parser_declspecs (parser, specs, scspec_ok: true, typespec_ok: true, start_attr_ok: true, alignspec_ok: true, auto_type_ok: false,
5370 start_std_attr_ok: !have_gnu_attrs, end_std_attr_ok: true, la: cla_nonabstract_decl);
5371 finish_declspecs (specs);
5372 pending_xref_error ();
5373 prefix_attrs = specs->attrs;
5374 specs->attrs = NULL_TREE;
5375 declarator = c_parser_declarator (parser,
5376 type_seen_p: specs->typespec_kind != ctsk_none,
5377 kind: C_DTR_PARM, seen_id: &dummy);
5378 if (declarator == NULL)
5379 {
5380 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
5381 return NULL;
5382 }
5383 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5384 postfix_attrs = c_parser_gnu_attributes (parser);
5385
5386 /* Generate a location for the parameter, ranging from the start of the
5387 initial token to the end of the final token.
5388
5389 If we have a identifier, then use it for the caret location, e.g.
5390
5391 extern int callee (int one, int (*two)(int, int), float three);
5392 ~~~~~~^~~~~~~~~~~~~~
5393
5394 otherwise, reuse the start location for the caret location e.g.:
5395
5396 extern int callee (int one, int (*)(int, int), float three);
5397 ^~~~~~~~~~~~~~~~~
5398 */
5399 location_t end_loc = parser->last_token_location;
5400
5401 /* Find any cdk_id declarator; determine if we have an identifier. */
5402 c_declarator *id_declarator = declarator;
5403 while (id_declarator && id_declarator->kind != cdk_id)
5404 id_declarator = id_declarator->declarator;
5405 location_t caret_loc = (id_declarator->u.id.id
5406 ? id_declarator->id_loc
5407 : start_loc);
5408 location_t param_loc = make_location (caret: caret_loc, start: start_loc, finish: end_loc);
5409
5410 return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
5411 declarator, param_loc);
5412}
5413
5414/* Parse a string literal in an asm expression. It should not be
5415 translated, and wide string literals are an error although
5416 permitted by the syntax. This is a GNU extension.
5417
5418 asm-string-literal:
5419 string-literal
5420*/
5421
5422static tree
5423c_parser_asm_string_literal (c_parser *parser)
5424{
5425 tree str;
5426 int save_flag = warn_overlength_strings;
5427 warn_overlength_strings = 0;
5428 str = c_parser_string_literal (parser, false, false).value;
5429 warn_overlength_strings = save_flag;
5430 return str;
5431}
5432
5433/* Parse a simple asm expression. This is used in restricted
5434 contexts, where a full expression with inputs and outputs does not
5435 make sense. This is a GNU extension.
5436
5437 simple-asm-expr:
5438 asm ( asm-string-literal )
5439*/
5440
5441static tree
5442c_parser_simple_asm_expr (c_parser *parser)
5443{
5444 tree str;
5445 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
5446 c_parser_consume_token (parser);
5447 matching_parens parens;
5448 if (!parens.require_open (parser))
5449 return NULL_TREE;
5450 str = c_parser_asm_string_literal (parser);
5451 if (!parens.require_close (parser))
5452 {
5453 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5454 return NULL_TREE;
5455 }
5456 return str;
5457}
5458
5459static tree
5460c_parser_gnu_attribute_any_word (c_parser *parser)
5461{
5462 tree attr_name = NULL_TREE;
5463
5464 if (c_parser_next_token_is (parser, type: CPP_KEYWORD))
5465 {
5466 /* ??? See comment above about what keywords are accepted here. */
5467 bool ok;
5468 switch (c_parser_peek_token (parser)->keyword)
5469 {
5470 case RID_STATIC:
5471 case RID_UNSIGNED:
5472 case RID_LONG:
5473 case RID_CONST:
5474 case RID_EXTERN:
5475 case RID_REGISTER:
5476 case RID_TYPEDEF:
5477 case RID_SHORT:
5478 case RID_INLINE:
5479 case RID_NORETURN:
5480 case RID_VOLATILE:
5481 case RID_SIGNED:
5482 case RID_AUTO:
5483 case RID_RESTRICT:
5484 case RID_COMPLEX:
5485 case RID_THREAD:
5486 case RID_INT:
5487 case RID_CHAR:
5488 case RID_FLOAT:
5489 case RID_DOUBLE:
5490 case RID_VOID:
5491 case RID_DFLOAT32:
5492 case RID_DFLOAT64:
5493 case RID_DFLOAT128:
5494 case RID_DFLOAT64X:
5495 CASE_RID_FLOATN_NX:
5496 case RID_BOOL:
5497 case RID_BITINT:
5498 case RID_FRACT:
5499 case RID_ACCUM:
5500 case RID_SAT:
5501 case RID_TRANSACTION_ATOMIC:
5502 case RID_TRANSACTION_CANCEL:
5503 case RID_ATOMIC:
5504 case RID_AUTO_TYPE:
5505 case RID_CONSTEXPR:
5506 case RID_INT_N_0:
5507 case RID_INT_N_1:
5508 case RID_INT_N_2:
5509 case RID_INT_N_3:
5510 ok = true;
5511 break;
5512 default:
5513 ok = false;
5514 break;
5515 }
5516 if (!ok)
5517 return NULL_TREE;
5518
5519 /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
5520 attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
5521 }
5522 else if (c_parser_next_token_is (parser, type: CPP_NAME))
5523 attr_name = c_parser_peek_token (parser)->value;
5524
5525 return attr_name;
5526}
5527
5528/* Parse attribute arguments. This is a common form of syntax
5529 covering all currently valid GNU and standard attributes.
5530
5531 gnu-attribute-arguments:
5532 identifier
5533 identifier , nonempty-expr-list
5534 expr-list
5535
5536 where the "identifier" must not be declared as a type. ??? Why not
5537 allow identifiers declared as types to start the arguments? */
5538
5539static tree
5540c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
5541 bool require_string, bool assume_attr,
5542 bool allow_empty_args)
5543{
5544 vec<tree, va_gc> *expr_list;
5545 tree attr_args;
5546 /* Parse the attribute contents. If they start with an
5547 identifier which is followed by a comma or close
5548 parenthesis, then the arguments start with that
5549 identifier; otherwise they are an expression list.
5550 In objective-c the identifier may be a classname. */
5551 if (c_parser_next_token_is (parser, type: CPP_NAME)
5552 && (c_parser_peek_token (parser)->id_kind == C_ID_ID
5553 || (c_dialect_objc ()
5554 && c_parser_peek_token (parser)->id_kind
5555 == C_ID_CLASSNAME))
5556 && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
5557 || (c_parser_peek_2nd_token (parser)->type
5558 == CPP_CLOSE_PAREN))
5559 && (takes_identifier
5560 || (c_dialect_objc ()
5561 && !assume_attr
5562 && c_parser_peek_token (parser)->id_kind
5563 == C_ID_CLASSNAME)))
5564 {
5565 tree arg1 = c_parser_peek_token (parser)->value;
5566 c_parser_consume_token (parser);
5567 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5568 attr_args = build_tree_list (NULL_TREE, arg1);
5569 else
5570 {
5571 tree tree_list;
5572 c_parser_consume_token (parser);
5573 expr_list = c_parser_expr_list (parser, false, true,
5574 NULL, NULL, NULL, NULL);
5575 tree_list = build_tree_list_vec (expr_list);
5576 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
5577 release_tree_vector (expr_list);
5578 }
5579 }
5580 else
5581 {
5582 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5583 {
5584 if (!allow_empty_args)
5585 error_at (c_parser_peek_token (parser)->location,
5586 "parentheses must be omitted if "
5587 "attribute argument list is empty");
5588 attr_args = NULL_TREE;
5589 }
5590 else if (require_string)
5591 {
5592 /* The only valid argument for this attribute is a string
5593 literal. Handle this specially here to avoid accepting
5594 string literals with excess parentheses. */
5595 tree string = c_parser_string_literal (parser, false, true).value;
5596 attr_args = build_tree_list (NULL_TREE, string);
5597 }
5598 else if (assume_attr)
5599 {
5600 tree cond
5601 = c_parser_conditional_expression (parser, NULL, NULL_TREE).value;
5602 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
5603 attr_args = build_tree_list (NULL_TREE, cond);
5604 else
5605 {
5606 tree tree_list;
5607 c_parser_consume_token (parser);
5608 expr_list = c_parser_expr_list (parser, false, true,
5609 NULL, NULL, NULL, NULL);
5610 tree_list = build_tree_list_vec (expr_list);
5611 attr_args = tree_cons (NULL_TREE, cond, tree_list);
5612 release_tree_vector (expr_list);
5613 }
5614 }
5615 else
5616 {
5617 expr_list = c_parser_expr_list (parser, false, true,
5618 NULL, NULL, NULL, NULL);
5619 attr_args = build_tree_list_vec (expr_list);
5620 release_tree_vector (expr_list);
5621 }
5622 }
5623 return attr_args;
5624}
5625
5626/* Parse (possibly empty) gnu-attributes. This is a GNU extension.
5627
5628 gnu-attributes:
5629 empty
5630 gnu-attributes gnu-attribute
5631
5632 gnu-attribute:
5633 __attribute__ ( ( gnu-attribute-list ) )
5634
5635 gnu-attribute-list:
5636 gnu-attrib
5637 gnu-attribute_list , gnu-attrib
5638
5639 gnu-attrib:
5640 empty
5641 any-word
5642 any-word ( gnu-attribute-arguments )
5643
5644 where "any-word" may be any identifier (including one declared as a
5645 type), a reserved word storage class specifier, type specifier or
5646 type qualifier. ??? This still leaves out most reserved keywords
5647 (following the old parser), shouldn't we include them?
5648 When EXPECT_COMMA is true, expect the attribute to be preceded
5649 by a comma and fail if it isn't.
5650 When EMPTY_OK is true, allow and consume any number of consecutive
5651 commas with no attributes in between. */
5652
5653static tree
5654c_parser_gnu_attribute (c_parser *parser, tree attrs,
5655 bool expect_comma = false, bool empty_ok = true)
5656{
5657 bool comma_first = c_parser_next_token_is (parser, type: CPP_COMMA);
5658 if (!comma_first
5659 && !c_parser_next_token_is (parser, type: CPP_NAME)
5660 && !c_parser_next_token_is (parser, type: CPP_KEYWORD))
5661 return NULL_TREE;
5662
5663 while (c_parser_next_token_is (parser, type: CPP_COMMA))
5664 {
5665 c_parser_consume_token (parser);
5666 if (!empty_ok)
5667 return attrs;
5668 }
5669
5670 tree attr_name = c_parser_gnu_attribute_any_word (parser);
5671 if (attr_name == NULL_TREE)
5672 return NULL_TREE;
5673
5674 attr_name = canonicalize_attr_name (attr_name);
5675 c_parser_consume_token (parser);
5676
5677 tree attr;
5678 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
5679 {
5680 if (expect_comma && !comma_first)
5681 {
5682 /* A comma is missing between the last attribute on the chain
5683 and this one. */
5684 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5685 msgid: "expected %<)%>");
5686 return error_mark_node;
5687 }
5688 attr = build_tree_list (attr_name, NULL_TREE);
5689 /* Add this attribute to the list. */
5690 attrs = chainon (attrs, attr);
5691 return attrs;
5692 }
5693 c_parser_consume_token (parser);
5694
5695 tree attr_args
5696 = c_parser_attribute_arguments (parser,
5697 takes_identifier: attribute_takes_identifier_p (attr_name),
5698 require_string: false,
5699 assume_attr: is_attribute_p (attr_name: "assume", ident: attr_name),
5700 allow_empty_args: true);
5701
5702 attr = build_tree_list (attr_name, attr_args);
5703 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5704 c_parser_consume_token (parser);
5705 else
5706 {
5707 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5708 msgid: "expected %<)%>");
5709 return error_mark_node;
5710 }
5711
5712 if (expect_comma && !comma_first)
5713 {
5714 /* A comma is missing between the last attribute on the chain
5715 and this one. */
5716 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5717 msgid: "expected %<)%>");
5718 return error_mark_node;
5719 }
5720
5721 /* Add this attribute to the list. */
5722 attrs = chainon (attrs, attr);
5723 return attrs;
5724}
5725
5726static tree
5727c_parser_gnu_attributes (c_parser *parser)
5728{
5729 tree attrs = NULL_TREE;
5730 while (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
5731 {
5732 bool save_translate_strings_p = parser->translate_strings_p;
5733 parser->translate_strings_p = false;
5734 /* Consume the `__attribute__' keyword. */
5735 c_parser_consume_token (parser);
5736 /* Look for the two `(' tokens. */
5737 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5738 {
5739 parser->translate_strings_p = save_translate_strings_p;
5740 return attrs;
5741 }
5742 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
5743 {
5744 parser->translate_strings_p = save_translate_strings_p;
5745 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
5746 return attrs;
5747 }
5748 /* Parse the attribute list. Require a comma between successive
5749 (possibly empty) attributes. */
5750 for (bool expect_comma = false; ; expect_comma = true)
5751 {
5752 /* Parse a single attribute. */
5753 tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
5754 if (attr == error_mark_node)
5755 return attrs;
5756 if (!attr)
5757 break;
5758 attrs = attr;
5759 }
5760
5761 /* Look for the two `)' tokens. */
5762 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5763 c_parser_consume_token (parser);
5764 else
5765 {
5766 parser->translate_strings_p = save_translate_strings_p;
5767 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5768 msgid: "expected %<)%>");
5769 return attrs;
5770 }
5771 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
5772 c_parser_consume_token (parser);
5773 else
5774 {
5775 parser->translate_strings_p = save_translate_strings_p;
5776 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
5777 msgid: "expected %<)%>");
5778 return attrs;
5779 }
5780 parser->translate_strings_p = save_translate_strings_p;
5781 }
5782
5783 return attrs;
5784}
5785
5786/* Parse an optional balanced token sequence.
5787
5788 balanced-token-sequence:
5789 balanced-token
5790 balanced-token-sequence balanced-token
5791
5792 balanced-token:
5793 ( balanced-token-sequence[opt] )
5794 [ balanced-token-sequence[opt] ]
5795 { balanced-token-sequence[opt] }
5796 any token other than ()[]{}
5797*/
5798
5799static void
5800c_parser_balanced_token_sequence (c_parser *parser)
5801{
5802 while (true)
5803 {
5804 c_token *token = c_parser_peek_token (parser);
5805 switch (token->type)
5806 {
5807 case CPP_OPEN_BRACE:
5808 {
5809 matching_braces braces;
5810 braces.consume_open (parser);
5811 c_parser_balanced_token_sequence (parser);
5812 braces.require_close (parser);
5813 break;
5814 }
5815
5816 case CPP_OPEN_PAREN:
5817 {
5818 matching_parens parens;
5819 parens.consume_open (parser);
5820 c_parser_balanced_token_sequence (parser);
5821 parens.require_close (parser);
5822 break;
5823 }
5824
5825 case CPP_OPEN_SQUARE:
5826 c_parser_consume_token (parser);
5827 c_parser_balanced_token_sequence (parser);
5828 c_parser_require (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
5829 break;
5830
5831 case CPP_CLOSE_BRACE:
5832 case CPP_CLOSE_PAREN:
5833 case CPP_CLOSE_SQUARE:
5834 case CPP_EOF:
5835 return;
5836
5837 case CPP_PRAGMA:
5838 c_parser_consume_pragma (parser);
5839 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
5840 break;
5841
5842 default:
5843 c_parser_consume_token (parser);
5844 break;
5845 }
5846 }
5847}
5848
5849static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
5850 unsigned int *);
5851
5852/* Parse arguments of omp::directive or omp::decl attribute.
5853
5854 directive-name ,[opt] clause-list[opt]
5855
5856 For directive just remember the tokens in a vector for subsequent
5857 parsing. */
5858
5859static void
5860c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
5861{
5862 unsigned int n = 1;
5863 c_token *first = c_parser_peek_token (parser);
5864 if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
5865 || (c_parser_peek_nth_token_raw (parser, n)->type
5866 != CPP_CLOSE_PAREN))
5867 {
5868 c_parser_balanced_token_sequence (parser);
5869 TREE_VALUE (attribute) = NULL_TREE;
5870 return;
5871 }
5872 if (n == 1)
5873 {
5874 error_at (first->location, "expected OpenMP directive name");
5875 TREE_VALUE (attribute) = NULL_TREE;
5876 return;
5877 }
5878 vec<c_token, va_gc> *v;
5879 vec_alloc (v, nelems: n - 1);
5880 for (--n; n; --n)
5881 {
5882 c_token *tok = c_parser_peek_token (parser);
5883 v->quick_push (obj: *tok);
5884 c_parser_consume_token (parser);
5885 }
5886 tree arg = make_node (C_TOKEN_VEC);
5887 C_TOKEN_VEC_TOKENS (arg) = v;
5888 if (decl_p)
5889 TREE_PUBLIC (arg) = 1;
5890 TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
5891}
5892
5893/* Parse arguments of omp::sequence attribute.
5894
5895 omp::[opt] directive-attr [ , omp::[opt] directive-attr ]... */
5896
5897static void
5898c_parser_omp_sequence_args (c_parser *parser, tree attribute)
5899{
5900 do
5901 {
5902 c_token *token = c_parser_peek_token (parser);
5903 if (token->type == CPP_NAME
5904 && strcmp (IDENTIFIER_POINTER (token->value), s2: "omp") == 0
5905 && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
5906 {
5907 c_parser_consume_token (parser);
5908 c_parser_consume_token (parser);
5909 token = c_parser_peek_token (parser);
5910 }
5911 bool directive = false;
5912 const char *p;
5913 if (token->type != CPP_NAME)
5914 p = "";
5915 else
5916 p = IDENTIFIER_POINTER (token->value);
5917 if (strcmp (s1: p, s2: "directive") == 0)
5918 directive = true;
5919 else if (strcmp (s1: p, s2: "sequence") != 0)
5920 {
5921 error_at (token->location, "expected %<directive%> or %<sequence%>");
5922 unsigned nesting_depth = 0;
5923
5924 while (true)
5925 {
5926 /* Peek at the next token. */
5927 token = c_parser_peek_token (parser);
5928 /* If we've reached the token we want, consume it and stop. */
5929 if ((token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
5930 && !nesting_depth)
5931 break;
5932 /* If we've run out of tokens, stop. */
5933 if (token->type == CPP_EOF)
5934 break;
5935 if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
5936 break;
5937 if (token->type == CPP_OPEN_BRACE
5938 || token->type == CPP_OPEN_PAREN
5939 || token->type == CPP_OPEN_SQUARE)
5940 ++nesting_depth;
5941 else if (token->type == CPP_CLOSE_BRACE
5942 || token->type == CPP_CLOSE_PAREN
5943 || token->type == CPP_CLOSE_SQUARE)
5944 {
5945 if (nesting_depth-- == 0)
5946 break;
5947 }
5948 /* Consume this token. */
5949 c_parser_consume_token (parser);
5950 }
5951 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5952 break;
5953 c_parser_consume_token (parser);
5954 continue;
5955 }
5956 c_parser_consume_token (parser);
5957 matching_parens parens;
5958 if (parens.require_open (parser))
5959 {
5960 if (directive)
5961 c_parser_omp_directive_args (parser, attribute, decl_p: false);
5962 else
5963 c_parser_omp_sequence_args (parser, attribute);
5964 parens.skip_until_found_close (parser);
5965 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5966 break;
5967 c_parser_consume_token (parser);
5968 }
5969 else if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
5970 break;
5971 else
5972 c_parser_consume_token (parser);
5973 }
5974 while (1);
5975}
5976
5977/* Parse standard (C23) attributes (including GNU attributes in the
5978 gnu:: namespace).
5979
5980 attribute-specifier-sequence:
5981 attribute-specifier-sequence[opt] attribute-specifier
5982
5983 attribute-specifier:
5984 [ [ attribute-list ] ]
5985
5986 attribute-list:
5987 attribute[opt]
5988 attribute-list, attribute[opt]
5989
5990 attribute:
5991 attribute-token attribute-argument-clause[opt]
5992
5993 attribute-token:
5994 standard-attribute
5995 attribute-prefixed-token
5996
5997 standard-attribute:
5998 identifier
5999
6000 attribute-prefixed-token:
6001 attribute-prefix :: identifier
6002
6003 attribute-prefix:
6004 identifier
6005
6006 attribute-argument-clause:
6007 ( balanced-token-sequence[opt] )
6008
6009 Keywords are accepted as identifiers for this purpose.
6010
6011 As an extension, we permit an attribute-specifier to be:
6012
6013 [ [ __extension__ attribute-list ] ]
6014
6015 Two colons are then accepted as a synonym for ::. No attempt is made
6016 to check whether the colons are immediately adjacent. LOOSE_SCOPE_P
6017 indicates whether this relaxation is in effect. */
6018
6019static tree
6020c_parser_std_attribute (c_parser *parser, bool for_tm)
6021{
6022 c_token *token = c_parser_peek_token (parser);
6023 tree ns, name, attribute;
6024
6025 /* Parse the attribute-token. */
6026 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6027 {
6028 c_parser_error (parser, gmsgid: "expected identifier");
6029 return error_mark_node;
6030 }
6031 name = canonicalize_attr_name (attr_name: token->value);
6032 c_parser_consume_token (parser);
6033 if (c_parser_next_token_is (parser, type: CPP_SCOPE)
6034 || (c_parser_next_token_is (parser, type: CPP_COLON)
6035 && (c_parser_peek_token (parser)->flags & COLON_SCOPE) != 0
6036 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
6037 {
6038 ns = name;
6039 if (c_parser_next_token_is (parser, type: CPP_COLON))
6040 c_parser_consume_token (parser);
6041 c_parser_consume_token (parser);
6042 token = c_parser_peek_token (parser);
6043 if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
6044 {
6045 c_parser_error (parser, gmsgid: "expected identifier");
6046 return error_mark_node;
6047 }
6048 name = canonicalize_attr_name (attr_name: token->value);
6049 c_parser_consume_token (parser);
6050 }
6051 else
6052 ns = NULL_TREE;
6053 attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
6054
6055 /* Parse the arguments, if any. */
6056 const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
6057 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
6058 {
6059 if ((flag_openmp || flag_openmp_simd)
6060 && ns
6061 && is_attribute_p (attr_name: "omp", ident: ns)
6062 && (is_attribute_p (attr_name: "directive", ident: name)
6063 || is_attribute_p (attr_name: "sequence", ident: name)
6064 || is_attribute_p (attr_name: "decl", ident: name)))
6065 {
6066 error ("%<omp::%E%> attribute requires argument", name);
6067 return error_mark_node;
6068 }
6069 goto out;
6070 }
6071 {
6072 location_t open_loc = c_parser_peek_token (parser)->location;
6073 matching_parens parens;
6074 parens.consume_open (parser);
6075 if ((as && as->max_length == 0)
6076 /* Special-case the transactional-memory attribute "outer",
6077 which is specially handled but not registered as an
6078 attribute, to avoid allowing arbitrary balanced token
6079 sequences as arguments. */
6080 || is_attribute_p (attr_name: "outer", ident: name))
6081 {
6082 error_at (open_loc, "%qE attribute does not take any arguments", name);
6083 parens.skip_until_found_close (parser);
6084 return error_mark_node;
6085 }
6086 /* If this is a fake attribute created to handle -Wno-attributes,
6087 we must skip parsing the arguments. */
6088 if (as && !attribute_ignored_p (as))
6089 {
6090 bool takes_identifier
6091 = (ns != NULL_TREE
6092 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
6093 && attribute_takes_identifier_p (name));
6094 bool require_string
6095 = (ns == NULL_TREE
6096 && (strcmp (IDENTIFIER_POINTER (name), s2: "deprecated") == 0
6097 || strcmp (IDENTIFIER_POINTER (name), s2: "nodiscard") == 0));
6098 bool assume_attr
6099 = (ns != NULL_TREE
6100 && strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0
6101 && strcmp (IDENTIFIER_POINTER (name), s2: "assume") == 0);
6102 TREE_VALUE (attribute)
6103 = c_parser_attribute_arguments (parser, takes_identifier,
6104 require_string, assume_attr, allow_empty_args: false);
6105 }
6106 else
6107 {
6108 if ((flag_openmp || flag_openmp_simd)
6109 && ns
6110 && is_attribute_p (attr_name: "omp", ident: ns))
6111 {
6112 if (is_attribute_p (attr_name: "directive", ident: name))
6113 {
6114 c_parser_omp_directive_args (parser, attribute, decl_p: false);
6115 parens.skip_until_found_close (parser);
6116 return attribute;
6117 }
6118 else if (is_attribute_p (attr_name: "decl", ident: name))
6119 {
6120 TREE_VALUE (TREE_PURPOSE (attribute))
6121 = get_identifier ("directive");
6122 c_parser_omp_directive_args (parser, attribute, decl_p: true);
6123 parens.skip_until_found_close (parser);
6124 return attribute;
6125 }
6126 else if (is_attribute_p (attr_name: "sequence", ident: name))
6127 {
6128 TREE_VALUE (TREE_PURPOSE (attribute))
6129 = get_identifier ("directive");
6130 c_parser_omp_sequence_args (parser, attribute);
6131 parens.skip_until_found_close (parser);
6132 TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
6133 return attribute;
6134 }
6135 }
6136 c_parser_balanced_token_sequence (parser);
6137 }
6138 parens.require_close (parser);
6139 }
6140 out:
6141 if (ns == NULL_TREE && !for_tm && !as)
6142 {
6143 /* An attribute with standard syntax and no namespace specified
6144 is a constraint violation if it is not one of the known
6145 standard attributes. Diagnose it here with a pedwarn and
6146 then discard it to prevent a duplicate warning later. */
6147 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
6148 name);
6149 return error_mark_node;
6150 }
6151 return attribute;
6152}
6153
6154static tree
6155c_parser_std_attribute_list (c_parser *parser, bool for_tm)
6156{
6157 tree attributes = NULL_TREE;
6158 while (true)
6159 {
6160 c_token *token = c_parser_peek_token (parser);
6161 if (token->type == CPP_CLOSE_SQUARE)
6162 break;
6163 if (token->type == CPP_COMMA)
6164 {
6165 c_parser_consume_token (parser);
6166 continue;
6167 }
6168 tree attribute = c_parser_std_attribute (parser, for_tm);
6169 if (attribute != error_mark_node)
6170 {
6171 TREE_CHAIN (attribute) = attributes;
6172 attributes = attribute;
6173 }
6174 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
6175 break;
6176 }
6177 return attributes;
6178}
6179
6180static tree
6181c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
6182{
6183 location_t loc = c_parser_peek_token (parser)->location;
6184 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
6185 return NULL_TREE;
6186 if (!c_parser_require (parser, type: CPP_OPEN_SQUARE, msgid: "expected %<[%>"))
6187 {
6188 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6189 return NULL_TREE;
6190 }
6191 tree attributes;
6192 if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
6193 {
6194 auto ext = disable_extension_diagnostics ();
6195 c_parser_consume_token (parser);
6196 attributes = c_parser_std_attribute_list (parser, for_tm);
6197 restore_extension_diagnostics (flags: ext);
6198 }
6199 else
6200 {
6201 if (!for_tm)
6202 pedwarn_c11 (loc, OPT_Wpedantic,
6203 "ISO C does not support %<[[]]%> attributes before C23");
6204 attributes = c_parser_std_attribute_list (parser, for_tm);
6205 }
6206 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6207 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, msgid: "expected %<]%>");
6208 return nreverse (attributes);
6209}
6210
6211/* Look past an optional balanced token sequence of raw look-ahead
6212 tokens starting with the *Nth token. *N is updated to point to the
6213 following token. Return true if such a sequence was found, false
6214 if the tokens parsed were not balanced. */
6215
6216static bool
6217c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
6218{
6219 while (true)
6220 {
6221 c_token *token = c_parser_peek_nth_token_raw (parser, n: *n);
6222 switch (token->type)
6223 {
6224 case CPP_OPEN_BRACE:
6225 {
6226 ++*n;
6227 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6228 {
6229 token = c_parser_peek_nth_token_raw (parser, n: *n);
6230 if (token->type == CPP_CLOSE_BRACE)
6231 ++*n;
6232 else
6233 return false;
6234 }
6235 else
6236 return false;
6237 break;
6238 }
6239
6240 case CPP_OPEN_PAREN:
6241 {
6242 ++*n;
6243 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6244 {
6245 token = c_parser_peek_nth_token_raw (parser, n: *n);
6246 if (token->type == CPP_CLOSE_PAREN)
6247 ++*n;
6248 else
6249 return false;
6250 }
6251 else
6252 return false;
6253 break;
6254 }
6255
6256 case CPP_OPEN_SQUARE:
6257 {
6258 ++*n;
6259 if (c_parser_check_balanced_raw_token_sequence (parser, n))
6260 {
6261 token = c_parser_peek_nth_token_raw (parser, n: *n);
6262 if (token->type == CPP_CLOSE_SQUARE)
6263 ++*n;
6264 else
6265 return false;
6266 }
6267 else
6268 return false;
6269 break;
6270 }
6271
6272 case CPP_CLOSE_BRACE:
6273 case CPP_CLOSE_PAREN:
6274 case CPP_CLOSE_SQUARE:
6275 case CPP_EOF:
6276 return true;
6277
6278 default:
6279 ++*n;
6280 break;
6281 }
6282 }
6283}
6284
6285/* Return whether standard attributes start with the Nth token. */
6286
6287static bool
6288c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
6289{
6290 if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
6291 && c_parser_peek_nth_token (parser, n: n + 1)->type == CPP_OPEN_SQUARE))
6292 return false;
6293 /* In C, '[[' must start attributes. In Objective-C, we need to
6294 check whether '[[' is matched by ']]'. */
6295 if (!c_dialect_objc ())
6296 return true;
6297 n += 2;
6298 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
6299 return false;
6300 c_token *token = c_parser_peek_nth_token_raw (parser, n);
6301 if (token->type != CPP_CLOSE_SQUARE)
6302 return false;
6303 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
6304 return token->type == CPP_CLOSE_SQUARE;
6305}
6306
6307/* Skip standard attribute tokens starting at Nth token (with 1 as the
6308 next token), return index of the first token after the standard
6309 attribute tokens, or N on failure. */
6310
6311static size_t
6312c_parser_skip_std_attribute_spec_seq (c_parser *parser, size_t n)
6313{
6314 size_t orig_n = n;
6315 while (true)
6316 {
6317 if (c_parser_peek_nth_token_raw (parser, n)->type == CPP_OPEN_SQUARE
6318 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
6319 == CPP_OPEN_SQUARE))
6320 {
6321 unsigned int m = n + 2;
6322 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &m))
6323 return orig_n;
6324 c_token *token = c_parser_peek_nth_token_raw (parser, n: m);
6325 if (token->type != CPP_CLOSE_SQUARE)
6326 return orig_n;
6327 token = c_parser_peek_nth_token_raw (parser, n: m + 1);
6328 if (token->type != CPP_CLOSE_SQUARE)
6329 return orig_n;
6330 n = m + 2;
6331 }
6332 else
6333 break;
6334 }
6335 return n;
6336}
6337
6338static tree
6339c_parser_std_attribute_specifier_sequence (c_parser *parser)
6340{
6341 tree attributes = NULL_TREE;
6342 do
6343 {
6344 tree attrs = c_parser_std_attribute_specifier (parser, for_tm: false);
6345 attributes = chainon (attributes, attrs);
6346 }
6347 while (c_parser_nth_token_starts_std_attributes (parser, n: 1));
6348 return attributes;
6349}
6350
6351/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
6352 says whether alignment specifiers are OK (only in cases that might
6353 be the type name of a compound literal).
6354
6355 type-name:
6356 specifier-qualifier-list abstract-declarator[opt]
6357*/
6358
6359struct c_type_name *
6360c_parser_type_name (c_parser *parser, bool alignas_ok)
6361{
6362 struct c_declspecs *specs = build_null_declspecs ();
6363 struct c_declarator *declarator;
6364 struct c_type_name *ret;
6365 bool dummy = false;
6366 c_parser_declspecs (parser, specs, scspec_ok: false, typespec_ok: true, start_attr_ok: true, alignspec_ok: alignas_ok, auto_type_ok: false,
6367 start_std_attr_ok: false, end_std_attr_ok: true, la: cla_prefer_type);
6368 if (!specs->declspecs_seen_p)
6369 {
6370 c_parser_error (parser, gmsgid: "expected specifier-qualifier-list");
6371 return NULL;
6372 }
6373 if (specs->type != error_mark_node)
6374 {
6375 pending_xref_error ();
6376 finish_declspecs (specs);
6377 }
6378 declarator = c_parser_declarator (parser,
6379 type_seen_p: specs->typespec_kind != ctsk_none,
6380 kind: C_DTR_ABSTRACT, seen_id: &dummy);
6381 if (declarator == NULL)
6382 return NULL;
6383 ret = XOBNEW (&parser_obstack, struct c_type_name);
6384 ret->specs = specs;
6385 ret->declarator = declarator;
6386 return ret;
6387}
6388
6389/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
6390
6391 initializer:
6392 assignment-expression
6393 { initializer-list }
6394 { initializer-list , }
6395
6396 initializer-list:
6397 designation[opt] initializer
6398 initializer-list , designation[opt] initializer
6399
6400 designation:
6401 designator-list =
6402
6403 designator-list:
6404 designator
6405 designator-list designator
6406
6407 designator:
6408 array-designator
6409 . identifier
6410
6411 array-designator:
6412 [ constant-expression ]
6413
6414 GNU extensions:
6415
6416 initializer:
6417 { }
6418
6419 designation:
6420 array-designator
6421 identifier :
6422
6423 array-designator:
6424 [ constant-expression ... constant-expression ]
6425
6426 Any expression without commas is accepted in the syntax for the
6427 constant-expressions, with non-constant expressions rejected later.
6428
6429 DECL is the declaration we're parsing this initializer for.
6430
6431 This function is only used for top-level initializers; for nested
6432 ones, see c_parser_initval. */
6433
6434static struct c_expr
6435c_parser_initializer (c_parser *parser, tree decl)
6436{
6437 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
6438 return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
6439 else
6440 {
6441 struct c_expr ret;
6442 location_t loc = c_parser_peek_token (parser)->location;
6443 ret = c_parser_expr_no_commas (parser, NULL);
6444 if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6445 {
6446 error_at (loc,
6447 "variable-sized object may not be initialized except "
6448 "with an empty initializer");
6449 ret.set_error ();
6450 }
6451 /* This is handled mostly by gimplify.cc, but we have to deal with
6452 not warning about int x = x; as it is a GCC extension to turn off
6453 this warning but only if warn_init_self is zero. */
6454 if (VAR_P (decl)
6455 && !DECL_EXTERNAL (decl)
6456 && !TREE_STATIC (decl)
6457 && ret.value == decl
6458 && !warning_enabled_at (DECL_SOURCE_LOCATION (decl), option_id: OPT_Winit_self))
6459 suppress_warning (decl, OPT_Winit_self);
6460 if (TREE_CODE (ret.value) != STRING_CST
6461 && (TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR
6462 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6463 (ret.value))))
6464 ret = convert_lvalue_to_rvalue (loc, ret, true, true, true);
6465 return ret;
6466 }
6467}
6468
6469/* The location of the last comma within the current initializer list,
6470 or UNKNOWN_LOCATION if not within one. */
6471
6472location_t last_init_list_comma;
6473
6474/* Parse a braced initializer list. TYPE is the type specified for a
6475 compound literal, and NULL_TREE for other initializers and for
6476 nested braced lists. NESTED_P is true for nested braced lists,
6477 false for the list of a compound literal or the list that is the
6478 top-level initializer in a declaration. DECL is the declaration for
6479 the top-level initializer for a declaration, otherwise NULL_TREE. */
6480
6481static struct c_expr
6482c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
6483 struct obstack *outer_obstack, tree decl)
6484{
6485 struct c_expr ret;
6486 struct obstack braced_init_obstack;
6487 location_t brace_loc = c_parser_peek_token (parser)->location;
6488 gcc_obstack_init (&braced_init_obstack);
6489 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
6490 bool save_c_omp_array_section_p = c_omp_array_section_p;
6491 c_omp_array_section_p = false;
6492 bool zero_init_padding_bits = false;
6493 matching_braces braces;
6494 braces.consume_open (parser);
6495 if (nested_p)
6496 {
6497 finish_implicit_inits (brace_loc, outer_obstack);
6498 push_init_level (brace_loc, 0, &braced_init_obstack);
6499 }
6500 else
6501 really_start_incremental_init (type);
6502 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6503 {
6504 pedwarn_c11 (brace_loc, OPT_Wpedantic,
6505 "ISO C forbids empty initializer braces before C23");
6506 if (flag_isoc23)
6507 zero_init_padding_bits = true;
6508 }
6509 else
6510 {
6511 if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
6512 error_at (brace_loc,
6513 "variable-sized object may not be initialized except "
6514 "with an empty initializer");
6515 /* Parse a non-empty initializer list, possibly with a trailing
6516 comma. */
6517 while (true)
6518 {
6519 c_parser_initelt (parser, &braced_init_obstack);
6520 if (parser->error)
6521 break;
6522 if (c_parser_next_token_is (parser, type: CPP_COMMA))
6523 {
6524 last_init_list_comma = c_parser_peek_token (parser)->location;
6525 c_parser_consume_token (parser);
6526 /* CPP_EMBED should be always in between two CPP_COMMA
6527 tokens. */
6528 while (c_parser_next_token_is (parser, type: CPP_EMBED))
6529 {
6530 c_token *embed = c_parser_peek_token (parser);
6531 c_parser_consume_token (parser);
6532 c_expr embed_val;
6533 embed_val.value = embed->value;
6534 embed_val.original_code = RAW_DATA_CST;
6535 embed_val.original_type = integer_type_node;
6536 set_c_expr_source_range (expr: &embed_val, src_range: embed->get_range ());
6537 embed_val.m_decimal = 0;
6538 process_init_element (embed->location, embed_val, false,
6539 &braced_init_obstack);
6540 gcc_checking_assert (c_parser_next_token_is (parser,
6541 CPP_COMMA));
6542 last_init_list_comma = c_parser_peek_token (parser)->location;
6543 c_parser_consume_token (parser);
6544 }
6545 }
6546 else
6547 break;
6548 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
6549 break;
6550 }
6551 }
6552 c_omp_array_section_p = save_c_omp_array_section_p;
6553 c_token *next_tok = c_parser_peek_token (parser);
6554 if (next_tok->type != CPP_CLOSE_BRACE)
6555 {
6556 ret.set_error ();
6557 ret.original_code = ERROR_MARK;
6558 ret.original_type = NULL;
6559 braces.skip_until_found_close (parser);
6560 pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
6561 obstack_free (&braced_init_obstack, NULL);
6562 return ret;
6563 }
6564 location_t close_loc = next_tok->location;
6565 c_parser_consume_token (parser);
6566 ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
6567 if (zero_init_padding_bits
6568 && ret.value
6569 && TREE_CODE (ret.value) == CONSTRUCTOR)
6570 CONSTRUCTOR_ZERO_PADDING_BITS (ret.value) = 1;
6571 obstack_free (&braced_init_obstack, NULL);
6572 set_c_expr_source_range (expr: &ret, start: brace_loc, finish: close_loc);
6573 return ret;
6574}
6575
6576/* Parse a nested initializer, including designators. */
6577
6578static void
6579c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
6580{
6581 /* Parse any designator or designator list. A single array
6582 designator may have the subsequent "=" omitted in GNU C, but a
6583 longer list or a structure member designator may not. */
6584 if (c_parser_next_token_is (parser, type: CPP_NAME)
6585 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
6586 {
6587 /* Old-style structure member designator. */
6588 set_init_label (c_parser_peek_token (parser)->location,
6589 c_parser_peek_token (parser)->value,
6590 c_parser_peek_token (parser)->location,
6591 braced_init_obstack);
6592 /* Use the colon as the error location. */
6593 pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
6594 "obsolete use of designated initializer with %<:%>");
6595 c_parser_consume_token (parser);
6596 c_parser_consume_token (parser);
6597 }
6598 else
6599 {
6600 /* des_seen is 0 if there have been no designators, 1 if there
6601 has been a single array designator and 2 otherwise. */
6602 int des_seen = 0;
6603 /* Location of a designator. */
6604 location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6605 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE)
6606 || c_parser_next_token_is (parser, type: CPP_DOT))
6607 {
6608 int des_prev = des_seen;
6609 if (!des_seen)
6610 des_loc = c_parser_peek_token (parser)->location;
6611 if (des_seen < 2)
6612 des_seen++;
6613 if (c_parser_next_token_is (parser, type: CPP_DOT))
6614 {
6615 des_seen = 2;
6616 c_parser_consume_token (parser);
6617 if (c_parser_next_token_is (parser, type: CPP_NAME))
6618 {
6619 set_init_label (des_loc, c_parser_peek_token (parser)->value,
6620 c_parser_peek_token (parser)->location,
6621 braced_init_obstack);
6622 c_parser_consume_token (parser);
6623 }
6624 else
6625 {
6626 struct c_expr init;
6627 init.set_error ();
6628 init.original_code = ERROR_MARK;
6629 init.original_type = NULL;
6630 c_parser_error (parser, gmsgid: "expected identifier");
6631 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6632 process_init_element (input_location, init, false,
6633 braced_init_obstack);
6634 return;
6635 }
6636 }
6637 else
6638 {
6639 struct c_expr first_expr;
6640 tree first, second;
6641 location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
6642 location_t array_index_loc = UNKNOWN_LOCATION;
6643 /* ??? Following the old parser, [ objc-receiver
6644 objc-message-args ] is accepted as an initializer,
6645 being distinguished from a designator by what follows
6646 the first assignment expression inside the square
6647 brackets, but after a first array designator a
6648 subsequent square bracket is for Objective-C taken to
6649 start an expression, using the obsolete form of
6650 designated initializer without '=', rather than
6651 possibly being a second level of designation: in LALR
6652 terms, the '[' is shifted rather than reducing
6653 designator to designator-list. */
6654 if (des_prev == 1 && c_dialect_objc ())
6655 {
6656 des_seen = des_prev;
6657 break;
6658 }
6659 if (des_prev == 0 && c_dialect_objc ())
6660 {
6661 /* This might be an array designator or an
6662 Objective-C message expression. If the former,
6663 continue parsing here; if the latter, parse the
6664 remainder of the initializer given the starting
6665 primary-expression. ??? It might make sense to
6666 distinguish when des_prev == 1 as well; see
6667 previous comment. */
6668 tree rec, args;
6669 struct c_expr mexpr;
6670 c_parser_consume_token (parser);
6671 if (c_parser_peek_token (parser)->type == CPP_NAME
6672 && ((c_parser_peek_token (parser)->id_kind
6673 == C_ID_TYPENAME)
6674 || (c_parser_peek_token (parser)->id_kind
6675 == C_ID_CLASSNAME)))
6676 {
6677 /* Type name receiver. */
6678 tree id = c_parser_peek_token (parser)->value;
6679 c_parser_consume_token (parser);
6680 rec = objc_get_class_reference (id);
6681 goto parse_message_args;
6682 }
6683 array_index_loc = c_parser_peek_token (parser)->location;
6684 first_expr = c_parser_expr_no_commas (parser, NULL);
6685 mark_exp_read (first_expr.value);
6686 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS)
6687 || c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6688 goto array_desig_after_first;
6689 first = first_expr.value;
6690 /* Expression receiver. So far only one part
6691 without commas has been parsed; there might be
6692 more of the expression. */
6693 rec = first;
6694 while (c_parser_next_token_is (parser, type: CPP_COMMA))
6695 {
6696 struct c_expr next;
6697 location_t comma_loc, exp_loc;
6698 comma_loc = c_parser_peek_token (parser)->location;
6699 c_parser_consume_token (parser);
6700 exp_loc = c_parser_peek_token (parser)->location;
6701 next = c_parser_expr_no_commas (parser, NULL);
6702 next = convert_lvalue_to_rvalue (exp_loc, next,
6703 true, true);
6704 rec = build_compound_expr (comma_loc, rec, next.value);
6705 }
6706 parse_message_args:
6707 /* Now parse the objc-message-args. */
6708 args = c_parser_objc_message_args (parser);
6709 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6710 msgid: "expected %<]%>");
6711 mexpr.value
6712 = objc_build_message_expr (rec, args);
6713 mexpr.original_code = ERROR_MARK;
6714 mexpr.original_type = NULL;
6715 mexpr.m_decimal = 0;
6716 /* Now parse and process the remainder of the
6717 initializer, starting with this message
6718 expression as a primary-expression. */
6719 c_parser_initval (parser, &mexpr, braced_init_obstack);
6720 return;
6721 }
6722 c_parser_consume_token (parser);
6723 array_index_loc = c_parser_peek_token (parser)->location;
6724 first_expr = c_parser_expr_no_commas (parser, NULL);
6725 mark_exp_read (first_expr.value);
6726 array_desig_after_first:
6727 first_expr = convert_lvalue_to_rvalue (array_index_loc,
6728 first_expr,
6729 true, true);
6730 first = first_expr.value;
6731 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
6732 {
6733 ellipsis_loc = c_parser_peek_token (parser)->location;
6734 c_parser_consume_token (parser);
6735 second = convert_lvalue_to_rvalue (ellipsis_loc,
6736 (c_parser_expr_no_commas
6737 (parser, NULL)),
6738 true, true).value;
6739 mark_exp_read (second);
6740 }
6741 else
6742 second = NULL_TREE;
6743 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
6744 {
6745 c_parser_consume_token (parser);
6746 set_init_index (array_index_loc, first, second,
6747 braced_init_obstack);
6748 if (second)
6749 pedwarn (ellipsis_loc, OPT_Wpedantic,
6750 "ISO C forbids specifying range of elements to initialize");
6751 }
6752 else
6753 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
6754 msgid: "expected %<]%>");
6755 }
6756 }
6757 if (des_seen >= 1)
6758 {
6759 if (c_parser_next_token_is (parser, type: CPP_EQ))
6760 {
6761 pedwarn_c90 (des_loc, OPT_Wpedantic,
6762 "ISO C90 forbids specifying subobject "
6763 "to initialize");
6764 c_parser_consume_token (parser);
6765 }
6766 else
6767 {
6768 if (des_seen == 1)
6769 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
6770 "obsolete use of designated initializer without %<=%>");
6771 else
6772 {
6773 struct c_expr init;
6774 init.set_error ();
6775 init.original_code = ERROR_MARK;
6776 init.original_type = NULL;
6777 c_parser_error (parser, gmsgid: "expected %<=%>");
6778 c_parser_skip_until_found (parser, type: CPP_COMMA, NULL);
6779 process_init_element (input_location, init, false,
6780 braced_init_obstack);
6781 return;
6782 }
6783 }
6784 }
6785 }
6786 c_parser_initval (parser, NULL, braced_init_obstack);
6787}
6788
6789/* Parse a nested initializer; as c_parser_initializer but parses
6790 initializers within braced lists, after any designators have been
6791 applied. If AFTER is not NULL then it is an Objective-C message
6792 expression which is the primary-expression starting the
6793 initializer. */
6794
6795static void
6796c_parser_initval (c_parser *parser, struct c_expr *after,
6797 struct obstack * braced_init_obstack)
6798{
6799 struct c_expr init;
6800 gcc_assert (!after || c_dialect_objc ());
6801 location_t loc = c_parser_peek_token (parser)->location;
6802
6803 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE) && !after)
6804 init = c_parser_braced_init (parser, NULL_TREE, nested_p: true,
6805 outer_obstack: braced_init_obstack, NULL_TREE);
6806 else
6807 {
6808 init = c_parser_expr_no_commas (parser, after);
6809 if (init.value != NULL_TREE
6810 && TREE_CODE (init.value) != STRING_CST
6811 && (TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR
6812 || C_DECL_DECLARED_CONSTEXPR (COMPOUND_LITERAL_EXPR_DECL
6813 (init.value))))
6814 init = convert_lvalue_to_rvalue (loc, init, true, true, true);
6815 }
6816 tree val = init.value;
6817 process_init_element (loc, init, false, braced_init_obstack);
6818
6819 /* Attempt to optimize large char array initializers into RAW_DATA_CST
6820 to save compile time and memory even when not using #embed. */
6821 static unsigned vals_to_ignore;
6822 if (vals_to_ignore)
6823 /* If earlier call determined there is certain number of CPP_COMMA
6824 CPP_NUMBER tokens with 0-255 int values, but not enough for
6825 RAW_DATA_CST to be beneficial, don't try to check it again until
6826 they are all parsed. */
6827 --vals_to_ignore;
6828 else if (val
6829 && TREE_CODE (val) == INTEGER_CST
6830 && TREE_TYPE (val) == integer_type_node
6831 && c_parser_next_token_is (parser, type: CPP_COMMA))
6832 if (unsigned int len = c_maybe_optimize_large_byte_initializer ())
6833 {
6834 char buf1[64];
6835 unsigned int i;
6836 gcc_checking_assert (len >= 64);
6837 location_t last_loc = UNKNOWN_LOCATION;
6838 for (i = 0; i < 64; ++i)
6839 {
6840 c_token *tok = c_parser_peek_nth_token_raw (parser, n: 1 + 2 * i);
6841 if (tok->type != CPP_COMMA)
6842 break;
6843 tok = c_parser_peek_nth_token_raw (parser, n: 2 + 2 * i);
6844 if (tok->type != CPP_NUMBER
6845 || TREE_CODE (tok->value) != INTEGER_CST
6846 || TREE_TYPE (tok->value) != integer_type_node
6847 || wi::neg_p (x: wi::to_wide (t: tok->value))
6848 || wi::to_widest (t: tok->value) > UCHAR_MAX)
6849 break;
6850 buf1[i] = (char) tree_to_uhwi (tok->value);
6851 if (i == 0)
6852 loc = tok->location;
6853 last_loc = tok->location;
6854 }
6855 if (i < 64)
6856 {
6857 vals_to_ignore = i;
6858 return;
6859 }
6860 c_token *tok = c_parser_peek_nth_token_raw (parser, n: 1 + 2 * i);
6861 /* If 64 CPP_COMMA CPP_NUMBER pairs are followed by CPP_CLOSE_BRACE,
6862 punt if len is INT_MAX as that can mean this is a flexible array
6863 member and in that case we need one CPP_NUMBER afterwards
6864 (as guaranteed for CPP_EMBED). */
6865 if (tok->type == CPP_CLOSE_BRACE && len != INT_MAX)
6866 len = i;
6867 else if (tok->type != CPP_COMMA
6868 || (c_parser_peek_nth_token_raw (parser, n: 2 + 2 * i)->type
6869 != CPP_NUMBER))
6870 {
6871 vals_to_ignore = i;
6872 return;
6873 }
6874 /* Ensure the STRING_CST fits into 128K. */
6875 unsigned int max_len = 131072 - offsetof (struct tree_string, str) - 1;
6876 unsigned int orig_len = len;
6877 unsigned int off = 0, last = 0;
6878 if (!wi::neg_p (x: wi::to_wide (t: val)) && wi::to_widest (t: val) <= UCHAR_MAX)
6879 off = 1;
6880 len = MIN (len, max_len - off);
6881 char *buf2 = XNEWVEC (char, len + off);
6882 if (off)
6883 buf2[0] = (char) tree_to_uhwi (val);
6884 memcpy (dest: buf2 + off, src: buf1, n: i);
6885 for (unsigned int j = 0; j < i; ++j)
6886 {
6887 c_parser_peek_token (parser);
6888 c_parser_consume_token (parser);
6889 c_parser_peek_token (parser);
6890 c_parser_consume_token (parser);
6891 }
6892 for (; i < len; ++i)
6893 {
6894 if (!c_parser_next_token_is (parser, type: CPP_COMMA))
6895 break;
6896 tok = c_parser_peek_2nd_token (parser);
6897 if (tok->type != CPP_NUMBER
6898 || TREE_CODE (tok->value) != INTEGER_CST
6899 || TREE_TYPE (tok->value) != integer_type_node
6900 || wi::neg_p (x: wi::to_wide (t: tok->value))
6901 || wi::to_widest (t: tok->value) > UCHAR_MAX)
6902 break;
6903 c_token *tok2 = c_parser_peek_nth_token (parser, n: 3);
6904 if (tok2->type != CPP_COMMA && tok2->type != CPP_CLOSE_BRACE)
6905 break;
6906 buf2[i + off] = (char) tree_to_uhwi (tok->value);
6907 /* If orig_len is INT_MAX, this can be flexible array member and
6908 in that case we need to ensure another element which
6909 for CPP_EMBED is normally guaranteed after it. Include
6910 that byte in the RAW_DATA_OWNER though, so it can be optimized
6911 later. */
6912 if (orig_len == INT_MAX
6913 && (tok2->type == CPP_CLOSE_BRACE
6914 || (c_parser_peek_nth_token (parser, n: 4)->type
6915 != CPP_NUMBER)))
6916 {
6917 last = 1;
6918 break;
6919 }
6920 last_loc = tok->location;
6921 c_parser_consume_token (parser);
6922 c_parser_consume_token (parser);
6923 }
6924 val = make_node (RAW_DATA_CST);
6925 TREE_TYPE (val) = integer_type_node;
6926 RAW_DATA_LENGTH (val) = i;
6927 tree owner = build_string (i + off + last, buf2);
6928 XDELETEVEC (buf2);
6929 TREE_TYPE (owner) = build_array_type_nelts (unsigned_char_type_node,
6930 i + off + last);
6931 RAW_DATA_OWNER (val) = owner;
6932 RAW_DATA_POINTER (val) = TREE_STRING_POINTER (owner) + off;
6933 init.value = val;
6934 set_c_expr_source_range (expr: &init, start: loc, finish: last_loc);
6935 init.original_code = RAW_DATA_CST;
6936 init.original_type = integer_type_node;
6937 init.m_decimal = 0;
6938 process_init_element (loc, init, false, braced_init_obstack);
6939 }
6940}
6941
6942/* Parse a compound statement (possibly a function body) (C90 6.6.2,
6943 C99 6.8.2, C11 6.8.2, C23 6.8.2).
6944
6945 compound-statement:
6946 { block-item-list[opt] }
6947 { label-declarations block-item-list }
6948
6949 block-item-list:
6950 block-item
6951 block-item-list block-item
6952
6953 block-item:
6954 label
6955 nested-declaration
6956 statement
6957
6958 nested-declaration:
6959 declaration
6960
6961 GNU extensions:
6962
6963 compound-statement:
6964 { label-declarations block-item-list }
6965
6966 nested-declaration:
6967 __extension__ nested-declaration
6968 nested-function-definition
6969
6970 label-declarations:
6971 label-declaration
6972 label-declarations label-declaration
6973
6974 label-declaration:
6975 __label__ identifier-list ;
6976
6977 Allowing the mixing of declarations and code is new in C99. The
6978 GNU syntax also permits (not shown above) labels at the end of
6979 compound statements, which yield an error. We don't allow labels
6980 on declarations; this might seem like a natural extension, but
6981 there would be a conflict between gnu-attributes on the label and
6982 prefix gnu-attributes on the declaration. ??? The syntax follows the
6983 old parser in requiring something after label declarations.
6984 Although they are erroneous if the labels declared aren't defined,
6985 is it useful for the syntax to be this way?
6986
6987 OpenACC:
6988
6989 block-item:
6990 openacc-directive
6991
6992 openacc-directive:
6993 update-directive
6994
6995 OpenMP:
6996
6997 block-item:
6998 openmp-directive
6999
7000 openmp-directive:
7001 barrier-directive
7002 flush-directive
7003 taskwait-directive
7004 taskyield-directive
7005 cancel-directive
7006 cancellation-point-directive */
7007
7008static tree
7009c_parser_compound_statement (c_parser *parser, location_t *endlocp)
7010{
7011 tree stmt;
7012 location_t brace_loc;
7013 brace_loc = c_parser_peek_token (parser)->location;
7014 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
7015 {
7016 /* Ensure a scope is entered and left anyway to avoid confusion
7017 if we have just prepared to enter a function body. */
7018 stmt = c_begin_compound_stmt (true);
7019 c_end_compound_stmt (brace_loc, stmt, true);
7020 return error_mark_node;
7021 }
7022 stmt = c_begin_compound_stmt (true);
7023 location_t end_loc = c_parser_compound_statement_nostart (parser);
7024 if (endlocp)
7025 *endlocp = end_loc;
7026
7027 return c_end_compound_stmt (brace_loc, stmt, true);
7028}
7029
7030/* Diagnose errors related to imperfectly nested loops in an OMP
7031 loop construct. This function is called when such code is seen.
7032 Only issue one such diagnostic no matter how much invalid
7033 intervening code there is in the loop.
7034 FIXME: maybe the location associated with the diagnostic should
7035 be the current parser token instead of the location of the outer loop
7036 nest. */
7037
7038static void
7039check_omp_intervening_code (c_parser *parser)
7040{
7041 struct omp_for_parse_data *omp_for_parse_state = parser->omp_for_parse_state;
7042 gcc_assert (omp_for_parse_state);
7043
7044 if (!omp_for_parse_state->in_intervening_code)
7045 return;
7046 omp_for_parse_state->saw_intervening_code = true;
7047
7048 /* Only diagnose errors related to perfect nesting once. */
7049 if (!omp_for_parse_state->perfect_nesting_fail)
7050 {
7051
7052 /* OpenACC does not (yet) permit intervening code, in
7053 addition to situations forbidden by the OpenMP spec. */
7054 if (omp_for_parse_state->code == OACC_LOOP)
7055 {
7056 error_at (omp_for_parse_state->for_loc,
7057 "inner loops must be perfectly nested in "
7058 "%<#pragma acc loop%>");
7059 omp_for_parse_state->perfect_nesting_fail = true;
7060 }
7061 else if (omp_for_parse_state->ordered)
7062 {
7063 error_at (omp_for_parse_state->for_loc,
7064 "inner loops must be perfectly nested with "
7065 "%<ordered%> clause");
7066 omp_for_parse_state->perfect_nesting_fail = true;
7067 }
7068 else if (omp_for_parse_state->inscan)
7069 {
7070 error_at (omp_for_parse_state->for_loc,
7071 "inner loops must be perfectly nested with "
7072 "%<reduction%> %<inscan%> clause");
7073 omp_for_parse_state->perfect_nesting_fail = true;
7074 }
7075 else if (omp_for_parse_state->code == OMP_TILE)
7076 {
7077 error_at (omp_for_parse_state->for_loc,
7078 "inner loops must be perfectly nested in "
7079 "%<pragma omp tile%>");
7080 omp_for_parse_state->perfect_nesting_fail = true;
7081 }
7082 if (omp_for_parse_state->perfect_nesting_fail)
7083 omp_for_parse_state->fail = true;
7084 }
7085}
7086
7087/* Helper function for below: wrap an OMP_STRUCTURED_BLOCK around SL
7088 and add the statement to the current list. If SL is an empty statement
7089 list, do nothing. */
7090static void
7091add_structured_block_stmt (tree sl)
7092{
7093 if (TREE_CODE (sl) != STATEMENT_LIST
7094 || !tsi_end_p (i: tsi_start (t: sl)))
7095 add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
7096}
7097
7098struct c_omp_attribute_data
7099{
7100 vec<c_token, va_gc> *tokens;
7101 const c_omp_directive *dir;
7102 c_omp_directive_kind kind;
7103};
7104
7105/* Handle omp::directive and omp::sequence attributes in ATTRS
7106 (if any) at the start of a statement or in attribute-declaration. */
7107
7108static bool
7109c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs,
7110 bool *have_std_attrs)
7111{
7112 if (!flag_openmp && !flag_openmp_simd)
7113 return false;
7114
7115 auto_vec<c_omp_attribute_data, 16> vd;
7116 int cnt = 0;
7117 int tokens = 0;
7118 bool bad = false;
7119 for (tree *pa = &attrs; *pa; )
7120 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7121 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
7122 {
7123 cnt++;
7124 for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
7125 {
7126 tree d = TREE_VALUE (a);
7127 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7128 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7129 c_token *first = toks->address ();
7130 c_token *last = first + toks->length ();
7131 if (parser->omp_attrs_forbidden_p)
7132 {
7133 error_at (first->location,
7134 "mixing OpenMP directives with attribute and pragma "
7135 "syntax on the same statement");
7136 parser->omp_attrs_forbidden_p = false;
7137 bad = true;
7138 }
7139 else if (TREE_PUBLIC (d))
7140 {
7141 error_at (first->location,
7142 "OpenMP %<omp::decl%> attribute on a statement");
7143 bad = true;
7144 }
7145 const char *directive[3] = {};
7146 for (int i = 0; i < 3; i++)
7147 {
7148 tree id = NULL_TREE;
7149 if (first + i == last)
7150 break;
7151 if (first[i].type == CPP_NAME)
7152 id = first[i].value;
7153 else if (first[i].type == CPP_KEYWORD)
7154 id = ridpointers[(int) first[i].keyword];
7155 else
7156 break;
7157 directive[i] = IDENTIFIER_POINTER (id);
7158 }
7159 const c_omp_directive *dir = NULL;
7160 if (directive[0])
7161 dir = c_omp_categorize_directive (directive[0], directive[1],
7162 directive[2]);
7163 if (dir == NULL)
7164 {
7165 error_at (first->location,
7166 "unknown OpenMP directive name in %qs attribute "
7167 "argument",
7168 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7169 continue;
7170 }
7171 c_omp_directive_kind kind = dir->kind;
7172 if (dir->id == PRAGMA_OMP_ORDERED)
7173 {
7174 /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
7175 depend/doacross clause. */
7176 if (directive[1]
7177 && (strcmp (s1: directive[1], s2: "depend") == 0
7178 || strcmp (s1: directive[1], s2: "doacross") == 0))
7179 kind = C_OMP_DIR_STANDALONE;
7180 else if (first + 2 < last
7181 && first[1].type == CPP_COMMA
7182 && first[2].type == CPP_NAME
7183 && (strcmp (IDENTIFIER_POINTER (first[2].value),
7184 s2: "depend") == 0
7185 || strcmp (IDENTIFIER_POINTER (first[2].value),
7186 s2: "doacross") == 0))
7187 kind = C_OMP_DIR_STANDALONE;
7188 }
7189 else if (dir->id == PRAGMA_OMP_ERROR)
7190 {
7191 /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */
7192 int paren_depth = 0;
7193 for (int i = 1; first + i < last; i++)
7194 if (first[i].type == CPP_OPEN_PAREN)
7195 paren_depth++;
7196 else if (first[i].type == CPP_CLOSE_PAREN)
7197 paren_depth--;
7198 else if (paren_depth == 0
7199 && first + i + 2 < last
7200 && first[i].type == CPP_NAME
7201 && first[i + 1].type == CPP_OPEN_PAREN
7202 && first[i + 2].type == CPP_NAME
7203 && !strcmp (IDENTIFIER_POINTER (first[i].value),
7204 s2: "at")
7205 && !strcmp (IDENTIFIER_POINTER (first[i
7206 + 2].value),
7207 s2: "execution"))
7208 {
7209 kind = C_OMP_DIR_STANDALONE;
7210 break;
7211 }
7212 }
7213 c_omp_attribute_data v = { .tokens: toks, .dir: dir, .kind: kind };
7214 vd.safe_push (obj: v);
7215 if (flag_openmp || dir->simd)
7216 tokens += (last - first) + 1;
7217 }
7218 c_omp_attribute_data v = {};
7219 vd.safe_push (obj: v);
7220 *pa = TREE_CHAIN (*pa);
7221 }
7222 else
7223 pa = &TREE_CHAIN (*pa);
7224
7225 if (bad)
7226 {
7227 fail:
7228 if (have_std_attrs && attrs == NULL)
7229 *have_std_attrs = false;
7230 return false;
7231 }
7232
7233 unsigned int i;
7234 c_omp_attribute_data *v;
7235 c_omp_attribute_data *construct_seen = nullptr;
7236 c_omp_attribute_data *standalone_seen = nullptr;
7237 c_omp_attribute_data *prev_standalone_seen = nullptr;
7238 FOR_EACH_VEC_ELT (vd, i, v)
7239 if (v->tokens)
7240 {
7241 if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
7242 construct_seen = v;
7243 else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
7244 standalone_seen = v;
7245 }
7246 else
7247 {
7248 if (standalone_seen && !prev_standalone_seen)
7249 {
7250 prev_standalone_seen = standalone_seen;
7251 standalone_seen = nullptr;
7252 }
7253 }
7254
7255 if (cnt > 1 && construct_seen)
7256 {
7257 error_at ((*construct_seen->tokens)[0].location,
7258 "OpenMP construct among %<omp::directive%> attributes"
7259 " requires all %<omp::directive%> attributes on the"
7260 " same statement to be in the same %<omp::sequence%>");
7261 goto fail;
7262 }
7263 if (cnt > 1 && standalone_seen && prev_standalone_seen)
7264 {
7265 error_at ((*standalone_seen->tokens)[0].location,
7266 "multiple OpenMP standalone directives among"
7267 " %<omp::directive%> attributes must be all within the"
7268 " same %<omp::sequence%>");
7269 goto fail;
7270 }
7271
7272 if (prev_standalone_seen)
7273 standalone_seen = prev_standalone_seen;
7274 if (standalone_seen
7275 && !c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7276 {
7277 error_at (standalone_seen->tokens->address ()->location,
7278 "standalone OpenMP directives in %<omp::directive%> attribute"
7279 " can only appear on an empty statement");
7280 goto fail;
7281 }
7282 if (cnt && c_parser_next_token_is (parser, type: CPP_PRAGMA))
7283 {
7284 c_token *token = c_parser_peek_token (parser);
7285 enum pragma_kind kind = token->pragma_kind;
7286 if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
7287 {
7288 error_at (token->location,
7289 "mixing OpenMP directives with attribute and pragma "
7290 "syntax on the same statement");
7291 goto fail;
7292 }
7293 }
7294
7295 if (!tokens)
7296 return false;
7297
7298 unsigned int tokens_avail = parser->tokens_avail;
7299
7300 tokens++;
7301 vec<c_token, va_gc> *toks = NULL;
7302 vec_safe_reserve (v&: toks, nelems: tokens, exact: true);
7303 FOR_EACH_VEC_ELT (vd, i, v)
7304 {
7305 if (!v->tokens)
7306 continue;
7307 if (!flag_openmp && !v->dir->simd)
7308 continue;
7309 c_token *first = v->tokens->address ();
7310 c_token *last = first + v->tokens->length ();
7311 c_token tok = {};
7312 tok.type = CPP_PRAGMA;
7313 tok.keyword = RID_MAX;
7314 tok.pragma_kind = pragma_kind (v->dir->id);
7315 tok.location = first->location;
7316 toks->quick_push (obj: tok);
7317 while (++first < last)
7318 toks->quick_push (obj: *first);
7319 tok = {};
7320 tok.type = CPP_PRAGMA_EOL;
7321 tok.keyword = RID_MAX;
7322 tok.location = last[-1].location;
7323 toks->quick_push (obj: tok);
7324 }
7325
7326 c_token tok = {};
7327 tok.type = CPP_EOF;
7328 tok.keyword = RID_MAX;
7329 tok.location = toks->last ().location;
7330 toks->quick_push (obj: tok);
7331
7332 gcc_assert (!parser->in_omp_attribute_pragma);
7333 parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
7334 parser->in_omp_attribute_pragma->token_vec = toks;
7335 parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
7336 parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
7337 parser->tokens = toks->address ();
7338 parser->tokens_avail = tokens;
7339 return true;
7340}
7341
7342/* Handle omp::directive and omp::sequence attributes in ATTRS
7343 (if any) at the start or after declaration-id of a declaration. */
7344
7345static void
7346c_parser_handle_directive_omp_attributes (tree &attrs,
7347 vec<c_token> *&pragma_clauses,
7348 vec<c_token> *attr_clauses)
7349{
7350 if (!flag_openmp && !flag_openmp_simd)
7351 return;
7352
7353 for (tree *pa = &attrs; *pa; )
7354 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7355 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (*pa)))
7356 {
7357 int cnt = 0;
7358 for (tree *pa2 = &TREE_VALUE (*pa); *pa2; )
7359 {
7360 tree a = *pa2;
7361 tree d = TREE_VALUE (a);
7362 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
7363 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
7364 c_token *first = toks->address ();
7365 c_token *last = first + toks->length ();
7366 const char *directive[3] = {};
7367 for (int i = 0; i < 3; i++)
7368 {
7369 tree id = NULL_TREE;
7370 if (first + i == last)
7371 break;
7372 if (first[i].type == CPP_NAME)
7373 id = first[i].value;
7374 else if (first[i].type == CPP_KEYWORD)
7375 id = ridpointers[(int) first[i].keyword];
7376 else
7377 break;
7378 directive[i] = IDENTIFIER_POINTER (id);
7379 }
7380 const c_omp_directive *dir = NULL;
7381 if (directive[0])
7382 dir = c_omp_categorize_directive (directive[0], directive[1],
7383 directive[2]);
7384 if (dir == NULL)
7385 {
7386 error_at (first->location,
7387 "unknown OpenMP directive name in "
7388 "%qs attribute argument",
7389 TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
7390 *pa2 = TREE_CHAIN (a);
7391 }
7392 else if (dir->id == PRAGMA_OMP_DECLARE
7393 && (strcmp (s1: directive[1], s2: "simd") == 0
7394 || strcmp (s1: directive[1], s2: "variant") == 0))
7395 {
7396 if (pragma_clauses)
7397 {
7398 error_at (first->location,
7399 "mixing OpenMP directives with attribute and "
7400 "pragma syntax on the same declaration");
7401 for (pa = &attrs; *pa; )
7402 if (is_attribute_namespace_p (attr_ns: "omp", attr: *pa)
7403 && is_attribute_p (attr_name: "directive",
7404 ident: get_attribute_name (*pa)))
7405 *pa = TREE_CHAIN (*pa);
7406 else
7407 pa = &TREE_CHAIN (*pa);
7408 return;
7409 }
7410 ++cnt;
7411 attr_clauses->reserve (nelems: attr_clauses->length ()
7412 + toks->length () + 2);
7413 for (++first; first < last; ++first)
7414 attr_clauses->quick_push (obj: *first);
7415 c_token tok = {};
7416 tok.type = CPP_PRAGMA_EOL;
7417 tok.keyword = RID_MAX;
7418 tok.location = last[-1].location;
7419 attr_clauses->quick_push (obj: tok);
7420 *pa2 = TREE_CHAIN (a);
7421 }
7422 else
7423 pa2 = &TREE_CHAIN (a);
7424 }
7425 if (cnt && TREE_VALUE (*pa) == NULL_TREE)
7426 *pa = TREE_CHAIN (*pa);
7427 else
7428 pa = &TREE_CHAIN (*pa);
7429 }
7430 else
7431 pa = &TREE_CHAIN (*pa);
7432 if (attr_clauses->length ())
7433 {
7434 c_token tok = {};
7435 tok.type = CPP_EOF;
7436 tok.keyword = RID_MAX;
7437 tok.location = attr_clauses->last ().location;
7438 attr_clauses->quick_push (obj: tok);
7439 attr_clauses->quick_push (obj: tok);
7440 pragma_clauses = attr_clauses;
7441 }
7442}
7443
7444/* Check if STD_ATTR contains a musttail attribute and remove if it
7445 precedes a return. PARSER is the parser and ATTR is the output
7446 attr_state. */
7447
7448static tree
7449c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &attr)
7450{
7451 if (c_parser_next_token_is_keyword (parser, keyword: RID_RETURN))
7452 {
7453 if (tree a = lookup_attribute (attr_ns: "gnu", attr_name: "musttail", list: std_attrs))
7454 {
7455 for (; a; a = lookup_attribute (attr_ns: "gnu", attr_name: "musttail", TREE_CHAIN (a)))
7456 if (TREE_VALUE (a))
7457 error ("%qs attribute does not take any arguments",
7458 "musttail");
7459 std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
7460 attr.musttail_p = true;
7461 }
7462 if (lookup_attribute (attr_ns: "clang", attr_name: "musttail", list: std_attrs))
7463 {
7464 std_attrs = remove_attribute ("clang", "musttail", std_attrs);
7465 attr.musttail_p = true;
7466 }
7467 }
7468 return std_attrs;
7469}
7470
7471/* Return a statement before optional series of LABEL_EXPR/CASE_LABEL_EXPRs.
7472 Instead of collecting vectors of labels before each stmt just in case
7473 the statement would be iteration or switch statement for named loops,
7474 we just remember last emitted statement and let the iteration/switch
7475 statement search backwards in cur_stmt_list until that stmt for loop
7476 names if any. */
7477
7478static tree
7479get_before_labels ()
7480{
7481 if (!building_stmt_list_p ())
7482 return NULL_TREE;
7483 tree_stmt_iterator tsi = tsi_last (cur_stmt_list);
7484 if (tsi_end_p (i: tsi))
7485 return NULL_TREE;
7486 return tsi_stmt (i: tsi);
7487}
7488
7489/* Parse a compound statement except for the opening brace. This is
7490 used for parsing both compound statements and statement expressions
7491 (which follow different paths to handling the opening). */
7492
7493static location_t
7494c_parser_compound_statement_nostart (c_parser *parser)
7495{
7496 bool last_stmt = false;
7497 bool last_label = false;
7498 bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
7499 location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
7500 struct omp_for_parse_data *omp_for_parse_state
7501 = parser->omp_for_parse_state;
7502 bool in_omp_loop_block
7503 = omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
7504 tree sl = NULL_TREE;
7505 attr_state a = {};
7506
7507 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7508 {
7509 location_t endloc = c_parser_peek_token (parser)->location;
7510 add_debug_begin_stmt (loc: endloc);
7511 c_parser_consume_token (parser);
7512 return endloc;
7513 }
7514
7515 /* If we're parsing a {} sequence in an OMP_FOR body, start a
7516 statement list for intervening code. */
7517 if (in_omp_loop_block)
7518 sl = push_stmt_list ();
7519
7520 mark_valid_location_for_stdc_pragma (true);
7521 if (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
7522 {
7523 /* Read zero or more forward-declarations for labels that nested
7524 functions can jump to. */
7525 mark_valid_location_for_stdc_pragma (false);
7526 if (in_omp_loop_block)
7527 check_omp_intervening_code (parser);
7528 while (c_parser_next_token_is_keyword (parser, keyword: RID_LABEL))
7529 {
7530 label_loc = c_parser_peek_token (parser)->location;
7531 c_parser_consume_token (parser);
7532 /* Any identifiers, including those declared as type names,
7533 are OK here. */
7534 while (true)
7535 {
7536 tree label;
7537 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
7538 {
7539 c_parser_error (parser, gmsgid: "expected identifier");
7540 break;
7541 }
7542 label
7543 = declare_label (c_parser_peek_token (parser)->value);
7544 C_DECLARED_LABEL_FLAG (label) = 1;
7545 add_stmt (build_stmt (label_loc, DECL_EXPR, label));
7546 c_parser_consume_token (parser);
7547 if (c_parser_next_token_is (parser, type: CPP_COMMA))
7548 c_parser_consume_token (parser);
7549 else
7550 break;
7551 }
7552 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
7553 }
7554 pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
7555 }
7556 /* We must now have at least one statement, label or declaration. */
7557 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
7558 {
7559 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7560 c_parser_error (parser, gmsgid: "expected declaration or statement");
7561 location_t endloc = c_parser_peek_token (parser)->location;
7562 c_parser_consume_token (parser);
7563 return endloc;
7564 }
7565 tree before_labels = get_before_labels ();
7566 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_BRACE))
7567 {
7568 location_t loc = c_parser_peek_token (parser)->location;
7569 loc = expansion_point_location_if_in_system_header (loc);
7570
7571 bool want_nested_loop = (omp_for_parse_state
7572 ? omp_for_parse_state->want_nested_loop
7573 : false);
7574
7575 /* First take care of special cases for OpenMP "canonical loop
7576 nest form", that do not allow standard attributes, labels, or
7577 __extension__ before the nested statement. */
7578 if (in_omp_loop_block && !last_label)
7579 {
7580 tree_code code = omp_for_parse_state->code;
7581 if (want_nested_loop
7582 && c_parser_omp_next_tokens_can_be_canon_loop (parser, code,
7583 false))
7584 {
7585 /* Found the next nested loop. If there were intervening
7586 code statements collected before now, wrap them in an
7587 OMP_STRUCTURED_BLOCK node, and start a new structured
7588 block to hold statements that may come after the FOR. */
7589 gcc_assert (sl);
7590 add_structured_block_stmt (sl: pop_stmt_list (sl));
7591 omp_for_parse_state->depth++;
7592 add_stmt (c_parser_omp_loop_nest (parser, NULL));
7593 omp_for_parse_state->depth--;
7594 sl = push_stmt_list ();
7595 parser->error = false;
7596 before_labels = get_before_labels ();
7597 continue;
7598 }
7599 else if (want_nested_loop
7600 && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
7601 {
7602 /* If this nested compound statement contains the nested loop,
7603 we need to separate the other statements in the current
7604 statement into separate blocks of intervening code. If
7605 there's no nested loop, it's all part of the same
7606 chunk of intervening code. */
7607 tree pre_sl = pop_stmt_list (sl);
7608 tree nested_sl = push_stmt_list ();
7609 mark_valid_location_for_stdc_pragma (false);
7610 c_parser_statement_after_labels (parser, NULL, NULL_TREE);
7611 nested_sl = pop_stmt_list (nested_sl);
7612 if (omp_for_parse_state->want_nested_loop)
7613 {
7614 /* This block didn't contain a loop-nest, so it's
7615 all part of the same chunk of intervening code. */
7616 check_omp_intervening_code (parser);
7617 sl = push_stmt_list ();
7618 add_stmt (pre_sl);
7619 add_stmt (nested_sl);
7620 }
7621 else
7622 {
7623 /* It contains the nested loop. */
7624 add_structured_block_stmt (sl: pre_sl);
7625 add_stmt (nested_sl);
7626 sl = push_stmt_list ();
7627 }
7628 parser->error = false;
7629 before_labels = get_before_labels ();
7630 continue;
7631 }
7632 else if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7633 {
7634 /* Prior to implementing the OpenMP 5.1 syntax for canonical
7635 loop form, GCC used to accept an empty statements that
7636 would now be flagged as intervening code. Continue to
7637 do that, as an extension. */
7638 /* FIXME: Maybe issue a warning or something here? */
7639 c_parser_consume_token (parser);
7640 before_labels = get_before_labels ();
7641 continue;
7642 }
7643 }
7644
7645 /* Standard attributes may start a label, statement or declaration. */
7646 bool have_std_attrs
7647 = c_parser_nth_token_starts_std_attributes (parser, n: 1);
7648 tree std_attrs = NULL_TREE;
7649 if (have_std_attrs)
7650 {
7651 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7652 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr&: a);
7653 }
7654 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7655 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7656 || (c_parser_next_token_is (parser, type: CPP_NAME)
7657 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7658 {
7659 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7660 label_loc = c_parser_peek_2nd_token (parser)->location;
7661 else
7662 label_loc = c_parser_peek_token (parser)->location;
7663 last_label = true;
7664 last_stmt = false;
7665 mark_valid_location_for_stdc_pragma (false);
7666 if (in_omp_loop_block)
7667 check_omp_intervening_code (parser);
7668 c_parser_label (parser, std_attrs);
7669 }
7670 else if (c_parser_next_tokens_start_declaration (parser)
7671 || (have_std_attrs
7672 && !c_parser_handle_statement_omp_attributes
7673 (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7674 && c_parser_next_token_is (parser, type: CPP_SEMICOLON)
7675 && (have_std_attrs = true)))
7676 {
7677 if (last_label)
7678 pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wfree_labels,
7679 "a label can only be part of a statement and "
7680 "a declaration is not a statement");
7681 /* It's unlikely we'll see a nested loop in a declaration in
7682 intervening code in an OMP loop, but disallow it anyway. */
7683 if (in_omp_loop_block)
7684 {
7685 check_omp_intervening_code (parser);
7686 omp_for_parse_state->want_nested_loop = false;
7687 }
7688 mark_valid_location_for_stdc_pragma (false);
7689 bool fallthru_attr_p = false;
7690 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: !have_std_attrs,
7691 empty_ok: true, nested: true, start_attr_ok: true, simple_ok: false, NULL,
7692 NULL, have_attrs: have_std_attrs, attrs: std_attrs,
7693 NULL, fallthru_attr_p: &fallthru_attr_p);
7694
7695 if (in_omp_loop_block)
7696 omp_for_parse_state->want_nested_loop = want_nested_loop;
7697 if (last_stmt && !fallthru_attr_p)
7698 pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7699 "ISO C90 forbids mixed declarations and code");
7700 last_stmt = fallthru_attr_p;
7701 last_label = false;
7702 before_labels = get_before_labels ();
7703 }
7704 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
7705 {
7706 /* __extension__ can start a declaration, but is also an
7707 unary operator that can start an expression. Consume all
7708 but the last of a possible series of __extension__ to
7709 determine which. If standard attributes have already
7710 been seen, it must start a statement, not a declaration,
7711 but standard attributes starting a declaration may appear
7712 after __extension__. */
7713 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
7714 && (c_parser_peek_2nd_token (parser)->keyword
7715 == RID_EXTENSION))
7716 c_parser_consume_token (parser);
7717 if (!have_std_attrs
7718 && (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
7719 || c_parser_nth_token_starts_std_attributes (parser, n: 2)))
7720 {
7721 int ext;
7722 ext = disable_extension_diagnostics ();
7723 c_parser_consume_token (parser);
7724 last_label = false;
7725 /* It's unlikely we'll see a nested loop in a declaration in
7726 intervening code in an OMP loop, but disallow it anyway. */
7727 if (in_omp_loop_block)
7728 {
7729 check_omp_intervening_code (parser);
7730 omp_for_parse_state->want_nested_loop = false;
7731 }
7732 mark_valid_location_for_stdc_pragma (false);
7733 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
7734 start_attr_ok: true, simple_ok: false);
7735 if (in_omp_loop_block)
7736 omp_for_parse_state->want_nested_loop = want_nested_loop;
7737 /* Following the old parser, __extension__ does not
7738 disable this diagnostic. */
7739 restore_extension_diagnostics (flags: ext);
7740 if (last_stmt)
7741 pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
7742 "ISO C90 forbids mixed declarations and code");
7743 last_stmt = false;
7744 before_labels = get_before_labels ();
7745 }
7746 else
7747 goto statement;
7748 }
7749 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
7750 {
7751 if (have_std_attrs && !parser->in_omp_attribute_pragma)
7752 c_parser_error (parser, gmsgid: "expected declaration or statement");
7753 else if (std_attrs)
7754 c_warn_unused_attributes (std_attrs);
7755 /* External pragmas, and some omp pragmas, are not associated
7756 with regular c code, and so are not to be considered statements
7757 syntactically. This ensures that the user doesn't put them
7758 places that would turn into syntax errors if the directive
7759 were ignored. */
7760 if (omp_for_parse_state)
7761 omp_for_parse_state->want_nested_loop = false;
7762 if (c_parser_pragma (parser,
7763 last_label ? pragma_stmt : pragma_compound,
7764 NULL, before_labels))
7765 {
7766 last_label = false;
7767 last_stmt = true;
7768 if (omp_for_parse_state)
7769 check_omp_intervening_code (parser);
7770 }
7771 if (omp_for_parse_state)
7772 omp_for_parse_state->want_nested_loop = want_nested_loop;
7773 before_labels = get_before_labels ();
7774 }
7775 else if (c_parser_next_token_is (parser, type: CPP_EOF))
7776 {
7777 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7778 c_parser_error (parser, gmsgid: "expected declaration or statement");
7779 return c_parser_peek_token (parser)->location;
7780 }
7781 else if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
7782 {
7783 if (parser->in_if_block)
7784 {
7785 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7786 error_at (loc, "expected %<}%> before %<else%>");
7787 return c_parser_peek_token (parser)->location;
7788 }
7789 else
7790 {
7791 error_at (loc, "%<else%> without a previous %<if%>");
7792 c_parser_consume_token (parser);
7793 before_labels = get_before_labels ();
7794 continue;
7795 }
7796 }
7797 else
7798 {
7799 statement:
7800 c_warn_unused_attributes (std_attrs);
7801 last_label = false;
7802 last_stmt = true;
7803 mark_valid_location_for_stdc_pragma (false);
7804 if (!omp_for_parse_state)
7805 c_parser_statement_after_labels (parser, NULL, before_labels,
7806 NULL, a);
7807 else
7808 {
7809 /* In canonical loop nest form, nested loops can only appear
7810 directly, or in a directly nested compound statement. We
7811 already took care of those cases above, so now we have
7812 something else. This statement and everything inside
7813 it must be intervening code. */
7814 omp_for_parse_state->want_nested_loop = false;
7815 check_omp_intervening_code (parser);
7816 c_parser_statement_after_labels (parser, NULL, before_labels);
7817 omp_for_parse_state->want_nested_loop = want_nested_loop;
7818 }
7819 before_labels = get_before_labels ();
7820 }
7821
7822 parser->error = false;
7823 }
7824 if (last_label)
7825 pedwarn_c11 (label_loc, OPT_Wfree_labels,
7826 "label at end of compound statement");
7827 location_t endloc = c_parser_peek_token (parser)->location;
7828 c_parser_consume_token (parser);
7829
7830 /* Restore the value we started with. */
7831 mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
7832
7833 /* Package leftover intervening code, or the whole contents of the
7834 compound statement if we were looking for a nested loop in an OMP_FOR
7835 construct and didn't find one. */
7836 if (sl)
7837 {
7838 sl = pop_stmt_list (sl);
7839 if (omp_for_parse_state->want_nested_loop)
7840 add_stmt (sl);
7841 else
7842 add_structured_block_stmt (sl);
7843 }
7844 return endloc;
7845}
7846
7847/* Parse all consecutive labels, possibly preceded by standard
7848 attributes. In this context, a statement is required, not a
7849 declaration, so attributes must be followed by a statement that is
7850 not just a semicolon. Returns an attr_state. */
7851
7852static attr_state
7853c_parser_all_labels (c_parser *parser)
7854{
7855 attr_state attr = {};
7856 bool have_std_attrs;
7857 tree std_attrs = NULL;
7858 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1)))
7859 {
7860 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7861 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
7862 }
7863
7864 while (c_parser_next_token_is_keyword (parser, keyword: RID_CASE)
7865 || c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
7866 || (c_parser_next_token_is (parser, type: CPP_NAME)
7867 && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
7868 {
7869 c_parser_label (parser, std_attrs);
7870 std_attrs = NULL;
7871 if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser,
7872 n: 1)))
7873 {
7874 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
7875 std_attrs = c_parser_handle_musttail (parser, std_attrs, attr);
7876 }
7877 }
7878 if (std_attrs
7879 && (!c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, have_std_attrs: &have_std_attrs)
7880 || std_attrs))
7881 {
7882 if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7883 c_parser_error (parser, gmsgid: "expected statement");
7884 c_warn_unused_attributes (std_attrs);
7885 }
7886 else if (have_std_attrs && c_parser_next_token_is (parser, type: CPP_SEMICOLON))
7887 c_parser_error (parser, gmsgid: "expected statement");
7888 return attr;
7889}
7890
7891
7892/* Information used while parsing an OpenMP metadirective. */
7893struct omp_metadirective_parse_data {
7894 /* These fields are used to unique-ify labels when reparsing the
7895 code in a metadirective alternative. */
7896 vec<tree> * GTY((skip)) body_labels;
7897 unsigned int region_num;
7898};
7899
7900/* Helper function for c_parser_label: mangle a metadirective region
7901 label NAME. */
7902static tree
7903mangle_metadirective_region_label (c_parser *parser, tree name)
7904{
7905 if (parser->omp_metadirective_state->body_labels->contains (search: name))
7906 {
7907 const char *old_name = IDENTIFIER_POINTER (name);
7908 char *new_name = (char *) XALLOCAVEC (char, strlen (old_name) + 32);
7909 sprintf (s: new_name, format: "%s_MDR%u", old_name,
7910 parser->omp_metadirective_state->region_num);
7911 return get_identifier (new_name);
7912 }
7913 return name;
7914}
7915
7916/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
7917
7918 label:
7919 identifier : gnu-attributes[opt]
7920 case constant-expression :
7921 default :
7922
7923 GNU extensions:
7924
7925 label:
7926 case constant-expression ... constant-expression :
7927
7928 The use of gnu-attributes on labels is a GNU extension. The syntax in
7929 GNU C accepts any expressions without commas, non-constant
7930 expressions being rejected later. Any standard
7931 attribute-specifier-sequence before the first label has been parsed
7932 in the caller, to distinguish statements from declarations. Any
7933 attribute-specifier-sequence after the label is parsed in this
7934 function. */
7935static void
7936c_parser_label (c_parser *parser, tree std_attrs)
7937{
7938 location_t loc1 = c_parser_peek_token (parser)->location;
7939 tree label = NULL_TREE;
7940
7941 /* Remember whether this case or a user-defined label is allowed to fall
7942 through to. */
7943 bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
7944
7945 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
7946 {
7947 tree exp1, exp2;
7948 c_parser_consume_token (parser);
7949 exp1 = convert_lvalue_to_rvalue (loc1,
7950 c_parser_expr_no_commas (parser, NULL),
7951 true, true).value;
7952 if (c_parser_next_token_is (parser, type: CPP_COLON))
7953 {
7954 c_parser_consume_token (parser);
7955 label = do_case (loc1, exp1, NULL_TREE, std_attrs);
7956 }
7957 else if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
7958 {
7959 c_parser_consume_token (parser);
7960 exp2 = convert_lvalue_to_rvalue (loc1,
7961 c_parser_expr_no_commas (parser,
7962 NULL),
7963 true, true).value;
7964 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7965 label = do_case (loc1, exp1, exp2, std_attrs);
7966 }
7967 else
7968 c_parser_error (parser, gmsgid: "expected %<:%> or %<...%>");
7969 }
7970 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
7971 {
7972 c_parser_consume_token (parser);
7973 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
7974 label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs);
7975 }
7976 else
7977 {
7978 tree name = c_parser_peek_token (parser)->value;
7979 tree tlab;
7980 tree attrs;
7981 location_t loc2 = c_parser_peek_token (parser)->location;
7982 gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
7983 c_parser_consume_token (parser);
7984 gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
7985 c_parser_consume_token (parser);
7986 attrs = c_parser_gnu_attributes (parser);
7987 if (parser->omp_metadirective_state)
7988 name = mangle_metadirective_region_label (parser, name);
7989 tlab = define_label (loc2, name);
7990 if (tlab)
7991 {
7992 decl_attributes (&tlab, attrs, 0);
7993 decl_attributes (&tlab, std_attrs, 0);
7994 label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
7995 }
7996 if (attrs
7997 && c_parser_next_tokens_start_declaration (parser))
7998 warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
7999 " label and declaration appertains to the label");
8000 }
8001 if (label)
8002 {
8003 if (TREE_CODE (label) == LABEL_EXPR)
8004 FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
8005 else
8006 FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
8007 }
8008}
8009
8010/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
8011
8012 statement:
8013 labeled-statement
8014 attribute-specifier-sequence[opt] compound-statement
8015 expression-statement
8016 attribute-specifier-sequence[opt] selection-statement
8017 attribute-specifier-sequence[opt] iteration-statement
8018 attribute-specifier-sequence[opt] jump-statement
8019
8020 labeled-statement:
8021 attribute-specifier-sequence[opt] label statement
8022
8023 expression-statement:
8024 expression[opt] ;
8025 attribute-specifier-sequence expression ;
8026
8027 selection-statement:
8028 if-statement
8029 switch-statement
8030
8031 iteration-statement:
8032 while-statement
8033 do-statement
8034 for-statement
8035
8036 jump-statement:
8037 goto identifier ;
8038 continue ;
8039 break ;
8040 return expression[opt] ;
8041
8042 GNU extensions:
8043
8044 statement:
8045 attribute-specifier-sequence[opt] asm-statement
8046
8047 jump-statement:
8048 goto * expression ;
8049
8050 expression-statement:
8051 gnu-attributes ;
8052
8053 Objective-C:
8054
8055 statement:
8056 attribute-specifier-sequence[opt] objc-throw-statement
8057 attribute-specifier-sequence[opt] objc-try-catch-statement
8058 attribute-specifier-sequence[opt] objc-synchronized-statement
8059
8060 objc-throw-statement:
8061 @throw expression ;
8062 @throw ;
8063
8064 OpenACC:
8065
8066 statement:
8067 attribute-specifier-sequence[opt] openacc-construct
8068
8069 openacc-construct:
8070 parallel-construct
8071 kernels-construct
8072 data-construct
8073 loop-construct
8074
8075 parallel-construct:
8076 parallel-directive structured-block
8077
8078 kernels-construct:
8079 kernels-directive structured-block
8080
8081 data-construct:
8082 data-directive structured-block
8083
8084 loop-construct:
8085 loop-directive structured-block
8086
8087 OpenMP:
8088
8089 statement:
8090 attribute-specifier-sequence[opt] openmp-construct
8091
8092 openmp-construct:
8093 parallel-construct
8094 for-construct
8095 simd-construct
8096 for-simd-construct
8097 sections-construct
8098 single-construct
8099 parallel-for-construct
8100 parallel-for-simd-construct
8101 parallel-sections-construct
8102 master-construct
8103 critical-construct
8104 atomic-construct
8105 ordered-construct
8106
8107 parallel-construct:
8108 parallel-directive structured-block
8109
8110 for-construct:
8111 for-directive iteration-statement
8112
8113 simd-construct:
8114 simd-directive iteration-statements
8115
8116 for-simd-construct:
8117 for-simd-directive iteration-statements
8118
8119 sections-construct:
8120 sections-directive section-scope
8121
8122 single-construct:
8123 single-directive structured-block
8124
8125 parallel-for-construct:
8126 parallel-for-directive iteration-statement
8127
8128 parallel-for-simd-construct:
8129 parallel-for-simd-directive iteration-statement
8130
8131 parallel-sections-construct:
8132 parallel-sections-directive section-scope
8133
8134 master-construct:
8135 master-directive structured-block
8136
8137 critical-construct:
8138 critical-directive structured-block
8139
8140 atomic-construct:
8141 atomic-directive expression-statement
8142
8143 ordered-construct:
8144 ordered-directive structured-block
8145
8146 Transactional Memory:
8147
8148 statement:
8149 attribute-specifier-sequence[opt] transaction-statement
8150 attribute-specifier-sequence[opt] transaction-cancel-statement
8151
8152 IF_P is used to track whether there's a (possibly labeled) if statement
8153 which is not enclosed in braces and has an else clause. This is used to
8154 implement -Wparentheses. */
8155
8156static void
8157c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
8158{
8159 tree before_labels = get_before_labels ();
8160 attr_state a = c_parser_all_labels (parser);
8161 if (loc_after_labels)
8162 *loc_after_labels = c_parser_peek_token (parser)->location;
8163 parser->omp_attrs_forbidden_p = false;
8164 c_parser_statement_after_labels (parser, if_p, before_labels, NULL, a);
8165}
8166
8167/* Parse and handle optional identifier after break or continue keywords. */
8168
8169static tree
8170c_parser_bc_name (c_parser *parser, bool is_break)
8171{
8172 if (!c_parser_next_token_is (parser, type: CPP_NAME))
8173 return NULL_TREE;
8174
8175 c_token *tok = c_parser_peek_token (parser);
8176 tree label = c_finish_bc_name (tok->location, tok->value, is_break);
8177 c_parser_consume_token (parser);
8178 return label;
8179}
8180
8181/* Parse a statement, other than a labeled statement. CHAIN is a vector
8182 of if-else-if conditions. All labels and standard attributes have
8183 been parsed in the caller.
8184
8185 IF_P is used to track whether there's a (possibly labeled) if statement
8186 which is not enclosed in braces and has an else clause. This is used to
8187 implement -Wparentheses. ASTATE is an earlier parsed attribute state.
8188
8189 BEFORE_LABELS is last statement before possible labels, see
8190 get_before_labels description for details. */
8191
8192static void
8193c_parser_statement_after_labels (c_parser *parser, bool *if_p,
8194 tree before_labels,
8195 vec<tree> *chain, attr_state astate)
8196{
8197 location_t loc = c_parser_peek_token (parser)->location;
8198 tree stmt = NULL_TREE;
8199 bool in_if_block = parser->in_if_block;
8200 parser->in_if_block = false;
8201 if (if_p != NULL)
8202 *if_p = false;
8203
8204 if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
8205 add_debug_begin_stmt (loc);
8206
8207 restart:
8208 switch (c_parser_peek_token (parser)->type)
8209 {
8210 case CPP_OPEN_BRACE:
8211 add_stmt (c_parser_compound_statement (parser));
8212 break;
8213 case CPP_KEYWORD:
8214 switch (c_parser_peek_token (parser)->keyword)
8215 {
8216 case RID_IF:
8217 c_parser_if_statement (parser, if_p, chain);
8218 break;
8219 case RID_SWITCH:
8220 c_parser_switch_statement (parser, if_p, before_labels);
8221 break;
8222 case RID_WHILE:
8223 c_parser_while_statement (parser, false, 0, false, if_p, before_labels);
8224 break;
8225 case RID_DO:
8226 c_parser_do_statement (parser, false, 0, false, before_labels);
8227 break;
8228 case RID_FOR:
8229 c_parser_for_statement (parser, false, 0, false, if_p, before_labels);
8230 break;
8231 case RID_GOTO:
8232 c_parser_consume_token (parser);
8233 if (c_parser_next_token_is (parser, type: CPP_NAME))
8234 {
8235 tree name = c_parser_peek_token (parser)->value;
8236 if (parser->omp_metadirective_state)
8237 name = mangle_metadirective_region_label (parser, name);
8238 stmt = c_finish_goto_label (loc, name);
8239 c_parser_consume_token (parser);
8240 }
8241 else if (c_parser_next_token_is (parser, type: CPP_MULT))
8242 {
8243 struct c_expr val;
8244
8245 c_parser_consume_token (parser);
8246 val = c_parser_expression (parser);
8247 val = convert_lvalue_to_rvalue (loc, val, false, true);
8248 stmt = c_finish_goto_ptr (loc, val);
8249 }
8250 else
8251 c_parser_error (parser, gmsgid: "expected identifier or %<*%>");
8252 goto expect_semicolon;
8253 case RID_CONTINUE:
8254 c_parser_consume_token (parser);
8255 stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false,
8256 c_parser_bc_name (parser, is_break: false));
8257 goto expect_semicolon;
8258 case RID_BREAK:
8259 c_parser_consume_token (parser);
8260 stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true,
8261 c_parser_bc_name (parser, is_break: true));
8262 goto expect_semicolon;
8263 case RID_RETURN:
8264 c_parser_consume_token (parser);
8265 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8266 {
8267 stmt = c_finish_return (loc, NULL_TREE, NULL_TREE,
8268 astate.musttail_p);
8269 c_parser_consume_token (parser);
8270 }
8271 else
8272 {
8273 location_t xloc = c_parser_peek_token (parser)->location;
8274 struct c_expr expr = c_parser_expression_conv (parser);
8275 mark_exp_read (expr.value);
8276 stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
8277 expr.value, expr.original_type,
8278 astate.musttail_p);
8279 goto expect_semicolon;
8280 }
8281 break;
8282 case RID_ASM:
8283 stmt = c_parser_asm_statement (parser);
8284 break;
8285 case RID_TRANSACTION_ATOMIC:
8286 case RID_TRANSACTION_RELAXED:
8287 stmt = c_parser_transaction (parser,
8288 c_parser_peek_token (parser)->keyword);
8289 break;
8290 case RID_TRANSACTION_CANCEL:
8291 stmt = c_parser_transaction_cancel (parser);
8292 goto expect_semicolon;
8293 case RID_AT_THROW:
8294 gcc_assert (c_dialect_objc ());
8295 c_parser_consume_token (parser);
8296 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8297 {
8298 stmt = objc_build_throw_stmt (loc, NULL_TREE);
8299 c_parser_consume_token (parser);
8300 }
8301 else
8302 {
8303 struct c_expr expr = c_parser_expression (parser);
8304 expr = convert_lvalue_to_rvalue (loc, expr, false, false);
8305 expr.value = c_fully_fold (expr.value, false, NULL);
8306 stmt = objc_build_throw_stmt (loc, expr.value);
8307 goto expect_semicolon;
8308 }
8309 break;
8310 case RID_AT_TRY:
8311 gcc_assert (c_dialect_objc ());
8312 c_parser_objc_try_catch_finally_statement (parser);
8313 break;
8314 case RID_AT_SYNCHRONIZED:
8315 gcc_assert (c_dialect_objc ());
8316 c_parser_objc_synchronized_statement (parser);
8317 break;
8318 case RID_ATTRIBUTE:
8319 {
8320 /* Allow '__attribute__((fallthrough));' or
8321 '__attribute__((assume(cond)));' or
8322 '__attribute__((musttail))) return'. */
8323 tree attrs = c_parser_gnu_attributes (parser);
8324 bool has_assume = lookup_attribute (attr_name: "assume", list: attrs);
8325 if (has_assume)
8326 {
8327 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8328 attrs = handle_assume_attribute (here: loc, attrs, nested: true);
8329 else
8330 {
8331 auto_urlify_attributes sentinel;
8332 warning_at (loc, OPT_Wattributes,
8333 "%<assume%> attribute not followed by %<;%>");
8334 has_assume = false;
8335 }
8336 }
8337 gcc_assert (!astate.musttail_p);
8338 attrs = c_parser_handle_musttail (parser, std_attrs: attrs, attr&: astate);
8339 if (astate.musttail_p)
8340 {
8341 if (attrs)
8342 {
8343 auto_urlify_attributes sentinel;
8344 warning_at (c_parser_peek_token (parser)->location,
8345 OPT_Wattributes,
8346 "attribute %<musttail%> mixed with other "
8347 "attributes on %<return%> statement");
8348 }
8349 goto restart;
8350 }
8351 if (attribute_fallthrough_p (attrs))
8352 {
8353 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8354 {
8355 tree fn = build_call_expr_internal_loc (loc,
8356 IFN_FALLTHROUGH,
8357 void_type_node, 0);
8358 add_stmt (fn);
8359 /* Eat the ';'. */
8360 c_parser_consume_token (parser);
8361 }
8362 else
8363 {
8364 auto_urlify_attributes sentinel;
8365 warning_at (loc, OPT_Wattributes,
8366 "%<fallthrough%> attribute not followed "
8367 "by %<;%>");
8368 }
8369 }
8370 else if (has_assume)
8371 /* Eat the ';'. */
8372 c_parser_consume_token (parser);
8373 else if (attrs != NULL_TREE)
8374 {
8375 auto_urlify_attributes sentinel;
8376 warning_at (loc, OPT_Wattributes,
8377 "only attribute %<fallthrough%> or %<assume%> can "
8378 "be applied to a null statement");
8379 }
8380 break;
8381 }
8382 default:
8383 goto expr_stmt;
8384 }
8385 break;
8386 case CPP_SEMICOLON:
8387 c_parser_consume_token (parser);
8388 break;
8389 case CPP_CLOSE_PAREN:
8390 case CPP_CLOSE_SQUARE:
8391 /* Avoid infinite loop in error recovery:
8392 c_parser_skip_until_found stops at a closing nesting
8393 delimiter without consuming it, but here we need to consume
8394 it to proceed further. */
8395 c_parser_error (parser, gmsgid: "expected statement");
8396 c_parser_consume_token (parser);
8397 break;
8398 case CPP_PRAGMA:
8399 if (!c_parser_pragma (parser, pragma_stmt, if_p, before_labels))
8400 goto restart;
8401 break;
8402 default:
8403 expr_stmt:
8404 stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
8405 expect_semicolon:
8406 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
8407 break;
8408 }
8409 /* Two cases cannot and do not have line numbers associated: If stmt
8410 is degenerate, such as "2;", then stmt is an INTEGER_CST, which
8411 cannot hold line numbers. But that's OK because the statement
8412 will either be changed to a MODIFY_EXPR during gimplification of
8413 the statement expr, or discarded. If stmt was compound, but
8414 without new variables, we will have skipped the creation of a
8415 BIND and will have a bare STATEMENT_LIST. But that's OK because
8416 (recursively) all of the component statements should already have
8417 line numbers assigned. ??? Can we discard no-op statements
8418 earlier? */
8419 if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
8420 protected_set_expr_location (stmt, loc);
8421
8422 parser->in_if_block = in_if_block;
8423}
8424
8425/* Parse the condition from an if, do, while or for statements. */
8426
8427static tree
8428c_parser_condition (c_parser *parser)
8429{
8430 location_t loc = c_parser_peek_token (parser)->location;
8431 tree cond;
8432 cond = c_parser_expression_conv (parser).value;
8433 cond = c_objc_common_truthvalue_conversion (loc, cond);
8434 cond = c_fully_fold (cond, false, NULL);
8435 if (warn_sequence_point)
8436 verify_sequence_points (cond);
8437 return cond;
8438}
8439
8440/* Parse a parenthesized condition from a do or while statement.
8441
8442 condition:
8443 ( expression )
8444*/
8445
8446static tree
8447c_parser_paren_condition (c_parser *parser)
8448{
8449 tree cond;
8450 matching_parens parens;
8451 if (!parens.require_open (parser))
8452 return error_mark_node;
8453 cond = c_parser_condition (parser);
8454 parens.skip_until_found_close (parser);
8455 return cond;
8456}
8457
8458/* Parse a selection-header:
8459
8460 selection-header:
8461 expression
8462 declaration expression
8463 simple-declaration
8464
8465 simple-declaration:
8466 attribute-specifier-sequence[opt] declaration-specifiers declarator
8467 = initializer
8468
8469 SWITCH_P is true if we are called from c_parser_switch_statement; in
8470 that case, don't perform the truthvalue conversion. */
8471
8472static c_expr
8473c_parser_selection_header (c_parser *parser, bool switch_p)
8474{
8475 location_t loc = c_parser_peek_token (parser)->location;
8476 c_expr expr;
8477 bool parse_expr = true;
8478 tree std_attrs;
8479 bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
8480 if (have_std_attrs)
8481 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
8482 else
8483 std_attrs = NULL_TREE;
8484 if (c_parser_next_tokens_start_declaration (parser))
8485 {
8486 pedwarn_c23 (loc, OPT_Wpedantic,
8487 "ISO C does not support if declarations before C2Y");
8488 expr.value
8489 = c_parser_declaration_or_fndef (parser,
8490 /*fndef_ok=*/false,
8491 /*static_assert_ok=*/false,
8492 /*empty_ok=*/false,
8493 /*nested=*/true,
8494 /*start_attr_ok=*/true,
8495 /*simple_ok=*/true,
8496 /*objc_foreach_object_decl=*/objc_foreach_object_declaration: nullptr,
8497 /*omp_declare_simd_clauses=*/nullptr,
8498 have_attrs: have_std_attrs,
8499 attrs: std_attrs);
8500 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8501 c_parser_consume_token (parser);
8502 else
8503 {
8504 /* A simple-declaration is a declaration that can appear in
8505 place of the controlling expression of a selection statement.
8506 In that case, there shall be an initializer. */
8507 if (!expr.value)
8508 {
8509 error_at (loc, "declaration in the controlling expression must "
8510 "have an initializer");
8511 expr.original_type = error_mark_node;
8512 expr.set_error ();
8513 return expr;
8514 }
8515 parse_expr = false;
8516 }
8517 if (expr.value)
8518 {
8519 expr.original_type = TREE_TYPE (expr.value);
8520 expr = convert_lvalue_to_rvalue (loc, expr, /*convert_p=*/true,
8521 /*read_p=*/true);
8522 }
8523 }
8524 else if (have_std_attrs)
8525 {
8526 c_parser_error (parser, gmsgid: "expected declaration");
8527 expr.original_type = error_mark_node;
8528 expr.set_error ();
8529 return expr;
8530 }
8531
8532 if (parse_expr)
8533 expr = c_parser_expression_conv (parser);
8534 if (!switch_p)
8535 {
8536 expr.value = c_objc_common_truthvalue_conversion (loc, expr.value);
8537 expr.value = c_fully_fold (expr.value, false, NULL);
8538 if (warn_sequence_point)
8539 verify_sequence_points (expr.value);
8540 }
8541 return expr;
8542}
8543
8544/* Parse a selection-header enclosed in parentheses:
8545
8546 ( selection-header )
8547*/
8548
8549static tree
8550c_parser_paren_selection_header (c_parser *parser)
8551{
8552 matching_parens parens;
8553 if (!parens.require_open (parser))
8554 return error_mark_node;
8555 tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value;
8556 parens.skip_until_found_close (parser);
8557 return cond;
8558}
8559
8560/* Parse a statement which is a block in C99.
8561
8562 IF_P is used to track whether there's a (possibly labeled) if statement
8563 which is not enclosed in braces and has an else clause. This is used to
8564 implement -Wparentheses. */
8565
8566static tree
8567c_parser_c99_block_statement (c_parser *parser, bool *if_p,
8568 location_t *loc_after_labels)
8569{
8570 tree block = c_begin_compound_stmt (flag_isoc99);
8571 location_t loc = c_parser_peek_token (parser)->location;
8572 c_parser_statement (parser, if_p, loc_after_labels);
8573 return c_end_compound_stmt (loc, block, flag_isoc99);
8574}
8575
8576/* Parse the body of an if statement. This is just parsing a
8577 statement but (a) it is a block in C99, (b) we track whether the
8578 body is an if statement for the sake of -Wparentheses warnings, (c)
8579 we handle an empty body specially for the sake of -Wempty-body
8580 warnings, and (d) we call parser_compound_statement directly
8581 because c_parser_statement_after_labels resets
8582 parser->in_if_block.
8583
8584 IF_P is used to track whether there's a (possibly labeled) if statement
8585 which is not enclosed in braces and has an else clause. This is used to
8586 implement -Wparentheses. */
8587
8588static tree
8589c_parser_if_body (c_parser *parser, bool *if_p,
8590 const token_indent_info &if_tinfo)
8591{
8592 tree block = c_begin_compound_stmt (flag_isoc99);
8593 location_t body_loc = c_parser_peek_token (parser)->location;
8594 location_t body_loc_after_labels = UNKNOWN_LOCATION;
8595 token_indent_info body_tinfo
8596 = get_token_indent_info (token: c_parser_peek_token (parser));
8597 tree before_labels = get_before_labels ();
8598 attr_state a = c_parser_all_labels (parser);
8599
8600 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8601 {
8602 location_t loc = c_parser_peek_token (parser)->location;
8603 add_stmt (build_empty_stmt (loc));
8604 c_parser_consume_token (parser);
8605 if (!c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
8606 warning_at (loc, OPT_Wempty_body,
8607 "suggest braces around empty body in an %<if%> statement");
8608 }
8609 else if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
8610 add_stmt (c_parser_compound_statement (parser));
8611 else
8612 {
8613 body_loc_after_labels = c_parser_peek_token (parser)->location;
8614 c_parser_statement_after_labels (parser, if_p, before_labels, NULL, astate: a);
8615 }
8616
8617 token_indent_info next_tinfo
8618 = get_token_indent_info (token: c_parser_peek_token (parser));
8619 warn_for_misleading_indentation (guard_tinfo: if_tinfo, body_tinfo, next_tinfo);
8620 if (body_loc_after_labels != UNKNOWN_LOCATION
8621 && next_tinfo.type != CPP_SEMICOLON)
8622 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8623 if_tinfo.location, RID_IF);
8624
8625 return c_end_compound_stmt (body_loc, block, flag_isoc99);
8626}
8627
8628/* Parse the else body of an if statement. This is just parsing a
8629 statement but (a) it is a block in C99, (b) we handle an empty body
8630 specially for the sake of -Wempty-body warnings. CHAIN is a vector
8631 of if-else-if conditions. */
8632
8633static tree
8634c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
8635 vec<tree> *chain)
8636{
8637 location_t body_loc = c_parser_peek_token (parser)->location;
8638 tree block = c_begin_compound_stmt (flag_isoc99);
8639 token_indent_info body_tinfo
8640 = get_token_indent_info (token: c_parser_peek_token (parser));
8641 location_t body_loc_after_labels = UNKNOWN_LOCATION;
8642 tree before_labels = get_before_labels ();
8643 attr_state a = c_parser_all_labels (parser);
8644
8645 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8646 {
8647 location_t loc = c_parser_peek_token (parser)->location;
8648 warning_at (loc,
8649 OPT_Wempty_body,
8650 "suggest braces around empty body in an %<else%> statement");
8651 add_stmt (build_empty_stmt (loc));
8652 c_parser_consume_token (parser);
8653 }
8654 else
8655 {
8656 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
8657 body_loc_after_labels = c_parser_peek_token (parser)->location;
8658 c_parser_statement_after_labels (parser, NULL, before_labels, chain, astate: a);
8659 }
8660
8661 token_indent_info next_tinfo
8662 = get_token_indent_info (token: c_parser_peek_token (parser));
8663 warn_for_misleading_indentation (guard_tinfo: else_tinfo, body_tinfo, next_tinfo);
8664 if (body_loc_after_labels != UNKNOWN_LOCATION
8665 && next_tinfo.type != CPP_SEMICOLON)
8666 warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
8667 else_tinfo.location, RID_ELSE);
8668
8669 return c_end_compound_stmt (body_loc, block, flag_isoc99);
8670}
8671
8672/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8673
8674 if-statement:
8675 if ( selection-header ) statement
8676 if ( selection-header ) statement else statement
8677
8678 CHAIN is a vector of if-else-if conditions.
8679 IF_P is used to track whether there's a (possibly labeled) if statement
8680 which is not enclosed in braces and has an else clause. This is used to
8681 implement -Wparentheses. */
8682
8683static void
8684c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
8685{
8686 tree block;
8687 location_t loc;
8688 tree cond;
8689 bool nested_if = false;
8690 tree first_body, second_body;
8691 bool in_if_block;
8692
8693 gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
8694 token_indent_info if_tinfo
8695 = get_token_indent_info (token: c_parser_peek_token (parser));
8696 c_parser_consume_token (parser);
8697 block = c_begin_compound_stmt (flag_isoc99);
8698 loc = c_parser_peek_token (parser)->location;
8699 cond = c_parser_paren_selection_header (parser);
8700 in_if_block = parser->in_if_block;
8701 parser->in_if_block = true;
8702 first_body = c_parser_if_body (parser, if_p: &nested_if, if_tinfo);
8703 parser->in_if_block = in_if_block;
8704
8705 if (warn_duplicated_cond)
8706 warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
8707
8708 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
8709 {
8710 token_indent_info else_tinfo
8711 = get_token_indent_info (token: c_parser_peek_token (parser));
8712 c_parser_consume_token (parser);
8713 if (warn_duplicated_cond)
8714 {
8715 if (c_parser_next_token_is_keyword (parser, keyword: RID_IF)
8716 && chain == NULL)
8717 {
8718 /* We've got "if (COND) else if (COND2)". Start the
8719 condition chain and add COND as the first element. */
8720 chain = new vec<tree> ();
8721 if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
8722 chain->safe_push (obj: cond);
8723 }
8724 else if (!c_parser_next_token_is_keyword (parser, keyword: RID_IF))
8725 /* This is if-else without subsequent if. Zap the condition
8726 chain; we would have already warned at this point. */
8727 vec_free (v&: chain);
8728 }
8729 second_body = c_parser_else_body (parser, else_tinfo, chain);
8730 /* Set IF_P to true to indicate that this if statement has an
8731 else clause. This may trigger the Wparentheses warning
8732 below when we get back up to the parent if statement. */
8733 if (if_p != NULL)
8734 *if_p = true;
8735 }
8736 else
8737 {
8738 second_body = NULL_TREE;
8739
8740 /* Diagnose an ambiguous else if if-then-else is nested inside
8741 if-then. */
8742 if (nested_if)
8743 warning_at (loc, OPT_Wdangling_else,
8744 "suggest explicit braces to avoid ambiguous %<else%>");
8745
8746 if (warn_duplicated_cond)
8747 /* This if statement does not have an else clause. We don't
8748 need the condition chain anymore. */
8749 vec_free (v&: chain);
8750 }
8751 c_finish_if_stmt (loc, cond, first_body, second_body);
8752 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8753
8754 c_parser_maybe_reclassify_token (parser);
8755}
8756
8757/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
8758
8759 switch-statement:
8760 switch (expression) statement
8761
8762 BEFORE_LABELS is last statement before possible labels, see
8763 get_before_labels description for details. */
8764
8765static void
8766c_parser_switch_statement (c_parser *parser, bool *if_p, tree before_labels)
8767{
8768 struct c_expr ce;
8769 tree block, expr, body;
8770 unsigned char save_in_statement;
8771 location_t switch_loc = c_parser_peek_token (parser)->location;
8772 location_t switch_cond_loc;
8773 gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
8774 c_parser_consume_token (parser);
8775 tree switch_name;
8776 int num_names = c_get_loop_names (before_labels, true, &switch_name);
8777 block = c_begin_compound_stmt (flag_isoc99);
8778 bool explicit_cast_p = false;
8779 matching_parens parens;
8780 if (parens.require_open (parser))
8781 {
8782 switch_cond_loc = c_parser_peek_token (parser)->location;
8783 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
8784 && c_token_starts_typename (token: c_parser_peek_2nd_token (parser)))
8785 explicit_cast_p = true;
8786 ce = c_parser_selection_header (parser, /*switch_p=*/true);
8787 /* The call above already performed convert_lvalue_to_rvalue, but
8788 if it parsed an expression, read_p was false. Make sure we mark
8789 the expression as read. */
8790 ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
8791 expr = ce.value;
8792 /* ??? expr has no valid location? */
8793 parens.skip_until_found_close (parser);
8794 }
8795 else
8796 {
8797 switch_cond_loc = UNKNOWN_LOCATION;
8798 expr = error_mark_node;
8799 ce.original_type = error_mark_node;
8800 }
8801 tree stmt
8802 = c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p,
8803 switch_name);
8804 save_in_statement = in_statement;
8805 in_statement |= IN_SWITCH_STMT;
8806 if (switch_name)
8807 {
8808 C_DECL_LOOP_SWITCH_NAME_VALID (switch_name) = 1;
8809 in_statement |= IN_NAMED_STMT;
8810 }
8811 else
8812 in_statement &= ~IN_NAMED_STMT;
8813 location_t loc_after_labels;
8814 bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
8815 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8816 location_t next_loc = c_parser_peek_token (parser)->location;
8817 if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
8818 warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
8819 RID_SWITCH);
8820 c_finish_switch (body, ce.original_type);
8821 in_statement = save_in_statement;
8822 if (num_names)
8823 {
8824 if (!C_DECL_LOOP_SWITCH_NAME_USED (switch_name))
8825 SWITCH_STMT_NAME (stmt) = NULL_TREE;
8826 else
8827 SWITCH_STMT_NO_BREAK_P (stmt) = 0;
8828 c_release_loop_names (num_names);
8829 }
8830 add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
8831 c_parser_maybe_reclassify_token (parser);
8832}
8833
8834/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8835
8836 while-statement:
8837 while (expression) statement
8838
8839 IF_P is used to track whether there's a (possibly labeled) if statement
8840 which is not enclosed in braces and has an else clause. This is used to
8841 implement -Wparentheses.
8842
8843 BEFORE_LABELS is last statement before possible labels, see
8844 get_before_labels description for details. */
8845
8846static void
8847c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8848 bool novector, bool *if_p, tree before_labels)
8849{
8850 tree block, cond, body;
8851 unsigned char save_in_statement;
8852 location_t loc;
8853 gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
8854 token_indent_info while_tinfo
8855 = get_token_indent_info (token: c_parser_peek_token (parser));
8856 tree loop_name;
8857 int num_names = c_get_loop_names (before_labels, false, &loop_name);
8858
8859 if (parser->omp_for_parse_state)
8860 {
8861 error_at (c_parser_peek_token (parser)->location,
8862 "loop not permitted in intervening code in OpenMP loop body");
8863 parser->omp_for_parse_state->fail = true;
8864 }
8865
8866 c_parser_consume_token (parser);
8867 block = c_begin_compound_stmt (flag_isoc99);
8868 loc = c_parser_peek_token (parser)->location;
8869 cond = c_parser_paren_condition (parser);
8870 if (ivdep && cond != error_mark_node)
8871 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8872 build_int_cst (integer_type_node,
8873 annot_expr_ivdep_kind),
8874 integer_zero_node);
8875 if (unroll && cond != error_mark_node)
8876 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8877 build_int_cst (integer_type_node,
8878 annot_expr_unroll_kind),
8879 build_int_cst (integer_type_node, unroll));
8880 if (novector && cond != error_mark_node)
8881 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8882 build_int_cst (integer_type_node,
8883 annot_expr_no_vector_kind),
8884 integer_zero_node);
8885 save_in_statement = in_statement;
8886 in_statement = IN_ITERATION_STMT;
8887 if (loop_name)
8888 {
8889 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
8890 in_statement |= IN_NAMED_STMT;
8891 }
8892
8893 token_indent_info body_tinfo
8894 = get_token_indent_info (token: c_parser_peek_token (parser));
8895
8896 location_t loc_after_labels;
8897 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
8898 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
8899 if (loop_name && !C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8900 loop_name = NULL_TREE;
8901 add_stmt (build_stmt (loc, WHILE_STMT, cond, body, loop_name, NULL_TREE,
8902 NULL_TREE));
8903 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8904 c_parser_maybe_reclassify_token (parser);
8905 if (num_names)
8906 c_release_loop_names (num_names);
8907
8908 token_indent_info next_tinfo
8909 = get_token_indent_info (token: c_parser_peek_token (parser));
8910 warn_for_misleading_indentation (guard_tinfo: while_tinfo, body_tinfo, next_tinfo);
8911
8912 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
8913 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
8914 while_tinfo.location, RID_WHILE);
8915
8916 in_statement = save_in_statement;
8917}
8918
8919/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8920
8921 do-statement:
8922 do statement while ( expression ) ;
8923
8924 BEFORE_LABELS is last statement before possible labels, see
8925 get_before_labels description for details. */
8926
8927static void
8928c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
8929 bool novector, tree before_labels)
8930{
8931 tree block, cond, body;
8932 unsigned char save_in_statement;
8933 location_t loc;
8934 gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
8935 tree loop_name;
8936 int num_names = c_get_loop_names (before_labels, false, &loop_name);
8937
8938 if (parser->omp_for_parse_state)
8939 {
8940 error_at (c_parser_peek_token (parser)->location,
8941 "loop not permitted in intervening code in OpenMP loop body");
8942 parser->omp_for_parse_state->fail = true;
8943 }
8944
8945 c_parser_consume_token (parser);
8946 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
8947 warning_at (c_parser_peek_token (parser)->location,
8948 OPT_Wempty_body,
8949 "suggest braces around empty body in %<do%> statement");
8950 block = c_begin_compound_stmt (flag_isoc99);
8951 loc = c_parser_peek_token (parser)->location;
8952 save_in_statement = in_statement;
8953 in_statement = IN_ITERATION_STMT;
8954 if (loop_name)
8955 {
8956 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
8957 in_statement |= IN_NAMED_STMT;
8958 }
8959 body = c_parser_c99_block_statement (parser, NULL);
8960 c_parser_require_keyword (parser, keyword: RID_WHILE, msgid: "expected %<while%>");
8961 in_statement = save_in_statement;
8962 if (num_names)
8963 {
8964 if (!C_DECL_LOOP_SWITCH_NAME_USED (loop_name))
8965 loop_name = NULL_TREE;
8966 c_release_loop_names (num_names);
8967 }
8968 cond = c_parser_paren_condition (parser);
8969 if (ivdep && cond != error_mark_node)
8970 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8971 build_int_cst (integer_type_node,
8972 annot_expr_ivdep_kind),
8973 integer_zero_node);
8974 if (unroll && cond != error_mark_node)
8975 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8976 build_int_cst (integer_type_node,
8977 annot_expr_unroll_kind),
8978 build_int_cst (integer_type_node, unroll));
8979 if (novector && cond != error_mark_node)
8980 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
8981 build_int_cst (integer_type_node,
8982 annot_expr_no_vector_kind),
8983 integer_zero_node);
8984 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
8985 c_parser_skip_to_end_of_block_or_statement (parser);
8986
8987 add_stmt (build_stmt (loc, DO_STMT, cond, body, loop_name));
8988 add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
8989}
8990
8991/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
8992
8993 for-statement:
8994 for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
8995 for ( nested-declaration expression[opt] ; expression[opt] ) statement
8996
8997 The form with a declaration is new in C99.
8998
8999 ??? In accordance with the old parser, the declaration may be a
9000 nested function, which is then rejected in check_for_loop_decls,
9001 but does it make any sense for this to be included in the grammar?
9002 Note in particular that the nested function does not include a
9003 trailing ';', whereas the "declaration" production includes one.
9004 Also, can we reject bad declarations earlier and cheaper than
9005 check_for_loop_decls?
9006
9007 In Objective-C, there are two additional variants:
9008
9009 foreach-statement:
9010 for ( expression in expresssion ) statement
9011 for ( declaration in expression ) statement
9012
9013 This is inconsistent with C, because the second variant is allowed
9014 even if c99 is not enabled.
9015
9016 The rest of the comment documents these Objective-C foreach-statement.
9017
9018 Here is the canonical example of the first variant:
9019 for (object in array) { do something with object }
9020 we call the first expression ("object") the "object_expression" and
9021 the second expression ("array") the "collection_expression".
9022 object_expression must be an lvalue of type "id" (a generic Objective-C
9023 object) because the loop works by assigning to object_expression the
9024 various objects from the collection_expression. collection_expression
9025 must evaluate to something of type "id" which responds to the method
9026 countByEnumeratingWithState:objects:count:.
9027
9028 The canonical example of the second variant is:
9029 for (id object in array) { do something with object }
9030 which is completely equivalent to
9031 {
9032 id object;
9033 for (object in array) { do something with object }
9034 }
9035 Note that initizializing 'object' in some way (eg, "for ((object =
9036 xxx) in array) { do something with object }") is possibly
9037 technically valid, but completely pointless as 'object' will be
9038 assigned to something else as soon as the loop starts. We should
9039 most likely reject it (TODO).
9040
9041 The beginning of the Objective-C foreach-statement looks exactly
9042 like the beginning of the for-statement, and we can tell it is a
9043 foreach-statement only because the initial declaration or
9044 expression is terminated by 'in' instead of ';'.
9045
9046 IF_P is used to track whether there's a (possibly labeled) if statement
9047 which is not enclosed in braces and has an else clause. This is used to
9048 implement -Wparentheses.
9049
9050 BEFORE_LABELS is last statement before possible labels, see
9051 get_before_labels description for details. */
9052
9053static void
9054c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
9055 bool novector, bool *if_p, tree before_labels)
9056{
9057 tree block, cond, incr, body;
9058 unsigned char save_in_statement;
9059 tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
9060 /* The following are only used when parsing an ObjC foreach statement. */
9061 tree object_expression;
9062 /* Silence the bogus uninitialized warning. */
9063 tree collection_expression = NULL;
9064 location_t loc = c_parser_peek_token (parser)->location;
9065 location_t for_loc = loc;
9066 bool is_foreach_statement = false;
9067 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
9068 token_indent_info for_tinfo
9069 = get_token_indent_info (token: c_parser_peek_token (parser));
9070 tree loop_name;
9071 int num_names = c_get_loop_names (before_labels, false, &loop_name);
9072
9073 if (parser->omp_for_parse_state)
9074 {
9075 error_at (for_loc,
9076 "loop not permitted in intervening code in OpenMP loop body");
9077 parser->omp_for_parse_state->fail = true;
9078 }
9079
9080 c_parser_consume_token (parser);
9081 /* Open a compound statement in Objective-C as well, just in case this is
9082 as foreach expression. */
9083 block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
9084 cond = error_mark_node;
9085 incr = error_mark_node;
9086 matching_parens parens;
9087 if (parens.require_open (parser))
9088 {
9089 /* Parse the initialization declaration or expression. */
9090 object_expression = error_mark_node;
9091 parser->objc_could_be_foreach_context = c_dialect_objc ();
9092 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
9093 {
9094 parser->objc_could_be_foreach_context = false;
9095 c_parser_consume_token (parser);
9096 c_finish_expr_stmt (loc, NULL_TREE);
9097 }
9098 else if (c_parser_next_tokens_start_declaration (parser)
9099 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
9100 {
9101 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
9102 simple_ok: false, objc_foreach_object_declaration: &object_expression);
9103 parser->objc_could_be_foreach_context = false;
9104
9105 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9106 {
9107 c_parser_consume_token (parser);
9108 is_foreach_statement = true;
9109 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9110 c_parser_error (parser, gmsgid: "multiple iterating variables in "
9111 "fast enumeration");
9112 }
9113 else
9114 check_for_loop_decls (for_loc, flag_isoc99);
9115 }
9116 else if (c_parser_next_token_is_keyword (parser, keyword: RID_EXTENSION))
9117 {
9118 /* __extension__ can start a declaration, but is also an
9119 unary operator that can start an expression. Consume all
9120 but the last of a possible series of __extension__ to
9121 determine which. */
9122 while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
9123 && (c_parser_peek_2nd_token (parser)->keyword
9124 == RID_EXTENSION))
9125 c_parser_consume_token (parser);
9126 if (c_token_starts_declaration (token: c_parser_peek_2nd_token (parser))
9127 || c_parser_nth_token_starts_std_attributes (parser, n: 2))
9128 {
9129 int ext;
9130 ext = disable_extension_diagnostics ();
9131 c_parser_consume_token (parser);
9132 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
9133 start_attr_ok: true, simple_ok: false, objc_foreach_object_declaration: &object_expression);
9134 parser->objc_could_be_foreach_context = false;
9135
9136 restore_extension_diagnostics (flags: ext);
9137 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9138 {
9139 c_parser_consume_token (parser);
9140 is_foreach_statement = true;
9141 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
9142 c_parser_error (parser, gmsgid: "multiple iterating variables in "
9143 "fast enumeration");
9144 }
9145 else
9146 check_for_loop_decls (for_loc, flag_isoc99);
9147 }
9148 else
9149 goto init_expr;
9150 }
9151 else
9152 {
9153 init_expr:
9154 {
9155 struct c_expr ce;
9156 tree init_expression;
9157 ce = c_parser_expression (parser);
9158 init_expression = ce.value;
9159 parser->objc_could_be_foreach_context = false;
9160 if (c_parser_next_token_is_keyword (parser, keyword: RID_IN))
9161 {
9162 c_parser_consume_token (parser);
9163 is_foreach_statement = true;
9164 if (! lvalue_p (init_expression))
9165 c_parser_error (parser, gmsgid: "invalid iterating variable in "
9166 "fast enumeration");
9167 object_expression
9168 = c_fully_fold (init_expression, false, NULL);
9169 }
9170 else
9171 {
9172 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9173 init_expression = ce.value;
9174 c_finish_expr_stmt (loc, init_expression);
9175 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
9176 msgid: "expected %<;%>");
9177 }
9178 }
9179 }
9180 /* Parse the loop condition. In the case of a foreach
9181 statement, there is no loop condition. */
9182 gcc_assert (!parser->objc_could_be_foreach_context);
9183 if (!is_foreach_statement)
9184 {
9185 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
9186 {
9187 if (ivdep)
9188 {
9189 c_parser_error (parser, gmsgid: "missing loop condition in loop "
9190 "with %<GCC ivdep%> pragma");
9191 cond = error_mark_node;
9192 }
9193 else if (unroll)
9194 {
9195 c_parser_error (parser, gmsgid: "missing loop condition in loop "
9196 "with %<GCC unroll%> pragma");
9197 cond = error_mark_node;
9198 }
9199 else
9200 {
9201 c_parser_consume_token (parser);
9202 cond = NULL_TREE;
9203 }
9204 }
9205 else
9206 {
9207 cond = c_parser_condition (parser);
9208 c_parser_skip_until_found (parser, type: CPP_SEMICOLON,
9209 msgid: "expected %<;%>");
9210 }
9211 if (ivdep && cond != error_mark_node)
9212 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9213 build_int_cst (integer_type_node,
9214 annot_expr_ivdep_kind),
9215 integer_zero_node);
9216 if (unroll && cond != error_mark_node)
9217 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9218 build_int_cst (integer_type_node,
9219 annot_expr_unroll_kind),
9220 build_int_cst (integer_type_node, unroll));
9221 if (novector && cond && cond != error_mark_node)
9222 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
9223 build_int_cst (integer_type_node,
9224 annot_expr_no_vector_kind),
9225 integer_zero_node);
9226 }
9227 /* Parse the increment expression (the third expression in a
9228 for-statement). In the case of a foreach-statement, this is
9229 the expression that follows the 'in'. */
9230 loc = c_parser_peek_token (parser)->location;
9231 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
9232 {
9233 if (is_foreach_statement)
9234 {
9235 c_parser_error (parser,
9236 gmsgid: "missing collection in fast enumeration");
9237 collection_expression = error_mark_node;
9238 }
9239 else
9240 incr = c_process_expr_stmt (loc, NULL_TREE);
9241 }
9242 else
9243 {
9244 if (is_foreach_statement)
9245 collection_expression
9246 = c_fully_fold (c_parser_expression (parser).value, false, NULL);
9247 else
9248 {
9249 struct c_expr ce = c_parser_expression (parser);
9250 ce = convert_lvalue_to_rvalue (loc, ce, true, false);
9251 incr = c_process_expr_stmt (loc, ce.value);
9252 }
9253 }
9254 parens.skip_until_found_close (parser);
9255 }
9256 save_in_statement = in_statement;
9257 if (is_foreach_statement)
9258 {
9259 in_statement = IN_OBJC_FOREACH;
9260 save_objc_foreach_break_label = objc_foreach_break_label;
9261 save_objc_foreach_continue_label = objc_foreach_continue_label;
9262 objc_foreach_break_label = create_artificial_label (loc);
9263 objc_foreach_continue_label = create_artificial_label (loc);
9264 if (loop_name)
9265 {
9266 gcc_checking_assert (!DECL_CHAIN (loop_name)
9267 && !DECL_CHAIN (objc_foreach_break_label));
9268 C_DECL_SWITCH_NAME (loop_name) = 1;
9269 DECL_CHAIN (loop_name) = objc_foreach_break_label;
9270 DECL_CHAIN (objc_foreach_break_label) = objc_foreach_continue_label;
9271 }
9272 }
9273 else
9274 in_statement = IN_ITERATION_STMT;
9275 if (loop_name)
9276 {
9277 C_DECL_LOOP_SWITCH_NAME_VALID (loop_name) = 1;
9278 in_statement |= IN_NAMED_STMT;
9279 }
9280
9281 token_indent_info body_tinfo
9282 = get_token_indent_info (token: c_parser_peek_token (parser));
9283
9284 location_t loc_after_labels;
9285 bool open_brace = c_parser_next_token_is (parser, type: CPP_OPEN_BRACE);
9286 body = c_parser_c99_block_statement (parser, if_p, loc_after_labels: &loc_after_labels);
9287
9288 if (loop_name && is_foreach_statement)
9289 {
9290 gcc_checking_assert (DECL_CHAIN (loop_name) == objc_foreach_break_label
9291 && (DECL_CHAIN (objc_foreach_break_label)
9292 == objc_foreach_continue_label));
9293 C_DECL_SWITCH_NAME (loop_name) = 0;
9294 DECL_CHAIN (loop_name) = NULL_TREE;
9295 DECL_CHAIN (objc_foreach_break_label) = NULL_TREE;
9296 }
9297
9298 if (is_foreach_statement)
9299 objc_finish_foreach_loop (for_loc, object_expression,
9300 collection_expression, body,
9301 objc_foreach_break_label,
9302 objc_foreach_continue_label);
9303 else
9304 add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
9305 body, NULL_TREE,
9306 loop_name && C_DECL_LOOP_SWITCH_NAME_USED (loop_name)
9307 ? loop_name : NULL_TREE, NULL_TREE, NULL_TREE));
9308 add_stmt (c_end_compound_stmt (for_loc, block,
9309 flag_isoc99 || c_dialect_objc ()));
9310 c_parser_maybe_reclassify_token (parser);
9311
9312 token_indent_info next_tinfo
9313 = get_token_indent_info (token: c_parser_peek_token (parser));
9314 warn_for_misleading_indentation (guard_tinfo: for_tinfo, body_tinfo, next_tinfo);
9315
9316 if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
9317 warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
9318 for_tinfo.location, RID_FOR);
9319
9320 in_statement = save_in_statement;
9321 if (num_names)
9322 c_release_loop_names (num_names);
9323 if (is_foreach_statement)
9324 {
9325 objc_foreach_break_label = save_objc_foreach_break_label;
9326 objc_foreach_continue_label = save_objc_foreach_continue_label;
9327 }
9328}
9329
9330/* Parse an asm statement, a GNU extension. This is a full-blown asm
9331 statement with inputs, outputs, clobbers, and volatile, inline, and goto
9332 tags allowed.
9333
9334 asm-qualifier:
9335 volatile
9336 inline
9337 goto
9338
9339 asm-qualifier-list:
9340 asm-qualifier-list asm-qualifier
9341 asm-qualifier
9342
9343 asm-statement:
9344 asm asm-qualifier-list[opt] ( asm-argument ) ;
9345
9346 asm-argument:
9347 asm-string-literal
9348 asm-string-literal : asm-operands[opt]
9349 asm-string-literal : asm-operands[opt] : asm-operands[opt]
9350 asm-string-literal : asm-operands[opt] : asm-operands[opt] \
9351 : asm-clobbers[opt]
9352 asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
9353 : asm-goto-operands
9354
9355 The form with asm-goto-operands is valid if and only if the
9356 asm-qualifier-list contains goto, and is the only allowed form in that case.
9357 Duplicate asm-qualifiers are not allowed.
9358
9359 The :: token is considered equivalent to two consecutive : tokens. */
9360
9361static tree
9362c_parser_asm_statement (c_parser *parser)
9363{
9364 tree str, outputs, inputs, clobbers, labels, ret;
9365 bool simple;
9366 location_t asm_loc = c_parser_peek_token (parser)->location;
9367 int section, nsections;
9368
9369 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
9370 c_parser_consume_token (parser);
9371
9372 /* Handle the asm-qualifier-list. */
9373 location_t volatile_loc = UNKNOWN_LOCATION;
9374 location_t inline_loc = UNKNOWN_LOCATION;
9375 location_t goto_loc = UNKNOWN_LOCATION;
9376 for (;;)
9377 {
9378 c_token *token = c_parser_peek_token (parser);
9379 location_t loc = token->location;
9380 switch (token->keyword)
9381 {
9382 case RID_VOLATILE:
9383 if (volatile_loc)
9384 {
9385 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9386 inform (volatile_loc, "first seen here");
9387 }
9388 else
9389 volatile_loc = loc;
9390 c_parser_consume_token (parser);
9391 continue;
9392
9393 case RID_INLINE:
9394 if (inline_loc)
9395 {
9396 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9397 inform (inline_loc, "first seen here");
9398 }
9399 else
9400 inline_loc = loc;
9401 c_parser_consume_token (parser);
9402 continue;
9403
9404 case RID_GOTO:
9405 if (goto_loc)
9406 {
9407 error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
9408 inform (goto_loc, "first seen here");
9409 }
9410 else
9411 goto_loc = loc;
9412 c_parser_consume_token (parser);
9413 continue;
9414
9415 case RID_CONST:
9416 case RID_RESTRICT:
9417 error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
9418 c_parser_consume_token (parser);
9419 continue;
9420
9421 default:
9422 break;
9423 }
9424 break;
9425 }
9426
9427 bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
9428 bool is_inline = (inline_loc != UNKNOWN_LOCATION);
9429 bool is_goto = (goto_loc != UNKNOWN_LOCATION);
9430
9431 ret = NULL;
9432
9433 matching_parens parens;
9434 if (!parens.require_open (parser))
9435 goto error;
9436
9437 str = c_parser_asm_string_literal (parser);
9438 if (str == NULL_TREE)
9439 goto error_close_paren;
9440
9441 simple = true;
9442 outputs = NULL_TREE;
9443 inputs = NULL_TREE;
9444 clobbers = NULL_TREE;
9445 labels = NULL_TREE;
9446
9447 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
9448 goto done_asm;
9449
9450 /* Parse each colon-delimited section of operands. */
9451 nsections = 3 + is_goto;
9452 for (section = 0; section < nsections; ++section)
9453 {
9454 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
9455 {
9456 ++section;
9457 if (section == nsections)
9458 {
9459 c_parser_error (parser, gmsgid: "expected %<)%>");
9460 goto error_close_paren;
9461 }
9462 c_parser_consume_token (parser);
9463 }
9464 else if (!c_parser_require (parser, type: CPP_COLON,
9465 msgid: is_goto
9466 ? G_("expected %<:%>")
9467 : G_("expected %<:%> or %<)%>"),
9468 UNKNOWN_LOCATION, type_is_unique: is_goto))
9469 goto error_close_paren;
9470
9471 /* Once past any colon, we're no longer a simple asm. */
9472 simple = false;
9473
9474 if ((!c_parser_next_token_is (parser, type: CPP_COLON)
9475 && !c_parser_next_token_is (parser, type: CPP_SCOPE)
9476 && !c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
9477 || section == 3)
9478 switch (section)
9479 {
9480 case 0:
9481 outputs = c_parser_asm_operands (parser);
9482 break;
9483 case 1:
9484 inputs = c_parser_asm_operands (parser);
9485 break;
9486 case 2:
9487 clobbers = c_parser_asm_clobbers (parser);
9488 break;
9489 case 3:
9490 labels = c_parser_asm_goto_operands (parser);
9491 break;
9492 default:
9493 gcc_unreachable ();
9494 }
9495
9496 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN) && !is_goto)
9497 goto done_asm;
9498 }
9499
9500 done_asm:
9501 if (!parens.require_close (parser))
9502 {
9503 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9504 goto error;
9505 }
9506
9507 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
9508 c_parser_skip_to_end_of_block_or_statement (parser);
9509
9510 ret = build_asm_stmt (is_volatile,
9511 build_asm_expr (asm_loc, str, outputs, inputs,
9512 clobbers, labels, simple, is_inline));
9513
9514 error:
9515 return ret;
9516
9517 error_close_paren:
9518 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9519 goto error;
9520}
9521
9522/* Parse asm operands, a GNU extension.
9523
9524 asm-operands:
9525 asm-operand
9526 asm-operands , asm-operand
9527
9528 asm-operand:
9529 asm-string-literal ( expression )
9530 [ identifier ] asm-string-literal ( expression )
9531*/
9532
9533static tree
9534c_parser_asm_operands (c_parser *parser)
9535{
9536 tree list = NULL_TREE;
9537 while (true)
9538 {
9539 tree name, str;
9540 struct c_expr expr;
9541 if (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
9542 {
9543 c_parser_consume_token (parser);
9544 if (c_parser_next_token_is (parser, type: CPP_NAME))
9545 {
9546 tree id = c_parser_peek_token (parser)->value;
9547 c_parser_consume_token (parser);
9548 name = build_string (IDENTIFIER_LENGTH (id),
9549 IDENTIFIER_POINTER (id));
9550 }
9551 else
9552 {
9553 c_parser_error (parser, gmsgid: "expected identifier");
9554 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE, NULL);
9555 return NULL_TREE;
9556 }
9557 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
9558 msgid: "expected %<]%>");
9559 }
9560 else
9561 name = NULL_TREE;
9562 str = c_parser_asm_string_literal (parser);
9563 if (str == NULL_TREE)
9564 return NULL_TREE;
9565 matching_parens parens;
9566 if (!parens.require_open (parser))
9567 return NULL_TREE;
9568 expr = c_parser_expression (parser);
9569 mark_exp_read (expr.value);
9570 if (!parens.require_close (parser))
9571 {
9572 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
9573 return NULL_TREE;
9574 }
9575 list = chainon (list, build_tree_list (build_tree_list (name, str),
9576 expr.value));
9577 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9578 c_parser_consume_token (parser);
9579 else
9580 break;
9581 }
9582 return list;
9583}
9584
9585/* Parse asm clobbers, a GNU extension.
9586
9587 asm-clobbers:
9588 asm-string-literal
9589 asm-clobbers , asm-string-literal
9590*/
9591
9592static tree
9593c_parser_asm_clobbers (c_parser *parser)
9594{
9595 tree list = NULL_TREE;
9596 while (true)
9597 {
9598 tree str = c_parser_asm_string_literal (parser);
9599 if (str)
9600 list = tree_cons (NULL_TREE, str, list);
9601 else
9602 return NULL_TREE;
9603 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9604 c_parser_consume_token (parser);
9605 else
9606 break;
9607 }
9608 return list;
9609}
9610
9611/* Parse asm goto labels, a GNU extension.
9612
9613 asm-goto-operands:
9614 identifier
9615 asm-goto-operands , identifier
9616*/
9617
9618static tree
9619c_parser_asm_goto_operands (c_parser *parser)
9620{
9621 tree list = NULL_TREE;
9622 while (true)
9623 {
9624 tree name, label;
9625
9626 if (c_parser_next_token_is (parser, type: CPP_NAME))
9627 {
9628 c_token *tok = c_parser_peek_token (parser);
9629 name = tok->value;
9630 label = lookup_label_for_goto (tok->location, name);
9631 c_parser_consume_token (parser);
9632 TREE_USED (label) = 1;
9633 }
9634 else
9635 {
9636 c_parser_error (parser, gmsgid: "expected identifier");
9637 return NULL_TREE;
9638 }
9639
9640 name = build_string (IDENTIFIER_LENGTH (name),
9641 IDENTIFIER_POINTER (name));
9642 list = tree_cons (name, label, list);
9643 if (c_parser_next_token_is (parser, type: CPP_COMMA))
9644 c_parser_consume_token (parser);
9645 else
9646 return nreverse (list);
9647 }
9648}
9649
9650/* Parse a possibly concatenated sequence of string literals.
9651 TRANSLATE says whether to translate them to the execution character
9652 set; WIDE_OK says whether any kind of prefixed string literal is
9653 permitted in this context. This code is based on that in
9654 lex_string. */
9655
9656struct c_expr
9657c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
9658{
9659 struct c_expr ret;
9660 size_t count;
9661 struct obstack str_ob;
9662 struct obstack loc_ob;
9663 cpp_string str, istr, *strs;
9664 c_token *tok;
9665 location_t loc, last_tok_loc;
9666 enum cpp_ttype type;
9667 tree value, string_tree;
9668
9669 tok = c_parser_peek_token (parser);
9670 loc = tok->location;
9671 last_tok_loc = linemap_resolve_location (line_table, loc,
9672 lrk: LRK_MACRO_DEFINITION_LOCATION,
9673 NULL);
9674 type = tok->type;
9675 switch (type)
9676 {
9677 case CPP_STRING:
9678 case CPP_WSTRING:
9679 case CPP_STRING16:
9680 case CPP_STRING32:
9681 case CPP_UTF8STRING:
9682 string_tree = tok->value;
9683 break;
9684
9685 default:
9686 c_parser_error (parser, gmsgid: "expected string literal");
9687 ret.set_error ();
9688 ret.value = NULL_TREE;
9689 ret.original_code = ERROR_MARK;
9690 ret.original_type = NULL_TREE;
9691 return ret;
9692 }
9693
9694 /* Try to avoid the overhead of creating and destroying an obstack
9695 for the common case of just one string. */
9696 switch (c_parser_peek_2nd_token (parser)->type)
9697 {
9698 default:
9699 c_parser_consume_token (parser);
9700 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9701 str.len = TREE_STRING_LENGTH (string_tree);
9702 count = 1;
9703 strs = &str;
9704 break;
9705
9706 case CPP_STRING:
9707 case CPP_WSTRING:
9708 case CPP_STRING16:
9709 case CPP_STRING32:
9710 case CPP_UTF8STRING:
9711 gcc_obstack_init (&str_ob);
9712 gcc_obstack_init (&loc_ob);
9713 count = 0;
9714 do
9715 {
9716 c_parser_consume_token (parser);
9717 count++;
9718 str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
9719 str.len = TREE_STRING_LENGTH (string_tree);
9720 if (type != tok->type)
9721 {
9722 if (type == CPP_STRING)
9723 type = tok->type;
9724 else if (tok->type != CPP_STRING)
9725 error ("unsupported non-standard concatenation "
9726 "of string literals");
9727 }
9728 obstack_grow (&str_ob, &str, sizeof (cpp_string));
9729 obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
9730 tok = c_parser_peek_token (parser);
9731 string_tree = tok->value;
9732 last_tok_loc
9733 = linemap_resolve_location (line_table, loc: tok->location,
9734 lrk: LRK_MACRO_DEFINITION_LOCATION, NULL);
9735 }
9736 while (tok->type == CPP_STRING
9737 || tok->type == CPP_WSTRING
9738 || tok->type == CPP_STRING16
9739 || tok->type == CPP_STRING32
9740 || tok->type == CPP_UTF8STRING);
9741 strs = (cpp_string *) obstack_finish (&str_ob);
9742 }
9743
9744 if (count > 1 && !in_system_header_at (loc: input_location))
9745 warning (OPT_Wtraditional,
9746 "traditional C rejects string constant concatenation");
9747
9748 if ((type == CPP_STRING || wide_ok)
9749 && ((translate
9750 ? cpp_interpret_string : cpp_interpret_string_notranslate)
9751 (parse_in, strs, count, &istr, type)))
9752 {
9753 value = build_string (istr.len, (const char *) istr.text);
9754 free (CONST_CAST (unsigned char *, istr.text));
9755 if (count > 1)
9756 {
9757 location_t *locs = (location_t *) obstack_finish (&loc_ob);
9758 gcc_assert (g_string_concat_db);
9759 g_string_concat_db->record_string_concatenation (num: count, locs);
9760 }
9761 }
9762 else
9763 {
9764 if (type != CPP_STRING && !wide_ok)
9765 {
9766 error_at (loc, "a wide string is invalid in this context");
9767 type = CPP_STRING;
9768 }
9769 /* Callers cannot generally handle error_mark_node in this
9770 context, so return the empty string instead. An error has
9771 been issued, either above or from cpp_interpret_string. */
9772 switch (type)
9773 {
9774 default:
9775 case CPP_STRING:
9776 case CPP_UTF8STRING:
9777 if (type == CPP_UTF8STRING && flag_char8_t)
9778 {
9779 value = build_string (TYPE_PRECISION (char8_type_node)
9780 / TYPE_PRECISION (char_type_node),
9781 ""); /* char8_t is 8 bits */
9782 }
9783 else
9784 value = build_string (1, "");
9785 break;
9786 case CPP_STRING16:
9787 value = build_string (TYPE_PRECISION (char16_type_node)
9788 / TYPE_PRECISION (char_type_node),
9789 "\0"); /* char16_t is 16 bits */
9790 break;
9791 case CPP_STRING32:
9792 value = build_string (TYPE_PRECISION (char32_type_node)
9793 / TYPE_PRECISION (char_type_node),
9794 "\0\0\0"); /* char32_t is 32 bits */
9795 break;
9796 case CPP_WSTRING:
9797 value = build_string (TYPE_PRECISION (wchar_type_node)
9798 / TYPE_PRECISION (char_type_node),
9799 "\0\0\0"); /* widest supported wchar_t
9800 is 32 bits */
9801 break;
9802 }
9803 }
9804
9805 switch (type)
9806 {
9807 default:
9808 case CPP_STRING:
9809 TREE_TYPE (value) = char_array_type_node;
9810 break;
9811 case CPP_UTF8STRING:
9812 if (flag_char8_t)
9813 TREE_TYPE (value) = char8_array_type_node;
9814 else
9815 TREE_TYPE (value) = char_array_type_node;
9816 break;
9817 case CPP_STRING16:
9818 TREE_TYPE (value) = char16_array_type_node;
9819 break;
9820 case CPP_STRING32:
9821 TREE_TYPE (value) = char32_array_type_node;
9822 break;
9823 case CPP_WSTRING:
9824 TREE_TYPE (value) = wchar_array_type_node;
9825 }
9826 value = fix_string_type (value);
9827
9828 if (count > 1)
9829 {
9830 obstack_free (&str_ob, 0);
9831 obstack_free (&loc_ob, 0);
9832 }
9833
9834 ret.value = value;
9835 ret.original_code = STRING_CST;
9836 ret.original_type = NULL_TREE;
9837 set_c_expr_source_range (expr: &ret, src_range: get_range_from_loc (set: line_table, loc));
9838 ret.m_decimal = 0;
9839 parser->seen_string_literal = true;
9840 return ret;
9841}
9842
9843/* Parse an expression other than a compound expression; that is, an
9844 assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
9845 AFTER is not NULL then it is an Objective-C message expression which
9846 is the primary-expression starting the expression as an initializer.
9847
9848 assignment-expression:
9849 conditional-expression
9850 unary-expression assignment-operator assignment-expression
9851
9852 assignment-operator: one of
9853 = *= /= %= += -= <<= >>= &= ^= |=
9854
9855 In GNU C we accept any conditional expression on the LHS and
9856 diagnose the invalid lvalue rather than producing a syntax
9857 error. */
9858
9859static struct c_expr
9860c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
9861 tree omp_atomic_lhs)
9862{
9863 struct c_expr lhs, rhs, ret;
9864 enum tree_code code;
9865 location_t op_location, exp_location;
9866 bool save_in_omp_for = c_in_omp_for;
9867 c_in_omp_for = false;
9868 gcc_assert (!after || c_dialect_objc ());
9869 lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
9870 op_location = c_parser_peek_token (parser)->location;
9871 switch (c_parser_peek_token (parser)->type)
9872 {
9873 case CPP_EQ:
9874 code = NOP_EXPR;
9875 break;
9876 case CPP_MULT_EQ:
9877 code = MULT_EXPR;
9878 break;
9879 case CPP_DIV_EQ:
9880 code = TRUNC_DIV_EXPR;
9881 break;
9882 case CPP_MOD_EQ:
9883 code = TRUNC_MOD_EXPR;
9884 break;
9885 case CPP_PLUS_EQ:
9886 code = PLUS_EXPR;
9887 break;
9888 case CPP_MINUS_EQ:
9889 code = MINUS_EXPR;
9890 break;
9891 case CPP_LSHIFT_EQ:
9892 code = LSHIFT_EXPR;
9893 break;
9894 case CPP_RSHIFT_EQ:
9895 code = RSHIFT_EXPR;
9896 break;
9897 case CPP_AND_EQ:
9898 code = BIT_AND_EXPR;
9899 break;
9900 case CPP_XOR_EQ:
9901 code = BIT_XOR_EXPR;
9902 break;
9903 case CPP_OR_EQ:
9904 code = BIT_IOR_EXPR;
9905 break;
9906 default:
9907 c_in_omp_for = save_in_omp_for;
9908 return lhs;
9909 }
9910 c_parser_consume_token (parser);
9911 exp_location = c_parser_peek_token (parser)->location;
9912 rhs = c_parser_expr_no_commas (parser, NULL);
9913 rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
9914
9915 ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
9916 code, exp_location, rhs.value,
9917 rhs.original_type);
9918 ret.m_decimal = 0;
9919 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
9920 if (code == NOP_EXPR)
9921 ret.original_code = MODIFY_EXPR;
9922 else
9923 {
9924 suppress_warning (ret.value, OPT_Wparentheses);
9925 ret.original_code = ERROR_MARK;
9926 }
9927 ret.original_type = NULL;
9928 c_in_omp_for = save_in_omp_for;
9929 return ret;
9930}
9931
9932/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
9933 AFTER is not NULL then it is an Objective-C message expression which is
9934 the primary-expression starting the expression as an initializer.
9935
9936 conditional-expression:
9937 logical-OR-expression
9938 logical-OR-expression ? expression : conditional-expression
9939
9940 GNU extensions:
9941
9942 conditional-expression:
9943 logical-OR-expression ? : conditional-expression
9944*/
9945
9946static struct c_expr
9947c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
9948 tree omp_atomic_lhs)
9949{
9950 struct c_expr cond, exp1, exp2, ret;
9951 location_t start, cond_loc, colon_loc;
9952 bool save_c_omp_array_section_p = c_omp_array_section_p;
9953
9954 gcc_assert (!after || c_dialect_objc ());
9955
9956 cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
9957
9958 if (c_parser_next_token_is_not (parser, type: CPP_QUERY))
9959 return cond;
9960 c_omp_array_section_p = false;
9961 if (cond.value != error_mark_node)
9962 start = cond.get_start ();
9963 else
9964 start = UNKNOWN_LOCATION;
9965 cond_loc = c_parser_peek_token (parser)->location;
9966 cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
9967 c_parser_consume_token (parser);
9968 if (c_parser_next_token_is (parser, type: CPP_COLON))
9969 {
9970 tree eptype = NULL_TREE;
9971
9972 location_t middle_loc = c_parser_peek_token (parser)->location;
9973 pedwarn (middle_loc, OPT_Wpedantic,
9974 "ISO C forbids omitting the middle term of a %<?:%> expression");
9975 if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
9976 {
9977 eptype = TREE_TYPE (cond.value);
9978 cond.value = TREE_OPERAND (cond.value, 0);
9979 }
9980 tree e = cond.value;
9981 while (TREE_CODE (e) == COMPOUND_EXPR)
9982 e = TREE_OPERAND (e, 1);
9983 warn_for_omitted_condop (middle_loc, e);
9984 /* Make sure first operand is calculated only once. */
9985 exp1.value = save_expr (default_conversion (cond.value));
9986 if (eptype)
9987 exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
9988 exp1.original_type = NULL;
9989 exp1.src_range = cond.src_range;
9990 cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
9991 c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
9992 }
9993 else
9994 {
9995 cond.value
9996 = c_objc_common_truthvalue_conversion
9997 (cond_loc, default_conversion (cond.value));
9998 c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
9999 exp1 = c_parser_expression_conv (parser);
10000 mark_exp_read (exp1.value);
10001 c_inhibit_evaluation_warnings +=
10002 ((cond.value == truthvalue_true_node)
10003 - (cond.value == truthvalue_false_node));
10004 }
10005
10006 colon_loc = c_parser_peek_token (parser)->location;
10007 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
10008 {
10009 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10010 ret.set_error ();
10011 ret.original_code = ERROR_MARK;
10012 ret.original_type = NULL;
10013 c_omp_array_section_p = save_c_omp_array_section_p;
10014 return ret;
10015 }
10016 {
10017 location_t exp2_loc = c_parser_peek_token (parser)->location;
10018 exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
10019 exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
10020 }
10021 c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
10022 location_t loc1 = make_location (caret: exp1.get_start (), src_range: exp1.src_range);
10023 location_t loc2 = make_location (caret: exp2.get_start (), src_range: exp2.src_range);
10024 if (UNLIKELY (omp_atomic_lhs != NULL)
10025 && (TREE_CODE (cond.value) == GT_EXPR
10026 || TREE_CODE (cond.value) == LT_EXPR
10027 || TREE_CODE (cond.value) == EQ_EXPR)
10028 && c_tree_equal (exp2.value, omp_atomic_lhs)
10029 && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
10030 || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
10031 ret.value = build3_loc (loc: colon_loc, code: COND_EXPR, TREE_TYPE (omp_atomic_lhs),
10032 arg0: cond.value, arg1: exp1.value, arg2: exp2.value);
10033 else
10034 ret.value
10035 = build_conditional_expr (colon_loc, cond.value,
10036 cond.original_code == C_MAYBE_CONST_EXPR,
10037 exp1.value, exp1.original_type, loc1,
10038 exp2.value, exp2.original_type, loc2);
10039 ret.original_code = ERROR_MARK;
10040 if (exp1.value == error_mark_node || exp2.value == error_mark_node)
10041 ret.original_type = NULL;
10042 else
10043 {
10044 tree t1, t2;
10045
10046 /* If both sides are enum type, the default conversion will have
10047 made the type of the result be an integer type. We want to
10048 remember the enum types we started with. */
10049 t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
10050 t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
10051 ret.original_type = ((t1 != error_mark_node
10052 && t2 != error_mark_node
10053 && (TYPE_MAIN_VARIANT (t1)
10054 == TYPE_MAIN_VARIANT (t2)))
10055 ? t1
10056 : NULL);
10057 }
10058 set_c_expr_source_range (expr: &ret, start, finish: exp2.get_finish ());
10059 ret.m_decimal = 0;
10060 c_omp_array_section_p = save_c_omp_array_section_p;
10061 return ret;
10062}
10063
10064/* Parse a binary expression; that is, a logical-OR-expression (C90
10065 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
10066 NULL then it is an Objective-C message expression which is the
10067 primary-expression starting the expression as an initializer.
10068
10069 OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
10070 when it should be the unfolded lhs. In a valid OpenMP source,
10071 one of the operands of the toplevel binary expression must be equal
10072 to it. In that case, just return a build2 created binary operation
10073 rather than result of parser_build_binary_op.
10074
10075 multiplicative-expression:
10076 cast-expression
10077 multiplicative-expression * cast-expression
10078 multiplicative-expression / cast-expression
10079 multiplicative-expression % cast-expression
10080
10081 additive-expression:
10082 multiplicative-expression
10083 additive-expression + multiplicative-expression
10084 additive-expression - multiplicative-expression
10085
10086 shift-expression:
10087 additive-expression
10088 shift-expression << additive-expression
10089 shift-expression >> additive-expression
10090
10091 relational-expression:
10092 shift-expression
10093 relational-expression < shift-expression
10094 relational-expression > shift-expression
10095 relational-expression <= shift-expression
10096 relational-expression >= shift-expression
10097
10098 equality-expression:
10099 relational-expression
10100 equality-expression == relational-expression
10101 equality-expression != relational-expression
10102
10103 AND-expression:
10104 equality-expression
10105 AND-expression & equality-expression
10106
10107 exclusive-OR-expression:
10108 AND-expression
10109 exclusive-OR-expression ^ AND-expression
10110
10111 inclusive-OR-expression:
10112 exclusive-OR-expression
10113 inclusive-OR-expression | exclusive-OR-expression
10114
10115 logical-AND-expression:
10116 inclusive-OR-expression
10117 logical-AND-expression && inclusive-OR-expression
10118
10119 logical-OR-expression:
10120 logical-AND-expression
10121 logical-OR-expression || logical-AND-expression
10122*/
10123
10124static struct c_expr
10125c_parser_binary_expression (c_parser *parser, struct c_expr *after,
10126 tree omp_atomic_lhs)
10127{
10128 /* A binary expression is parsed using operator-precedence parsing,
10129 with the operands being cast expressions. All the binary
10130 operators are left-associative. Thus a binary expression is of
10131 form:
10132
10133 E0 op1 E1 op2 E2 ...
10134
10135 which we represent on a stack. On the stack, the precedence
10136 levels are strictly increasing. When a new operator is
10137 encountered of higher precedence than that at the top of the
10138 stack, it is pushed; its LHS is the top expression, and its RHS
10139 is everything parsed until it is popped. When a new operator is
10140 encountered with precedence less than or equal to that at the top
10141 of the stack, triples E[i-1] op[i] E[i] are popped and replaced
10142 by the result of the operation until the operator at the top of
10143 the stack has lower precedence than the new operator or there is
10144 only one element on the stack; then the top expression is the LHS
10145 of the new operator. In the case of logical AND and OR
10146 expressions, we also need to adjust c_inhibit_evaluation_warnings
10147 as appropriate when the operators are pushed and popped. */
10148
10149 struct {
10150 /* The expression at this stack level. */
10151 struct c_expr expr;
10152 /* The precedence of the operator on its left, PREC_NONE at the
10153 bottom of the stack. */
10154 enum c_parser_prec prec;
10155 /* The operation on its left. */
10156 enum tree_code op;
10157 /* The source location of this operation. */
10158 location_t loc;
10159 /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
10160 tree sizeof_arg;
10161 } stack[NUM_PRECS];
10162 int sp;
10163 /* Location of the binary operator. */
10164 location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
10165#define POP \
10166 do { \
10167 switch (stack[sp].op) \
10168 { \
10169 case TRUTH_ANDIF_EXPR: \
10170 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10171 == truthvalue_false_node); \
10172 break; \
10173 case TRUTH_ORIF_EXPR: \
10174 c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
10175 == truthvalue_true_node); \
10176 break; \
10177 case TRUNC_DIV_EXPR: \
10178 if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
10179 || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
10180 && (stack[sp].expr.original_code == SIZEOF_EXPR \
10181 || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
10182 { \
10183 tree type0 = stack[sp - 1].sizeof_arg; \
10184 tree type1 = stack[sp].sizeof_arg; \
10185 tree first_arg = type0; \
10186 if (!TYPE_P (type0)) \
10187 type0 = TREE_TYPE (type0); \
10188 if (!TYPE_P (type1)) \
10189 type1 = TREE_TYPE (type1); \
10190 if (POINTER_TYPE_P (type0) \
10191 && comptypes (TREE_TYPE (type0), type1) \
10192 && !(TREE_CODE (first_arg) == PARM_DECL \
10193 && C_ARRAY_PARAMETER (first_arg) \
10194 && warn_sizeof_array_argument)) \
10195 { \
10196 auto_diagnostic_group d; \
10197 if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
10198 "division %<sizeof (%T) / sizeof (%T)%> " \
10199 "does not compute the number of array " \
10200 "elements", \
10201 type0, type1)) \
10202 if (DECL_P (first_arg)) \
10203 inform (DECL_SOURCE_LOCATION (first_arg), \
10204 "first %<sizeof%> operand was declared here"); \
10205 } \
10206 else if (TREE_CODE (type0) == ARRAY_TYPE \
10207 && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
10208 && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
10209 maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
10210 stack[sp].sizeof_arg, type1); \
10211 } \
10212 break; \
10213 default: \
10214 break; \
10215 } \
10216 stack[sp - 1].expr \
10217 = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
10218 stack[sp - 1].expr, true, true); \
10219 stack[sp].expr \
10220 = convert_lvalue_to_rvalue (stack[sp].loc, \
10221 stack[sp].expr, true, true); \
10222 if (UNLIKELY (omp_atomic_lhs != NULL_TREE) && sp == 1 \
10223 && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
10224 && ((1 << stack[sp].prec) \
10225 & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
10226 | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
10227 | (1 << PREC_ADD) | (1 << PREC_MULT) \
10228 | (1 << PREC_EQ)))) \
10229 || ((c_parser_next_token_is (parser, CPP_QUERY) \
10230 || (omp_atomic_lhs == void_list_node \
10231 && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
10232 && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
10233 && stack[sp].op != TRUNC_MOD_EXPR \
10234 && stack[sp].op != GE_EXPR \
10235 && stack[sp].op != LE_EXPR \
10236 && stack[sp].op != NE_EXPR \
10237 && stack[0].expr.value != error_mark_node \
10238 && stack[1].expr.value != error_mark_node \
10239 && (omp_atomic_lhs == void_list_node \
10240 || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
10241 || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
10242 || (stack[sp].op == EQ_EXPR \
10243 && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
10244 { \
10245 tree t = make_node (stack[1].op); \
10246 TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
10247 TREE_OPERAND (t, 0) = stack[0].expr.value; \
10248 TREE_OPERAND (t, 1) = stack[1].expr.value; \
10249 stack[0].expr.value = t; \
10250 stack[0].expr.m_decimal = 0; \
10251 } \
10252 else \
10253 stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
10254 stack[sp].op, \
10255 stack[sp - 1].expr, \
10256 stack[sp].expr); \
10257 sp--; \
10258 } while (0)
10259 gcc_assert (!after || c_dialect_objc ());
10260 stack[0].loc = c_parser_peek_token (parser)->location;
10261 stack[0].expr = c_parser_cast_expression (parser, after);
10262 stack[0].prec = PREC_NONE;
10263 stack[0].sizeof_arg = c_last_sizeof_arg;
10264 sp = 0;
10265 while (true)
10266 {
10267 enum c_parser_prec oprec;
10268 enum tree_code ocode;
10269 source_range src_range;
10270 if (parser->error)
10271 goto out;
10272 switch (c_parser_peek_token (parser)->type)
10273 {
10274 case CPP_MULT:
10275 oprec = PREC_MULT;
10276 ocode = MULT_EXPR;
10277 break;
10278 case CPP_DIV:
10279 oprec = PREC_MULT;
10280 ocode = TRUNC_DIV_EXPR;
10281 break;
10282 case CPP_MOD:
10283 oprec = PREC_MULT;
10284 ocode = TRUNC_MOD_EXPR;
10285 break;
10286 case CPP_PLUS:
10287 oprec = PREC_ADD;
10288 ocode = PLUS_EXPR;
10289 break;
10290 case CPP_MINUS:
10291 oprec = PREC_ADD;
10292 ocode = MINUS_EXPR;
10293 break;
10294 case CPP_LSHIFT:
10295 oprec = PREC_SHIFT;
10296 ocode = LSHIFT_EXPR;
10297 break;
10298 case CPP_RSHIFT:
10299 oprec = PREC_SHIFT;
10300 ocode = RSHIFT_EXPR;
10301 break;
10302 case CPP_LESS:
10303 oprec = PREC_REL;
10304 ocode = LT_EXPR;
10305 break;
10306 case CPP_GREATER:
10307 oprec = PREC_REL;
10308 ocode = GT_EXPR;
10309 break;
10310 case CPP_LESS_EQ:
10311 oprec = PREC_REL;
10312 ocode = LE_EXPR;
10313 break;
10314 case CPP_GREATER_EQ:
10315 oprec = PREC_REL;
10316 ocode = GE_EXPR;
10317 break;
10318 case CPP_EQ_EQ:
10319 oprec = PREC_EQ;
10320 ocode = EQ_EXPR;
10321 break;
10322 case CPP_NOT_EQ:
10323 oprec = PREC_EQ;
10324 ocode = NE_EXPR;
10325 break;
10326 case CPP_AND:
10327 oprec = PREC_BITAND;
10328 ocode = BIT_AND_EXPR;
10329 break;
10330 case CPP_XOR:
10331 oprec = PREC_BITXOR;
10332 ocode = BIT_XOR_EXPR;
10333 break;
10334 case CPP_OR:
10335 oprec = PREC_BITOR;
10336 ocode = BIT_IOR_EXPR;
10337 break;
10338 case CPP_AND_AND:
10339 oprec = PREC_LOGAND;
10340 ocode = TRUTH_ANDIF_EXPR;
10341 break;
10342 case CPP_OR_OR:
10343 oprec = PREC_LOGOR;
10344 ocode = TRUTH_ORIF_EXPR;
10345 break;
10346 default:
10347 /* Not a binary operator, so end of the binary
10348 expression. */
10349 goto out;
10350 }
10351 binary_loc = c_parser_peek_token (parser)->location;
10352 while (oprec <= stack[sp].prec)
10353 POP;
10354 c_parser_consume_token (parser);
10355 switch (ocode)
10356 {
10357 case TRUTH_ANDIF_EXPR:
10358 src_range = stack[sp].expr.src_range;
10359 stack[sp].expr
10360 = convert_lvalue_to_rvalue (stack[sp].loc,
10361 stack[sp].expr, true, true);
10362 stack[sp].expr.value = c_objc_common_truthvalue_conversion
10363 (stack[sp].loc, default_conversion (stack[sp].expr.value));
10364 c_inhibit_evaluation_warnings += (stack[sp].expr.value
10365 == truthvalue_false_node);
10366 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
10367 break;
10368 case TRUTH_ORIF_EXPR:
10369 src_range = stack[sp].expr.src_range;
10370 stack[sp].expr
10371 = convert_lvalue_to_rvalue (stack[sp].loc,
10372 stack[sp].expr, true, true);
10373 stack[sp].expr.value = c_objc_common_truthvalue_conversion
10374 (stack[sp].loc, default_conversion (stack[sp].expr.value));
10375 c_inhibit_evaluation_warnings += (stack[sp].expr.value
10376 == truthvalue_true_node);
10377 set_c_expr_source_range (expr: &stack[sp].expr, src_range);
10378 break;
10379 default:
10380 break;
10381 }
10382 sp++;
10383 stack[sp].loc = binary_loc;
10384 stack[sp].expr = c_parser_cast_expression (parser, NULL);
10385 stack[sp].prec = oprec;
10386 stack[sp].op = ocode;
10387 stack[sp].sizeof_arg = c_last_sizeof_arg;
10388 }
10389 out:
10390 while (sp > 0)
10391 POP;
10392 return stack[0].expr;
10393#undef POP
10394}
10395
10396/* Parse any storage class specifiers after an open parenthesis in a
10397 context where a compound literal is permitted. */
10398
10399static struct c_declspecs *
10400c_parser_compound_literal_scspecs (c_parser *parser)
10401{
10402 bool seen_scspec = false;
10403 struct c_declspecs *specs = build_null_declspecs ();
10404 while (c_parser_next_token_is (parser, type: CPP_KEYWORD))
10405 {
10406 switch (c_parser_peek_token (parser)->keyword)
10407 {
10408 case RID_CONSTEXPR:
10409 case RID_REGISTER:
10410 case RID_STATIC:
10411 case RID_THREAD:
10412 seen_scspec = true;
10413 declspecs_add_scspec (c_parser_peek_token (parser)->location,
10414 specs, c_parser_peek_token (parser)->value);
10415 c_parser_consume_token (parser);
10416 break;
10417 default:
10418 goto out;
10419 }
10420 }
10421 out:
10422 return seen_scspec ? specs : NULL;
10423}
10424
10425/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
10426 is not NULL then it is an Objective-C message expression which is the
10427 primary-expression starting the expression as an initializer.
10428
10429 cast-expression:
10430 unary-expression
10431 ( type-name ) unary-expression
10432*/
10433
10434static struct c_expr
10435c_parser_cast_expression (c_parser *parser, struct c_expr *after)
10436{
10437 location_t cast_loc = c_parser_peek_token (parser)->location;
10438 gcc_assert (!after || c_dialect_objc ());
10439 if (after)
10440 return c_parser_postfix_expression_after_primary (parser,
10441 loc: cast_loc, *after);
10442 /* If the expression begins with a parenthesized type name, it may
10443 be either a cast or a compound literal; we need to see whether
10444 the next character is '{' to tell the difference. If not, it is
10445 an unary expression. Full detection of unknown typenames here
10446 would require a 3-token lookahead. */
10447 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10448 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10449 {
10450 struct c_declspecs *scspecs;
10451 struct c_type_name *type_name;
10452 struct c_expr ret;
10453 struct c_expr expr;
10454 matching_parens parens;
10455 parens.consume_open (parser);
10456 scspecs = c_parser_compound_literal_scspecs (parser);
10457 type_name = c_parser_type_name (parser, alignas_ok: true);
10458 parens.skip_until_found_close (parser);
10459 if (type_name == NULL)
10460 {
10461 ret.set_error ();
10462 ret.original_code = ERROR_MARK;
10463 ret.original_type = NULL;
10464 return ret;
10465 }
10466
10467 /* Save casted types in the function's used types hash table. */
10468 used_types_insert (type_name->specs->type);
10469
10470 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10471 return c_parser_postfix_expression_after_paren_type (parser, scspecs,
10472 type_name,
10473 cast_loc);
10474 if (scspecs)
10475 error_at (cast_loc, "storage class specifier in cast");
10476 if (type_name->specs->alignas_p)
10477 error_at (type_name->specs->locations[cdw_alignas],
10478 "alignment specified for type name in cast");
10479 {
10480 location_t expr_loc = c_parser_peek_token (parser)->location;
10481 expr = c_parser_cast_expression (parser, NULL);
10482 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
10483 }
10484 ret.value = c_cast_expr (cast_loc, type_name, expr.value);
10485 if (ret.value && expr.value)
10486 set_c_expr_source_range (expr: &ret, start: cast_loc, finish: expr.get_finish ());
10487 ret.original_code = ERROR_MARK;
10488 ret.original_type = NULL;
10489 ret.m_decimal = 0;
10490 return ret;
10491 }
10492 else
10493 return c_parser_unary_expression (parser);
10494}
10495
10496/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
10497
10498 unary-expression:
10499 postfix-expression
10500 ++ unary-expression
10501 -- unary-expression
10502 unary-operator cast-expression
10503 _Countof unary-expression
10504 _Countof ( type-name )
10505 sizeof unary-expression
10506 sizeof ( type-name )
10507
10508 (_Countof is new in C2y.)
10509
10510 unary-operator: one of
10511 & * + - ~ !
10512
10513 GNU extensions:
10514
10515 unary-expression:
10516 __alignof__ unary-expression
10517 __alignof__ ( type-name )
10518 && identifier
10519
10520 (C11 permits _Alignof with type names only.)
10521
10522 unary-operator: one of
10523 __extension__ __real__ __imag__
10524
10525 Transactional Memory:
10526
10527 unary-expression:
10528 transaction-expression
10529
10530 In addition, the GNU syntax treats ++ and -- as unary operators, so
10531 they may be applied to cast expressions with errors for non-lvalues
10532 given later. */
10533
10534static struct c_expr
10535c_parser_unary_expression (c_parser *parser)
10536{
10537 int ext;
10538 struct c_expr ret, op;
10539 location_t op_loc = c_parser_peek_token (parser)->location;
10540 location_t exp_loc;
10541 location_t finish;
10542 ret.original_code = ERROR_MARK;
10543 ret.original_type = NULL;
10544 switch (c_parser_peek_token (parser)->type)
10545 {
10546 case CPP_PLUS_PLUS:
10547 c_parser_consume_token (parser);
10548 exp_loc = c_parser_peek_token (parser)->location;
10549 op = c_parser_cast_expression (parser, NULL);
10550
10551 op = default_function_array_read_conversion (exp_loc, op);
10552 return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
10553 case CPP_MINUS_MINUS:
10554 c_parser_consume_token (parser);
10555 exp_loc = c_parser_peek_token (parser)->location;
10556 op = c_parser_cast_expression (parser, NULL);
10557
10558 op = default_function_array_read_conversion (exp_loc, op);
10559 return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
10560 case CPP_AND:
10561 c_parser_consume_token (parser);
10562 op = c_parser_cast_expression (parser, NULL);
10563 mark_exp_read (op.value);
10564 return parser_build_unary_op (op_loc, ADDR_EXPR, op);
10565 case CPP_MULT:
10566 {
10567 c_parser_consume_token (parser);
10568 exp_loc = c_parser_peek_token (parser)->location;
10569 op = c_parser_cast_expression (parser, NULL);
10570 finish = op.get_finish ();
10571 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10572 location_t combined_loc = make_location (caret: op_loc, start: op_loc, finish);
10573 ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
10574 ret.src_range.m_start = op_loc;
10575 ret.src_range.m_finish = finish;
10576 ret.m_decimal = 0;
10577 return ret;
10578 }
10579 case CPP_PLUS:
10580 if (!c_dialect_objc () && !in_system_header_at (loc: input_location))
10581 warning_at (op_loc,
10582 OPT_Wtraditional,
10583 "traditional C rejects the unary plus operator");
10584 c_parser_consume_token (parser);
10585 exp_loc = c_parser_peek_token (parser)->location;
10586 op = c_parser_cast_expression (parser, NULL);
10587 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10588 return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
10589 case CPP_MINUS:
10590 c_parser_consume_token (parser);
10591 exp_loc = c_parser_peek_token (parser)->location;
10592 op = c_parser_cast_expression (parser, NULL);
10593 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10594 return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
10595 case CPP_COMPL:
10596 c_parser_consume_token (parser);
10597 exp_loc = c_parser_peek_token (parser)->location;
10598 op = c_parser_cast_expression (parser, NULL);
10599 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10600 return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
10601 case CPP_NOT:
10602 c_parser_consume_token (parser);
10603 exp_loc = c_parser_peek_token (parser)->location;
10604 op = c_parser_cast_expression (parser, NULL);
10605 op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
10606 return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
10607 case CPP_AND_AND:
10608 /* Refer to the address of a label as a pointer. */
10609 c_parser_consume_token (parser);
10610 if (c_parser_next_token_is (parser, type: CPP_NAME))
10611 {
10612 ret.value = finish_label_address_expr
10613 (c_parser_peek_token (parser)->value, op_loc);
10614 set_c_expr_source_range (expr: &ret, start: op_loc,
10615 finish: c_parser_peek_token (parser)->get_finish ());
10616 c_parser_consume_token (parser);
10617 }
10618 else
10619 {
10620 c_parser_error (parser, gmsgid: "expected identifier");
10621 ret.set_error ();
10622 }
10623 return ret;
10624 case CPP_KEYWORD:
10625 switch (c_parser_peek_token (parser)->keyword)
10626 {
10627 case RID_COUNTOF:
10628 return c_parser_countof_expression (parser);
10629 case RID_SIZEOF:
10630 return c_parser_sizeof_expression (parser);
10631 case RID_ALIGNOF:
10632 return c_parser_alignof_expression (parser);
10633 case RID_BUILTIN_HAS_ATTRIBUTE:
10634 return c_parser_has_attribute_expression (parser);
10635 case RID_EXTENSION:
10636 c_parser_consume_token (parser);
10637 ext = disable_extension_diagnostics ();
10638 ret = c_parser_cast_expression (parser, NULL);
10639 restore_extension_diagnostics (flags: ext);
10640 return ret;
10641 case RID_REALPART:
10642 c_parser_consume_token (parser);
10643 exp_loc = c_parser_peek_token (parser)->location;
10644 op = c_parser_cast_expression (parser, NULL);
10645 op = default_function_array_conversion (exp_loc, op);
10646 return parser_build_unary_op (op_loc, REALPART_EXPR, op);
10647 case RID_IMAGPART:
10648 c_parser_consume_token (parser);
10649 exp_loc = c_parser_peek_token (parser)->location;
10650 op = c_parser_cast_expression (parser, NULL);
10651 op = default_function_array_conversion (exp_loc, op);
10652 return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
10653 case RID_TRANSACTION_ATOMIC:
10654 case RID_TRANSACTION_RELAXED:
10655 return c_parser_transaction_expression (parser,
10656 c_parser_peek_token (parser)->keyword);
10657 default:
10658 return c_parser_postfix_expression (parser);
10659 }
10660 default:
10661 return c_parser_postfix_expression (parser);
10662 }
10663}
10664
10665/* Parse a sizeof expression. */
10666
10667static inline struct c_expr
10668c_parser_sizeof_expression (c_parser *parser)
10669{
10670 return c_parser_sizeof_or_countof_expression (parser, RID_SIZEOF);
10671}
10672
10673/* Parse a _Countof expression. */
10674
10675static inline struct c_expr
10676c_parser_countof_expression (c_parser *parser)
10677{
10678 return c_parser_sizeof_or_countof_expression (parser, RID_COUNTOF);
10679}
10680
10681/* Parse a sizeof or _Countof expression. */
10682
10683static struct c_expr
10684c_parser_sizeof_or_countof_expression (c_parser *parser, enum rid rid)
10685{
10686 const char *op_name = (rid == RID_COUNTOF) ? "_Countof" : "sizeof";
10687 struct c_expr expr;
10688 struct c_expr result;
10689 location_t expr_loc;
10690 gcc_assert (c_parser_next_token_is_keyword (parser, rid));
10691
10692 location_t start;
10693 location_t finish = UNKNOWN_LOCATION;
10694
10695 start = c_parser_peek_token (parser)->location;
10696
10697 if (rid == RID_COUNTOF)
10698 pedwarn_c23 (start, OPT_Wpedantic,
10699 "ISO C does not support %qs before C2Y", op_name);
10700
10701 c_parser_consume_token (parser);
10702 c_inhibit_evaluation_warnings++;
10703 if (rid == RID_COUNTOF)
10704 in_countof++;
10705 else
10706 in_sizeof++;
10707 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10708 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10709 {
10710 /* Either sizeof ( type-name ) or sizeof unary-expression
10711 starting with a compound literal. */
10712 struct c_declspecs *scspecs;
10713 struct c_type_name *type_name;
10714 matching_parens parens;
10715 parens.consume_open (parser);
10716 expr_loc = c_parser_peek_token (parser)->location;
10717 scspecs = c_parser_compound_literal_scspecs (parser);
10718 type_name = c_parser_type_name (parser, alignas_ok: true);
10719 parens.skip_until_found_close (parser);
10720 finish = parser->tokens_buf[0].location;
10721 if (type_name == NULL)
10722 {
10723 /* Let c_expr_sizeof_expr call pop_maybe_used and fill in c_expr
10724 for parsing error; the parsing of the expression could have
10725 called record_maybe_used_decl. */
10726 expr.set_error ();
10727 goto Xof_expr;
10728 }
10729 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10730 {
10731 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10732 type_name,
10733 expr_loc);
10734 finish = expr.get_finish ();
10735 goto Xof_expr;
10736 }
10737 /* sizeof ( type-name ). */
10738 if (scspecs)
10739 error_at (expr_loc, "storage class specifier in %qs", op_name);
10740 if (type_name->specs->alignas_p)
10741 error_at (type_name->specs->locations[cdw_alignas],
10742 "alignment specified for type name in %qs", op_name);
10743 c_inhibit_evaluation_warnings--;
10744 if (rid == RID_COUNTOF)
10745 {
10746 in_countof--;
10747 result = c_expr_countof_type (loc: expr_loc, type_name);
10748 }
10749 else
10750 {
10751 in_sizeof--;
10752 result = c_expr_sizeof_type (expr_loc, type_name);
10753 }
10754 }
10755 else
10756 {
10757 expr_loc = c_parser_peek_token (parser)->location;
10758 expr = c_parser_unary_expression (parser);
10759 finish = expr.get_finish ();
10760 Xof_expr:
10761 c_inhibit_evaluation_warnings--;
10762 if (rid == RID_COUNTOF)
10763 in_countof--;
10764 else
10765 in_sizeof--;
10766 mark_exp_read (expr.value);
10767 if (TREE_CODE (expr.value) == COMPONENT_REF
10768 && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
10769 error_at (expr_loc, "%qs applied to a bit-field", op_name);
10770 if (rid == RID_COUNTOF)
10771 result = c_expr_countof_expr (expr_loc, expr);
10772 else
10773 result = c_expr_sizeof_expr (expr_loc, expr);
10774 }
10775 if (finish == UNKNOWN_LOCATION)
10776 finish = start;
10777 set_c_expr_source_range (expr: &result, start, finish);
10778 return result;
10779}
10780
10781/* Parse an alignof expression. */
10782
10783static struct c_expr
10784c_parser_alignof_expression (c_parser *parser)
10785{
10786 struct c_expr expr;
10787 location_t start_loc = c_parser_peek_token (parser)->location;
10788 location_t end_loc;
10789 tree alignof_spelling = c_parser_peek_token (parser)->value;
10790 gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
10791 bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
10792 s2: "_Alignof") == 0
10793 || strcmp (IDENTIFIER_POINTER (alignof_spelling),
10794 s2: "alignof") == 0);
10795 /* A diagnostic is not required for the use of this identifier in
10796 the implementation namespace; only diagnose it for the C11 or C23
10797 spelling because of existing code using the other spellings. */
10798 if (is_c11_alignof)
10799 {
10800 if (flag_isoc99)
10801 pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
10802 alignof_spelling);
10803 else
10804 pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
10805 alignof_spelling);
10806 }
10807 c_parser_consume_token (parser);
10808 c_inhibit_evaluation_warnings++;
10809 in_alignof++;
10810 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
10811 && c_token_starts_compound_literal (token: c_parser_peek_2nd_token (parser)))
10812 {
10813 /* Either __alignof__ ( type-name ) or __alignof__
10814 unary-expression starting with a compound literal. */
10815 location_t loc;
10816 struct c_declspecs *scspecs;
10817 struct c_type_name *type_name;
10818 struct c_expr ret;
10819 matching_parens parens;
10820 parens.consume_open (parser);
10821 loc = c_parser_peek_token (parser)->location;
10822 scspecs = c_parser_compound_literal_scspecs (parser);
10823 type_name = c_parser_type_name (parser, alignas_ok: true);
10824 end_loc = c_parser_peek_token (parser)->location;
10825 parens.skip_until_found_close (parser);
10826 if (type_name == NULL)
10827 {
10828 struct c_expr ret;
10829 c_inhibit_evaluation_warnings--;
10830 in_alignof--;
10831 ret.set_error ();
10832 ret.original_code = ERROR_MARK;
10833 ret.original_type = NULL;
10834 return ret;
10835 }
10836 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
10837 {
10838 expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
10839 type_name,
10840 loc);
10841 goto alignof_expr;
10842 }
10843 /* alignof ( type-name ). */
10844 if (scspecs)
10845 error_at (loc, "storage class specifier in %qE", alignof_spelling);
10846 if (type_name->specs->alignas_p)
10847 error_at (type_name->specs->locations[cdw_alignas],
10848 "alignment specified for type name in %qE",
10849 alignof_spelling);
10850 c_inhibit_evaluation_warnings--;
10851 in_alignof--;
10852 ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
10853 NULL, NULL),
10854 false, is_c11_alignof, 1);
10855 ret.original_code = ERROR_MARK;
10856 ret.original_type = NULL;
10857 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10858 ret.m_decimal = 0;
10859 return ret;
10860 }
10861 else
10862 {
10863 struct c_expr ret;
10864 expr = c_parser_unary_expression (parser);
10865 end_loc = expr.src_range.m_finish;
10866 alignof_expr:
10867 mark_exp_read (expr.value);
10868 c_inhibit_evaluation_warnings--;
10869 in_alignof--;
10870 if (is_c11_alignof)
10871 pedwarn (start_loc,
10872 OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
10873 alignof_spelling);
10874 ret.value = c_alignof_expr (start_loc, expr.value);
10875 ret.original_code = ERROR_MARK;
10876 ret.original_type = NULL;
10877 set_c_expr_source_range (expr: &ret, start: start_loc, finish: end_loc);
10878 ret.m_decimal = 0;
10879 return ret;
10880 }
10881}
10882
10883/* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
10884 expression. */
10885
10886static struct c_expr
10887c_parser_has_attribute_expression (c_parser *parser)
10888{
10889 gcc_assert (c_parser_next_token_is_keyword (parser,
10890 RID_BUILTIN_HAS_ATTRIBUTE));
10891 location_t start = c_parser_peek_token (parser)->location;
10892 c_parser_consume_token (parser);
10893
10894 c_inhibit_evaluation_warnings++;
10895
10896 matching_parens parens;
10897 if (!parens.require_open (parser))
10898 {
10899 c_inhibit_evaluation_warnings--;
10900 in_typeof--;
10901
10902 struct c_expr result;
10903 result.set_error ();
10904 result.original_code = ERROR_MARK;
10905 result.original_type = NULL;
10906 return result;
10907 }
10908
10909 /* Treat the type argument the same way as in typeof for the purposes
10910 of warnings. FIXME: Generalize this so the warning refers to
10911 __builtin_has_attribute rather than typeof. */
10912 in_typeof++;
10913
10914 /* The first operand: one of DECL, EXPR, or TYPE. */
10915 tree oper = NULL_TREE;
10916 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
10917 {
10918 struct c_type_name *tname = c_parser_type_name (parser);
10919 in_typeof--;
10920 if (tname)
10921 {
10922 oper = groktypename (tname, NULL, NULL);
10923 pop_maybe_used (c_type_variably_modified_p (t: oper));
10924 }
10925 }
10926 else
10927 {
10928 struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
10929 c_inhibit_evaluation_warnings--;
10930 in_typeof--;
10931 if (cexpr.value != error_mark_node)
10932 {
10933 mark_exp_read (cexpr.value);
10934 oper = cexpr.value;
10935 tree etype = TREE_TYPE (oper);
10936 bool was_vm = c_type_variably_modified_p (t: etype);
10937 /* This is returned with the type so that when the type is
10938 evaluated, this can be evaluated. */
10939 if (was_vm)
10940 oper = c_fully_fold (oper, false, NULL);
10941 pop_maybe_used (was_vm);
10942 }
10943 }
10944
10945 struct c_expr result;
10946 result.original_code = ERROR_MARK;
10947 result.original_type = NULL;
10948
10949 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
10950 {
10951 /* Consume the closing parenthesis if that's the next token
10952 in the likely case the built-in was invoked with fewer
10953 than two arguments. */
10954 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10955 c_parser_consume_token (parser);
10956 c_inhibit_evaluation_warnings--;
10957 result.set_error ();
10958 return result;
10959 }
10960
10961 bool save_translate_strings_p = parser->translate_strings_p;
10962
10963 location_t atloc = c_parser_peek_token (parser)->location;
10964 /* Parse a single attribute. Require no leading comma and do not
10965 allow empty attributes. */
10966 tree attr = c_parser_gnu_attribute (parser, NULL_TREE, expect_comma: false, empty_ok: false);
10967
10968 parser->translate_strings_p = save_translate_strings_p;
10969
10970 location_t finish = c_parser_peek_token (parser)->location;
10971 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
10972 c_parser_consume_token (parser);
10973 else
10974 {
10975 c_parser_error (parser, gmsgid: "expected identifier");
10976 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
10977
10978 result.set_error ();
10979 return result;
10980 }
10981
10982 if (!attr)
10983 {
10984 error_at (atloc, "expected identifier");
10985 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
10986 msgid: "expected %<)%>");
10987 result.set_error ();
10988 return result;
10989 }
10990
10991 result.original_code = INTEGER_CST;
10992 result.original_type = boolean_type_node;
10993
10994 if (has_attribute (atloc, oper, attr, default_conversion))
10995 result.value = boolean_true_node;
10996 else
10997 result.value = boolean_false_node;
10998
10999 set_c_expr_source_range (expr: &result, start, finish);
11000 result.m_decimal = 0;
11001 return result;
11002}
11003
11004/* Helper function to read arguments of builtins which are interfaces
11005 for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
11006 others. The name of the builtin is passed using BNAME parameter.
11007 Function returns true if there were no errors while parsing and
11008 stores the arguments in CEXPR_LIST. If it returns true,
11009 *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
11010 parenthesis. */
11011static bool
11012c_parser_get_builtin_args (c_parser *parser, const char *bname,
11013 vec<c_expr_t, va_gc> **ret_cexpr_list,
11014 bool choose_expr_p,
11015 location_t *out_close_paren_loc)
11016{
11017 location_t loc = c_parser_peek_token (parser)->location;
11018 vec<c_expr_t, va_gc> *cexpr_list;
11019 c_expr_t expr;
11020 bool saved_force_folding_builtin_constant_p;
11021
11022 *ret_cexpr_list = NULL;
11023 if (c_parser_next_token_is_not (parser, type: CPP_OPEN_PAREN))
11024 {
11025 error_at (loc, "cannot take address of %qs", bname);
11026 return false;
11027 }
11028
11029 c_parser_consume_token (parser);
11030
11031 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11032 {
11033 *out_close_paren_loc = c_parser_peek_token (parser)->location;
11034 c_parser_consume_token (parser);
11035 return true;
11036 }
11037
11038 saved_force_folding_builtin_constant_p
11039 = force_folding_builtin_constant_p;
11040 force_folding_builtin_constant_p |= choose_expr_p;
11041 expr = c_parser_expr_no_commas (parser, NULL);
11042 force_folding_builtin_constant_p
11043 = saved_force_folding_builtin_constant_p;
11044 vec_alloc (v&: cexpr_list, nelems: 1);
11045 vec_safe_push (v&: cexpr_list, obj: expr);
11046 while (c_parser_next_token_is (parser, type: CPP_COMMA))
11047 {
11048 c_parser_consume_token (parser);
11049 if (c_parser_next_token_is (parser, type: CPP_EMBED))
11050 {
11051 c_token *embed = c_parser_peek_token (parser);
11052 tree value = embed->value;
11053 expr.original_code = INTEGER_CST;
11054 expr.original_type = integer_type_node;
11055 expr.value = NULL_TREE;
11056 set_c_expr_source_range (expr: &expr, src_range: embed->get_range ());
11057 expr.m_decimal = 0;
11058 for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
11059 {
11060 expr.value = build_int_cst (integer_type_node,
11061 RAW_DATA_UCHAR_ELT (value, i));
11062 vec_safe_push (v&: cexpr_list, obj: expr);
11063 }
11064 c_parser_consume_token (parser);
11065 continue;
11066 }
11067 expr = c_parser_expr_no_commas (parser, NULL);
11068 vec_safe_push (v&: cexpr_list, obj: expr);
11069 }
11070
11071 *out_close_paren_loc = c_parser_peek_token (parser)->location;
11072 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
11073 return false;
11074
11075 *ret_cexpr_list = cexpr_list;
11076 return true;
11077}
11078
11079/* This represents a single generic-association. */
11080
11081struct c_generic_association
11082{
11083 /* The location of the starting token of the type. */
11084 location_t type_location;
11085 /* The association's type, or NULL_TREE for 'default'. */
11086 tree type;
11087 /* The association's expression. */
11088 struct c_expr expression;
11089};
11090
11091/* Parse a generic-selection. (C11 6.5.1.1).
11092
11093 generic-selection:
11094 _Generic ( generic-controlling-operand , generic-assoc-list )
11095
11096 generic-controlling-operand:
11097 assignment-expression
11098 type-name
11099
11100 (The use of a type-name is new in C2Y.)
11101
11102 generic-assoc-list:
11103 generic-association
11104 generic-assoc-list , generic-association
11105
11106 generic-association:
11107 type-name : assignment-expression
11108 default : assignment-expression
11109*/
11110
11111static struct c_expr
11112c_parser_generic_selection (c_parser *parser)
11113{
11114 struct c_expr selector, error_expr;
11115 tree selector_type;
11116 struct c_generic_association matched_assoc;
11117 int match_found = -1;
11118 location_t generic_loc, selector_loc;
11119
11120 error_expr.original_code = ERROR_MARK;
11121 error_expr.original_type = NULL;
11122 error_expr.set_error ();
11123 matched_assoc.type_location = UNKNOWN_LOCATION;
11124 matched_assoc.type = NULL_TREE;
11125 matched_assoc.expression = error_expr;
11126
11127 gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
11128 generic_loc = c_parser_peek_token (parser)->location;
11129 c_parser_consume_token (parser);
11130 if (flag_isoc99)
11131 pedwarn_c99 (generic_loc, OPT_Wpedantic,
11132 "ISO C99 does not support %<_Generic%>");
11133 else
11134 pedwarn_c99 (generic_loc, OPT_Wpedantic,
11135 "ISO C90 does not support %<_Generic%>");
11136
11137 matching_parens parens;
11138 if (!parens.require_open (parser))
11139 return error_expr;
11140
11141 selector_loc = c_parser_peek_token (parser)->location;
11142 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
11143 {
11144 c_inhibit_evaluation_warnings++;
11145 pedwarn_c23 (selector_loc, OPT_Wpedantic,
11146 "ISO C does not support use of type name as %<_Generic%> "
11147 "controlling operand before C2Y");
11148 struct c_type_name *type = c_parser_type_name (parser);
11149 if (type)
11150 selector_type = groktypename (type, NULL, NULL);
11151 c_inhibit_evaluation_warnings--;
11152 if (!type)
11153 {
11154 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11155 return error_expr;
11156 }
11157 }
11158 else
11159 {
11160 c_inhibit_evaluation_warnings++;
11161 selector = c_parser_expr_no_commas (parser, NULL);
11162 selector = default_function_array_conversion (selector_loc, selector);
11163 c_inhibit_evaluation_warnings--;
11164
11165 if (selector.value == error_mark_node)
11166 {
11167 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11168 return selector;
11169 }
11170 mark_exp_read (selector.value);
11171 selector_type = TREE_TYPE (selector.value);
11172 /* In ISO C terms, rvalues (including the controlling expression
11173 of _Generic) do not have qualified types. */
11174 if (TREE_CODE (selector_type) != ARRAY_TYPE)
11175 selector_type = TYPE_MAIN_VARIANT (selector_type);
11176 /* In ISO C terms, _Noreturn is not part of the type of expressions
11177 such as &abort, but in GCC it is represented internally as a type
11178 qualifier. */
11179 if (FUNCTION_POINTER_TYPE_P (selector_type)
11180 && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
11181 selector_type
11182 = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
11183 }
11184
11185 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11186 {
11187 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11188 return error_expr;
11189 }
11190
11191 auto_vec<c_generic_association> associations;
11192 while (1)
11193 {
11194 struct c_generic_association assoc, *iter;
11195 unsigned int ix;
11196 c_token *token = c_parser_peek_token (parser);
11197
11198 assoc.type_location = token->location;
11199 if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
11200 {
11201 c_parser_consume_token (parser);
11202 assoc.type = NULL_TREE;
11203 }
11204 else
11205 {
11206 struct c_type_name *type_name;
11207
11208 type_name = c_parser_type_name (parser);
11209 if (type_name == NULL)
11210 {
11211 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11212 return error_expr;
11213 }
11214 assoc.type = groktypename (type_name, NULL, NULL);
11215 if (assoc.type == error_mark_node)
11216 {
11217 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11218 return error_expr;
11219 }
11220
11221 if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
11222 pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11223 "ISO C does not support %<_Generic%> association with "
11224 "function type before C2Y");
11225 else if (!COMPLETE_TYPE_P (assoc.type))
11226 pedwarn_c23 (assoc.type_location, OPT_Wpedantic,
11227 "ISO C does not support %<_Generic%> association with "
11228 "incomplete type before C2Y");
11229
11230 if (c_type_variably_modified_p (t: assoc.type))
11231 error_at (assoc.type_location,
11232 "%<_Generic%> association has "
11233 "variable length type");
11234 }
11235
11236 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
11237 {
11238 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11239 return error_expr;
11240 }
11241
11242 bool match = assoc.type == NULL_TREE
11243 || comptypes (assoc.type, selector_type);
11244
11245 if (!match)
11246 c_inhibit_evaluation_warnings++;
11247
11248 assoc.expression = c_parser_expr_no_commas (parser, NULL);
11249
11250 if (!match)
11251 c_inhibit_evaluation_warnings--;
11252
11253 if (assoc.expression.value == error_mark_node)
11254 {
11255 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11256 return error_expr;
11257 }
11258
11259 for (ix = 0; associations.iterate (ix, ptr: &iter); ++ix)
11260 {
11261 if (assoc.type == NULL_TREE)
11262 {
11263 if (iter->type == NULL_TREE)
11264 {
11265 error_at (assoc.type_location,
11266 "duplicate %<default%> case in %<_Generic%>");
11267 inform (iter->type_location, "original %<default%> is here");
11268 }
11269 }
11270 else if (iter->type != NULL_TREE)
11271 {
11272 if (comptypes (assoc.type, iter->type))
11273 {
11274 error_at (assoc.type_location,
11275 "%<_Generic%> specifies two compatible types");
11276 inform (iter->type_location, "compatible type is here");
11277 }
11278 }
11279 }
11280
11281 if (assoc.type == NULL_TREE)
11282 {
11283 if (match_found < 0)
11284 {
11285 matched_assoc = assoc;
11286 match_found = associations.length ();
11287 }
11288 }
11289 else if (match)
11290 {
11291 if (match_found < 0 || matched_assoc.type == NULL_TREE)
11292 {
11293 matched_assoc = assoc;
11294 match_found = associations.length ();
11295 }
11296 else
11297 {
11298 error_at (assoc.type_location,
11299 "%<_Generic%> selector matches multiple associations");
11300 inform (matched_assoc.type_location,
11301 "other match is here");
11302 }
11303 }
11304
11305 associations.safe_push (obj: assoc);
11306
11307 if (c_parser_peek_token (parser)->type != CPP_COMMA)
11308 break;
11309 c_parser_consume_token (parser);
11310 }
11311
11312 unsigned int ix;
11313 struct c_generic_association *iter;
11314 FOR_EACH_VEC_ELT (associations, ix, iter)
11315 if (ix != (unsigned) match_found)
11316 mark_exp_read (iter->expression.value);
11317
11318 if (!parens.require_close (parser))
11319 {
11320 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11321 return error_expr;
11322 }
11323
11324 if (match_found < 0)
11325 {
11326 error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
11327 "compatible with any association",
11328 selector_type);
11329 return error_expr;
11330 }
11331
11332 return matched_assoc.expression;
11333}
11334
11335/* Check the validity of a function pointer argument *EXPR (argument
11336 position POS) to __builtin_tgmath. Return the number of function
11337 arguments if possibly valid; return 0 having reported an error if
11338 not valid. */
11339
11340static unsigned int
11341check_tgmath_function (c_expr *expr, unsigned int pos)
11342{
11343 tree type = TREE_TYPE (expr->value);
11344 if (!FUNCTION_POINTER_TYPE_P (type))
11345 {
11346 error_at (expr->get_location (),
11347 "argument %u of %<__builtin_tgmath%> is not a function pointer",
11348 pos);
11349 return 0;
11350 }
11351 type = TREE_TYPE (type);
11352 if (!prototype_p (type))
11353 {
11354 error_at (expr->get_location (),
11355 "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
11356 return 0;
11357 }
11358 if (stdarg_p (type))
11359 {
11360 error_at (expr->get_location (),
11361 "argument %u of %<__builtin_tgmath%> has variable arguments",
11362 pos);
11363 return 0;
11364 }
11365 unsigned int nargs = 0;
11366 function_args_iterator iter;
11367 tree t;
11368 FOREACH_FUNCTION_ARGS (type, t, iter)
11369 {
11370 if (t == void_type_node)
11371 break;
11372 nargs++;
11373 }
11374 if (nargs == 0)
11375 {
11376 error_at (expr->get_location (),
11377 "argument %u of %<__builtin_tgmath%> has no arguments", pos);
11378 return 0;
11379 }
11380 return nargs;
11381}
11382
11383/* Ways in which a parameter or return value of a type-generic macro
11384 may vary between the different functions the macro may call. */
11385enum tgmath_parm_kind
11386 {
11387 tgmath_fixed, tgmath_real, tgmath_complex
11388 };
11389
11390/* Helper function for c_parser_postfix_expression. Parse predefined
11391 identifiers. */
11392
11393static struct c_expr
11394c_parser_predefined_identifier (c_parser *parser)
11395{
11396 location_t loc = c_parser_peek_token (parser)->location;
11397 switch (c_parser_peek_token (parser)->keyword)
11398 {
11399 case RID_FUNCTION_NAME:
11400 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11401 "identifier", "__FUNCTION__");
11402 break;
11403 case RID_PRETTY_FUNCTION_NAME:
11404 pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
11405 "identifier", "__PRETTY_FUNCTION__");
11406 break;
11407 case RID_C99_FUNCTION_NAME:
11408 pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
11409 "%<__func__%> predefined identifier");
11410 break;
11411 default:
11412 gcc_unreachable ();
11413 }
11414
11415 struct c_expr expr;
11416 expr.original_code = ERROR_MARK;
11417 expr.original_type = NULL;
11418 expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
11419 c_parser_peek_token (parser)->value);
11420 set_c_expr_source_range (expr: &expr, start: loc, finish: loc);
11421 expr.m_decimal = 0;
11422 c_parser_consume_token (parser);
11423 return expr;
11424}
11425
11426/* Check whether the ARRAY_REF has an counted-by object associated with it
11427 through the "counted_by" attribute. */
11428
11429static bool
11430has_counted_by_object (tree array_ref)
11431{
11432 /* Currently, only when the array_ref is an indirect_ref to a call to the
11433 .ACCESS_WITH_SIZE, return true.
11434 More cases can be included later when the counted_by attribute is
11435 extended to other situations. */
11436 if (TREE_CODE (array_ref) == INDIRECT_REF
11437 && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11438 return true;
11439 return false;
11440}
11441
11442/* Get the reference to the counted-by object associated with the ARRAY_REF. */
11443
11444static tree
11445get_counted_by_ref (tree array_ref)
11446{
11447 /* Currently, only when the array_ref is an indirect_ref to a call to the
11448 .ACCESS_WITH_SIZE, get the corresponding counted_by ref.
11449 More cases can be included later when the counted_by attribute is
11450 extended to other situations. */
11451 if (TREE_CODE (array_ref) == INDIRECT_REF
11452 && is_access_with_size_p (TREE_OPERAND (array_ref, 0)))
11453 return CALL_EXPR_ARG (TREE_OPERAND (array_ref, 0), 1);
11454 return NULL_TREE;
11455}
11456
11457/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
11458 C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
11459 call c_parser_postfix_expression_after_paren_type on encountering them.
11460
11461 postfix-expression:
11462 primary-expression
11463 postfix-expression [ expression ]
11464 postfix-expression ( argument-expression-list[opt] )
11465 postfix-expression . identifier
11466 postfix-expression -> identifier
11467 postfix-expression ++
11468 postfix-expression --
11469 ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
11470 ( storage-class-specifiers[opt] type-name ) { initializer-list , }
11471
11472 argument-expression-list:
11473 argument-expression
11474 argument-expression-list , argument-expression
11475
11476 primary-expression:
11477 identifier
11478 constant
11479 string-literal
11480 ( expression )
11481 generic-selection
11482
11483 GNU extensions:
11484
11485 primary-expression:
11486 __func__
11487 (treated as a keyword in GNU C)
11488 __FUNCTION__
11489 __PRETTY_FUNCTION__
11490 ( compound-statement )
11491 __builtin_va_arg ( assignment-expression , type-name )
11492 __builtin_offsetof ( type-name , offsetof-member-designator )
11493 __builtin_choose_expr ( assignment-expression ,
11494 assignment-expression ,
11495 assignment-expression )
11496 __builtin_types_compatible_p ( type-name , type-name )
11497 __builtin_tgmath ( expr-list )
11498 __builtin_complex ( assignment-expression , assignment-expression )
11499 __builtin_shuffle ( assignment-expression , assignment-expression )
11500 __builtin_shuffle ( assignment-expression ,
11501 assignment-expression ,
11502 assignment-expression, )
11503 __builtin_convertvector ( assignment-expression , type-name )
11504 __builtin_assoc_barrier ( assignment-expression )
11505
11506 offsetof-member-designator:
11507 identifier
11508 offsetof-member-designator . identifier
11509 offsetof-member-designator [ expression ]
11510
11511 Objective-C:
11512
11513 primary-expression:
11514 [ objc-receiver objc-message-args ]
11515 @selector ( objc-selector-arg )
11516 @protocol ( identifier )
11517 @encode ( type-name )
11518 objc-string-literal
11519 Classname . identifier
11520*/
11521
11522static struct c_expr
11523c_parser_postfix_expression (c_parser *parser)
11524{
11525 struct c_expr expr, e1;
11526 struct c_type_name *t1, *t2;
11527 location_t loc = c_parser_peek_token (parser)->location;
11528 source_range tok_range = c_parser_peek_token (parser)->get_range ();
11529 expr.original_code = ERROR_MARK;
11530 expr.original_type = NULL;
11531 expr.m_decimal = 0;
11532 switch (c_parser_peek_token (parser)->type)
11533 {
11534 case CPP_NUMBER:
11535 expr.value = c_parser_peek_token (parser)->value;
11536 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11537 loc = c_parser_peek_token (parser)->location;
11538 expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT;
11539 c_parser_consume_token (parser);
11540 if (TREE_CODE (expr.value) == FIXED_CST
11541 && !targetm.fixed_point_supported_p ())
11542 {
11543 error_at (loc, "fixed-point types not supported for this target");
11544 expr.set_error ();
11545 }
11546 break;
11547 case CPP_CHAR:
11548 case CPP_CHAR16:
11549 case CPP_CHAR32:
11550 case CPP_UTF8CHAR:
11551 case CPP_WCHAR:
11552 expr.value = c_parser_peek_token (parser)->value;
11553 /* For the purpose of warning when a pointer is compared with
11554 a zero character constant. */
11555 expr.original_type = char_type_node;
11556 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11557 c_parser_consume_token (parser);
11558 break;
11559 case CPP_STRING:
11560 case CPP_STRING16:
11561 case CPP_STRING32:
11562 case CPP_WSTRING:
11563 case CPP_UTF8STRING:
11564 expr = c_parser_string_literal (parser, translate: parser->translate_strings_p,
11565 wide_ok: true);
11566 break;
11567 case CPP_OBJC_STRING:
11568 gcc_assert (c_dialect_objc ());
11569 expr.value
11570 = objc_build_string_object (c_parser_peek_token (parser)->value);
11571 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11572 c_parser_consume_token (parser);
11573 break;
11574 case CPP_NAME:
11575 switch (c_parser_peek_token (parser)->id_kind)
11576 {
11577 case C_ID_ID:
11578 {
11579 tree id = c_parser_peek_token (parser)->value;
11580 c_parser_consume_token (parser);
11581 expr.value = build_external_ref (loc, id,
11582 (c_parser_peek_token (parser)->type
11583 == CPP_OPEN_PAREN),
11584 &expr.original_type);
11585 set_c_expr_source_range (expr: &expr, src_range: tok_range);
11586 break;
11587 }
11588 case C_ID_CLASSNAME:
11589 {
11590 /* Here we parse the Objective-C 2.0 Class.name dot
11591 syntax. */
11592 tree class_name = c_parser_peek_token (parser)->value;
11593 tree component;
11594 c_parser_consume_token (parser);
11595 gcc_assert (c_dialect_objc ());
11596 if (!c_parser_require (parser, type: CPP_DOT, msgid: "expected %<.%>"))
11597 {
11598 expr.set_error ();
11599 break;
11600 }
11601 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
11602 {
11603 c_parser_error (parser, gmsgid: "expected identifier");
11604 expr.set_error ();
11605 break;
11606 }
11607 c_token *component_tok = c_parser_peek_token (parser);
11608 component = component_tok->value;
11609 location_t end_loc = component_tok->get_finish ();
11610 c_parser_consume_token (parser);
11611 expr.value = objc_build_class_component_ref (class_name,
11612 component);
11613 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
11614 break;
11615 }
11616 default:
11617 c_parser_error (parser, gmsgid: "expected expression");
11618 expr.set_error ();
11619 break;
11620 }
11621 break;
11622 case CPP_OPEN_PAREN:
11623 /* A parenthesized expression, statement expression or compound
11624 literal. */
11625 if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
11626 {
11627 /* A statement expression. */
11628 tree stmt;
11629 location_t brace_loc;
11630 bool save_c_omp_array_section_p = c_omp_array_section_p;
11631 c_parser_consume_token (parser);
11632 brace_loc = c_parser_peek_token (parser)->location;
11633 c_parser_consume_token (parser);
11634 /* If we've not yet started the current function's statement list,
11635 or we're in the parameter scope of an old-style function
11636 declaration, statement expressions are not allowed. */
11637 if (!building_stmt_list_p () || old_style_parameter_scope ())
11638 {
11639 error_at (loc, "braced-group within expression allowed "
11640 "only inside a function");
11641 parser->error = true;
11642 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE, NULL);
11643 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11644 expr.set_error ();
11645 break;
11646 }
11647 c_omp_array_section_p = false;
11648 stmt = c_begin_stmt_expr ();
11649 c_parser_compound_statement_nostart (parser);
11650 location_t close_loc = c_parser_peek_token (parser)->location;
11651 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11652 msgid: "expected %<)%>");
11653 pedwarn (loc, OPT_Wpedantic,
11654 "ISO C forbids braced-groups within expressions");
11655 expr.value = c_finish_stmt_expr (brace_loc, stmt);
11656 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
11657 mark_exp_read (expr.value);
11658 c_omp_array_section_p = save_c_omp_array_section_p;
11659 }
11660 else
11661 {
11662 /* A parenthesized expression. */
11663 location_t loc_open_paren = c_parser_peek_token (parser)->location;
11664 c_parser_consume_token (parser);
11665 expr = c_parser_expression (parser);
11666 if (TREE_CODE (expr.value) == MODIFY_EXPR)
11667 suppress_warning (expr.value, OPT_Wparentheses);
11668 if (expr.original_code != C_MAYBE_CONST_EXPR
11669 && expr.original_code != SIZEOF_EXPR)
11670 expr.original_code = ERROR_MARK;
11671 /* Remember that we saw ( ) around the sizeof. */
11672 if (expr.original_code == SIZEOF_EXPR)
11673 expr.original_code = PAREN_SIZEOF_EXPR;
11674 /* Don't change EXPR.ORIGINAL_TYPE. */
11675 location_t loc_close_paren = c_parser_peek_token (parser)->location;
11676 set_c_expr_source_range (expr: &expr, start: loc_open_paren, finish: loc_close_paren);
11677 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11678 msgid: "expected %<)%>", matching_location: loc_open_paren);
11679 }
11680 break;
11681 case CPP_KEYWORD:
11682 switch (c_parser_peek_token (parser)->keyword)
11683 {
11684 case RID_FUNCTION_NAME:
11685 case RID_PRETTY_FUNCTION_NAME:
11686 case RID_C99_FUNCTION_NAME:
11687 expr = c_parser_predefined_identifier (parser);
11688 break;
11689 case RID_VA_ARG:
11690 {
11691 location_t start_loc = loc;
11692 c_parser_consume_token (parser);
11693 matching_parens parens;
11694 if (!parens.require_open (parser))
11695 {
11696 expr.set_error ();
11697 break;
11698 }
11699 e1 = c_parser_expr_no_commas (parser, NULL);
11700 mark_exp_read (e1.value);
11701 e1.value = c_fully_fold (e1.value, false, NULL);
11702 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11703 {
11704 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11705 expr.set_error ();
11706 break;
11707 }
11708 loc = c_parser_peek_token (parser)->location;
11709 t1 = c_parser_type_name (parser);
11710 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11711 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11712 msgid: "expected %<)%>");
11713 if (t1 == NULL)
11714 {
11715 expr.set_error ();
11716 }
11717 else
11718 {
11719 tree type_expr = NULL_TREE;
11720 expr.value = c_build_va_arg (start_loc, e1.value, loc,
11721 groktypename (t1, &type_expr, NULL));
11722 if (type_expr)
11723 {
11724 expr.value = build2 (C_MAYBE_CONST_EXPR,
11725 TREE_TYPE (expr.value), type_expr,
11726 expr.value);
11727 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
11728 }
11729 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
11730 }
11731 }
11732 break;
11733 case RID_C23_VA_START:
11734 {
11735 c_parser_consume_token (parser);
11736 matching_parens parens;
11737 if (!parens.require_open (parser))
11738 {
11739 expr.set_error ();
11740 break;
11741 }
11742 e1 = c_parser_expr_no_commas (parser, NULL);
11743 e1 = convert_lvalue_to_rvalue (e1.get_location (), e1, true, true);
11744 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11745 {
11746 location_t cloc = c_parser_peek_token (parser)->location;
11747 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11748 {
11749 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11750 expr.set_error ();
11751 break;
11752 }
11753 if (c_parser_next_token_is (parser, type: CPP_NAME)
11754 && c_parser_peek_token (parser)->id_kind == C_ID_ID
11755 && (c_parser_peek_2nd_token (parser)->type
11756 == CPP_CLOSE_PAREN))
11757 {
11758 tree name = c_parser_peek_token (parser)->value;
11759 location_t nloc = c_parser_peek_token (parser)->location;
11760 tree decl = lookup_name (name);
11761 tree last_parm
11762 = tree_last (DECL_ARGUMENTS (current_function_decl));
11763 if (!last_parm || decl != last_parm)
11764 warning_at (nloc, OPT_Wvarargs,
11765 "optional second parameter of %<va_start%> "
11766 "not last named argument");
11767 else if (DECL_REGISTER (decl))
11768 warning_at (nloc, OPT_Wvarargs,
11769 "undefined behavior when second parameter "
11770 "of %<va_start%> is declared with "
11771 "%<register%> storage");
11772 c_parser_consume_token (parser);
11773 }
11774 else
11775 {
11776 unsigned nesting_depth = 0;
11777 location_t sloc = c_parser_peek_token (parser)->location;
11778 location_t eloc = sloc;
11779
11780 /* For va_start (ap,) the ) comes from stdarg.h.
11781 Use location of , in that case, otherwise without
11782 -Wsystem-headers nothing is reported. After all,
11783 the problematic token is the comma in that case. */
11784 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
11785 sloc = eloc = cloc;
11786 while (true)
11787 {
11788 c_token *token = c_parser_peek_token (parser);
11789 if (token->type == CPP_CLOSE_PAREN && !nesting_depth)
11790 break;
11791
11792 if (token->type == CPP_EOF)
11793 break;
11794 if (token->type == CPP_OPEN_PAREN)
11795 ++nesting_depth;
11796 else if (token->type == CPP_CLOSE_PAREN)
11797 --nesting_depth;
11798 eloc = token->location;
11799 c_parser_consume_token (parser);
11800 }
11801 if (sloc != eloc)
11802 sloc = make_location (caret: sloc, start: sloc, finish: eloc);
11803 warning_at (sloc, OPT_Wvarargs,
11804 "%<va_start%> macro used with additional "
11805 "arguments other than identifier of the "
11806 "last named argument");
11807 }
11808 }
11809 parens.skip_until_found_close (parser);
11810 tree fndecl = builtin_decl_explicit (fncode: BUILT_IN_VA_START);
11811 vec<tree, va_gc> *params;
11812 vec_alloc (v&: params, nelems: 2);
11813 params->quick_push (obj: e1.value);
11814 params->quick_push (integer_zero_node);
11815 auto_vec<location_t> arg_loc (2);
11816 arg_loc.quick_push (obj: e1.get_location ());
11817 arg_loc.quick_push (UNKNOWN_LOCATION);
11818 expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
11819 params, NULL);
11820 set_c_expr_source_range (expr: &expr, start: loc,
11821 finish: parser->tokens_buf[0].get_finish ());
11822 expr.m_decimal = 0;
11823 expr.original_code = ERROR_MARK;
11824 expr.original_type = NULL;
11825 release_tree_vector (params);
11826 break;
11827 }
11828 case RID_OFFSETOF:
11829 {
11830 c_parser_consume_token (parser);
11831 matching_parens parens;
11832 if (!parens.require_open (parser))
11833 {
11834 expr.set_error ();
11835 break;
11836 }
11837 t1 = c_parser_type_name (parser);
11838 if (t1 == NULL)
11839 parser->error = true;
11840 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11841 gcc_assert (parser->error);
11842 if (parser->error)
11843 {
11844 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11845 expr.set_error ();
11846 break;
11847 }
11848 tree type = groktypename (t1, NULL, NULL);
11849 tree offsetof_ref;
11850 if (type == error_mark_node)
11851 offsetof_ref = error_mark_node;
11852 else
11853 {
11854 offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
11855 SET_EXPR_LOCATION (offsetof_ref, loc);
11856 }
11857 /* Parse the second argument to __builtin_offsetof. We
11858 must have one identifier, and beyond that we want to
11859 accept sub structure and sub array references. */
11860 if (c_parser_next_token_is (parser, type: CPP_NAME))
11861 {
11862 c_token *comp_tok = c_parser_peek_token (parser);
11863 /* Ignore the counted_by attribute for reference inside
11864 offsetof since the information is not useful at all. */
11865 offsetof_ref
11866 = build_component_ref (loc, offsetof_ref, comp_tok->value,
11867 comp_tok->location, UNKNOWN_LOCATION,
11868 false);
11869 c_parser_consume_token (parser);
11870 while (c_parser_next_token_is (parser, type: CPP_DOT)
11871 || c_parser_next_token_is (parser,
11872 type: CPP_OPEN_SQUARE)
11873 || c_parser_next_token_is (parser,
11874 type: CPP_DEREF))
11875 {
11876 if (c_parser_next_token_is (parser, type: CPP_DEREF))
11877 {
11878 loc = c_parser_peek_token (parser)->location;
11879 offsetof_ref = build_array_ref (loc,
11880 offsetof_ref,
11881 integer_zero_node);
11882 goto do_dot;
11883 }
11884 else if (c_parser_next_token_is (parser, type: CPP_DOT))
11885 {
11886 do_dot:
11887 c_parser_consume_token (parser);
11888 if (c_parser_next_token_is_not (parser,
11889 type: CPP_NAME))
11890 {
11891 c_parser_error (parser, gmsgid: "expected identifier");
11892 break;
11893 }
11894 c_token *comp_tok = c_parser_peek_token (parser);
11895 /* Ignore the counted_by attribute for reference inside
11896 offsetof since the information is not useful. */
11897 offsetof_ref
11898 = build_component_ref (loc, offsetof_ref,
11899 comp_tok->value,
11900 comp_tok->location,
11901 UNKNOWN_LOCATION,
11902 false);
11903 c_parser_consume_token (parser);
11904 }
11905 else
11906 {
11907 struct c_expr ce;
11908 tree idx;
11909 loc = c_parser_peek_token (parser)->location;
11910 c_parser_consume_token (parser);
11911 ce = c_parser_expression (parser);
11912 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
11913 idx = ce.value;
11914 idx = c_fully_fold (idx, false, NULL);
11915 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
11916 msgid: "expected %<]%>");
11917 offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
11918 }
11919 }
11920 }
11921 else
11922 c_parser_error (parser, gmsgid: "expected identifier");
11923 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
11924 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
11925 msgid: "expected %<)%>");
11926 expr.value = fold_offsetof (offsetof_ref);
11927 set_c_expr_source_range (expr: &expr, start: loc, finish: end_loc);
11928 }
11929 break;
11930 case RID_CHOOSE_EXPR:
11931 {
11932 vec<c_expr_t, va_gc> *cexpr_list;
11933 c_expr_t *e1_p, *e2_p, *e3_p;
11934 tree c;
11935 location_t close_paren_loc;
11936
11937 c_parser_consume_token (parser);
11938 if (!c_parser_get_builtin_args (parser,
11939 bname: "__builtin_choose_expr",
11940 ret_cexpr_list: &cexpr_list, choose_expr_p: true,
11941 out_close_paren_loc: &close_paren_loc))
11942 {
11943 expr.set_error ();
11944 break;
11945 }
11946
11947 if (vec_safe_length (v: cexpr_list) != 3)
11948 {
11949 error_at (loc, "wrong number of arguments to "
11950 "%<__builtin_choose_expr%>");
11951 expr.set_error ();
11952 break;
11953 }
11954
11955 e1_p = &(*cexpr_list)[0];
11956 e2_p = &(*cexpr_list)[1];
11957 e3_p = &(*cexpr_list)[2];
11958
11959 c = e1_p->value;
11960 mark_exp_read (e2_p->value);
11961 mark_exp_read (e3_p->value);
11962 if (TREE_CODE (c) != INTEGER_CST
11963 || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
11964 error_at (loc,
11965 "first argument to %<__builtin_choose_expr%> not"
11966 " a constant");
11967 constant_expression_warning (c);
11968 expr = integer_zerop (c) ? *e3_p : *e2_p;
11969 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
11970 break;
11971 }
11972 case RID_TYPES_COMPATIBLE_P:
11973 {
11974 c_parser_consume_token (parser);
11975 matching_parens parens;
11976 if (!parens.require_open (parser))
11977 {
11978 expr.set_error ();
11979 break;
11980 }
11981 t1 = c_parser_type_name (parser);
11982 if (t1 == NULL)
11983 {
11984 expr.set_error ();
11985 break;
11986 }
11987 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
11988 {
11989 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
11990 expr.set_error ();
11991 break;
11992 }
11993 t2 = c_parser_type_name (parser);
11994 if (t2 == NULL)
11995 {
11996 expr.set_error ();
11997 break;
11998 }
11999 location_t close_paren_loc = c_parser_peek_token (parser)->location;
12000 parens.skip_until_found_close (parser);
12001 tree e1, e2;
12002 e1 = groktypename (t1, NULL, NULL);
12003 e2 = groktypename (t2, NULL, NULL);
12004 if (e1 == error_mark_node || e2 == error_mark_node)
12005 {
12006 expr.set_error ();
12007 break;
12008 }
12009
12010 e1 = TYPE_MAIN_VARIANT (e1);
12011 e2 = TYPE_MAIN_VARIANT (e2);
12012
12013 expr.value
12014 = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
12015 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12016 }
12017 break;
12018 case RID_BUILTIN_TGMATH:
12019 {
12020 vec<c_expr_t, va_gc> *cexpr_list;
12021 location_t close_paren_loc;
12022
12023 c_parser_consume_token (parser);
12024 if (!c_parser_get_builtin_args (parser,
12025 bname: "__builtin_tgmath",
12026 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12027 out_close_paren_loc: &close_paren_loc))
12028 {
12029 expr.set_error ();
12030 break;
12031 }
12032
12033 if (vec_safe_length (v: cexpr_list) < 3)
12034 {
12035 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12036 expr.set_error ();
12037 break;
12038 }
12039
12040 unsigned int i;
12041 c_expr_t *p;
12042 FOR_EACH_VEC_ELT (*cexpr_list, i, p)
12043 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12044 unsigned int nargs = check_tgmath_function (expr: &(*cexpr_list)[0], pos: 1);
12045 if (nargs == 0)
12046 {
12047 expr.set_error ();
12048 break;
12049 }
12050 if (vec_safe_length (v: cexpr_list) < nargs)
12051 {
12052 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12053 expr.set_error ();
12054 break;
12055 }
12056 unsigned int num_functions = vec_safe_length (v: cexpr_list) - nargs;
12057 if (num_functions < 2)
12058 {
12059 error_at (loc, "too few arguments to %<__builtin_tgmath%>");
12060 expr.set_error ();
12061 break;
12062 }
12063
12064 /* The first NUM_FUNCTIONS expressions are the function
12065 pointers. The remaining NARGS expressions are the
12066 arguments that are to be passed to one of those
12067 functions, chosen following <tgmath.h> rules. */
12068 for (unsigned int j = 1; j < num_functions; j++)
12069 {
12070 unsigned int this_nargs
12071 = check_tgmath_function (expr: &(*cexpr_list)[j], pos: j + 1);
12072 if (this_nargs == 0)
12073 {
12074 expr.set_error ();
12075 goto out;
12076 }
12077 if (this_nargs != nargs)
12078 {
12079 error_at ((*cexpr_list)[j].get_location (),
12080 "argument %u of %<__builtin_tgmath%> has "
12081 "wrong number of arguments", j + 1);
12082 expr.set_error ();
12083 goto out;
12084 }
12085 }
12086
12087 /* The functions all have the same number of arguments.
12088 Determine whether arguments and return types vary in
12089 ways permitted for <tgmath.h> functions. */
12090 /* The first entry in each of these vectors is for the
12091 return type, subsequent entries for parameter
12092 types. */
12093 auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
12094 auto_vec<tree> parm_first (nargs + 1);
12095 auto_vec<bool> parm_complex (nargs + 1);
12096 auto_vec<bool> parm_varies (nargs + 1);
12097 tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
12098 tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
12099 parm_first.quick_push (obj: first_ret);
12100 parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
12101 parm_varies.quick_push (obj: false);
12102 function_args_iterator iter;
12103 tree t;
12104 unsigned int argpos;
12105 FOREACH_FUNCTION_ARGS (first_type, t, iter)
12106 {
12107 if (t == void_type_node)
12108 break;
12109 parm_first.quick_push (TYPE_MAIN_VARIANT (t));
12110 parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
12111 parm_varies.quick_push (obj: false);
12112 }
12113 for (unsigned int j = 1; j < num_functions; j++)
12114 {
12115 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12116 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12117 if (ret != parm_first[0])
12118 {
12119 parm_varies[0] = true;
12120 if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
12121 && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
12122 {
12123 error_at ((*cexpr_list)[0].get_location (),
12124 "invalid type-generic return type for "
12125 "argument %u of %<__builtin_tgmath%>",
12126 1);
12127 expr.set_error ();
12128 goto out;
12129 }
12130 if (!SCALAR_FLOAT_TYPE_P (ret)
12131 && !COMPLEX_FLOAT_TYPE_P (ret))
12132 {
12133 error_at ((*cexpr_list)[j].get_location (),
12134 "invalid type-generic return type for "
12135 "argument %u of %<__builtin_tgmath%>",
12136 j + 1);
12137 expr.set_error ();
12138 goto out;
12139 }
12140 }
12141 if (TREE_CODE (ret) == COMPLEX_TYPE)
12142 parm_complex[0] = true;
12143 argpos = 1;
12144 FOREACH_FUNCTION_ARGS (type, t, iter)
12145 {
12146 if (t == void_type_node)
12147 break;
12148 t = TYPE_MAIN_VARIANT (t);
12149 if (t != parm_first[argpos])
12150 {
12151 parm_varies[argpos] = true;
12152 if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
12153 && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
12154 {
12155 error_at ((*cexpr_list)[0].get_location (),
12156 "invalid type-generic type for "
12157 "argument %u of argument %u of "
12158 "%<__builtin_tgmath%>", argpos, 1);
12159 expr.set_error ();
12160 goto out;
12161 }
12162 if (!SCALAR_FLOAT_TYPE_P (t)
12163 && !COMPLEX_FLOAT_TYPE_P (t))
12164 {
12165 error_at ((*cexpr_list)[j].get_location (),
12166 "invalid type-generic type for "
12167 "argument %u of argument %u of "
12168 "%<__builtin_tgmath%>", argpos, j + 1);
12169 expr.set_error ();
12170 goto out;
12171 }
12172 }
12173 if (TREE_CODE (t) == COMPLEX_TYPE)
12174 parm_complex[argpos] = true;
12175 argpos++;
12176 }
12177 }
12178 enum tgmath_parm_kind max_variation = tgmath_fixed;
12179 for (unsigned int j = 0; j <= nargs; j++)
12180 {
12181 enum tgmath_parm_kind this_kind;
12182 if (parm_varies[j])
12183 {
12184 if (parm_complex[j])
12185 max_variation = this_kind = tgmath_complex;
12186 else
12187 {
12188 this_kind = tgmath_real;
12189 if (max_variation != tgmath_complex)
12190 max_variation = tgmath_real;
12191 }
12192 }
12193 else
12194 this_kind = tgmath_fixed;
12195 parm_kind.quick_push (obj: this_kind);
12196 }
12197 if (max_variation == tgmath_fixed)
12198 {
12199 error_at (loc, "function arguments of %<__builtin_tgmath%> "
12200 "all have the same type");
12201 expr.set_error ();
12202 break;
12203 }
12204
12205 /* Identify a parameter (not the return type) that varies,
12206 including with complex types if any variation includes
12207 complex types; there must be at least one such
12208 parameter. */
12209 unsigned int tgarg = 0;
12210 for (unsigned int j = 1; j <= nargs; j++)
12211 if (parm_kind[j] == max_variation)
12212 {
12213 tgarg = j;
12214 break;
12215 }
12216 if (tgarg == 0)
12217 {
12218 error_at (loc, "function arguments of %<__builtin_tgmath%> "
12219 "lack type-generic parameter");
12220 expr.set_error ();
12221 break;
12222 }
12223
12224 /* Determine the type of the relevant parameter for each
12225 function. */
12226 auto_vec<tree> tg_type (num_functions);
12227 for (unsigned int j = 0; j < num_functions; j++)
12228 {
12229 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12230 argpos = 1;
12231 FOREACH_FUNCTION_ARGS (type, t, iter)
12232 {
12233 if (argpos == tgarg)
12234 {
12235 tg_type.quick_push (TYPE_MAIN_VARIANT (t));
12236 break;
12237 }
12238 argpos++;
12239 }
12240 }
12241
12242 /* Verify that the corresponding types are different for
12243 all the listed functions. Also determine whether all
12244 the types are complex, whether all the types are
12245 standard or binary, and whether all the types are
12246 decimal. */
12247 bool all_complex = true;
12248 bool all_binary = true;
12249 bool all_decimal = true;
12250 hash_set<tree> tg_types;
12251 FOR_EACH_VEC_ELT (tg_type, i, t)
12252 {
12253 if (TREE_CODE (t) == COMPLEX_TYPE)
12254 all_decimal = false;
12255 else
12256 {
12257 all_complex = false;
12258 if (DECIMAL_FLOAT_TYPE_P (t))
12259 all_binary = false;
12260 else
12261 all_decimal = false;
12262 }
12263 if (tg_types.add (k: t))
12264 {
12265 error_at ((*cexpr_list)[i].get_location (),
12266 "duplicate type-generic parameter type for "
12267 "function argument %u of %<__builtin_tgmath%>",
12268 i + 1);
12269 expr.set_error ();
12270 goto out;
12271 }
12272 }
12273
12274 /* Verify that other parameters and the return type whose
12275 types vary have their types varying in the correct
12276 way. */
12277 for (unsigned int j = 0; j < num_functions; j++)
12278 {
12279 tree exp_type = tg_type[j];
12280 tree exp_real_type = exp_type;
12281 if (TREE_CODE (exp_type) == COMPLEX_TYPE)
12282 exp_real_type = TREE_TYPE (exp_type);
12283 tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
12284 tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
12285 if ((parm_kind[0] == tgmath_complex && ret != exp_type)
12286 || (parm_kind[0] == tgmath_real && ret != exp_real_type))
12287 {
12288 error_at ((*cexpr_list)[j].get_location (),
12289 "bad return type for function argument %u "
12290 "of %<__builtin_tgmath%>", j + 1);
12291 expr.set_error ();
12292 goto out;
12293 }
12294 argpos = 1;
12295 FOREACH_FUNCTION_ARGS (type, t, iter)
12296 {
12297 if (t == void_type_node)
12298 break;
12299 t = TYPE_MAIN_VARIANT (t);
12300 if ((parm_kind[argpos] == tgmath_complex
12301 && t != exp_type)
12302 || (parm_kind[argpos] == tgmath_real
12303 && t != exp_real_type))
12304 {
12305 error_at ((*cexpr_list)[j].get_location (),
12306 "bad type for argument %u of "
12307 "function argument %u of "
12308 "%<__builtin_tgmath%>", argpos, j + 1);
12309 expr.set_error ();
12310 goto out;
12311 }
12312 argpos++;
12313 }
12314 }
12315
12316 /* The functions listed are a valid set of functions for a
12317 <tgmath.h> macro to select between. Identify the
12318 matching function, if any. First, the argument types
12319 must be combined following <tgmath.h> rules. Integer
12320 types are treated as _Decimal64 if any type-generic
12321 argument is decimal, or if the only alternatives for
12322 type-generic arguments are of decimal types, and are
12323 otherwise treated as _Float32x (or _Complex _Float32x
12324 for complex integer types) if any type-generic argument
12325 has _FloatNx type, otherwise as double (or _Complex
12326 double for complex integer types). After that
12327 adjustment, types are combined following the usual
12328 arithmetic conversions. If the function only accepts
12329 complex arguments, a complex type is produced. */
12330 bool arg_complex = all_complex;
12331 bool arg_binary = all_binary;
12332 bool arg_int_decimal = all_decimal;
12333 bool arg_int_floatnx = false;
12334 bool arg_int_decimalx = false;
12335 for (unsigned int j = 1; j <= nargs; j++)
12336 {
12337 if (parm_kind[j] == tgmath_fixed)
12338 continue;
12339 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12340 tree type = TREE_TYPE (ce->value);
12341 if (!INTEGRAL_TYPE_P (type)
12342 && !SCALAR_FLOAT_TYPE_P (type)
12343 && TREE_CODE (type) != COMPLEX_TYPE)
12344 {
12345 error_at (ce->get_location (),
12346 "invalid type of argument %u of type-generic "
12347 "function", j);
12348 expr.set_error ();
12349 goto out;
12350 }
12351 if (DECIMAL_FLOAT_TYPE_P (type))
12352 {
12353 arg_int_decimal = true;
12354 if (all_complex)
12355 {
12356 error_at (ce->get_location (),
12357 "decimal floating-point argument %u to "
12358 "complex-only type-generic function", j);
12359 expr.set_error ();
12360 goto out;
12361 }
12362 else if (all_binary)
12363 {
12364 error_at (ce->get_location (),
12365 "decimal floating-point argument %u to "
12366 "binary-only type-generic function", j);
12367 expr.set_error ();
12368 goto out;
12369 }
12370 else if (arg_complex)
12371 {
12372 error_at (ce->get_location (),
12373 "both complex and decimal floating-point "
12374 "arguments to type-generic function");
12375 expr.set_error ();
12376 goto out;
12377 }
12378 else if (arg_binary)
12379 {
12380 error_at (ce->get_location (),
12381 "both binary and decimal floating-point "
12382 "arguments to type-generic function");
12383 expr.set_error ();
12384 goto out;
12385 }
12386 }
12387 else if (TREE_CODE (type) == COMPLEX_TYPE)
12388 {
12389 arg_complex = true;
12390 if (COMPLEX_FLOAT_TYPE_P (type))
12391 arg_binary = true;
12392 if (all_decimal)
12393 {
12394 error_at (ce->get_location (),
12395 "complex argument %u to "
12396 "decimal-only type-generic function", j);
12397 expr.set_error ();
12398 goto out;
12399 }
12400 else if (arg_int_decimal)
12401 {
12402 error_at (ce->get_location (),
12403 "both complex and decimal floating-point "
12404 "arguments to type-generic function");
12405 expr.set_error ();
12406 goto out;
12407 }
12408 }
12409 else if (SCALAR_FLOAT_TYPE_P (type))
12410 {
12411 arg_binary = true;
12412 if (all_decimal)
12413 {
12414 error_at (ce->get_location (),
12415 "binary argument %u to "
12416 "decimal-only type-generic function", j);
12417 expr.set_error ();
12418 goto out;
12419 }
12420 else if (arg_int_decimal)
12421 {
12422 error_at (ce->get_location (),
12423 "both binary and decimal floating-point "
12424 "arguments to type-generic function");
12425 expr.set_error ();
12426 goto out;
12427 }
12428 }
12429 tree rtype = TYPE_MAIN_VARIANT (type);
12430 if (TREE_CODE (rtype) == COMPLEX_TYPE)
12431 rtype = TREE_TYPE (rtype);
12432 if (SCALAR_FLOAT_TYPE_P (rtype))
12433 for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++)
12434 if (rtype == FLOATNX_TYPE_NODE (j))
12435 {
12436 arg_int_floatnx = true;
12437 break;
12438 }
12439 if (rtype == dfloat64x_type_node)
12440 arg_int_decimalx = true;
12441 }
12442 tree arg_real = NULL_TREE;
12443 for (unsigned int j = 1; j <= nargs; j++)
12444 {
12445 if (parm_kind[j] == tgmath_fixed)
12446 continue;
12447 c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
12448 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
12449 if (TREE_CODE (type) == COMPLEX_TYPE)
12450 type = TREE_TYPE (type);
12451 if (INTEGRAL_TYPE_P (type))
12452 type = (arg_int_decimalx
12453 ? dfloat64x_type_node
12454 : arg_int_floatnx
12455 ? float32x_type_node
12456 : arg_int_decimal
12457 ? dfloat64_type_node
12458 : double_type_node);
12459 if (arg_real == NULL_TREE)
12460 arg_real = type;
12461 else
12462 arg_real = common_type (arg_real, type);
12463 if (arg_real == error_mark_node)
12464 {
12465 expr.set_error ();
12466 goto out;
12467 }
12468 }
12469 tree arg_type = (arg_complex
12470 ? build_complex_type (arg_real)
12471 : arg_real);
12472
12473 /* Look for a function to call with type-generic parameter
12474 type ARG_TYPE. */
12475 c_expr_t *fn = NULL;
12476 for (unsigned int j = 0; j < num_functions; j++)
12477 {
12478 if (tg_type[j] == arg_type)
12479 {
12480 fn = &(*cexpr_list)[j];
12481 break;
12482 }
12483 }
12484 if (fn == NULL
12485 && parm_kind[0] == tgmath_fixed
12486 && SCALAR_FLOAT_TYPE_P (parm_first[0]))
12487 {
12488 /* Presume this is a macro that rounds its result to a
12489 narrower type, and look for the first function with
12490 at least the range and precision of the argument
12491 type. */
12492 for (unsigned int j = 0; j < num_functions; j++)
12493 {
12494 if (arg_complex
12495 != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
12496 continue;
12497 tree real_tg_type = (arg_complex
12498 ? TREE_TYPE (tg_type[j])
12499 : tg_type[j]);
12500 if (DECIMAL_FLOAT_TYPE_P (arg_real)
12501 != DECIMAL_FLOAT_TYPE_P (real_tg_type))
12502 continue;
12503 scalar_float_mode arg_mode
12504 = SCALAR_FLOAT_TYPE_MODE (arg_real);
12505 scalar_float_mode tg_mode
12506 = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
12507 const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
12508 const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
12509 if (arg_fmt->b == tg_fmt->b
12510 && arg_fmt->p <= tg_fmt->p
12511 && arg_fmt->emax <= tg_fmt->emax
12512 && (arg_fmt->emin - arg_fmt->p
12513 >= tg_fmt->emin - tg_fmt->p))
12514 {
12515 fn = &(*cexpr_list)[j];
12516 break;
12517 }
12518 }
12519 }
12520 if (fn == NULL)
12521 {
12522 error_at (loc, "no matching function for type-generic call");
12523 expr.set_error ();
12524 break;
12525 }
12526
12527 /* Construct a call to FN. */
12528 vec<tree, va_gc> *args;
12529 vec_alloc (v&: args, nelems: nargs);
12530 vec<tree, va_gc> *origtypes;
12531 vec_alloc (v&: origtypes, nelems: nargs);
12532 auto_vec<location_t> arg_loc (nargs);
12533 for (unsigned int j = 0; j < nargs; j++)
12534 {
12535 c_expr_t *ce = &(*cexpr_list)[num_functions + j];
12536 args->quick_push (obj: ce->value);
12537 arg_loc.quick_push (obj: ce->get_location ());
12538 origtypes->quick_push (obj: ce->original_type);
12539 }
12540 expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
12541 args, origtypes);
12542 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12543 break;
12544 }
12545 case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
12546 {
12547 vec<c_expr_t, va_gc> *cexpr_list;
12548 c_expr_t *e2_p;
12549 tree chain_value;
12550 location_t close_paren_loc;
12551
12552 c_parser_consume_token (parser);
12553 if (!c_parser_get_builtin_args (parser,
12554 bname: "__builtin_call_with_static_chain",
12555 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12556 out_close_paren_loc: &close_paren_loc))
12557 {
12558 expr.set_error ();
12559 break;
12560 }
12561 if (vec_safe_length (v: cexpr_list) != 2)
12562 {
12563 error_at (loc, "wrong number of arguments to "
12564 "%<__builtin_call_with_static_chain%>");
12565 expr.set_error ();
12566 break;
12567 }
12568
12569 expr = (*cexpr_list)[0];
12570 e2_p = &(*cexpr_list)[1];
12571 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12572 chain_value = e2_p->value;
12573 mark_exp_read (chain_value);
12574
12575 if (TREE_CODE (expr.value) != CALL_EXPR)
12576 error_at (loc, "first argument to "
12577 "%<__builtin_call_with_static_chain%> "
12578 "must be a call expression");
12579 else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
12580 error_at (loc, "second argument to "
12581 "%<__builtin_call_with_static_chain%> "
12582 "must be a pointer type");
12583 else
12584 CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
12585 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12586 break;
12587 }
12588 case RID_BUILTIN_COMPLEX:
12589 {
12590 vec<c_expr_t, va_gc> *cexpr_list;
12591 c_expr_t *e1_p, *e2_p;
12592 location_t close_paren_loc;
12593
12594 c_parser_consume_token (parser);
12595 if (!c_parser_get_builtin_args (parser,
12596 bname: "__builtin_complex",
12597 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12598 out_close_paren_loc: &close_paren_loc))
12599 {
12600 expr.set_error ();
12601 break;
12602 }
12603
12604 if (vec_safe_length (v: cexpr_list) != 2)
12605 {
12606 error_at (loc, "wrong number of arguments to "
12607 "%<__builtin_complex%>");
12608 expr.set_error ();
12609 break;
12610 }
12611
12612 e1_p = &(*cexpr_list)[0];
12613 e2_p = &(*cexpr_list)[1];
12614
12615 *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
12616 if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
12617 e1_p->value = convert (TREE_TYPE (e1_p->value),
12618 TREE_OPERAND (e1_p->value, 0));
12619 *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
12620 if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
12621 e2_p->value = convert (TREE_TYPE (e2_p->value),
12622 TREE_OPERAND (e2_p->value, 0));
12623 if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12624 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
12625 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
12626 || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
12627 {
12628 error_at (loc, "%<__builtin_complex%> operand "
12629 "not of real binary floating-point type");
12630 expr.set_error ();
12631 break;
12632 }
12633 if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
12634 != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
12635 {
12636 error_at (loc,
12637 "%<__builtin_complex%> operands of different types");
12638 expr.set_error ();
12639 break;
12640 }
12641 pedwarn_c90 (loc, OPT_Wpedantic,
12642 "ISO C90 does not support complex types");
12643 expr.value = build2_loc (loc, code: COMPLEX_EXPR,
12644 type: build_complex_type
12645 (TYPE_MAIN_VARIANT
12646 (TREE_TYPE (e1_p->value))),
12647 arg0: e1_p->value, arg1: e2_p->value);
12648 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12649 break;
12650 }
12651 case RID_BUILTIN_COUNTED_BY_REF:
12652 {
12653 vec<c_expr_t, va_gc> *cexpr_list;
12654 c_expr_t *e_p;
12655 location_t close_paren_loc;
12656
12657 c_parser_consume_token (parser);
12658 if (!c_parser_get_builtin_args (parser,
12659 bname: "__builtin_counted_by_ref",
12660 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12661 out_close_paren_loc: &close_paren_loc))
12662 {
12663 expr.set_error ();
12664 break;
12665 }
12666 if (vec_safe_length (v: cexpr_list) != 1)
12667 {
12668 error_at (loc, "wrong number of arguments to "
12669 "%<__builtin_counted_by_ref%>");
12670 expr.set_error ();
12671 break;
12672 }
12673
12674 e_p = &(*cexpr_list)[0];
12675 tree ref = e_p->value;
12676
12677 if (TREE_CODE (TREE_TYPE (ref)) != ARRAY_TYPE)
12678 {
12679 error_at (loc, "the argument to %<__builtin_counted_by_ref%>"
12680 " must be an array");
12681 expr.set_error ();
12682 break;
12683 }
12684
12685 /* If the array ref is inside TYPEOF or ALIGNOF, the call to
12686 .ACCESS_WITH_SIZE was not generated by the routine
12687 build_component_ref by default, we should generate it here. */
12688 if ((in_typeof || in_alignof) && TREE_CODE (ref) == COMPONENT_REF)
12689 ref = handle_counted_by_for_component_ref (loc, ref);
12690
12691 if (has_counted_by_object (array_ref: ref))
12692 expr.value = get_counted_by_ref (array_ref: ref);
12693 else
12694 expr.value = null_pointer_node;
12695
12696 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12697 break;
12698 }
12699 case RID_BUILTIN_SHUFFLE:
12700 {
12701 vec<c_expr_t, va_gc> *cexpr_list;
12702 unsigned int i;
12703 c_expr_t *p;
12704 location_t close_paren_loc;
12705
12706 c_parser_consume_token (parser);
12707 if (!c_parser_get_builtin_args (parser,
12708 bname: "__builtin_shuffle",
12709 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12710 out_close_paren_loc: &close_paren_loc))
12711 {
12712 expr.set_error ();
12713 break;
12714 }
12715
12716 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12717 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12718
12719 if (vec_safe_length (v: cexpr_list) == 2)
12720 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12721 NULL_TREE,
12722 (*cexpr_list)[1].value);
12723
12724 else if (vec_safe_length (v: cexpr_list) == 3)
12725 expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
12726 (*cexpr_list)[1].value,
12727 (*cexpr_list)[2].value);
12728 else
12729 {
12730 error_at (loc, "wrong number of arguments to "
12731 "%<__builtin_shuffle%>");
12732 expr.set_error ();
12733 }
12734 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12735 break;
12736 }
12737 case RID_BUILTIN_SHUFFLEVECTOR:
12738 {
12739 vec<c_expr_t, va_gc> *cexpr_list;
12740 unsigned int i;
12741 c_expr_t *p;
12742 location_t close_paren_loc;
12743
12744 c_parser_consume_token (parser);
12745 if (!c_parser_get_builtin_args (parser,
12746 bname: "__builtin_shufflevector",
12747 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12748 out_close_paren_loc: &close_paren_loc))
12749 {
12750 expr.set_error ();
12751 break;
12752 }
12753
12754 FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
12755 *p = convert_lvalue_to_rvalue (loc, *p, true, true);
12756
12757 if (vec_safe_length (v: cexpr_list) < 3)
12758 {
12759 error_at (loc, "wrong number of arguments to "
12760 "%<__builtin_shuffle%>");
12761 expr.set_error ();
12762 }
12763 else
12764 {
12765 auto_vec<tree, 16> mask;
12766 for (i = 2; i < cexpr_list->length (); ++i)
12767 mask.safe_push (obj: (*cexpr_list)[i].value);
12768 expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
12769 (*cexpr_list)[1].value,
12770 mask);
12771 }
12772 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
12773 break;
12774 }
12775 case RID_BUILTIN_CONVERTVECTOR:
12776 {
12777 location_t start_loc = loc;
12778 c_parser_consume_token (parser);
12779 matching_parens parens;
12780 if (!parens.require_open (parser))
12781 {
12782 expr.set_error ();
12783 break;
12784 }
12785 e1 = c_parser_expr_no_commas (parser, NULL);
12786 mark_exp_read (e1.value);
12787 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
12788 {
12789 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
12790 expr.set_error ();
12791 break;
12792 }
12793 loc = c_parser_peek_token (parser)->location;
12794 t1 = c_parser_type_name (parser);
12795 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12796 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
12797 msgid: "expected %<)%>");
12798 if (t1 == NULL)
12799 expr.set_error ();
12800 else
12801 {
12802 tree type_expr = NULL_TREE;
12803 expr.value = c_build_vec_convert (start_loc, e1.value, loc,
12804 groktypename (t1, &type_expr,
12805 NULL));
12806 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
12807 }
12808 }
12809 break;
12810 case RID_BUILTIN_ASSOC_BARRIER:
12811 {
12812 location_t start_loc = loc;
12813 c_parser_consume_token (parser);
12814 matching_parens parens;
12815 if (!parens.require_open (parser))
12816 {
12817 expr.set_error ();
12818 break;
12819 }
12820 e1 = c_parser_expr_no_commas (parser, NULL);
12821 mark_exp_read (e1.value);
12822 location_t end_loc = c_parser_peek_token (parser)->get_finish ();
12823 parens.skip_until_found_close (parser);
12824 expr = parser_build_unary_op (loc, PAREN_EXPR, e1);
12825 set_c_expr_source_range (expr: &expr, start: start_loc, finish: end_loc);
12826 }
12827 break;
12828 case RID_BUILTIN_STDC:
12829 {
12830 vec<c_expr_t, va_gc> *cexpr_list;
12831 c_expr_t *arg_p;
12832 location_t close_paren_loc;
12833 enum c_builtin_stdc {
12834 C_BUILTIN_STDC_BIT_CEIL,
12835 C_BUILTIN_STDC_BIT_FLOOR,
12836 C_BUILTIN_STDC_BIT_WIDTH,
12837 C_BUILTIN_STDC_COUNT_ONES,
12838 C_BUILTIN_STDC_COUNT_ZEROS,
12839 C_BUILTIN_STDC_FIRST_LEADING_ONE,
12840 C_BUILTIN_STDC_FIRST_LEADING_ZERO,
12841 C_BUILTIN_STDC_FIRST_TRAILING_ONE,
12842 C_BUILTIN_STDC_FIRST_TRAILING_ZERO,
12843 C_BUILTIN_STDC_HAS_SINGLE_BIT,
12844 C_BUILTIN_STDC_LEADING_ONES,
12845 C_BUILTIN_STDC_LEADING_ZEROS,
12846 C_BUILTIN_STDC_ROTATE_LEFT,
12847 C_BUILTIN_STDC_ROTATE_RIGHT,
12848 C_BUILTIN_STDC_TRAILING_ONES,
12849 C_BUILTIN_STDC_TRAILING_ZEROS,
12850 C_BUILTIN_STDC_MAX
12851 } stdc_rid = C_BUILTIN_STDC_MAX;
12852 const char *name
12853 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
12854 unsigned num_args = 1;
12855 switch (name[sizeof ("__builtin_stdc_") - 1])
12856 {
12857 case 'b':
12858 switch (name[sizeof ("__builtin_stdc_bit_") - 1])
12859 {
12860 case 'c':
12861 stdc_rid = C_BUILTIN_STDC_BIT_CEIL;
12862 break;
12863 case 'f':
12864 stdc_rid = C_BUILTIN_STDC_BIT_FLOOR;
12865 break;
12866 default:
12867 stdc_rid = C_BUILTIN_STDC_BIT_WIDTH;
12868 break;
12869 }
12870 break;
12871 case 'c':
12872 if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o')
12873 stdc_rid = C_BUILTIN_STDC_COUNT_ONES;
12874 else
12875 stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS;
12876 break;
12877 case 'f':
12878 switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1])
12879 {
12880 case 'n':
12881 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE;
12882 break;
12883 case 'e':
12884 stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO;
12885 break;
12886 case 'o':
12887 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE;
12888 break;
12889 default:
12890 stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO;
12891 break;
12892 }
12893 break;
12894 case 'h':
12895 stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT;
12896 break;
12897 case 'l':
12898 if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o')
12899 stdc_rid = C_BUILTIN_STDC_LEADING_ONES;
12900 else
12901 stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS;
12902 break;
12903 case 'r':
12904 if (name[sizeof ("__builtin_stdc_rotate_") - 1] == 'l')
12905 stdc_rid = C_BUILTIN_STDC_ROTATE_LEFT;
12906 else
12907 stdc_rid = C_BUILTIN_STDC_ROTATE_RIGHT;
12908 num_args = 2;
12909 break;
12910 case 't':
12911 if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o')
12912 stdc_rid = C_BUILTIN_STDC_TRAILING_ONES;
12913 else
12914 stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS;
12915 break;
12916 }
12917 gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX);
12918
12919 c_parser_consume_token (parser);
12920 if (!c_parser_get_builtin_args (parser, bname: name,
12921 ret_cexpr_list: &cexpr_list, choose_expr_p: false,
12922 out_close_paren_loc: &close_paren_loc))
12923 {
12924 expr.set_error ();
12925 break;
12926 }
12927
12928 if (vec_safe_length (v: cexpr_list) != num_args)
12929 {
12930 error_at (loc, "wrong number of arguments to %qs", name);
12931 expr.set_error ();
12932 break;
12933 }
12934
12935 arg_p = &(*cexpr_list)[0];
12936 *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
12937 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
12938 {
12939 error_at (loc, "%qs operand not an integral type", name);
12940 expr.set_error ();
12941 break;
12942 }
12943 if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
12944 {
12945 error_at (loc, "argument %u in call to function "
12946 "%qs has enumerated type", 1, name);
12947 expr.set_error ();
12948 break;
12949 }
12950 if (TREE_CODE (TREE_TYPE (arg_p->value)) == BOOLEAN_TYPE)
12951 {
12952 error_at (loc, "argument %u in call to function "
12953 "%qs has boolean type", 1, name);
12954 expr.set_error ();
12955 break;
12956 }
12957 if (!TYPE_UNSIGNED (TREE_TYPE (arg_p->value)))
12958 {
12959 error_at (loc, "argument 1 in call to function "
12960 "%qs has signed type", name);
12961 expr.set_error ();
12962 break;
12963 }
12964 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_p->value))
12965 == char_type_node)
12966 {
12967 error_at (loc, "argument 1 in call to function "
12968 "%qs has %<char%> type", name);
12969 expr.set_error ();
12970 break;
12971 }
12972 tree arg = arg_p->value;
12973 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg));
12974 /* Expand:
12975 __builtin_stdc_leading_zeros (arg) as
12976 (unsigned int) __builtin_clzg (arg, prec)
12977 __builtin_stdc_leading_ones (arg) as
12978 (unsigned int) __builtin_clzg ((type) ~arg, prec)
12979 __builtin_stdc_trailing_zeros (arg) as
12980 (unsigned int) __builtin_ctzg (arg, prec)
12981 __builtin_stdc_trailing_ones (arg) as
12982 (unsigned int) __builtin_ctzg ((type) ~arg, prec)
12983 __builtin_stdc_first_leading_zero (arg) as
12984 __builtin_clzg ((type) ~arg, -1) + 1U
12985 __builtin_stdc_first_leading_one (arg) as
12986 __builtin_clzg (arg, -1) + 1U
12987 __builtin_stdc_first_trailing_zero (arg) as
12988 __builtin_ctzg ((type) ~arg, -1) + 1U
12989 __builtin_stdc_first_trailing_one (arg) as
12990 __builtin_ctzg (arg, -1) + 1U
12991 __builtin_stdc_count_zeros (arg) as
12992 (unsigned int) __builtin_popcountg ((type) ~arg)
12993 __builtin_stdc_count_ones (arg) as
12994 (unsigned int) __builtin_popcountg (arg)
12995 __builtin_stdc_has_single_bit (arg) as
12996 (_Bool) (__builtin_popcountg (arg) == 1)
12997 __builtin_stdc_bit_width (arg) as
12998 (unsigned int) (prec - __builtin_clzg (arg, prec))
12999 __builtin_stdc_bit_floor (arg) as
13000 arg == 0 ? (type) 0
13001 : (type) 1 << (prec - 1 - __builtin_clzg (arg))
13002 __builtin_stdc_bit_ceil (arg) as
13003 arg <= 1 ? (type) 1
13004 : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1))
13005 without evaluating arg multiple times, type being
13006 __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */
13007 int prec = TYPE_PRECISION (type);
13008 if (num_args == 2)
13009 {
13010 /* Expand:
13011 __builtin_stdc_rotate_left (arg1, arg2) as
13012 arg1 r<< (arg2 % prec)
13013 __builtin_stdc_rotate_right (arg1, arg2) as
13014 arg1 r>> (arg2 % prec). */
13015 arg_p = &(*cexpr_list)[1];
13016 *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true);
13017 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value)))
13018 {
13019 error_at (loc, "%qs operand not an integral type", name);
13020 expr.set_error ();
13021 break;
13022 }
13023 if (TREE_CODE (TREE_TYPE (arg_p->value)) == ENUMERAL_TYPE)
13024 {
13025 error_at (loc, "argument %u in call to function "
13026 "%qs has enumerated type", 2, name);
13027 expr.set_error ();
13028 break;
13029 }
13030 tree arg1 = save_expr (arg);
13031 tree arg2 = save_expr (arg_p->value);
13032 tree_code code;
13033 if (stdc_rid == C_BUILTIN_STDC_ROTATE_LEFT)
13034 code = LROTATE_EXPR;
13035 else
13036 code = RROTATE_EXPR;
13037
13038 if (TREE_CODE (arg2) == INTEGER_CST
13039 && tree_int_cst_sgn (arg2) < 0)
13040 warning_at (loc, OPT_Wshift_count_negative,
13041 "rotate count is negative");
13042
13043 tree instrument_expr = NULL_TREE;
13044 if (sanitize_flags_p (flag: SANITIZE_SHIFT))
13045 instrument_expr = ubsan_instrument_shift (loc, code,
13046 arg1, arg2);
13047
13048 /* Promote arg2 to unsigned just so that we don't
13049 need to deal with arg2 type not being able to represent
13050 prec. In the end gimplification uses unsigned int
13051 for all shifts/rotates anyway. */
13052 if (TYPE_PRECISION (TREE_TYPE (arg2))
13053 < TYPE_PRECISION (integer_type_node))
13054 arg2 = fold_convert (unsigned_type_node, arg2);
13055
13056 if (TYPE_UNSIGNED (TREE_TYPE (arg2)))
13057 arg2 = build2_loc (loc, code: TRUNC_MOD_EXPR, TREE_TYPE (arg2),
13058 arg0: arg2, arg1: build_int_cst (TREE_TYPE (arg2),
13059 prec));
13060 else
13061 {
13062 /* When second argument is signed, just do the modulo in
13063 unsigned type, that results in better generated code
13064 (for power of 2 precisions bitwise AND). */
13065 tree utype = c_common_unsigned_type (TREE_TYPE (arg2));
13066 arg2 = build2_loc (loc, code: TRUNC_MOD_EXPR, type: utype,
13067 fold_convert (utype, arg2),
13068 arg1: build_int_cst (utype, prec));
13069 }
13070
13071 /* The middle-end isn't prepared to handle {L,R}ROTATE_EXPR
13072 on types without mode precision, except for large/huge
13073 _BitInt types. */
13074 if (type_has_mode_precision_p (TREE_TYPE (arg1))
13075 || (TREE_CODE (TREE_TYPE (arg1)) == BITINT_TYPE
13076 && prec > MAX_FIXED_MODE_SIZE))
13077 expr.value = build2_loc (loc, code, TREE_TYPE (arg1), arg0: arg1,
13078 arg1: arg2);
13079 else
13080 {
13081 arg2 = save_expr (arg2);
13082 tree t1 = build2_loc (loc, code: (code == LROTATE_EXPR
13083 ? LSHIFT_EXPR : RSHIFT_EXPR),
13084 TREE_TYPE (arg1), arg0: arg1, arg1: arg2);
13085 tree t2 = build2_loc (loc, code: MINUS_EXPR,
13086 TREE_TYPE (arg2),
13087 arg0: build_int_cst (TREE_TYPE (arg2),
13088 prec), arg1: arg2);
13089 t2 = build2_loc (loc, code: (code == LROTATE_EXPR
13090 ? RSHIFT_EXPR : LSHIFT_EXPR),
13091 TREE_TYPE (arg1), arg0: arg1, arg1: t2);
13092 suppress_warning (t2, OPT_Wshift_count_overflow);
13093 tree t3 = build2_loc (loc, code: BIT_IOR_EXPR,
13094 TREE_TYPE (arg1), arg0: t1, arg1: t2);
13095 tree t4 = build2_loc (loc, code: NE_EXPR, boolean_type_node,
13096 arg0: arg2,
13097 arg1: build_zero_cst (TREE_TYPE (arg2)));
13098 t4 = build2_loc (loc, code: COMPOUND_EXPR, boolean_type_node,
13099 arg0: arg1, arg1: t4);
13100 expr.value = build3_loc (loc, code: COND_EXPR,
13101 TREE_TYPE (arg1), arg0: t4, arg1: t3, arg2: arg1);
13102 }
13103 if (instrument_expr)
13104 expr.value = build2_loc (loc, code: COMPOUND_EXPR,
13105 TREE_TYPE (expr.value),
13106 arg0: instrument_expr, arg1: expr.value);
13107 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
13108 break;
13109 }
13110 tree barg1 = arg;
13111 switch (stdc_rid)
13112 {
13113 case C_BUILTIN_STDC_BIT_CEIL:
13114 arg = save_expr (arg);
13115 barg1 = build2_loc (loc, code: PLUS_EXPR, type, arg0: arg,
13116 arg1: build_int_cst (type, -1));
13117 break;
13118 case C_BUILTIN_STDC_BIT_FLOOR:
13119 barg1 = arg = save_expr (arg);
13120 break;
13121 case C_BUILTIN_STDC_COUNT_ZEROS:
13122 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13123 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13124 case C_BUILTIN_STDC_LEADING_ONES:
13125 case C_BUILTIN_STDC_TRAILING_ONES:
13126 barg1 = build1_loc (loc, code: BIT_NOT_EXPR, type, arg1: arg);
13127 break;
13128 default:
13129 break;
13130 }
13131 tree barg2 = NULL_TREE;
13132 switch (stdc_rid)
13133 {
13134 case C_BUILTIN_STDC_BIT_WIDTH:
13135 case C_BUILTIN_STDC_LEADING_ONES:
13136 case C_BUILTIN_STDC_LEADING_ZEROS:
13137 case C_BUILTIN_STDC_TRAILING_ONES:
13138 case C_BUILTIN_STDC_TRAILING_ZEROS:
13139 barg2 = build_int_cst (integer_type_node, prec);
13140 break;
13141 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13142 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13143 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13144 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13145 barg2 = integer_minus_one_node;
13146 break;
13147 default:
13148 break;
13149 }
13150 tree fndecl = NULL_TREE;
13151 switch (stdc_rid)
13152 {
13153 case C_BUILTIN_STDC_BIT_CEIL:
13154 case C_BUILTIN_STDC_BIT_FLOOR:
13155 case C_BUILTIN_STDC_BIT_WIDTH:
13156 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13157 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13158 case C_BUILTIN_STDC_LEADING_ONES:
13159 case C_BUILTIN_STDC_LEADING_ZEROS:
13160 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CLZG);
13161 break;
13162 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13163 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13164 case C_BUILTIN_STDC_TRAILING_ONES:
13165 case C_BUILTIN_STDC_TRAILING_ZEROS:
13166 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CTZG);
13167 break;
13168 case C_BUILTIN_STDC_COUNT_ONES:
13169 case C_BUILTIN_STDC_COUNT_ZEROS:
13170 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13171 fndecl = builtin_decl_explicit (fncode: BUILT_IN_POPCOUNTG);
13172 break;
13173 default:
13174 gcc_unreachable ();
13175 }
13176 /* Construct a call to __builtin_{clz,ctz,popcount}g. */
13177 int nargs = barg2 != NULL_TREE ? 2 : 1;
13178 vec<tree, va_gc> *args;
13179 vec_alloc (v&: args, nelems: nargs);
13180 vec<tree, va_gc> *origtypes;
13181 vec_alloc (v&: origtypes, nelems: nargs);
13182 auto_vec<location_t> arg_loc (nargs);
13183 args->quick_push (obj: barg1);
13184 arg_loc.quick_push (obj: arg_p->get_location ());
13185 origtypes->quick_push (obj: arg_p->original_type);
13186 if (nargs == 2)
13187 {
13188 args->quick_push (obj: barg2);
13189 arg_loc.quick_push (obj: loc);
13190 origtypes->quick_push (integer_type_node);
13191 }
13192 expr.value = c_build_function_call_vec (loc, arg_loc, fndecl,
13193 args, origtypes);
13194 set_c_expr_source_range (expr: &expr, start: loc, finish: close_paren_loc);
13195 if (expr.value == error_mark_node)
13196 break;
13197 switch (stdc_rid)
13198 {
13199 case C_BUILTIN_STDC_BIT_CEIL:
13200 case C_BUILTIN_STDC_BIT_FLOOR:
13201 --prec;
13202 /* FALLTHRU */
13203 case C_BUILTIN_STDC_BIT_WIDTH:
13204 expr.value = build2_loc (loc, code: MINUS_EXPR, integer_type_node,
13205 arg0: build_int_cst (integer_type_node,
13206 prec), arg1: expr.value);
13207 break;
13208 case C_BUILTIN_STDC_FIRST_LEADING_ONE:
13209 case C_BUILTIN_STDC_FIRST_LEADING_ZERO:
13210 case C_BUILTIN_STDC_FIRST_TRAILING_ONE:
13211 case C_BUILTIN_STDC_FIRST_TRAILING_ZERO:
13212 expr.value = build2_loc (loc, code: PLUS_EXPR, integer_type_node,
13213 arg0: expr.value, integer_one_node);
13214 break;
13215 case C_BUILTIN_STDC_HAS_SINGLE_BIT:
13216 expr.value = build2_loc (loc, code: EQ_EXPR, boolean_type_node,
13217 arg0: expr.value, integer_one_node);
13218 break;
13219 default:
13220 break;
13221 }
13222
13223 if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL
13224 && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR)
13225 {
13226 if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT)
13227 expr.value = fold_convert_loc (loc, unsigned_type_node,
13228 expr.value);
13229 break;
13230 }
13231 /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U)
13232 or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-*
13233 warnings. The LSHIFT_EXPR is in dead code in that case. */
13234 if (integer_zerop (arg)
13235 || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg)))
13236 expr.value = build_int_cst (type, 0);
13237 else
13238 expr.value
13239 = build2_loc (loc, code: LSHIFT_EXPR, type,
13240 arg0: build_int_cst (type,
13241 (stdc_rid
13242 == C_BUILTIN_STDC_BIT_CEIL
13243 ? 2 : 1)), arg1: expr.value);
13244 if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL)
13245 expr.value = build3_loc (loc, code: COND_EXPR, type,
13246 arg0: build2_loc (loc, code: LE_EXPR,
13247 boolean_type_node, arg0: arg,
13248 arg1: build_int_cst (type, 1)),
13249 arg1: build_int_cst (type, 1),
13250 arg2: expr.value);
13251 else
13252 expr.value = build3_loc (loc, code: COND_EXPR, type,
13253 arg0: build2_loc (loc, code: EQ_EXPR,
13254 boolean_type_node, arg0: arg,
13255 arg1: build_int_cst (type, 0)),
13256 arg1: build_int_cst (type, 0),
13257 arg2: expr.value);
13258 break;
13259 }
13260 case RID_AT_SELECTOR:
13261 {
13262 gcc_assert (c_dialect_objc ());
13263 c_parser_consume_token (parser);
13264 matching_parens parens;
13265 if (!parens.require_open (parser))
13266 {
13267 expr.set_error ();
13268 break;
13269 }
13270 tree sel = c_parser_objc_selector_arg (parser);
13271 location_t close_loc = c_parser_peek_token (parser)->location;
13272 parens.skip_until_found_close (parser);
13273 expr.value = objc_build_selector_expr (loc, sel);
13274 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13275 }
13276 break;
13277 case RID_AT_PROTOCOL:
13278 {
13279 gcc_assert (c_dialect_objc ());
13280 c_parser_consume_token (parser);
13281 matching_parens parens;
13282 if (!parens.require_open (parser))
13283 {
13284 expr.set_error ();
13285 break;
13286 }
13287 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
13288 {
13289 c_parser_error (parser, gmsgid: "expected identifier");
13290 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13291 expr.set_error ();
13292 break;
13293 }
13294 tree id = c_parser_peek_token (parser)->value;
13295 c_parser_consume_token (parser);
13296 location_t close_loc = c_parser_peek_token (parser)->location;
13297 parens.skip_until_found_close (parser);
13298 expr.value = objc_build_protocol_expr (id);
13299 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13300 }
13301 break;
13302 case RID_AT_ENCODE:
13303 {
13304 /* Extension to support C-structures in the archiver. */
13305 gcc_assert (c_dialect_objc ());
13306 c_parser_consume_token (parser);
13307 matching_parens parens;
13308 if (!parens.require_open (parser))
13309 {
13310 expr.set_error ();
13311 break;
13312 }
13313 t1 = c_parser_type_name (parser);
13314 if (t1 == NULL)
13315 {
13316 expr.set_error ();
13317 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
13318 break;
13319 }
13320 location_t close_loc = c_parser_peek_token (parser)->location;
13321 parens.skip_until_found_close (parser);
13322 tree type = groktypename (t1, NULL, NULL);
13323 expr.value = objc_build_encode_expr (type);
13324 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13325 }
13326 break;
13327 case RID_GENERIC:
13328 expr = c_parser_generic_selection (parser);
13329 break;
13330 case RID_OMP_ALL_MEMORY:
13331 gcc_assert (flag_openmp);
13332 c_parser_consume_token (parser);
13333 error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
13334 "%<depend%> clause");
13335 expr.set_error ();
13336 break;
13337 /* C23 'nullptr' literal. */
13338 case RID_NULLPTR:
13339 c_parser_consume_token (parser);
13340 expr.value = nullptr_node;
13341 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13342 pedwarn_c11 (loc, OPT_Wpedantic,
13343 "ISO C does not support %qs before C23", "nullptr");
13344 break;
13345 case RID_TRUE:
13346 c_parser_consume_token (parser);
13347 expr.value = boolean_true_node;
13348 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13349 break;
13350 case RID_FALSE:
13351 c_parser_consume_token (parser);
13352 expr.value = boolean_false_node;
13353 set_c_expr_source_range (expr: &expr, src_range: tok_range);
13354 break;
13355 default:
13356 c_parser_error (parser, gmsgid: "expected expression");
13357 expr.set_error ();
13358 break;
13359 }
13360 break;
13361 case CPP_OPEN_SQUARE:
13362 if (c_dialect_objc ())
13363 {
13364 tree receiver, args;
13365 c_parser_consume_token (parser);
13366 receiver = c_parser_objc_receiver (parser);
13367 args = c_parser_objc_message_args (parser);
13368 location_t close_loc = c_parser_peek_token (parser)->location;
13369 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
13370 msgid: "expected %<]%>");
13371 expr.value = objc_build_message_expr (receiver, args);
13372 set_c_expr_source_range (expr: &expr, start: loc, finish: close_loc);
13373 break;
13374 }
13375 /* Else fall through to report error. */
13376 /* FALLTHRU */
13377 default:
13378 c_parser_error (parser, gmsgid: "expected expression");
13379 expr.set_error ();
13380 break;
13381 }
13382 out:
13383 return c_parser_postfix_expression_after_primary
13384 (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
13385}
13386
13387/* Parse a postfix expression after a parenthesized type name: the
13388 brace-enclosed initializer of a compound literal, possibly followed
13389 by some postfix operators. This is separate because it is not
13390 possible to tell until after the type name whether a cast
13391 expression has a cast or a compound literal, or whether the operand
13392 of sizeof is a parenthesized type name or starts with a compound
13393 literal. TYPE_LOC is the location where TYPE_NAME starts--the
13394 location of the first token after the parentheses around the type
13395 name. */
13396
13397static struct c_expr
13398c_parser_postfix_expression_after_paren_type (c_parser *parser,
13399 struct c_declspecs *scspecs,
13400 struct c_type_name *type_name,
13401 location_t type_loc)
13402{
13403 tree type;
13404 struct c_expr init;
13405 bool non_const;
13406 struct c_expr expr;
13407 location_t start_loc;
13408 tree type_expr = NULL_TREE;
13409 bool type_expr_const = true;
13410 bool constexpr_p = scspecs ? scspecs->constexpr_p : false;
13411 unsigned int underspec_state = 0;
13412 check_compound_literal_type (type_loc, type_name);
13413 rich_location richloc (line_table, type_loc);
13414 start_loc = c_parser_peek_token (parser)->location;
13415 if (constexpr_p)
13416 {
13417 underspec_state = start_underspecified_init (start_loc, NULL_TREE);
13418 /* A constexpr compound literal is subject to the constraints on
13419 underspecified declarations, which may not declare tags or
13420 members or structures or unions; it is undefined behavior to
13421 declare the members of an enumeration. Where the structure,
13422 union or enumeration type is declared within the compound
13423 literal initializer, this is diagnosed elsewhere as a result
13424 of the above call to start_underspecified_init. Diagnose
13425 here the case of declaring such a type in the type specifiers
13426 of the compound literal. */
13427 switch (type_name->specs->typespec_kind)
13428 {
13429 case ctsk_tagfirstref:
13430 case ctsk_tagfirstref_attrs:
13431 error_at (type_loc, "%qT declared in %<constexpr%> compound literal",
13432 type_name->specs->type);
13433 break;
13434
13435 case ctsk_tagdef:
13436 error_at (type_loc, "%qT defined in %<constexpr%> compound literal",
13437 type_name->specs->type);
13438 break;
13439
13440 default:
13441 break;
13442 }
13443 }
13444 start_init (NULL_TREE, NULL,
13445 (global_bindings_p ()
13446 || (scspecs && scspecs->storage_class == csc_static)
13447 || constexpr_p), constexpr_p, &richloc);
13448 type = groktypename (type_name, &type_expr, &type_expr_const);
13449 if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
13450 {
13451 error_at (type_loc, "compound literal has variable size");
13452 type = error_mark_node;
13453 }
13454 else if (TREE_CODE (type) == FUNCTION_TYPE)
13455 {
13456 error_at (type_loc, "compound literal has function type");
13457 type = error_mark_node;
13458 }
13459 if (constexpr_p && type != error_mark_node)
13460 {
13461 tree type_no_array = strip_array_types (type);
13462 /* The type of a constexpr object must not be variably modified
13463 (which applies to all compound literals), volatile, atomic or
13464 restrict qualified or have a member with such a qualifier.
13465 const qualification is implicitly added. */
13466 if (TYPE_QUALS (type_no_array)
13467 & (TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC))
13468 error_at (type_loc, "invalid qualifiers for %<constexpr%> object");
13469 else if (RECORD_OR_UNION_TYPE_P (type_no_array)
13470 && C_TYPE_FIELDS_NON_CONSTEXPR (type_no_array))
13471 error_at (type_loc, "invalid qualifiers for field of "
13472 "%<constexpr%> object");
13473 type = c_build_qualified_type (type,
13474 (TYPE_QUALS (type_no_array)
13475 | TYPE_QUAL_CONST));
13476 }
13477 init = c_parser_braced_init (parser, type, nested_p: false, NULL, NULL_TREE);
13478 if (constexpr_p)
13479 finish_underspecified_init (NULL_TREE, underspec_state);
13480 finish_init ();
13481 maybe_warn_string_init (type_loc, type, init);
13482
13483 if (type != error_mark_node
13484 && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
13485 && current_function_decl)
13486 {
13487 error ("compound literal qualified by address-space qualifier");
13488 type = error_mark_node;
13489 }
13490
13491 if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
13492 "ISO C90 forbids compound literals") && scspecs)
13493 pedwarn_c11 (start_loc, OPT_Wpedantic,
13494 "ISO C forbids storage class specifiers in compound literals "
13495 "before C23");
13496 non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
13497 ? CONSTRUCTOR_NON_CONST (init.value)
13498 : init.original_code == C_MAYBE_CONST_EXPR);
13499 non_const |= !type_expr_const;
13500 unsigned int alignas_align = 0;
13501 if (type != error_mark_node
13502 && type_name->specs->align_log != -1)
13503 {
13504 alignas_align = 1U << type_name->specs->align_log;
13505 if (alignas_align < min_align_of_type (type))
13506 {
13507 error_at (type_name->specs->locations[cdw_alignas],
13508 "%<_Alignas%> specifiers cannot reduce "
13509 "alignment of compound literal");
13510 alignas_align = 0;
13511 }
13512 }
13513 expr.value = build_compound_literal (start_loc, type, init.value, non_const,
13514 alignas_align, scspecs);
13515 set_c_expr_source_range (expr: &expr, src_range: init.src_range);
13516 expr.m_decimal = 0;
13517 expr.original_code = ERROR_MARK;
13518 expr.original_type = NULL;
13519 if (type != error_mark_node
13520 && expr.value != error_mark_node
13521 && type_expr)
13522 {
13523 if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
13524 {
13525 gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
13526 C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
13527 }
13528 else
13529 {
13530 gcc_assert (!non_const);
13531 expr.value = build2 (C_MAYBE_CONST_EXPR, type,
13532 type_expr, expr.value);
13533 }
13534 }
13535 return c_parser_postfix_expression_after_primary (parser, loc: start_loc, expr);
13536}
13537
13538/* Callback function for sizeof_pointer_memaccess_warning to compare
13539 types. */
13540
13541static bool
13542sizeof_ptr_memacc_comptypes (tree type1, tree type2)
13543{
13544 return comptypes (type1, type2) == 1;
13545}
13546
13547/* Warn for patterns where abs-like function appears to be used incorrectly,
13548 gracefully ignore any non-abs-like function. The warning location should
13549 be LOC. FNDECL is the declaration of called function, it must be a
13550 BUILT_IN_NORMAL function. ARG is the first and only argument of the
13551 call. */
13552
13553static void
13554warn_for_abs (location_t loc, tree fndecl, tree arg)
13555{
13556 /* Avoid warning in unreachable subexpressions. */
13557 if (c_inhibit_evaluation_warnings)
13558 return;
13559
13560 tree atype = TREE_TYPE (arg);
13561
13562 /* Casts from pointers (and thus arrays and fndecls) will generate
13563 -Wint-conversion warnings. Most other wrong types hopefully lead to type
13564 mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
13565 types and possibly other exotic types. */
13566 if (!INTEGRAL_TYPE_P (atype)
13567 && !SCALAR_FLOAT_TYPE_P (atype)
13568 && TREE_CODE (atype) != COMPLEX_TYPE)
13569 return;
13570
13571 enum built_in_function fcode = DECL_FUNCTION_CODE (decl: fndecl);
13572
13573 switch (fcode)
13574 {
13575 case BUILT_IN_ABS:
13576 case BUILT_IN_LABS:
13577 case BUILT_IN_LLABS:
13578 case BUILT_IN_IMAXABS:
13579 if (!INTEGRAL_TYPE_P (atype))
13580 {
13581 if (SCALAR_FLOAT_TYPE_P (atype))
13582 warning_at (loc, OPT_Wabsolute_value,
13583 "using integer absolute value function %qD when "
13584 "argument is of floating-point type %qT",
13585 fndecl, atype);
13586 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13587 warning_at (loc, OPT_Wabsolute_value,
13588 "using integer absolute value function %qD when "
13589 "argument is of complex type %qT", fndecl, atype);
13590 else
13591 gcc_unreachable ();
13592 return;
13593 }
13594 if (TYPE_UNSIGNED (atype))
13595 warning_at (loc, OPT_Wabsolute_value,
13596 "taking the absolute value of unsigned type %qT "
13597 "has no effect", atype);
13598 break;
13599
13600 CASE_FLT_FN (BUILT_IN_FABS):
13601 CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
13602 if (!SCALAR_FLOAT_TYPE_P (atype)
13603 || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
13604 {
13605 if (INTEGRAL_TYPE_P (atype))
13606 warning_at (loc, OPT_Wabsolute_value,
13607 "using floating-point absolute value function %qD "
13608 "when argument is of integer type %qT", fndecl, atype);
13609 else if (DECIMAL_FLOAT_TYPE_P (atype))
13610 warning_at (loc, OPT_Wabsolute_value,
13611 "using floating-point absolute value function %qD "
13612 "when argument is of decimal floating-point type %qT",
13613 fndecl, atype);
13614 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13615 warning_at (loc, OPT_Wabsolute_value,
13616 "using floating-point absolute value function %qD when "
13617 "argument is of complex type %qT", fndecl, atype);
13618 else
13619 gcc_unreachable ();
13620 return;
13621 }
13622 break;
13623
13624 CASE_FLT_FN (BUILT_IN_CABS):
13625 if (TREE_CODE (atype) != COMPLEX_TYPE)
13626 {
13627 if (INTEGRAL_TYPE_P (atype))
13628 warning_at (loc, OPT_Wabsolute_value,
13629 "using complex absolute value function %qD when "
13630 "argument is of integer type %qT", fndecl, atype);
13631 else if (SCALAR_FLOAT_TYPE_P (atype))
13632 warning_at (loc, OPT_Wabsolute_value,
13633 "using complex absolute value function %qD when "
13634 "argument is of floating-point type %qT",
13635 fndecl, atype);
13636 else
13637 gcc_unreachable ();
13638
13639 return;
13640 }
13641 break;
13642
13643 case BUILT_IN_FABSD32:
13644 case BUILT_IN_FABSD64:
13645 case BUILT_IN_FABSD128:
13646 case BUILT_IN_FABSD64X:
13647 if (!DECIMAL_FLOAT_TYPE_P (atype))
13648 {
13649 if (INTEGRAL_TYPE_P (atype))
13650 warning_at (loc, OPT_Wabsolute_value,
13651 "using decimal floating-point absolute value "
13652 "function %qD when argument is of integer type %qT",
13653 fndecl, atype);
13654 else if (SCALAR_FLOAT_TYPE_P (atype))
13655 warning_at (loc, OPT_Wabsolute_value,
13656 "using decimal floating-point absolute value "
13657 "function %qD when argument is of floating-point "
13658 "type %qT", fndecl, atype);
13659 else if (TREE_CODE (atype) == COMPLEX_TYPE)
13660 warning_at (loc, OPT_Wabsolute_value,
13661 "using decimal floating-point absolute value "
13662 "function %qD when argument is of complex type %qT",
13663 fndecl, atype);
13664 else
13665 gcc_unreachable ();
13666 return;
13667 }
13668 break;
13669
13670 default:
13671 return;
13672 }
13673
13674 if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13675 return;
13676
13677 tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13678 if (TREE_CODE (atype) == COMPLEX_TYPE)
13679 {
13680 gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
13681 atype = TREE_TYPE (atype);
13682 ftype = TREE_TYPE (ftype);
13683 }
13684
13685 if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
13686 warning_at (loc, OPT_Wabsolute_value,
13687 "absolute value function %qD given an argument of type %qT "
13688 "but has parameter of type %qT which may cause truncation "
13689 "of value", fndecl, atype, ftype);
13690}
13691
13692
13693/* Parse a postfix expression after the initial primary or compound
13694 literal; that is, parse a series of postfix operators.
13695
13696 EXPR_LOC is the location of the primary expression. */
13697
13698static struct c_expr
13699c_parser_postfix_expression_after_primary (c_parser *parser,
13700 location_t expr_loc,
13701 struct c_expr expr)
13702{
13703 struct c_expr orig_expr;
13704 tree ident, idx, len;
13705 location_t sizeof_arg_loc[6], comp_loc;
13706 tree sizeof_arg[6];
13707 unsigned int literal_zero_mask;
13708 unsigned int i;
13709 vec<tree, va_gc> *exprlist;
13710 vec<tree, va_gc> *origtypes = NULL;
13711 vec<location_t> arg_loc = vNULL;
13712 location_t start;
13713 location_t finish;
13714
13715 while (true)
13716 {
13717 location_t op_loc = c_parser_peek_token (parser)->location;
13718 switch (c_parser_peek_token (parser)->type)
13719 {
13720 case CPP_OPEN_SQUARE:
13721 /* Array reference. */
13722 c_parser_consume_token (parser);
13723 idx = len = NULL_TREE;
13724 if (!c_omp_array_section_p
13725 || c_parser_next_token_is_not (parser, type: CPP_COLON))
13726 idx = c_parser_expression (parser).value;
13727
13728 if (c_omp_array_section_p
13729 && c_parser_next_token_is (parser, type: CPP_COLON))
13730 {
13731 c_parser_consume_token (parser);
13732 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_SQUARE))
13733 len = c_parser_expression (parser).value;
13734
13735 expr.value = build_omp_array_section (op_loc, expr.value, idx,
13736 len);
13737 }
13738 else
13739 expr.value = build_array_ref (op_loc, expr.value, idx);
13740
13741 c_parser_skip_until_found (parser, type: CPP_CLOSE_SQUARE,
13742 msgid: "expected %<]%>");
13743
13744 start = expr.get_start ();
13745 finish = parser->tokens_buf[0].location;
13746 set_c_expr_source_range (expr: &expr, start, finish);
13747 expr.original_code = ERROR_MARK;
13748 expr.original_type = NULL;
13749 expr.m_decimal = 0;
13750 break;
13751 case CPP_OPEN_PAREN:
13752 /* Function call. */
13753 {
13754 matching_parens parens;
13755 parens.consume_open (parser);
13756 for (i = 0; i < 6; i++)
13757 {
13758 sizeof_arg[i] = NULL_TREE;
13759 sizeof_arg_loc[i] = UNKNOWN_LOCATION;
13760 }
13761 literal_zero_mask = 0;
13762 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
13763 exprlist = NULL;
13764 else if (TREE_CODE (expr.value) == FUNCTION_DECL
13765 && fndecl_built_in_p (node: expr.value, name1: BUILT_IN_CLASSIFY_TYPE)
13766 && c_parser_next_tokens_start_typename (parser,
13767 la: cla_prefer_id))
13768 {
13769 /* __builtin_classify_type (type) */
13770 c_inhibit_evaluation_warnings++;
13771 in_alignof++;
13772 struct c_type_name *type = c_parser_type_name (parser);
13773 c_inhibit_evaluation_warnings--;
13774 in_alignof--;
13775 struct c_typespec ret;
13776 ret.expr = NULL_TREE;
13777 ret.spec = error_mark_node;
13778 ret.expr_const_operands = false;
13779 if (type != NULL)
13780 ret.spec = groktypename (type, &ret.expr,
13781 &ret.expr_const_operands);
13782 parens.skip_until_found_close (parser);
13783 expr.value = build_int_cst (integer_type_node,
13784 type_to_class (ret.spec));
13785 break;
13786 }
13787 else
13788 exprlist = c_parser_expr_list (parser, true, false, &origtypes,
13789 sizeof_arg_loc, sizeof_arg,
13790 &arg_loc, &literal_zero_mask);
13791 parens.skip_until_found_close (parser);
13792 }
13793 orig_expr = expr;
13794 mark_exp_read (expr.value);
13795 if (warn_sizeof_pointer_memaccess)
13796 sizeof_pointer_memaccess_warning (sizeof_arg_loc,
13797 expr.value, exprlist,
13798 sizeof_arg,
13799 sizeof_ptr_memacc_comptypes);
13800 if (TREE_CODE (expr.value) == FUNCTION_DECL)
13801 {
13802 if (fndecl_built_in_p (node: expr.value, name1: BUILT_IN_MEMSET)
13803 && vec_safe_length (v: exprlist) == 3)
13804 {
13805 tree arg0 = (*exprlist)[0];
13806 tree arg2 = (*exprlist)[2];
13807 warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
13808 }
13809 if (warn_absolute_value
13810 && fndecl_built_in_p (node: expr.value, klass: BUILT_IN_NORMAL)
13811 && vec_safe_length (v: exprlist) == 1)
13812 warn_for_abs (loc: expr_loc, fndecl: expr.value, arg: (*exprlist)[0]);
13813 if (parser->omp_for_parse_state
13814 && parser->omp_for_parse_state->in_intervening_code
13815 && omp_runtime_api_call (fndecl: expr.value))
13816 {
13817 error_at (expr_loc, "calls to the OpenMP runtime API are "
13818 "not permitted in intervening code");
13819 parser->omp_for_parse_state->fail = true;
13820 }
13821 if (warn_calloc_transposed_args)
13822 if (tree attr = lookup_attribute (attr_name: "alloc_size",
13823 TYPE_ATTRIBUTES
13824 (TREE_TYPE (expr.value))))
13825 if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr)))
13826 warn_for_calloc (sizeof_arg_loc, expr.value, exprlist,
13827 sizeof_arg, attr);
13828 }
13829
13830 start = expr.get_start ();
13831 finish = parser->tokens_buf[0].get_finish ();
13832 expr.value
13833 = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
13834 exprlist, origtypes);
13835 set_c_expr_source_range (expr: &expr, start, finish);
13836 expr.m_decimal = 0;
13837
13838 expr.original_code = ERROR_MARK;
13839 if (TREE_CODE (expr.value) == INTEGER_CST
13840 && TREE_CODE (orig_expr.value) == FUNCTION_DECL
13841 && fndecl_built_in_p (node: orig_expr.value, name1: BUILT_IN_CONSTANT_P))
13842 expr.original_code = C_MAYBE_CONST_EXPR;
13843 expr.original_type = NULL;
13844 if (exprlist)
13845 {
13846 release_tree_vector (exprlist);
13847 release_tree_vector (origtypes);
13848 }
13849 arg_loc.release ();
13850 break;
13851 case CPP_DOT:
13852 /* Structure element reference. */
13853 c_parser_consume_token (parser);
13854 expr = default_function_array_conversion (expr_loc, expr);
13855 if (c_parser_next_token_is (parser, type: CPP_NAME))
13856 {
13857 c_token *comp_tok = c_parser_peek_token (parser);
13858 ident = comp_tok->value;
13859 comp_loc = comp_tok->location;
13860 }
13861 else
13862 {
13863 c_parser_error (parser, gmsgid: "expected identifier");
13864 expr.set_error ();
13865 expr.original_code = ERROR_MARK;
13866 expr.original_type = NULL;
13867 return expr;
13868 }
13869 start = expr.get_start ();
13870 finish = c_parser_peek_token (parser)->get_finish ();
13871 c_parser_consume_token (parser);
13872 expr.value = build_component_ref (op_loc, expr.value, ident,
13873 comp_loc, UNKNOWN_LOCATION);
13874 set_c_expr_source_range (expr: &expr, start, finish);
13875 expr.original_code = ERROR_MARK;
13876 if (TREE_CODE (expr.value) != COMPONENT_REF)
13877 expr.original_type = NULL;
13878 else
13879 {
13880 /* Remember the original type of a bitfield. */
13881 tree field = TREE_OPERAND (expr.value, 1);
13882 if (TREE_CODE (field) != FIELD_DECL)
13883 expr.original_type = NULL;
13884 else
13885 expr.original_type = DECL_BIT_FIELD_TYPE (field);
13886 }
13887 expr.m_decimal = 0;
13888 break;
13889 case CPP_DEREF:
13890 /* Structure element reference. */
13891 c_parser_consume_token (parser);
13892 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
13893 if (c_parser_next_token_is (parser, type: CPP_NAME))
13894 {
13895 c_token *comp_tok = c_parser_peek_token (parser);
13896 ident = comp_tok->value;
13897 comp_loc = comp_tok->location;
13898 }
13899 else
13900 {
13901 c_parser_error (parser, gmsgid: "expected identifier");
13902 expr.set_error ();
13903 expr.original_code = ERROR_MARK;
13904 expr.original_type = NULL;
13905 return expr;
13906 }
13907 start = expr.get_start ();
13908 finish = c_parser_peek_token (parser)->get_finish ();
13909 c_parser_consume_token (parser);
13910 expr.value = build_component_ref (op_loc,
13911 build_indirect_ref (op_loc,
13912 expr.value,
13913 RO_ARROW),
13914 ident, comp_loc,
13915 expr.get_location ());
13916 set_c_expr_source_range (expr: &expr, start, finish);
13917 expr.original_code = ERROR_MARK;
13918 if (TREE_CODE (expr.value) != COMPONENT_REF)
13919 expr.original_type = NULL;
13920 else
13921 {
13922 /* Remember the original type of a bitfield. */
13923 tree field = TREE_OPERAND (expr.value, 1);
13924 if (TREE_CODE (field) != FIELD_DECL)
13925 expr.original_type = NULL;
13926 else
13927 expr.original_type = DECL_BIT_FIELD_TYPE (field);
13928 }
13929 expr.m_decimal = 0;
13930 break;
13931 case CPP_PLUS_PLUS:
13932 /* Postincrement. */
13933 start = expr.get_start ();
13934 finish = c_parser_peek_token (parser)->get_finish ();
13935 c_parser_consume_token (parser);
13936 expr = default_function_array_read_conversion (expr_loc, expr);
13937 expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
13938 expr.value, false);
13939 set_c_expr_source_range (expr: &expr, start, finish);
13940 expr.original_code = ERROR_MARK;
13941 expr.original_type = NULL;
13942 break;
13943 case CPP_MINUS_MINUS:
13944 /* Postdecrement. */
13945 start = expr.get_start ();
13946 finish = c_parser_peek_token (parser)->get_finish ();
13947 c_parser_consume_token (parser);
13948 expr = default_function_array_read_conversion (expr_loc, expr);
13949 expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
13950 expr.value, false);
13951 set_c_expr_source_range (expr: &expr, start, finish);
13952 expr.original_code = ERROR_MARK;
13953 expr.original_type = NULL;
13954 break;
13955 default:
13956 return expr;
13957 }
13958 }
13959}
13960
13961/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
13962
13963 expression:
13964 assignment-expression
13965 expression , assignment-expression
13966*/
13967
13968static struct c_expr
13969c_parser_expression (c_parser *parser)
13970{
13971 location_t tloc = c_parser_peek_token (parser)->location;
13972 struct c_expr expr;
13973 expr = c_parser_expr_no_commas (parser, NULL);
13974 if (c_parser_next_token_is (parser, type: CPP_COMMA))
13975 expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
13976 while (c_parser_next_token_is (parser, type: CPP_COMMA))
13977 {
13978 struct c_expr next;
13979 tree lhsval;
13980 location_t loc = c_parser_peek_token (parser)->location;
13981 location_t expr_loc;
13982 c_parser_consume_token (parser);
13983 expr_loc = c_parser_peek_token (parser)->location;
13984 lhsval = expr.value;
13985 while (TREE_CODE (lhsval) == COMPOUND_EXPR
13986 || TREE_CODE (lhsval) == NOP_EXPR)
13987 {
13988 if (TREE_CODE (lhsval) == COMPOUND_EXPR)
13989 lhsval = TREE_OPERAND (lhsval, 1);
13990 else
13991 lhsval = TREE_OPERAND (lhsval, 0);
13992 }
13993 if (DECL_P (lhsval) || handled_component_p (t: lhsval))
13994 mark_exp_read (lhsval);
13995 if (c_parser_next_token_is (parser, type: CPP_EMBED))
13996 {
13997 /* Users aren't interested in milions of -Wunused-value
13998 warnings when using #embed inside of a comma expression,
13999 and one CPP_NUMBER plus CPP_COMMA before it and one
14000 CPP_COMMA plus CPP_NUMBER after it is guaranteed by
14001 the preprocessor. Thus, parse the whole CPP_EMBED just
14002 as a single INTEGER_CST, the last byte in it. */
14003 c_token *embed = c_parser_peek_token (parser);
14004 tree val = embed->value;
14005 unsigned last = RAW_DATA_LENGTH (val) - 1;
14006 next.value = build_int_cst (TREE_TYPE (val),
14007 RAW_DATA_UCHAR_ELT (val, last));
14008 next.original_type = integer_type_node;
14009 c_parser_consume_token (parser);
14010 }
14011 else
14012 {
14013 next = c_parser_expr_no_commas (parser, NULL);
14014 next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
14015 }
14016 expr.value = build_compound_expr (loc, expr.value, next.value);
14017 expr.original_code = COMPOUND_EXPR;
14018 expr.original_type = next.original_type;
14019 expr.m_decimal = 0;
14020 }
14021 return expr;
14022}
14023
14024/* Parse an expression and convert functions or arrays to pointers and
14025 lvalues to rvalues. */
14026
14027static struct c_expr
14028c_parser_expression_conv (c_parser *parser)
14029{
14030 struct c_expr expr;
14031 location_t loc = c_parser_peek_token (parser)->location;
14032 expr = c_parser_expression (parser);
14033 expr = convert_lvalue_to_rvalue (loc, expr, true, false);
14034 return expr;
14035}
14036
14037/* Helper function of c_parser_expr_list. Check if IDXth (0 based)
14038 argument is a literal zero alone and if so, set it in literal_zero_mask. */
14039
14040static inline void
14041c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
14042 unsigned int idx)
14043{
14044 if (idx >= HOST_BITS_PER_INT)
14045 return;
14046
14047 c_token *tok = c_parser_peek_token (parser);
14048 switch (tok->type)
14049 {
14050 case CPP_NUMBER:
14051 case CPP_CHAR:
14052 case CPP_WCHAR:
14053 case CPP_CHAR16:
14054 case CPP_CHAR32:
14055 case CPP_UTF8CHAR:
14056 /* If a parameter is literal zero alone, remember it
14057 for -Wmemset-transposed-args warning. */
14058 if (integer_zerop (tok->value)
14059 && !TREE_OVERFLOW (tok->value)
14060 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14061 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
14062 *literal_zero_mask |= 1U << idx;
14063 default:
14064 break;
14065 }
14066}
14067
14068/* Parse a non-empty list of expressions. If CONVERT_P, convert
14069 functions and arrays to pointers and lvalues to rvalues. If
14070 FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
14071 locations of function arguments into this vector.
14072
14073 nonempty-expr-list:
14074 assignment-expression
14075 nonempty-expr-list , assignment-expression
14076*/
14077
14078static vec<tree, va_gc> *
14079c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
14080 vec<tree, va_gc> **p_orig_types,
14081 location_t *sizeof_arg_loc, tree *sizeof_arg,
14082 vec<location_t> *locations,
14083 unsigned int *literal_zero_mask)
14084{
14085 vec<tree, va_gc> *ret;
14086 vec<tree, va_gc> *orig_types;
14087 struct c_expr expr;
14088 unsigned int idx = 0;
14089 bool save_c_omp_array_section_p = c_omp_array_section_p;
14090 c_omp_array_section_p = false;
14091
14092 ret = make_tree_vector ();
14093 if (p_orig_types == NULL)
14094 orig_types = NULL;
14095 else
14096 orig_types = make_tree_vector ();
14097
14098 if (literal_zero_mask)
14099 c_parser_check_literal_zero (parser, literal_zero_mask, idx: 0);
14100 expr = c_parser_expr_no_commas (parser, NULL);
14101 if (convert_p)
14102 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
14103 if (fold_p)
14104 expr.value = c_fully_fold (expr.value, false, NULL);
14105 ret->quick_push (obj: expr.value);
14106 if (orig_types)
14107 orig_types->quick_push (obj: expr.original_type);
14108 if (locations)
14109 locations->safe_push (obj: expr.get_location ());
14110 if (sizeof_arg != NULL
14111 && (expr.original_code == SIZEOF_EXPR
14112 || expr.original_code == PAREN_SIZEOF_EXPR))
14113 {
14114 sizeof_arg[0] = c_last_sizeof_arg;
14115 sizeof_arg_loc[0] = c_last_sizeof_loc;
14116 }
14117 while (c_parser_next_token_is (parser, type: CPP_COMMA))
14118 {
14119 c_parser_consume_token (parser);
14120 if (c_parser_next_token_is (parser, type: CPP_EMBED))
14121 {
14122 c_token *embed = c_parser_peek_token (parser);
14123 tree value = embed->value;
14124 expr.original_code = INTEGER_CST;
14125 expr.original_type = integer_type_node;
14126 expr.value = NULL_TREE;
14127 set_c_expr_source_range (expr: &expr, src_range: embed->get_range ());
14128 expr.m_decimal = 0;
14129 for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value); i++)
14130 {
14131 if (literal_zero_mask
14132 && idx + 1 < HOST_BITS_PER_INT
14133 && RAW_DATA_POINTER (value)[i] == 0)
14134 *literal_zero_mask |= 1U << (idx + 1);
14135 expr.value = build_int_cst (integer_type_node,
14136 RAW_DATA_UCHAR_ELT (value, i));
14137 vec_safe_push (v&: ret, obj: expr.value);
14138 if (orig_types)
14139 vec_safe_push (v&: orig_types, obj: expr.original_type);
14140 if (locations)
14141 locations->safe_push (obj: expr.get_location ());
14142 ++idx;
14143 }
14144 c_parser_consume_token (parser);
14145 continue;
14146 }
14147 if (literal_zero_mask)
14148 c_parser_check_literal_zero (parser, literal_zero_mask, idx: idx + 1);
14149 expr = c_parser_expr_no_commas (parser, NULL);
14150 if (convert_p)
14151 expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
14152 true);
14153 if (fold_p)
14154 expr.value = c_fully_fold (expr.value, false, NULL);
14155 vec_safe_push (v&: ret, obj: expr.value);
14156 if (orig_types)
14157 vec_safe_push (v&: orig_types, obj: expr.original_type);
14158 if (locations)
14159 locations->safe_push (obj: expr.get_location ());
14160 if (++idx < 6
14161 && sizeof_arg != NULL
14162 && (expr.original_code == SIZEOF_EXPR
14163 || expr.original_code == PAREN_SIZEOF_EXPR))
14164 {
14165 sizeof_arg[idx] = c_last_sizeof_arg;
14166 sizeof_arg_loc[idx] = c_last_sizeof_loc;
14167 }
14168 }
14169 if (orig_types)
14170 *p_orig_types = orig_types;
14171 c_omp_array_section_p = save_c_omp_array_section_p;
14172 return ret;
14173}
14174
14175/* Parse Objective-C-specific constructs. */
14176
14177/* Parse an objc-class-definition.
14178
14179 objc-class-definition:
14180 @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
14181 objc-class-instance-variables[opt] objc-methodprotolist @end
14182 @implementation identifier objc-superclass[opt]
14183 objc-class-instance-variables[opt]
14184 @interface identifier ( identifier ) objc-protocol-refs[opt]
14185 objc-methodprotolist @end
14186 @interface identifier ( ) objc-protocol-refs[opt]
14187 objc-methodprotolist @end
14188 @implementation identifier ( identifier )
14189
14190 objc-superclass:
14191 : identifier
14192
14193 "@interface identifier (" must start "@interface identifier (
14194 identifier ) ...": objc-methodprotolist in the first production may
14195 not start with a parenthesized identifier as a declarator of a data
14196 definition with no declaration specifiers if the objc-superclass,
14197 objc-protocol-refs and objc-class-instance-variables are omitted. */
14198
14199static void
14200c_parser_objc_class_definition (c_parser *parser, tree attributes)
14201{
14202 bool iface_p;
14203 tree id1;
14204 tree superclass;
14205 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_INTERFACE))
14206 iface_p = true;
14207 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_IMPLEMENTATION))
14208 iface_p = false;
14209 else
14210 gcc_unreachable ();
14211
14212 c_parser_consume_token (parser);
14213 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14214 {
14215 c_parser_error (parser, gmsgid: "expected identifier");
14216 return;
14217 }
14218 id1 = c_parser_peek_token (parser)->value;
14219 location_t loc1 = c_parser_peek_token (parser)->location;
14220 c_parser_consume_token (parser);
14221 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
14222 {
14223 /* We have a category or class extension. */
14224 tree id2;
14225 tree proto = NULL_TREE;
14226 matching_parens parens;
14227 parens.consume_open (parser);
14228 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14229 {
14230 if (iface_p && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
14231 {
14232 /* We have a class extension. */
14233 id2 = NULL_TREE;
14234 }
14235 else
14236 {
14237 c_parser_error (parser, gmsgid: "expected identifier or %<)%>");
14238 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
14239 return;
14240 }
14241 }
14242 else
14243 {
14244 id2 = c_parser_peek_token (parser)->value;
14245 c_parser_consume_token (parser);
14246 }
14247 parens.skip_until_found_close (parser);
14248 if (!iface_p)
14249 {
14250 objc_start_category_implementation (id1, id2);
14251 return;
14252 }
14253 if (c_parser_next_token_is (parser, type: CPP_LESS))
14254 proto = c_parser_objc_protocol_refs (parser);
14255 objc_start_category_interface (id1, id2, proto, attributes);
14256 c_parser_objc_methodprotolist (parser);
14257 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14258 objc_finish_interface ();
14259 return;
14260 }
14261 if (c_parser_next_token_is (parser, type: CPP_COLON))
14262 {
14263 c_parser_consume_token (parser);
14264 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14265 {
14266 c_parser_error (parser, gmsgid: "expected identifier");
14267 return;
14268 }
14269 superclass = c_parser_peek_token (parser)->value;
14270 c_parser_consume_token (parser);
14271 }
14272 else
14273 superclass = NULL_TREE;
14274 if (iface_p)
14275 {
14276 tree proto = NULL_TREE;
14277 if (c_parser_next_token_is (parser, type: CPP_LESS))
14278 proto = c_parser_objc_protocol_refs (parser);
14279 objc_start_class_interface (id1, loc1, superclass, proto, attributes);
14280 }
14281 else
14282 objc_start_class_implementation (id1, superclass);
14283 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
14284 c_parser_objc_class_instance_variables (parser);
14285 if (iface_p)
14286 {
14287 objc_continue_interface ();
14288 c_parser_objc_methodprotolist (parser);
14289 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14290 objc_finish_interface ();
14291 }
14292 else
14293 {
14294 objc_continue_implementation ();
14295 return;
14296 }
14297}
14298
14299/* Parse objc-class-instance-variables.
14300
14301 objc-class-instance-variables:
14302 { objc-instance-variable-decl-list[opt] }
14303
14304 objc-instance-variable-decl-list:
14305 objc-visibility-spec
14306 objc-instance-variable-decl ;
14307 ;
14308 objc-instance-variable-decl-list objc-visibility-spec
14309 objc-instance-variable-decl-list objc-instance-variable-decl ;
14310 objc-instance-variable-decl-list ;
14311
14312 objc-visibility-spec:
14313 @private
14314 @protected
14315 @public
14316
14317 objc-instance-variable-decl:
14318 struct-declaration
14319*/
14320
14321static void
14322c_parser_objc_class_instance_variables (c_parser *parser)
14323{
14324 gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
14325 c_parser_consume_token (parser);
14326 while (c_parser_next_token_is_not (parser, type: CPP_EOF))
14327 {
14328 tree decls;
14329 /* Parse any stray semicolon. */
14330 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14331 {
14332 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14333 "extra semicolon");
14334 c_parser_consume_token (parser);
14335 continue;
14336 }
14337 /* Stop if at the end of the instance variables. */
14338 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
14339 {
14340 c_parser_consume_token (parser);
14341 break;
14342 }
14343 /* Parse any objc-visibility-spec. */
14344 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PRIVATE))
14345 {
14346 c_parser_consume_token (parser);
14347 objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
14348 continue;
14349 }
14350 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROTECTED))
14351 {
14352 c_parser_consume_token (parser);
14353 objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
14354 continue;
14355 }
14356 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PUBLIC))
14357 {
14358 c_parser_consume_token (parser);
14359 objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
14360 continue;
14361 }
14362 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PACKAGE))
14363 {
14364 c_parser_consume_token (parser);
14365 objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
14366 continue;
14367 }
14368 else if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
14369 {
14370 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14371 continue;
14372 }
14373
14374 /* Parse some comma-separated declarations. */
14375 decls = c_parser_struct_declaration (parser, NULL);
14376 if (decls == NULL)
14377 {
14378 /* There is a syntax error. We want to skip the offending
14379 tokens up to the next ';' (included) or '}'
14380 (excluded). */
14381
14382 /* First, skip manually a ')' or ']'. This is because they
14383 reduce the nesting level, so c_parser_skip_until_found()
14384 wouldn't be able to skip past them. */
14385 c_token *token = c_parser_peek_token (parser);
14386 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
14387 c_parser_consume_token (parser);
14388
14389 /* Then, do the standard skipping. */
14390 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14391
14392 /* We hopefully recovered. Start normal parsing again. */
14393 parser->error = false;
14394 continue;
14395 }
14396 else
14397 {
14398 /* Comma-separated instance variables are chained together
14399 in reverse order; add them one by one. */
14400 tree ivar = nreverse (decls);
14401 for (; ivar; ivar = DECL_CHAIN (ivar))
14402 objc_add_instance_variable (copy_node (ivar));
14403 }
14404 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14405 }
14406}
14407
14408/* Parse an objc-class-declaration.
14409
14410 objc-class-declaration:
14411 @class identifier-list ;
14412*/
14413
14414static void
14415c_parser_objc_class_declaration (c_parser *parser)
14416{
14417 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
14418 c_parser_consume_token (parser);
14419 /* Any identifiers, including those declared as type names, are OK
14420 here. */
14421 while (true)
14422 {
14423 tree id;
14424 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14425 {
14426 c_parser_error (parser, gmsgid: "expected identifier");
14427 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14428 parser->error = false;
14429 return;
14430 }
14431 id = c_parser_peek_token (parser)->value;
14432 objc_declare_class (id);
14433 c_parser_consume_token (parser);
14434 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14435 c_parser_consume_token (parser);
14436 else
14437 break;
14438 }
14439 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14440}
14441
14442/* Parse an objc-alias-declaration.
14443
14444 objc-alias-declaration:
14445 @compatibility_alias identifier identifier ;
14446*/
14447
14448static void
14449c_parser_objc_alias_declaration (c_parser *parser)
14450{
14451 tree id1, id2;
14452 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
14453 c_parser_consume_token (parser);
14454 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14455 {
14456 c_parser_error (parser, gmsgid: "expected identifier");
14457 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14458 return;
14459 }
14460 id1 = c_parser_peek_token (parser)->value;
14461 c_parser_consume_token (parser);
14462 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14463 {
14464 c_parser_error (parser, gmsgid: "expected identifier");
14465 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
14466 return;
14467 }
14468 id2 = c_parser_peek_token (parser)->value;
14469 c_parser_consume_token (parser);
14470 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14471 objc_declare_alias (id1, id2);
14472}
14473
14474/* Parse an objc-protocol-definition.
14475
14476 objc-protocol-definition:
14477 @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
14478 @protocol identifier-list ;
14479
14480 "@protocol identifier ;" should be resolved as "@protocol
14481 identifier-list ;": objc-methodprotolist may not start with a
14482 semicolon in the first alternative if objc-protocol-refs are
14483 omitted. */
14484
14485static void
14486c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
14487{
14488 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
14489
14490 c_parser_consume_token (parser);
14491 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14492 {
14493 c_parser_error (parser, gmsgid: "expected identifier");
14494 return;
14495 }
14496 if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
14497 || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
14498 {
14499 /* Any identifiers, including those declared as type names, are
14500 OK here. */
14501 while (true)
14502 {
14503 tree id;
14504 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14505 {
14506 c_parser_error (parser, gmsgid: "expected identifier");
14507 break;
14508 }
14509 id = c_parser_peek_token (parser)->value;
14510 objc_declare_protocol (id, attributes);
14511 c_parser_consume_token (parser);
14512 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14513 c_parser_consume_token (parser);
14514 else
14515 break;
14516 }
14517 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14518 }
14519 else
14520 {
14521 tree id = c_parser_peek_token (parser)->value;
14522 tree proto = NULL_TREE;
14523 c_parser_consume_token (parser);
14524 if (c_parser_next_token_is (parser, type: CPP_LESS))
14525 proto = c_parser_objc_protocol_refs (parser);
14526 parser->objc_pq_context = true;
14527 objc_start_protocol (id, proto, attributes);
14528 c_parser_objc_methodprotolist (parser);
14529 c_parser_require_keyword (parser, keyword: RID_AT_END, msgid: "expected %<@end%>");
14530 parser->objc_pq_context = false;
14531 objc_finish_interface ();
14532 }
14533}
14534
14535/* Parse an objc-method-type.
14536
14537 objc-method-type:
14538 +
14539 -
14540
14541 Return true if it is a class method (+) and false if it is
14542 an instance method (-).
14543*/
14544static inline bool
14545c_parser_objc_method_type (c_parser *parser)
14546{
14547 switch (c_parser_peek_token (parser)->type)
14548 {
14549 case CPP_PLUS:
14550 c_parser_consume_token (parser);
14551 return true;
14552 case CPP_MINUS:
14553 c_parser_consume_token (parser);
14554 return false;
14555 default:
14556 gcc_unreachable ();
14557 }
14558}
14559
14560/* Parse an objc-method-definition.
14561
14562 objc-method-definition:
14563 objc-method-type objc-method-decl ;[opt] compound-statement
14564*/
14565
14566static void
14567c_parser_objc_method_definition (c_parser *parser)
14568{
14569 bool is_class_method = c_parser_objc_method_type (parser);
14570 tree decl, attributes = NULL_TREE, expr = NULL_TREE;
14571 parser->objc_pq_context = true;
14572 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14573 &expr);
14574 if (decl == error_mark_node)
14575 return; /* Bail here. */
14576
14577 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14578 {
14579 c_parser_consume_token (parser);
14580 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14581 "extra semicolon in method definition specified");
14582 }
14583
14584 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
14585 {
14586 c_parser_error (parser, gmsgid: "expected %<{%>");
14587 return;
14588 }
14589
14590 parser->objc_pq_context = false;
14591 if (objc_start_method_definition (is_class_method, decl, attributes, expr))
14592 {
14593 add_stmt (c_parser_compound_statement (parser));
14594 objc_finish_method_definition (current_function_decl);
14595 }
14596 else
14597 {
14598 /* This code is executed when we find a method definition
14599 outside of an @implementation context (or invalid for other
14600 reasons). Parse the method (to keep going) but do not emit
14601 any code.
14602 */
14603 c_parser_compound_statement (parser);
14604 }
14605}
14606
14607/* Parse an objc-methodprotolist.
14608
14609 objc-methodprotolist:
14610 empty
14611 objc-methodprotolist objc-methodproto
14612 objc-methodprotolist declaration
14613 objc-methodprotolist ;
14614 @optional
14615 @required
14616
14617 The declaration is a data definition, which may be missing
14618 declaration specifiers under the same rules and diagnostics as
14619 other data definitions outside functions, and the stray semicolon
14620 is diagnosed the same way as a stray semicolon outside a
14621 function. */
14622
14623static void
14624c_parser_objc_methodprotolist (c_parser *parser)
14625{
14626 while (true)
14627 {
14628 /* The list is terminated by @end. */
14629 switch (c_parser_peek_token (parser)->type)
14630 {
14631 case CPP_SEMICOLON:
14632 pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
14633 "ISO C does not allow extra %<;%> outside of a function");
14634 c_parser_consume_token (parser);
14635 break;
14636 case CPP_PLUS:
14637 case CPP_MINUS:
14638 c_parser_objc_methodproto (parser);
14639 break;
14640 case CPP_PRAGMA:
14641 c_parser_pragma (parser, pragma_external, NULL, NULL_TREE);
14642 break;
14643 case CPP_EOF:
14644 return;
14645 default:
14646 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_END))
14647 return;
14648 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_PROPERTY))
14649 c_parser_objc_at_property_declaration (parser);
14650 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_OPTIONAL))
14651 {
14652 objc_set_method_opt (true);
14653 c_parser_consume_token (parser);
14654 }
14655 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_REQUIRED))
14656 {
14657 objc_set_method_opt (false);
14658 c_parser_consume_token (parser);
14659 }
14660 else
14661 c_parser_declaration_or_fndef (parser, fndef_ok: false, static_assert_ok: false, empty_ok: true,
14662 nested: false, start_attr_ok: true, simple_ok: false);
14663 break;
14664 }
14665 }
14666}
14667
14668/* Parse an objc-methodproto.
14669
14670 objc-methodproto:
14671 objc-method-type objc-method-decl ;
14672*/
14673
14674static void
14675c_parser_objc_methodproto (c_parser *parser)
14676{
14677 bool is_class_method = c_parser_objc_method_type (parser);
14678 tree decl, attributes = NULL_TREE;
14679
14680 /* Remember protocol qualifiers in prototypes. */
14681 parser->objc_pq_context = true;
14682 decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
14683 NULL);
14684 /* Forget protocol qualifiers now. */
14685 parser->objc_pq_context = false;
14686
14687 /* Do not allow the presence of attributes to hide an erroneous
14688 method implementation in the interface section. */
14689 if (!c_parser_next_token_is (parser, type: CPP_SEMICOLON))
14690 {
14691 c_parser_error (parser, gmsgid: "expected %<;%>");
14692 return;
14693 }
14694
14695 if (decl != error_mark_node)
14696 objc_add_method_declaration (is_class_method, decl, attributes);
14697
14698 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
14699}
14700
14701/* If we are at a position that method attributes may be present, check that
14702 there are not any parsed already (a syntax error) and then collect any
14703 specified at the current location. Finally, if new attributes were present,
14704 check that the next token is legal ( ';' for decls and '{' for defs). */
14705
14706static bool
14707c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
14708{
14709 bool bad = false;
14710 if (*attributes)
14711 {
14712 c_parser_error (parser,
14713 gmsgid: "method attributes must be specified at the end only");
14714 *attributes = NULL_TREE;
14715 bad = true;
14716 }
14717
14718 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
14719 *attributes = c_parser_gnu_attributes (parser);
14720
14721 /* If there were no attributes here, just report any earlier error. */
14722 if (*attributes == NULL_TREE || bad)
14723 return bad;
14724
14725 /* If the attributes are followed by a ; or {, then just report any earlier
14726 error. */
14727 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
14728 || c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
14729 return bad;
14730
14731 /* We've got attributes, but not at the end. */
14732 c_parser_error (parser,
14733 gmsgid: "expected %<;%> or %<{%> after method attribute definition");
14734 return true;
14735}
14736
14737/* Parse an objc-method-decl.
14738
14739 objc-method-decl:
14740 ( objc-type-name ) objc-selector
14741 objc-selector
14742 ( objc-type-name ) objc-keyword-selector objc-optparmlist
14743 objc-keyword-selector objc-optparmlist
14744 gnu-attributes
14745
14746 objc-keyword-selector:
14747 objc-keyword-decl
14748 objc-keyword-selector objc-keyword-decl
14749
14750 objc-keyword-decl:
14751 objc-selector : ( objc-type-name ) identifier
14752 objc-selector : identifier
14753 : ( objc-type-name ) identifier
14754 : identifier
14755
14756 objc-optparmlist:
14757 objc-optparms objc-optellipsis
14758
14759 objc-optparms:
14760 empty
14761 objc-opt-parms , parameter-declaration
14762
14763 objc-optellipsis:
14764 empty
14765 , ...
14766*/
14767
14768static tree
14769c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
14770 tree *attributes, tree *expr)
14771{
14772 tree type = NULL_TREE;
14773 tree sel;
14774 tree parms = NULL_TREE;
14775 bool ellipsis = false;
14776 bool attr_err = false;
14777
14778 *attributes = NULL_TREE;
14779 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
14780 {
14781 matching_parens parens;
14782 parens.consume_open (parser);
14783 type = c_parser_objc_type_name (parser);
14784 parens.skip_until_found_close (parser);
14785 }
14786 sel = c_parser_objc_selector (parser);
14787 /* If there is no selector, or a colon follows, we have an
14788 objc-keyword-selector. If there is a selector, and a colon does
14789 not follow, that selector ends the objc-method-decl. */
14790 if (!sel || c_parser_next_token_is (parser, type: CPP_COLON))
14791 {
14792 tree tsel = sel;
14793 tree list = NULL_TREE;
14794 while (true)
14795 {
14796 tree atype = NULL_TREE, id, keyworddecl;
14797 tree param_attr = NULL_TREE;
14798 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
14799 break;
14800 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
14801 {
14802 c_parser_consume_token (parser);
14803 atype = c_parser_objc_type_name (parser);
14804 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
14805 msgid: "expected %<)%>");
14806 }
14807 /* New ObjC allows attributes on method parameters. */
14808 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
14809 param_attr = c_parser_gnu_attributes (parser);
14810 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14811 {
14812 c_parser_error (parser, gmsgid: "expected identifier");
14813 return error_mark_node;
14814 }
14815 id = c_parser_peek_token (parser)->value;
14816 c_parser_consume_token (parser);
14817 keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
14818 list = chainon (list, keyworddecl);
14819 tsel = c_parser_objc_selector (parser);
14820 if (!tsel && c_parser_next_token_is_not (parser, type: CPP_COLON))
14821 break;
14822 }
14823
14824 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14825
14826 /* Parse the optional parameter list. Optional Objective-C
14827 method parameters follow the C syntax, and may include '...'
14828 to denote a variable number of arguments. */
14829 parms = make_node (TREE_LIST);
14830 while (c_parser_next_token_is (parser, type: CPP_COMMA))
14831 {
14832 struct c_parm *parm;
14833 c_parser_consume_token (parser);
14834 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
14835 {
14836 ellipsis = true;
14837 c_parser_consume_token (parser);
14838 attr_err |= c_parser_objc_maybe_method_attributes
14839 (parser, attributes) ;
14840 break;
14841 }
14842 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
14843 if (parm == NULL)
14844 break;
14845 parms = chainon (parms,
14846 build_tree_list (NULL_TREE, grokparm (parm, expr)));
14847 }
14848 sel = list;
14849 }
14850 else
14851 attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
14852
14853 if (sel == NULL)
14854 {
14855 c_parser_error (parser, gmsgid: "objective-c method declaration is expected");
14856 return error_mark_node;
14857 }
14858
14859 if (attr_err)
14860 return error_mark_node;
14861
14862 return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
14863}
14864
14865/* Parse an objc-type-name.
14866
14867 objc-type-name:
14868 objc-type-qualifiers[opt] type-name
14869 objc-type-qualifiers[opt]
14870
14871 objc-type-qualifiers:
14872 objc-type-qualifier
14873 objc-type-qualifiers objc-type-qualifier
14874
14875 objc-type-qualifier: one of
14876 in out inout bycopy byref oneway
14877*/
14878
14879static tree
14880c_parser_objc_type_name (c_parser *parser)
14881{
14882 tree quals = NULL_TREE;
14883 struct c_type_name *type_name = NULL;
14884 tree type = NULL_TREE;
14885 while (true)
14886 {
14887 c_token *token = c_parser_peek_token (parser);
14888 if (token->type == CPP_KEYWORD
14889 && (token->keyword == RID_IN
14890 || token->keyword == RID_OUT
14891 || token->keyword == RID_INOUT
14892 || token->keyword == RID_BYCOPY
14893 || token->keyword == RID_BYREF
14894 || token->keyword == RID_ONEWAY))
14895 {
14896 quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
14897 c_parser_consume_token (parser);
14898 }
14899 else
14900 break;
14901 }
14902 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_type))
14903 type_name = c_parser_type_name (parser);
14904 if (type_name)
14905 type = groktypename (type_name, NULL, NULL);
14906
14907 /* If the type is unknown, and error has already been produced and
14908 we need to recover from the error. In that case, use NULL_TREE
14909 for the type, as if no type had been specified; this will use the
14910 default type ('id') which is good for error recovery. */
14911 if (type == error_mark_node)
14912 type = NULL_TREE;
14913
14914 return build_tree_list (quals, type);
14915}
14916
14917/* Parse objc-protocol-refs.
14918
14919 objc-protocol-refs:
14920 < identifier-list >
14921*/
14922
14923static tree
14924c_parser_objc_protocol_refs (c_parser *parser)
14925{
14926 tree list = NULL_TREE;
14927 gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
14928 c_parser_consume_token (parser);
14929 /* Any identifiers, including those declared as type names, are OK
14930 here. */
14931 while (true)
14932 {
14933 tree id;
14934 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
14935 {
14936 c_parser_error (parser, gmsgid: "expected identifier");
14937 break;
14938 }
14939 id = c_parser_peek_token (parser)->value;
14940 list = chainon (list, build_tree_list (NULL_TREE, id));
14941 c_parser_consume_token (parser);
14942 if (c_parser_next_token_is (parser, type: CPP_COMMA))
14943 c_parser_consume_token (parser);
14944 else
14945 break;
14946 }
14947 c_parser_require (parser, type: CPP_GREATER, msgid: "expected %<>%>");
14948 return list;
14949}
14950
14951/* Parse an objc-try-catch-finally-statement.
14952
14953 objc-try-catch-finally-statement:
14954 @try compound-statement objc-catch-list[opt]
14955 @try compound-statement objc-catch-list[opt] @finally compound-statement
14956
14957 objc-catch-list:
14958 @catch ( objc-catch-parameter-declaration ) compound-statement
14959 objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
14960
14961 objc-catch-parameter-declaration:
14962 parameter-declaration
14963 '...'
14964
14965 where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
14966
14967 PS: This function is identical to cp_parser_objc_try_catch_finally_statement
14968 for C++. Keep them in sync. */
14969
14970static void
14971c_parser_objc_try_catch_finally_statement (c_parser *parser)
14972{
14973 location_t location;
14974 tree stmt;
14975
14976 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
14977 c_parser_consume_token (parser);
14978 location = c_parser_peek_token (parser)->location;
14979 objc_maybe_warn_exceptions (location);
14980 stmt = c_parser_compound_statement (parser);
14981 objc_begin_try_stmt (location, stmt);
14982
14983 while (c_parser_next_token_is_keyword (parser, keyword: RID_AT_CATCH))
14984 {
14985 struct c_parm *parm;
14986 tree parameter_declaration = error_mark_node;
14987 bool seen_open_paren = false;
14988
14989 c_parser_consume_token (parser);
14990 matching_parens parens;
14991 if (!parens.require_open (parser))
14992 seen_open_paren = true;
14993 if (c_parser_next_token_is (parser, type: CPP_ELLIPSIS))
14994 {
14995 /* We have "@catch (...)" (where the '...' are literally
14996 what is in the code). Skip the '...'.
14997 parameter_declaration is set to NULL_TREE, and
14998 objc_being_catch_clauses() knows that that means
14999 '...'. */
15000 c_parser_consume_token (parser);
15001 parameter_declaration = NULL_TREE;
15002 }
15003 else
15004 {
15005 /* We have "@catch (NSException *exception)" or something
15006 like that. Parse the parameter declaration. */
15007 parm = c_parser_parameter_declaration (parser, NULL_TREE, have_gnu_attrs: false);
15008 if (parm == NULL)
15009 parameter_declaration = error_mark_node;
15010 else
15011 parameter_declaration = grokparm (parm, NULL);
15012 }
15013 if (seen_open_paren)
15014 parens.require_close (parser);
15015 else
15016 {
15017 /* If there was no open parenthesis, we are recovering from
15018 an error, and we are trying to figure out what mistake
15019 the user has made. */
15020
15021 /* If there is an immediate closing parenthesis, the user
15022 probably forgot the opening one (ie, they typed "@catch
15023 NSException *e)". Parse the closing parenthesis and keep
15024 going. */
15025 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
15026 c_parser_consume_token (parser);
15027
15028 /* If these is no immediate closing parenthesis, the user
15029 probably doesn't know that parenthesis are required at
15030 all (ie, they typed "@catch NSException *e"). So, just
15031 forget about the closing parenthesis and keep going. */
15032 }
15033 objc_begin_catch_clause (parameter_declaration);
15034 if (c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
15035 c_parser_compound_statement_nostart (parser);
15036 objc_finish_catch_clause ();
15037 }
15038 if (c_parser_next_token_is_keyword (parser, keyword: RID_AT_FINALLY))
15039 {
15040 c_parser_consume_token (parser);
15041 location = c_parser_peek_token (parser)->location;
15042 stmt = c_parser_compound_statement (parser);
15043 objc_build_finally_clause (location, stmt);
15044 }
15045 objc_finish_try_stmt ();
15046}
15047
15048/* Parse an objc-synchronized-statement.
15049
15050 objc-synchronized-statement:
15051 @synchronized ( expression ) compound-statement
15052*/
15053
15054static void
15055c_parser_objc_synchronized_statement (c_parser *parser)
15056{
15057 location_t loc;
15058 tree expr, stmt;
15059 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
15060 c_parser_consume_token (parser);
15061 loc = c_parser_peek_token (parser)->location;
15062 objc_maybe_warn_exceptions (loc);
15063 matching_parens parens;
15064 if (parens.require_open (parser))
15065 {
15066 struct c_expr ce = c_parser_expression (parser);
15067 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15068 expr = ce.value;
15069 expr = c_fully_fold (expr, false, NULL);
15070 parens.skip_until_found_close (parser);
15071 }
15072 else
15073 expr = error_mark_node;
15074 stmt = c_parser_compound_statement (parser);
15075 objc_build_synchronized (loc, expr, stmt);
15076}
15077
15078/* Parse an objc-selector; return NULL_TREE without an error if the
15079 next token is not an objc-selector.
15080
15081 objc-selector:
15082 identifier
15083 one of
15084 enum struct union if else while do for switch case default
15085 break continue return goto asm sizeof typeof typeof_unqual __alignof
15086 unsigned long const short volatile signed restrict _Complex
15087 in out inout bycopy byref oneway int char float double void _Bool
15088 _Atomic
15089
15090 ??? Why this selection of keywords but not, for example, storage
15091 class specifiers? */
15092
15093static tree
15094c_parser_objc_selector (c_parser *parser)
15095{
15096 c_token *token = c_parser_peek_token (parser);
15097 tree value = token->value;
15098 if (token->type == CPP_NAME)
15099 {
15100 c_parser_consume_token (parser);
15101 return value;
15102 }
15103 if (token->type != CPP_KEYWORD)
15104 return NULL_TREE;
15105 switch (token->keyword)
15106 {
15107 case RID_ENUM:
15108 case RID_STRUCT:
15109 case RID_UNION:
15110 case RID_IF:
15111 case RID_ELSE:
15112 case RID_WHILE:
15113 case RID_DO:
15114 case RID_FOR:
15115 case RID_SWITCH:
15116 case RID_CASE:
15117 case RID_DEFAULT:
15118 case RID_BREAK:
15119 case RID_CONTINUE:
15120 case RID_RETURN:
15121 case RID_GOTO:
15122 case RID_ASM:
15123 case RID_SIZEOF:
15124 case RID_TYPEOF:
15125 case RID_TYPEOF_UNQUAL:
15126 case RID_ALIGNOF:
15127 case RID_UNSIGNED:
15128 case RID_LONG:
15129 case RID_CONST:
15130 case RID_SHORT:
15131 case RID_VOLATILE:
15132 case RID_SIGNED:
15133 case RID_RESTRICT:
15134 case RID_COMPLEX:
15135 case RID_IN:
15136 case RID_OUT:
15137 case RID_INOUT:
15138 case RID_BYCOPY:
15139 case RID_BYREF:
15140 case RID_ONEWAY:
15141 case RID_INT:
15142 case RID_CHAR:
15143 case RID_FLOAT:
15144 case RID_DOUBLE:
15145 CASE_RID_FLOATN_NX:
15146 case RID_VOID:
15147 case RID_BOOL:
15148 case RID_ATOMIC:
15149 case RID_AUTO_TYPE:
15150 case RID_INT_N_0:
15151 case RID_INT_N_1:
15152 case RID_INT_N_2:
15153 case RID_INT_N_3:
15154 c_parser_consume_token (parser);
15155 return value;
15156 default:
15157 return NULL_TREE;
15158 }
15159}
15160
15161/* Parse an objc-selector-arg.
15162
15163 objc-selector-arg:
15164 objc-selector
15165 objc-keywordname-list
15166
15167 objc-keywordname-list:
15168 objc-keywordname
15169 objc-keywordname-list objc-keywordname
15170
15171 objc-keywordname:
15172 objc-selector :
15173 :
15174*/
15175
15176static tree
15177c_parser_objc_selector_arg (c_parser *parser)
15178{
15179 tree sel = c_parser_objc_selector (parser);
15180 tree list = NULL_TREE;
15181 if (sel
15182 && c_parser_next_token_is_not (parser, type: CPP_COLON)
15183 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
15184 return sel;
15185 while (true)
15186 {
15187 if (c_parser_next_token_is (parser, type: CPP_SCOPE))
15188 {
15189 c_parser_consume_token (parser);
15190 list = chainon (list, build_tree_list (sel, NULL_TREE));
15191 list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
15192 }
15193 else
15194 {
15195 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
15196 return list;
15197 list = chainon (list, build_tree_list (sel, NULL_TREE));
15198 }
15199 sel = c_parser_objc_selector (parser);
15200 if (!sel
15201 && c_parser_next_token_is_not (parser, type: CPP_COLON)
15202 && c_parser_next_token_is_not (parser, type: CPP_SCOPE))
15203 break;
15204 }
15205 return list;
15206}
15207
15208/* Parse an objc-receiver.
15209
15210 objc-receiver:
15211 expression
15212 class-name
15213 type-name
15214*/
15215
15216static tree
15217c_parser_objc_receiver (c_parser *parser)
15218{
15219 location_t loc = c_parser_peek_token (parser)->location;
15220
15221 if (c_parser_peek_token (parser)->type == CPP_NAME
15222 && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
15223 || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
15224 {
15225 tree id = c_parser_peek_token (parser)->value;
15226 c_parser_consume_token (parser);
15227 return objc_get_class_reference (id);
15228 }
15229 struct c_expr ce = c_parser_expression (parser);
15230 ce = convert_lvalue_to_rvalue (loc, ce, false, false);
15231 return c_fully_fold (ce.value, false, NULL);
15232}
15233
15234/* Parse objc-message-args.
15235
15236 objc-message-args:
15237 objc-selector
15238 objc-keywordarg-list
15239
15240 objc-keywordarg-list:
15241 objc-keywordarg
15242 objc-keywordarg-list objc-keywordarg
15243
15244 objc-keywordarg:
15245 objc-selector : objc-keywordexpr
15246 : objc-keywordexpr
15247*/
15248
15249static tree
15250c_parser_objc_message_args (c_parser *parser)
15251{
15252 tree sel = c_parser_objc_selector (parser);
15253 tree list = NULL_TREE;
15254 if (sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
15255 return sel;
15256 while (true)
15257 {
15258 tree keywordexpr;
15259 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
15260 return error_mark_node;
15261 keywordexpr = c_parser_objc_keywordexpr (parser);
15262 list = chainon (list, build_tree_list (sel, keywordexpr));
15263 sel = c_parser_objc_selector (parser);
15264 if (!sel && c_parser_next_token_is_not (parser, type: CPP_COLON))
15265 break;
15266 }
15267 return list;
15268}
15269
15270/* Parse an objc-keywordexpr.
15271
15272 objc-keywordexpr:
15273 nonempty-expr-list
15274*/
15275
15276static tree
15277c_parser_objc_keywordexpr (c_parser *parser)
15278{
15279 tree ret;
15280 vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, convert_p: true, fold_p: true,
15281 NULL, NULL, NULL, NULL);
15282 if (vec_safe_length (v: expr_list) == 1)
15283 {
15284 /* Just return the expression, remove a level of
15285 indirection. */
15286 ret = (*expr_list)[0];
15287 }
15288 else
15289 {
15290 /* We have a comma expression, we will collapse later. */
15291 ret = build_tree_list_vec (expr_list);
15292 }
15293 release_tree_vector (expr_list);
15294 return ret;
15295}
15296
15297/* A check, needed in several places, that ObjC interface, implementation or
15298 method definitions are not prefixed by incorrect items. */
15299static bool
15300c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
15301 struct c_declspecs *specs)
15302{
15303 if (!specs->declspecs_seen_p || specs->non_sc_seen_p
15304 || specs->typespec_kind != ctsk_none)
15305 {
15306 c_parser_error (parser,
15307 gmsgid: "no type or storage class may be specified here,");
15308 c_parser_skip_to_end_of_block_or_statement (parser);
15309 return true;
15310 }
15311 return false;
15312}
15313
15314/* Parse an Objective-C @property declaration. The syntax is:
15315
15316 objc-property-declaration:
15317 '@property' objc-property-attributes[opt] struct-declaration ;
15318
15319 objc-property-attributes:
15320 '(' objc-property-attribute-list ')'
15321
15322 objc-property-attribute-list:
15323 objc-property-attribute
15324 objc-property-attribute-list, objc-property-attribute
15325
15326 objc-property-attribute
15327 'getter' = identifier
15328 'setter' = identifier
15329 'readonly'
15330 'readwrite'
15331 'assign'
15332 'retain'
15333 'copy'
15334 'nonatomic'
15335
15336 For example:
15337 @property NSString *name;
15338 @property (readonly) id object;
15339 @property (retain, nonatomic, getter=getTheName) id name;
15340 @property int a, b, c;
15341
15342 PS: This function is identical to cp_parser_objc_at_propery_declaration
15343 for C++. Keep them in sync. */
15344static void
15345c_parser_objc_at_property_declaration (c_parser *parser)
15346{
15347 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
15348 location_t loc = c_parser_peek_token (parser)->location;
15349 c_parser_consume_token (parser); /* Eat '@property'. */
15350
15351 /* Parse the optional attribute list.
15352
15353 A list of parsed, but not verified, attributes. */
15354 vec<property_attribute_info *> prop_attr_list = vNULL;
15355
15356 bool syntax_error = false;
15357 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
15358 {
15359 matching_parens parens;
15360
15361 location_t attr_start = c_parser_peek_token (parser)->location;
15362 /* Eat the '(' */
15363 parens.consume_open (parser);
15364
15365 /* Property attribute keywords are valid now. */
15366 parser->objc_property_attr_context = true;
15367
15368 /* Allow @property (), with a warning. */
15369 location_t attr_end = c_parser_peek_token (parser)->location;
15370
15371 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
15372 {
15373 location_t attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15374 warning_at (attr_comb, OPT_Wattributes,
15375 "empty property attribute list");
15376 }
15377 else
15378 while (true)
15379 {
15380 c_token *token = c_parser_peek_token (parser);
15381 attr_start = token->location;
15382 attr_end = get_finish (loc: token->location);
15383 location_t attr_comb = make_location (caret: attr_start, start: attr_start,
15384 finish: attr_end);
15385
15386 if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
15387 {
15388 warning_at (attr_comb, OPT_Wattributes,
15389 "missing property attribute");
15390 if (token->type == CPP_CLOSE_PAREN)
15391 break;
15392 c_parser_consume_token (parser);
15393 continue;
15394 }
15395
15396 tree attr_name = NULL_TREE;
15397 enum rid keyword = RID_MAX; /* Not a valid property attribute. */
15398 bool add_at = false;
15399 if (token->type == CPP_KEYWORD)
15400 {
15401 keyword = token->keyword;
15402 if (OBJC_IS_AT_KEYWORD (keyword))
15403 {
15404 /* For '@' keywords the token value has the keyword,
15405 prepend the '@' for diagnostics. */
15406 attr_name = token->value;
15407 add_at = true;
15408 }
15409 else
15410 attr_name = ridpointers[(int)keyword];
15411 }
15412 else if (token->type == CPP_NAME)
15413 attr_name = token->value;
15414 c_parser_consume_token (parser);
15415
15416 enum objc_property_attribute_kind prop_kind
15417 = objc_prop_attr_kind_for_rid (keyword);
15418 property_attribute_info *prop
15419 = new property_attribute_info (attr_name, attr_comb, prop_kind);
15420 prop_attr_list.safe_push (obj: prop);
15421
15422 tree meth_name;
15423 switch (prop->prop_kind)
15424 {
15425 default: break;
15426 case OBJC_PROPERTY_ATTR_UNKNOWN:
15427 if (attr_name)
15428 error_at (attr_comb, "unknown property attribute %<%s%s%>",
15429 add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
15430 else
15431 error_at (attr_comb, "unknown property attribute");
15432 prop->parse_error = syntax_error = true;
15433 break;
15434
15435 case OBJC_PROPERTY_ATTR_GETTER:
15436 case OBJC_PROPERTY_ATTR_SETTER:
15437 if (c_parser_next_token_is_not (parser, type: CPP_EQ))
15438 {
15439 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15440 error_at (attr_comb, "expected %<=%> after Objective-C %qE",
15441 attr_name);
15442 prop->parse_error = syntax_error = true;
15443 break;
15444 }
15445 token = c_parser_peek_token (parser);
15446 attr_end = token->location;
15447 c_parser_consume_token (parser); /* eat the = */
15448 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15449 {
15450 attr_comb = make_location (caret: attr_end, start: attr_start, finish: attr_end);
15451 error_at (attr_comb, "expected %qE selector name",
15452 attr_name);
15453 prop->parse_error = syntax_error = true;
15454 break;
15455 }
15456 /* Get the end of the method name, and consume the name. */
15457 token = c_parser_peek_token (parser);
15458 attr_end = get_finish (loc: token->location);
15459 meth_name = token->value;
15460 c_parser_consume_token (parser);
15461 if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
15462 {
15463 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
15464 {
15465 attr_comb = make_location (caret: attr_end, start: attr_start,
15466 finish: attr_end);
15467 error_at (attr_comb, "setter method names must"
15468 " terminate with %<:%>");
15469 prop->parse_error = syntax_error = true;
15470 }
15471 else
15472 {
15473 attr_end = get_finish (loc: c_parser_peek_token
15474 (parser)->location);
15475 c_parser_consume_token (parser);
15476 }
15477 attr_comb = make_location (caret: attr_start, start: attr_start,
15478 finish: attr_end);
15479 }
15480 else
15481 attr_comb = make_location (caret: attr_start, start: attr_start,
15482 finish: attr_end);
15483 prop->ident = meth_name;
15484 /* Updated location including all that was successfully
15485 parsed. */
15486 prop->prop_loc = attr_comb;
15487 break;
15488 }
15489
15490 /* If we see a comma here, then keep going - even if we already
15491 saw a syntax error. For simple mistakes e.g. (asign, getter=x)
15492 this makes a more useful output and avoid spurious warnings about
15493 missing attributes that are, in fact, specified after the one with
15494 the syntax error. */
15495 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15496 c_parser_consume_token (parser);
15497 else
15498 break;
15499 }
15500 parser->objc_property_attr_context = false;
15501
15502 if (syntax_error && c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
15503 /* We don't really want to chew the whole of the file looking for a
15504 matching closing parenthesis, so we will try to read the decl and
15505 let the error handling for that close out the statement. */
15506 ;
15507 else
15508 syntax_error = false, parens.skip_until_found_close (parser);
15509 }
15510
15511 /* 'properties' is the list of properties that we read. Usually a
15512 single one, but maybe more (eg, in "@property int a, b, c;" there
15513 are three). */
15514 tree properties = c_parser_struct_declaration (parser, NULL);
15515
15516 if (properties == error_mark_node)
15517 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15518 else
15519 {
15520 if (properties == NULL_TREE)
15521 c_parser_error (parser, gmsgid: "expected identifier");
15522 else
15523 {
15524 /* Comma-separated properties are chained together in reverse order;
15525 add them one by one. */
15526 properties = nreverse (properties);
15527 for (; properties; properties = TREE_CHAIN (properties))
15528 objc_add_property_declaration (loc, copy_node (properties),
15529 prop_attr_list);
15530 }
15531 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15532 }
15533
15534 while (!prop_attr_list.is_empty())
15535 delete prop_attr_list.pop ();
15536 prop_attr_list.release ();
15537 parser->error = false;
15538}
15539
15540/* Parse an Objective-C @synthesize declaration. The syntax is:
15541
15542 objc-synthesize-declaration:
15543 @synthesize objc-synthesize-identifier-list ;
15544
15545 objc-synthesize-identifier-list:
15546 objc-synthesize-identifier
15547 objc-synthesize-identifier-list, objc-synthesize-identifier
15548
15549 objc-synthesize-identifier
15550 identifier
15551 identifier = identifier
15552
15553 For example:
15554 @synthesize MyProperty;
15555 @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
15556
15557 PS: This function is identical to cp_parser_objc_at_synthesize_declaration
15558 for C++. Keep them in sync.
15559*/
15560static void
15561c_parser_objc_at_synthesize_declaration (c_parser *parser)
15562{
15563 tree list = NULL_TREE;
15564 location_t loc;
15565 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
15566 loc = c_parser_peek_token (parser)->location;
15567
15568 c_parser_consume_token (parser);
15569 while (true)
15570 {
15571 tree property, ivar;
15572 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15573 {
15574 c_parser_error (parser, gmsgid: "expected identifier");
15575 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15576 /* Once we find the semicolon, we can resume normal parsing.
15577 We have to reset parser->error manually because
15578 c_parser_skip_until_found() won't reset it for us if the
15579 next token is precisely a semicolon. */
15580 parser->error = false;
15581 return;
15582 }
15583 property = c_parser_peek_token (parser)->value;
15584 c_parser_consume_token (parser);
15585 if (c_parser_next_token_is (parser, type: CPP_EQ))
15586 {
15587 c_parser_consume_token (parser);
15588 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15589 {
15590 c_parser_error (parser, gmsgid: "expected identifier");
15591 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15592 parser->error = false;
15593 return;
15594 }
15595 ivar = c_parser_peek_token (parser)->value;
15596 c_parser_consume_token (parser);
15597 }
15598 else
15599 ivar = NULL_TREE;
15600 list = chainon (list, build_tree_list (ivar, property));
15601 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15602 c_parser_consume_token (parser);
15603 else
15604 break;
15605 }
15606 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15607 objc_add_synthesize_declaration (loc, list);
15608}
15609
15610/* Parse an Objective-C @dynamic declaration. The syntax is:
15611
15612 objc-dynamic-declaration:
15613 @dynamic identifier-list ;
15614
15615 For example:
15616 @dynamic MyProperty;
15617 @dynamic MyProperty, AnotherProperty;
15618
15619 PS: This function is identical to cp_parser_objc_at_dynamic_declaration
15620 for C++. Keep them in sync.
15621*/
15622static void
15623c_parser_objc_at_dynamic_declaration (c_parser *parser)
15624{
15625 tree list = NULL_TREE;
15626 location_t loc;
15627 gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
15628 loc = c_parser_peek_token (parser)->location;
15629
15630 c_parser_consume_token (parser);
15631 while (true)
15632 {
15633 tree property;
15634 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
15635 {
15636 c_parser_error (parser, gmsgid: "expected identifier");
15637 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, NULL);
15638 parser->error = false;
15639 return;
15640 }
15641 property = c_parser_peek_token (parser)->value;
15642 list = chainon (list, build_tree_list (NULL_TREE, property));
15643 c_parser_consume_token (parser);
15644 if (c_parser_next_token_is (parser, type: CPP_COMMA))
15645 c_parser_consume_token (parser);
15646 else
15647 break;
15648 }
15649 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
15650 objc_add_dynamic_declaration (loc, list);
15651}
15652
15653
15654/* Parse a pragma GCC ivdep. */
15655
15656static bool
15657c_parse_pragma_ivdep (c_parser *parser)
15658{
15659 c_parser_consume_pragma (parser);
15660 c_parser_skip_to_pragma_eol (parser);
15661 return true;
15662}
15663
15664/* Parse a pragma GCC novector. */
15665
15666static bool
15667c_parse_pragma_novector (c_parser *parser)
15668{
15669 c_parser_consume_pragma (parser);
15670 c_parser_skip_to_pragma_eol (parser);
15671 return true;
15672}
15673
15674/* Parse a pragma GCC unroll. */
15675
15676static unsigned short
15677c_parser_pragma_unroll (c_parser *parser)
15678{
15679 unsigned short unroll;
15680 c_parser_consume_pragma (parser);
15681 location_t location = c_parser_peek_token (parser)->location;
15682 tree expr = c_parser_expr_no_commas (parser, NULL).value;
15683 mark_exp_read (expr);
15684 expr = c_fully_fold (expr, false, NULL);
15685 HOST_WIDE_INT lunroll = 0;
15686 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
15687 || TREE_CODE (expr) != INTEGER_CST
15688 || (lunroll = tree_to_shwi (expr)) < 0
15689 || lunroll >= USHRT_MAX)
15690 {
15691 error_at (location, "%<#pragma GCC unroll%> requires an"
15692 " assignment-expression that evaluates to a non-negative"
15693 " integral constant less than %u", USHRT_MAX);
15694 unroll = 0;
15695 }
15696 else
15697 {
15698 unroll = (unsigned short)lunroll;
15699 if (unroll == 0)
15700 unroll = 1;
15701 }
15702
15703 c_parser_skip_to_pragma_eol (parser);
15704 return unroll;
15705}
15706
15707/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
15708 should be considered, statements. ALLOW_STMT is true if we're within
15709 the context of a function and such pragmas are to be allowed. Returns
15710 true if we actually parsed such a pragma. BEFORE_LABELS is last statement
15711 before possible labels, see get_before_labels description for details. */
15712
15713static bool
15714c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p,
15715 tree before_labels)
15716{
15717 unsigned int id;
15718 const char *construct = NULL;
15719
15720 input_location = c_parser_peek_token (parser)->location;
15721 id = c_parser_peek_token (parser)->pragma_kind;
15722 gcc_assert (id != PRAGMA_NONE);
15723 if (parser->omp_for_parse_state
15724 && parser->omp_for_parse_state->in_intervening_code
15725 && id >= PRAGMA_OMP__START_
15726 && id <= PRAGMA_OMP__LAST_)
15727 {
15728 error_at (input_location,
15729 "intervening code must not contain OpenMP directives");
15730 parser->omp_for_parse_state->fail = true;
15731 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15732 return false;
15733 }
15734
15735 switch (id)
15736 {
15737 case PRAGMA_OACC_DECLARE:
15738 c_parser_oacc_declare (parser);
15739 return false;
15740
15741 case PRAGMA_OACC_ENTER_DATA:
15742 if (context != pragma_compound)
15743 {
15744 construct = "acc enter data";
15745 in_compound:
15746 if (context == pragma_stmt)
15747 {
15748 error_at (c_parser_peek_token (parser)->location,
15749 "%<#pragma %s%> may only be used in compound "
15750 "statements", construct);
15751 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15752 return true;
15753 }
15754 goto bad_stmt;
15755 }
15756 c_parser_oacc_enter_exit_data (parser, true);
15757 return false;
15758
15759 case PRAGMA_OACC_EXIT_DATA:
15760 if (context != pragma_compound)
15761 {
15762 construct = "acc exit data";
15763 goto in_compound;
15764 }
15765 c_parser_oacc_enter_exit_data (parser, false);
15766 return false;
15767
15768 case PRAGMA_OACC_ROUTINE:
15769 if (context != pragma_external)
15770 {
15771 error_at (c_parser_peek_token (parser)->location,
15772 "%<#pragma acc routine%> must be at file scope");
15773 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15774 return false;
15775 }
15776 c_parser_oacc_routine (parser, context);
15777 return false;
15778
15779 case PRAGMA_OACC_UPDATE:
15780 if (context != pragma_compound)
15781 {
15782 construct = "acc update";
15783 goto in_compound;
15784 }
15785 c_parser_oacc_update (parser);
15786 return false;
15787
15788 case PRAGMA_OMP_BARRIER:
15789 if (context != pragma_compound)
15790 {
15791 construct = "omp barrier";
15792 goto in_compound;
15793 }
15794 c_parser_omp_barrier (parser);
15795 return false;
15796
15797 case PRAGMA_OMP_DEPOBJ:
15798 if (context != pragma_compound)
15799 {
15800 construct = "omp depobj";
15801 goto in_compound;
15802 }
15803 c_parser_omp_depobj (parser);
15804 return false;
15805
15806 case PRAGMA_OMP_FLUSH:
15807 if (context != pragma_compound)
15808 {
15809 construct = "omp flush";
15810 goto in_compound;
15811 }
15812 c_parser_omp_flush (parser);
15813 return false;
15814
15815 case PRAGMA_OMP_INTEROP:
15816 if (context != pragma_compound)
15817 {
15818 construct = "omp interop";
15819 goto in_compound;
15820 }
15821 c_parser_omp_interop (parser);
15822 return false;
15823
15824 case PRAGMA_OMP_TASKWAIT:
15825 if (context != pragma_compound)
15826 {
15827 construct = "omp taskwait";
15828 goto in_compound;
15829 }
15830 c_parser_omp_taskwait (parser);
15831 return false;
15832
15833 case PRAGMA_OMP_TASKYIELD:
15834 if (context != pragma_compound)
15835 {
15836 construct = "omp taskyield";
15837 goto in_compound;
15838 }
15839 c_parser_omp_taskyield (parser);
15840 return false;
15841
15842 case PRAGMA_OMP_CANCEL:
15843 if (context != pragma_compound)
15844 {
15845 construct = "omp cancel";
15846 goto in_compound;
15847 }
15848 c_parser_omp_cancel (parser);
15849 return false;
15850
15851 case PRAGMA_OMP_CANCELLATION_POINT:
15852 return c_parser_omp_cancellation_point (parser, context);
15853
15854 case PRAGMA_OMP_THREADPRIVATE:
15855 c_parser_omp_threadprivate (parser);
15856 return false;
15857
15858 case PRAGMA_OMP_TARGET:
15859 return c_parser_omp_target (parser, context, if_p);
15860
15861 case PRAGMA_OMP_BEGIN:
15862 c_parser_omp_begin (parser);
15863 return false;
15864
15865 case PRAGMA_OMP_END:
15866 c_parser_omp_end (parser);
15867 return false;
15868
15869 case PRAGMA_OMP_SCAN:
15870 error_at (c_parser_peek_token (parser)->location,
15871 "%<#pragma omp scan%> may only be used in "
15872 "a loop construct with %<inscan%> %<reduction%> clause");
15873 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15874 return false;
15875
15876 case PRAGMA_OMP_SECTION:
15877 error_at (c_parser_peek_token (parser)->location,
15878 "%<#pragma omp section%> may only be used in "
15879 "%<#pragma omp sections%> construct");
15880 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15881 return false;
15882
15883 case PRAGMA_OMP_DECLARE:
15884 return c_parser_omp_declare (parser, context);
15885
15886 case PRAGMA_OMP_REQUIRES:
15887 if (context != pragma_external)
15888 {
15889 error_at (c_parser_peek_token (parser)->location,
15890 "%<#pragma %s%> may only be used at file scope",
15891 "omp requires");
15892 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15893 return false;
15894 }
15895 c_parser_omp_requires (parser);
15896 return false;
15897
15898 case PRAGMA_OMP_ALLOCATE:
15899 c_parser_omp_allocate (parser);
15900 return false;
15901
15902 case PRAGMA_OMP_ASSUMES:
15903 if (context != pragma_external)
15904 {
15905 error_at (c_parser_peek_token (parser)->location,
15906 "%<#pragma %s%> may only be used at file scope",
15907 "omp assumes");
15908 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15909 return false;
15910 }
15911 c_parser_omp_assumes (parser);
15912 return false;
15913
15914 case PRAGMA_OMP_NOTHING:
15915 c_parser_omp_nothing (parser);
15916 return false;
15917
15918 case PRAGMA_OMP_METADIRECTIVE:
15919 c_parser_omp_metadirective (parser, if_p);
15920 return true;
15921
15922 case PRAGMA_OMP_ERROR:
15923 return c_parser_omp_error (parser, context);
15924
15925 case PRAGMA_OMP_ORDERED:
15926 return c_parser_omp_ordered (parser, context, if_p);
15927
15928 case PRAGMA_NOVECTOR:
15929 case PRAGMA_UNROLL:
15930 case PRAGMA_IVDEP:
15931 {
15932 bool novector = false;
15933 unsigned short unroll = 0;
15934 bool ivdep = false;
15935
15936 switch (id)
15937 {
15938 case PRAGMA_NOVECTOR:
15939 novector = c_parse_pragma_novector (parser);
15940 break;
15941 case PRAGMA_UNROLL:
15942 unroll = c_parser_pragma_unroll (parser);
15943 break;
15944 case PRAGMA_IVDEP:
15945 ivdep = c_parse_pragma_ivdep (parser);
15946 break;
15947 default:
15948 gcc_unreachable ();
15949 }
15950
15951 c_token *tok = c_parser_peek_token (parser);
15952 bool has_more = tok->type == CPP_PRAGMA;
15953 while (has_more)
15954 {
15955 switch (tok->pragma_kind)
15956 {
15957 case PRAGMA_IVDEP:
15958 ivdep = c_parse_pragma_ivdep (parser);
15959 break;
15960 case PRAGMA_UNROLL:
15961 unroll = c_parser_pragma_unroll (parser);
15962 break;
15963 case PRAGMA_NOVECTOR:
15964 novector = c_parse_pragma_novector (parser);
15965 break;
15966 default:
15967 has_more = false;
15968 break;
15969 }
15970 tok = c_parser_peek_token (parser);
15971 has_more = has_more && tok->type == CPP_PRAGMA;
15972 }
15973 if (!c_parser_next_token_is_keyword (parser, keyword: RID_FOR)
15974 && !c_parser_next_token_is_keyword (parser, keyword: RID_WHILE)
15975 && !c_parser_next_token_is_keyword (parser, keyword: RID_DO))
15976 {
15977 c_parser_error (parser, gmsgid: "for, while or do statement expected");
15978 return false;
15979 }
15980 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
15981 c_parser_for_statement (parser, ivdep, unroll, novector, if_p,
15982 before_labels);
15983 else if (c_parser_next_token_is_keyword (parser, keyword: RID_WHILE))
15984 c_parser_while_statement (parser, ivdep, unroll, novector, if_p,
15985 before_labels);
15986 else
15987 c_parser_do_statement (parser, ivdep, unroll, novector,
15988 before_labels);
15989 }
15990 return true;
15991
15992 case PRAGMA_GCC_PCH_PREPROCESS:
15993 c_parser_error (parser, gmsgid: "%<#pragma GCC pch_preprocess%> must be first");
15994 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
15995 return false;
15996
15997 case PRAGMA_OACC_WAIT:
15998 if (context != pragma_compound)
15999 {
16000 construct = "acc wait";
16001 goto in_compound;
16002 }
16003 /* FALL THROUGH. */
16004
16005 default:
16006 if (id < PRAGMA_FIRST_EXTERNAL)
16007 {
16008 if (context != pragma_stmt && context != pragma_compound)
16009 {
16010 bad_stmt:
16011 c_parser_error (parser, gmsgid: "expected declaration specifiers");
16012 c_parser_skip_until_found (parser, type: CPP_PRAGMA_EOL, NULL);
16013 return false;
16014 }
16015 c_parser_omp_construct (parser, if_p);
16016 return true;
16017 }
16018 break;
16019 }
16020
16021 c_parser_consume_pragma (parser);
16022 c_invoke_pragma_handler (id);
16023
16024 /* Skip to EOL, but suppress any error message. Those will have been
16025 generated by the handler routine through calling error, as opposed
16026 to calling c_parser_error. */
16027 parser->error = true;
16028 c_parser_skip_to_pragma_eol (parser);
16029
16030 return false;
16031}
16032
16033/* The interface the pragma parsers have to the lexer. */
16034
16035enum cpp_ttype
16036pragma_lex (tree *value, location_t *loc)
16037{
16038 c_token *tok = c_parser_peek_token (parser: the_parser);
16039 enum cpp_ttype ret = tok->type;
16040
16041 *value = tok->value;
16042 if (loc)
16043 *loc = tok->location;
16044
16045 if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
16046 ret = CPP_EOF;
16047 else if (ret == CPP_STRING)
16048 *value = c_parser_string_literal (parser: the_parser, translate: false, wide_ok: false).value;
16049 else
16050 {
16051 if (ret == CPP_KEYWORD)
16052 ret = CPP_NAME;
16053 c_parser_consume_token (parser: the_parser);
16054 }
16055
16056 return ret;
16057}
16058
16059void
16060pragma_lex_discard_to_eol ()
16061{
16062 cpp_ttype type;
16063 do
16064 {
16065 type = c_parser_peek_token (parser: the_parser)->type;
16066 gcc_assert (type != CPP_EOF);
16067 c_parser_consume_token (parser: the_parser);
16068 } while (type != CPP_PRAGMA_EOL);
16069}
16070
16071static void
16072c_parser_pragma_pch_preprocess (c_parser *parser)
16073{
16074 tree name = NULL;
16075
16076 parser->lex_joined_string = true;
16077 c_parser_consume_pragma (parser);
16078 if (c_parser_next_token_is (parser, type: CPP_STRING))
16079 {
16080 name = c_parser_peek_token (parser)->value;
16081 c_parser_consume_token (parser);
16082 }
16083 else
16084 c_parser_error (parser, gmsgid: "expected string literal");
16085 c_parser_skip_to_pragma_eol (parser);
16086 parser->lex_joined_string = false;
16087
16088 if (name)
16089 c_common_pch_pragma (pfile: parse_in, TREE_STRING_POINTER (name));
16090}
16091
16092/* OpenACC and OpenMP parsing routines. */
16093
16094/* Returns name of the next clause.
16095 If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
16096 the token is not consumed. Otherwise appropriate pragma_omp_clause is
16097 returned and the token is consumed. */
16098
16099static pragma_omp_clause
16100c_parser_omp_clause_name (c_parser *parser)
16101{
16102 pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
16103
16104 if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
16105 result = PRAGMA_OACC_CLAUSE_AUTO;
16106 else if (c_parser_next_token_is_keyword (parser, keyword: RID_IF))
16107 result = PRAGMA_OMP_CLAUSE_IF;
16108 else if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
16109 result = PRAGMA_OMP_CLAUSE_DEFAULT;
16110 else if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
16111 result = PRAGMA_OMP_CLAUSE_FOR;
16112 else if (c_parser_next_token_is (parser, type: CPP_NAME))
16113 {
16114 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
16115
16116 switch (p[0])
16117 {
16118 case 'a':
16119 if (!strcmp (s1: "affinity", s2: p))
16120 result = PRAGMA_OMP_CLAUSE_AFFINITY;
16121 else if (!strcmp (s1: "aligned", s2: p))
16122 result = PRAGMA_OMP_CLAUSE_ALIGNED;
16123 else if (!strcmp (s1: "allocate", s2: p))
16124 result = PRAGMA_OMP_CLAUSE_ALLOCATE;
16125 else if (!strcmp (s1: "async", s2: p))
16126 result = PRAGMA_OACC_CLAUSE_ASYNC;
16127 else if (!strcmp (s1: "attach", s2: p))
16128 result = PRAGMA_OACC_CLAUSE_ATTACH;
16129 break;
16130 case 'b':
16131 if (!strcmp (s1: "bind", s2: p))
16132 result = PRAGMA_OMP_CLAUSE_BIND;
16133 break;
16134 case 'c':
16135 if (!strcmp (s1: "collapse", s2: p))
16136 result = PRAGMA_OMP_CLAUSE_COLLAPSE;
16137 else if (!strcmp (s1: "copy", s2: p))
16138 result = PRAGMA_OACC_CLAUSE_COPY;
16139 else if (!strcmp (s1: "copyin", s2: p))
16140 result = PRAGMA_OMP_CLAUSE_COPYIN;
16141 else if (!strcmp (s1: "copyout", s2: p))
16142 result = PRAGMA_OACC_CLAUSE_COPYOUT;
16143 else if (!strcmp (s1: "copyprivate", s2: p))
16144 result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
16145 else if (!strcmp (s1: "create", s2: p))
16146 result = PRAGMA_OACC_CLAUSE_CREATE;
16147 break;
16148 case 'd':
16149 if (!strcmp (s1: "defaultmap", s2: p))
16150 result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
16151 else if (!strcmp (s1: "delete", s2: p))
16152 result = PRAGMA_OACC_CLAUSE_DELETE;
16153 else if (!strcmp (s1: "depend", s2: p))
16154 result = PRAGMA_OMP_CLAUSE_DEPEND;
16155 else if (!strcmp (s1: "destroy", s2: p))
16156 result = PRAGMA_OMP_CLAUSE_DESTROY;
16157 else if (!strcmp (s1: "detach", s2: p))
16158 result = PRAGMA_OACC_CLAUSE_DETACH;
16159 else if (!strcmp (s1: "device", s2: p))
16160 result = PRAGMA_OMP_CLAUSE_DEVICE;
16161 else if (!strcmp (s1: "deviceptr", s2: p))
16162 result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
16163 else if (!strcmp (s1: "device_resident", s2: p))
16164 result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
16165 else if (!strcmp (s1: "device_type", s2: p))
16166 result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
16167 else if (!strcmp (s1: "dist_schedule", s2: p))
16168 result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
16169 else if (!strcmp (s1: "doacross", s2: p))
16170 result = PRAGMA_OMP_CLAUSE_DOACROSS;
16171 break;
16172 case 'e':
16173 if (!strcmp (s1: "enter", s2: p))
16174 result = PRAGMA_OMP_CLAUSE_ENTER;
16175 break;
16176 case 'f':
16177 if (!strcmp (s1: "filter", s2: p))
16178 result = PRAGMA_OMP_CLAUSE_FILTER;
16179 else if (!strcmp (s1: "final", s2: p))
16180 result = PRAGMA_OMP_CLAUSE_FINAL;
16181 else if (!strcmp (s1: "finalize", s2: p))
16182 result = PRAGMA_OACC_CLAUSE_FINALIZE;
16183 else if (!strcmp (s1: "firstprivate", s2: p))
16184 result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
16185 else if (!strcmp (s1: "from", s2: p))
16186 result = PRAGMA_OMP_CLAUSE_FROM;
16187 else if (!strcmp (s1: "full", s2: p))
16188 result = PRAGMA_OMP_CLAUSE_FULL;
16189 break;
16190 case 'g':
16191 if (!strcmp (s1: "gang", s2: p))
16192 result = PRAGMA_OACC_CLAUSE_GANG;
16193 else if (!strcmp (s1: "grainsize", s2: p))
16194 result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
16195 break;
16196 case 'h':
16197 if (!strcmp (s1: "has_device_addr", s2: p))
16198 result = PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR;
16199 else if (!strcmp (s1: "hint", s2: p))
16200 result = PRAGMA_OMP_CLAUSE_HINT;
16201 else if (!strcmp (s1: "host", s2: p))
16202 result = PRAGMA_OACC_CLAUSE_HOST;
16203 break;
16204 case 'i':
16205 if (!strcmp (s1: "if_present", s2: p))
16206 result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
16207 else if (!strcmp (s1: "in_reduction", s2: p))
16208 result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
16209 else if (!strcmp (s1: "inbranch", s2: p))
16210 result = PRAGMA_OMP_CLAUSE_INBRANCH;
16211 else if (!strcmp (s1: "independent", s2: p))
16212 result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
16213 else if (!strcmp (s1: "indirect", s2: p))
16214 result = PRAGMA_OMP_CLAUSE_INDIRECT;
16215 else if (!strcmp (s1: "init", s2: p))
16216 result = PRAGMA_OMP_CLAUSE_INIT;
16217 else if (!strcmp (s1: "is_device_ptr", s2: p))
16218 result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
16219 else if (!strcmp (s1: "interop", s2: p))
16220 result = PRAGMA_OMP_CLAUSE_INTEROP;
16221 break;
16222 case 'l':
16223 if (!strcmp (s1: "lastprivate", s2: p))
16224 result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
16225 else if (!strcmp (s1: "linear", s2: p))
16226 result = PRAGMA_OMP_CLAUSE_LINEAR;
16227 else if (!strcmp (s1: "link", s2: p))
16228 result = PRAGMA_OMP_CLAUSE_LINK;
16229 break;
16230 case 'm':
16231 if (!strcmp (s1: "map", s2: p))
16232 result = PRAGMA_OMP_CLAUSE_MAP;
16233 else if (!strcmp (s1: "mergeable", s2: p))
16234 result = PRAGMA_OMP_CLAUSE_MERGEABLE;
16235 break;
16236 case 'n':
16237 if (!strcmp (s1: "no_create", s2: p))
16238 result = PRAGMA_OACC_CLAUSE_NO_CREATE;
16239 else if (!strcmp (s1: "nocontext", s2: p))
16240 result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
16241 else if (!strcmp (s1: "nogroup", s2: p))
16242 result = PRAGMA_OMP_CLAUSE_NOGROUP;
16243 else if (!strcmp (s1: "nohost", s2: p))
16244 result = PRAGMA_OACC_CLAUSE_NOHOST;
16245 else if (!strcmp (s1: "nontemporal", s2: p))
16246 result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
16247 else if (!strcmp (s1: "notinbranch", s2: p))
16248 result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
16249 else if (!strcmp (s1: "novariants", s2: p))
16250 result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
16251 else if (!strcmp (s1: "nowait", s2: p))
16252 result = PRAGMA_OMP_CLAUSE_NOWAIT;
16253 else if (!strcmp (s1: "num_gangs", s2: p))
16254 result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
16255 else if (!strcmp (s1: "num_tasks", s2: p))
16256 result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
16257 else if (!strcmp (s1: "num_teams", s2: p))
16258 result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
16259 else if (!strcmp (s1: "num_threads", s2: p))
16260 result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
16261 else if (!strcmp (s1: "num_workers", s2: p))
16262 result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
16263 break;
16264 case 'o':
16265 if (!strcmp (s1: "ordered", s2: p))
16266 result = PRAGMA_OMP_CLAUSE_ORDERED;
16267 else if (!strcmp (s1: "order", s2: p))
16268 result = PRAGMA_OMP_CLAUSE_ORDER;
16269 break;
16270 case 'p':
16271 if (!strcmp (s1: "parallel", s2: p))
16272 result = PRAGMA_OMP_CLAUSE_PARALLEL;
16273 else if (!strcmp (s1: "partial", s2: p))
16274 result = PRAGMA_OMP_CLAUSE_PARTIAL;
16275 else if (!strcmp (s1: "present", s2: p))
16276 result = PRAGMA_OACC_CLAUSE_PRESENT;
16277 /* As of OpenACC 2.5, these are now aliases of the non-present_or
16278 clauses. */
16279 else if (!strcmp (s1: "present_or_copy", s2: p)
16280 || !strcmp (s1: "pcopy", s2: p))
16281 result = PRAGMA_OACC_CLAUSE_COPY;
16282 else if (!strcmp (s1: "present_or_copyin", s2: p)
16283 || !strcmp (s1: "pcopyin", s2: p))
16284 result = PRAGMA_OACC_CLAUSE_COPYIN;
16285 else if (!strcmp (s1: "present_or_copyout", s2: p)
16286 || !strcmp (s1: "pcopyout", s2: p))
16287 result = PRAGMA_OACC_CLAUSE_COPYOUT;
16288 else if (!strcmp (s1: "present_or_create", s2: p)
16289 || !strcmp (s1: "pcreate", s2: p))
16290 result = PRAGMA_OACC_CLAUSE_CREATE;
16291 else if (!strcmp (s1: "priority", s2: p))
16292 result = PRAGMA_OMP_CLAUSE_PRIORITY;
16293 else if (!strcmp (s1: "private", s2: p))
16294 result = PRAGMA_OMP_CLAUSE_PRIVATE;
16295 else if (!strcmp (s1: "proc_bind", s2: p))
16296 result = PRAGMA_OMP_CLAUSE_PROC_BIND;
16297 break;
16298 case 'r':
16299 if (!strcmp (s1: "reduction", s2: p))
16300 result = PRAGMA_OMP_CLAUSE_REDUCTION;
16301 break;
16302 case 's':
16303 if (!strcmp (s1: "safelen", s2: p))
16304 result = PRAGMA_OMP_CLAUSE_SAFELEN;
16305 else if (!strcmp (s1: "schedule", s2: p))
16306 result = PRAGMA_OMP_CLAUSE_SCHEDULE;
16307 else if (!strcmp (s1: "sections", s2: p))
16308 result = PRAGMA_OMP_CLAUSE_SECTIONS;
16309 else if (!strcmp (s1: "self", s2: p))
16310 result = PRAGMA_OACC_CLAUSE_SELF;
16311 else if (!strcmp (s1: "seq", s2: p))
16312 result = PRAGMA_OACC_CLAUSE_SEQ;
16313 else if (!strcmp (s1: "shared", s2: p))
16314 result = PRAGMA_OMP_CLAUSE_SHARED;
16315 else if (!strcmp (s1: "simd", s2: p))
16316 result = PRAGMA_OMP_CLAUSE_SIMD;
16317 else if (!strcmp (s1: "simdlen", s2: p))
16318 result = PRAGMA_OMP_CLAUSE_SIMDLEN;
16319 break;
16320 case 't':
16321 if (!strcmp (s1: "task_reduction", s2: p))
16322 result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
16323 else if (!strcmp (s1: "taskgroup", s2: p))
16324 result = PRAGMA_OMP_CLAUSE_TASKGROUP;
16325 else if (!strcmp (s1: "thread_limit", s2: p))
16326 result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
16327 else if (!strcmp (s1: "threads", s2: p))
16328 result = PRAGMA_OMP_CLAUSE_THREADS;
16329 else if (!strcmp (s1: "tile", s2: p))
16330 result = PRAGMA_OACC_CLAUSE_TILE;
16331 else if (!strcmp (s1: "to", s2: p))
16332 result = PRAGMA_OMP_CLAUSE_TO;
16333 break;
16334 case 'u':
16335 if (!strcmp (s1: "uniform", s2: p))
16336 result = PRAGMA_OMP_CLAUSE_UNIFORM;
16337 else if (!strcmp (s1: "untied", s2: p))
16338 result = PRAGMA_OMP_CLAUSE_UNTIED;
16339 else if (!strcmp (s1: "use", s2: p))
16340 result = PRAGMA_OMP_CLAUSE_USE;
16341 else if (!strcmp (s1: "use_device", s2: p))
16342 result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
16343 else if (!strcmp (s1: "use_device_addr", s2: p))
16344 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
16345 else if (!strcmp (s1: "use_device_ptr", s2: p))
16346 result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
16347 break;
16348 case 'v':
16349 if (!strcmp (s1: "vector", s2: p))
16350 result = PRAGMA_OACC_CLAUSE_VECTOR;
16351 else if (!strcmp (s1: "vector_length", s2: p))
16352 result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
16353 break;
16354 case 'w':
16355 if (!strcmp (s1: "wait", s2: p))
16356 result = PRAGMA_OACC_CLAUSE_WAIT;
16357 else if (!strcmp (s1: "worker", s2: p))
16358 result = PRAGMA_OACC_CLAUSE_WORKER;
16359 break;
16360 }
16361 }
16362
16363 if (result != PRAGMA_OMP_CLAUSE_NONE)
16364 c_parser_consume_token (parser);
16365
16366 return result;
16367}
16368
16369/* Validate that a clause of the given type does not already exist. */
16370
16371static void
16372check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
16373 const char *name)
16374{
16375 if (tree c = omp_find_clause (clauses, kind: code))
16376 error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
16377}
16378
16379/* OpenACC 2.0
16380 Parse wait clause or wait directive parameters. */
16381
16382static tree
16383c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
16384{
16385 vec<tree, va_gc> *args;
16386 tree t, args_tree;
16387
16388 matching_parens parens;
16389 if (!parens.require_open (parser))
16390 return list;
16391
16392 args = c_parser_expr_list (parser, convert_p: false, fold_p: true, NULL, NULL, NULL, NULL);
16393 args_tree = build_tree_list_vec (args);
16394
16395 for (t = args_tree; t; t = TREE_CHAIN (t))
16396 {
16397 tree targ = TREE_VALUE (t);
16398
16399 if (targ != error_mark_node)
16400 {
16401 if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
16402 {
16403 c_parser_error (parser, gmsgid: "expression must be integral");
16404 targ = error_mark_node;
16405 }
16406 else
16407 {
16408 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
16409
16410 OMP_CLAUSE_DECL (c) = targ;
16411 OMP_CLAUSE_CHAIN (c) = list;
16412 list = c;
16413 }
16414 }
16415 }
16416
16417 release_tree_vector (args);
16418 parens.require_close (parser);
16419 return list;
16420}
16421
16422/* OpenACC 2.0, OpenMP 2.5:
16423 variable-list:
16424 identifier
16425 variable-list , identifier
16426
16427 If KIND is nonzero, create the appropriate node and install the
16428 decl in OMP_CLAUSE_DECL and add the node to the head of the list.
16429 If KIND is nonzero, CLAUSE_LOC is the location of the clause.
16430
16431 If KIND is zero (= OMP_CLAUSE_ERROR), create a TREE_LIST with the decl
16432 in TREE_PURPOSE and the location in TREE_VALUE (accessible using
16433 EXPR_LOCATION); return the list created.
16434
16435 The optional ALLOW_DEREF argument is true if list items can use the deref
16436 (->) operator. */
16437
16438struct omp_dim
16439{
16440 tree low_bound, length;
16441 location_t loc;
16442 bool no_colon;
16443 omp_dim (tree lb, tree len, location_t lo, bool nc)
16444 : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
16445};
16446
16447static tree
16448c_parser_omp_variable_list (c_parser *parser,
16449 location_t clause_loc,
16450 enum omp_clause_code kind, tree list,
16451 bool map_lvalue = false)
16452{
16453 auto_vec<omp_dim> dims;
16454 bool array_section_p;
16455 auto_vec<c_token> tokens;
16456 unsigned int tokens_avail = 0;
16457 c_token *saved_tokens = NULL;
16458
16459 while (1)
16460 {
16461 tree t = NULL_TREE;
16462 location_t tloc = c_parser_peek_token (parser)->location;
16463
16464 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16465 {
16466 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
16467 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
16468 {
16469 struct c_expr expr;
16470 if (kind == OMP_CLAUSE_DEPEND
16471 && c_parser_next_token_is_keyword (parser,
16472 keyword: RID_OMP_ALL_MEMORY)
16473 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
16474 || (c_parser_peek_2nd_token (parser)->type
16475 == CPP_CLOSE_PAREN)))
16476 {
16477 expr.value = ridpointers[RID_OMP_ALL_MEMORY];
16478 c_parser_consume_token (parser);
16479 }
16480 else
16481 expr = c_parser_expr_no_commas (parser, NULL);
16482 if (expr.value != error_mark_node)
16483 {
16484 tree u = build_omp_clause (clause_loc, kind);
16485 OMP_CLAUSE_DECL (u) = expr.value;
16486 OMP_CLAUSE_CHAIN (u) = list;
16487 list = u;
16488 }
16489
16490 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
16491 break;
16492
16493 c_parser_consume_token (parser);
16494 continue;
16495 }
16496
16497 tokens.truncate (size: 0);
16498 unsigned int nesting_depth = 0;
16499 while (1)
16500 {
16501 c_token *token = c_parser_peek_token (parser);
16502 switch (token->type)
16503 {
16504 case CPP_EOF:
16505 case CPP_PRAGMA_EOL:
16506 break;
16507 case CPP_OPEN_BRACE:
16508 case CPP_OPEN_PAREN:
16509 case CPP_OPEN_SQUARE:
16510 ++nesting_depth;
16511 goto add;
16512 case CPP_CLOSE_BRACE:
16513 case CPP_CLOSE_PAREN:
16514 case CPP_CLOSE_SQUARE:
16515 if (nesting_depth-- == 0)
16516 break;
16517 goto add;
16518 case CPP_COMMA:
16519 if (nesting_depth == 0)
16520 break;
16521 goto add;
16522 default:
16523 add:
16524 tokens.safe_push (obj: *token);
16525 c_parser_consume_token (parser);
16526 continue;
16527 }
16528 break;
16529 }
16530
16531 /* Make sure nothing tries to read past the end of the tokens. */
16532 c_token eof_token;
16533 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
16534 eof_token.type = CPP_EOF;
16535 tokens.safe_push (obj: eof_token);
16536 tokens.safe_push (obj: eof_token);
16537
16538 saved_tokens = parser->tokens;
16539 tokens_avail = parser->tokens_avail;
16540 parser->tokens = tokens.address ();
16541 parser->tokens_avail = tokens.length ();
16542 }
16543 else if (map_lvalue
16544 && (kind == OMP_CLAUSE_MAP
16545 || kind == OMP_CLAUSE_TO
16546 || kind == OMP_CLAUSE_FROM))
16547 {
16548 location_t loc = c_parser_peek_token (parser)->location;
16549 bool save_c_omp_array_section_p = c_omp_array_section_p;
16550 c_omp_array_section_p = true;
16551 c_expr expr = c_parser_expr_no_commas (parser, NULL);
16552 if (expr.value != error_mark_node)
16553 mark_exp_read (expr.value);
16554 c_omp_array_section_p = save_c_omp_array_section_p;
16555 tree decl = expr.value;
16556
16557 /* This code rewrites a parsed expression containing various tree
16558 codes used to represent array accesses into a more uniform nest of
16559 OMP_ARRAY_SECTION nodes before it is processed by
16560 c-typeck.cc:handle_omp_array_sections_1. It might be more
16561 efficient to move this logic to that function instead, analysing
16562 the parsed expression directly rather than this preprocessed
16563 form. (See also equivalent code in cp/parser.cc,
16564 cp/semantics.cc). */
16565 dims.truncate (size: 0);
16566 if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16567 {
16568 while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
16569 {
16570 tree low_bound = TREE_OPERAND (decl, 1);
16571 tree length = TREE_OPERAND (decl, 2);
16572 dims.safe_push (obj: omp_dim (low_bound, length, loc, false));
16573 decl = TREE_OPERAND (decl, 0);
16574 }
16575
16576 while (TREE_CODE (decl) == ARRAY_REF
16577 || TREE_CODE (decl) == INDIRECT_REF
16578 || TREE_CODE (decl) == COMPOUND_EXPR)
16579 {
16580 if (TREE_CODE (decl) == COMPOUND_EXPR)
16581 {
16582 decl = TREE_OPERAND (decl, 1);
16583 STRIP_NOPS (decl);
16584 }
16585 else if (TREE_CODE (decl) == INDIRECT_REF)
16586 {
16587 dims.safe_push (obj: omp_dim (integer_zero_node,
16588 integer_one_node, loc, true));
16589 decl = TREE_OPERAND (decl, 0);
16590 }
16591 else /* ARRAY_REF. */
16592 {
16593 tree index = TREE_OPERAND (decl, 1);
16594 dims.safe_push (obj: omp_dim (index, integer_one_node, loc,
16595 true));
16596 decl = TREE_OPERAND (decl, 0);
16597 }
16598 }
16599
16600 for (int i = dims.length () - 1; i >= 0; i--)
16601 decl = build_omp_array_section (loc, decl, dims[i].low_bound,
16602 dims[i].length);
16603 }
16604 else if (TREE_CODE (decl) == INDIRECT_REF)
16605 {
16606 /* Turn indirection of a pointer "*foo" into "foo[0:1]". */
16607 decl = TREE_OPERAND (decl, 0);
16608 STRIP_NOPS (decl);
16609
16610 decl = build_omp_array_section (loc, decl, integer_zero_node,
16611 integer_one_node);
16612 }
16613 else if (TREE_CODE (decl) == ARRAY_REF)
16614 {
16615 tree idx = TREE_OPERAND (decl, 1);
16616
16617 decl = TREE_OPERAND (decl, 0);
16618 STRIP_NOPS (decl);
16619
16620 decl = build_omp_array_section (loc, decl, idx, integer_one_node);
16621 }
16622 else if (TREE_CODE (decl) == NON_LVALUE_EXPR
16623 || CONVERT_EXPR_P (decl))
16624 decl = TREE_OPERAND (decl, 0);
16625
16626 tree u = build_omp_clause (clause_loc, kind);
16627 OMP_CLAUSE_DECL (u) = decl;
16628 OMP_CLAUSE_CHAIN (u) = list;
16629 list = u;
16630
16631 goto next_item;
16632 }
16633
16634 if (c_parser_next_token_is (parser, type: CPP_NAME)
16635 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
16636 {
16637 t = lookup_name (c_parser_peek_token (parser)->value);
16638
16639 if (t == NULL_TREE)
16640 {
16641 undeclared_variable (c_parser_peek_token (parser)->location,
16642 c_parser_peek_token (parser)->value);
16643 t = error_mark_node;
16644 }
16645
16646 c_parser_consume_token (parser);
16647 }
16648 else if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
16649 && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
16650 || (c_parser_peek_token (parser)->keyword
16651 == RID_PRETTY_FUNCTION_NAME)
16652 || (c_parser_peek_token (parser)->keyword
16653 == RID_C99_FUNCTION_NAME)))
16654 t = c_parser_predefined_identifier (parser).value;
16655 else
16656 {
16657 c_parser_error (parser, gmsgid: "expected identifier");
16658 break;
16659 }
16660
16661 if (t == error_mark_node)
16662 ;
16663 else if (kind != 0) /* kind != OMP_CLAUSE_ERROR */
16664 {
16665 switch (kind)
16666 {
16667 case OMP_CLAUSE__CACHE_:
16668 /* The OpenACC cache directive explicitly only allows "array
16669 elements or subarrays". */
16670 if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
16671 {
16672 c_parser_error (parser, gmsgid: "expected %<[%>");
16673 t = error_mark_node;
16674 break;
16675 }
16676 /* FALLTHROUGH */
16677 case OMP_CLAUSE_MAP:
16678 case OMP_CLAUSE_FROM:
16679 case OMP_CLAUSE_TO:
16680 start_component_ref:
16681 while (c_parser_next_token_is (parser, type: CPP_DOT)
16682 || c_parser_next_token_is (parser, type: CPP_DEREF))
16683 {
16684 location_t op_loc = c_parser_peek_token (parser)->location;
16685 location_t arrow_loc = UNKNOWN_LOCATION;
16686 if (c_parser_next_token_is (parser, type: CPP_DEREF))
16687 {
16688 c_expr t_expr;
16689 t_expr.value = t;
16690 t_expr.original_code = ERROR_MARK;
16691 t_expr.original_type = NULL;
16692 set_c_expr_source_range (expr: &t_expr, start: op_loc, finish: op_loc);
16693 t_expr.m_decimal = 0;
16694 t_expr = convert_lvalue_to_rvalue (op_loc, t_expr,
16695 true, false);
16696 t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW);
16697 arrow_loc = t_expr.get_location ();
16698 }
16699 c_parser_consume_token (parser);
16700 if (!c_parser_next_token_is (parser, type: CPP_NAME))
16701 {
16702 c_parser_error (parser, gmsgid: "expected identifier");
16703 t = error_mark_node;
16704 break;
16705 }
16706
16707 c_token *comp_tok = c_parser_peek_token (parser);
16708 tree ident = comp_tok->value;
16709 location_t comp_loc = comp_tok->location;
16710 c_parser_consume_token (parser);
16711 t = build_component_ref (op_loc, t, ident, comp_loc,
16712 arrow_loc);
16713 }
16714 /* FALLTHROUGH */
16715 case OMP_CLAUSE_AFFINITY:
16716 case OMP_CLAUSE_DEPEND:
16717 case OMP_CLAUSE_REDUCTION:
16718 case OMP_CLAUSE_IN_REDUCTION:
16719 case OMP_CLAUSE_TASK_REDUCTION:
16720 case OMP_CLAUSE_HAS_DEVICE_ADDR:
16721 array_section_p = false;
16722 dims.truncate (size: 0);
16723 while (c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
16724 {
16725 location_t loc = UNKNOWN_LOCATION;
16726 tree low_bound = NULL_TREE, length = NULL_TREE;
16727 bool no_colon = false;
16728
16729 c_parser_consume_token (parser);
16730 if (!c_parser_next_token_is (parser, type: CPP_COLON))
16731 {
16732 location_t expr_loc
16733 = c_parser_peek_token (parser)->location;
16734 c_expr expr = c_parser_expression (parser);
16735 expr = convert_lvalue_to_rvalue (expr_loc, expr,
16736 false, true);
16737 low_bound = expr.value;
16738 loc = expr_loc;
16739 }
16740 if (c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
16741 {
16742 length = integer_one_node;
16743 no_colon = true;
16744 }
16745 else
16746 {
16747 /* Look for `:'. */
16748 if (!c_parser_require (parser, type: CPP_COLON,
16749 msgid: "expected %<:%>"))
16750 {
16751 t = error_mark_node;
16752 break;
16753 }
16754 array_section_p = true;
16755 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_SQUARE))
16756 {
16757 location_t expr_loc
16758 = c_parser_peek_token (parser)->location;
16759 c_expr expr = c_parser_expression (parser);
16760 expr = convert_lvalue_to_rvalue (expr_loc, expr,
16761 false, true);
16762 length = expr.value;
16763 }
16764 }
16765 /* Look for the closing `]'. */
16766 if (!c_parser_require (parser, type: CPP_CLOSE_SQUARE,
16767 msgid: "expected %<]%>"))
16768 {
16769 t = error_mark_node;
16770 break;
16771 }
16772
16773 dims.safe_push (obj: omp_dim (low_bound, length, loc, no_colon));
16774 }
16775
16776 if (t != error_mark_node)
16777 {
16778 if ((kind == OMP_CLAUSE_MAP
16779 || kind == OMP_CLAUSE_FROM
16780 || kind == OMP_CLAUSE_TO)
16781 && !array_section_p
16782 && (c_parser_next_token_is (parser, type: CPP_DOT)
16783 || c_parser_next_token_is (parser, type: CPP_DEREF)))
16784 {
16785 for (unsigned i = 0; i < dims.length (); i++)
16786 {
16787 gcc_assert (dims[i].length == integer_one_node);
16788 t = build_array_ref (dims[i].loc,
16789 t, dims[i].low_bound);
16790 }
16791 goto start_component_ref;
16792 }
16793 else
16794 for (unsigned i = 0; i < dims.length (); i++)
16795 t = build_omp_array_section (clause_loc, t,
16796 dims[i].low_bound,
16797 dims[i].length);
16798 }
16799
16800 if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16801 && t != error_mark_node
16802 && parser->tokens_avail != 2)
16803 {
16804 if (array_section_p)
16805 {
16806 error_at (c_parser_peek_token (parser)->location,
16807 "expected %<)%> or %<,%>");
16808 t = error_mark_node;
16809 }
16810 else
16811 {
16812 parser->tokens = tokens.address ();
16813 parser->tokens_avail = tokens.length ();
16814
16815 t = c_parser_expr_no_commas (parser, NULL).value;
16816 if (t != error_mark_node && parser->tokens_avail != 2)
16817 {
16818 error_at (c_parser_peek_token (parser)->location,
16819 "expected %<)%> or %<,%>");
16820 t = error_mark_node;
16821 }
16822 }
16823 }
16824 break;
16825 default:
16826 break;
16827 }
16828
16829 if (t != error_mark_node)
16830 {
16831 tree u = build_omp_clause (clause_loc, kind);
16832 OMP_CLAUSE_DECL (u) = t;
16833 OMP_CLAUSE_CHAIN (u) = list;
16834 list = u;
16835 }
16836 }
16837 else /* kind == OMP_CLAUSE_ERROR */
16838 list = tree_cons (t, build_empty_stmt (tloc), list);
16839
16840 if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
16841 {
16842 parser->tokens = saved_tokens;
16843 parser->tokens_avail = tokens_avail;
16844 }
16845
16846 next_item:
16847 if (c_parser_next_token_is_not (parser, type: CPP_COMMA))
16848 break;
16849
16850 c_parser_consume_token (parser);
16851 }
16852
16853 return list;
16854}
16855
16856/* Similarly, but expect leading and trailing parenthesis. This is a very
16857 common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
16858 argument is true if list items can use the deref (->) operator. */
16859
16860static tree
16861c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
16862 tree list, bool map_lvalue = false)
16863{
16864 /* The clauses location. */
16865 location_t loc = c_parser_peek_token (parser)->location;
16866
16867 if (parser->in_omp_decl_attribute)
16868 {
16869 if (kind)
16870 {
16871 tree u = build_omp_clause (loc, kind);
16872 OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
16873 OMP_CLAUSE_CHAIN (u) = list;
16874 return u;
16875 }
16876 else
16877 return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
16878 }
16879
16880 matching_parens parens;
16881 if (parens.require_open (parser))
16882 {
16883 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list, map_lvalue);
16884 parens.skip_until_found_close (parser);
16885 }
16886 return list;
16887}
16888
16889/* OpenACC 2.0:
16890 copy ( variable-list )
16891 copyin ( variable-list )
16892 copyout ( variable-list )
16893 create ( variable-list )
16894 delete ( variable-list )
16895 present ( variable-list )
16896
16897 OpenACC 2.6:
16898 no_create ( variable-list )
16899 attach ( variable-list )
16900 detach ( variable-list )
16901
16902 OpenACC 2.7:
16903 copyin (readonly : variable-list )
16904 */
16905
16906static tree
16907c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
16908 tree list)
16909{
16910 enum gomp_map_kind kind;
16911 switch (c_kind)
16912 {
16913 case PRAGMA_OACC_CLAUSE_ATTACH:
16914 kind = GOMP_MAP_ATTACH;
16915 break;
16916 case PRAGMA_OACC_CLAUSE_COPY:
16917 kind = GOMP_MAP_TOFROM;
16918 break;
16919 case PRAGMA_OACC_CLAUSE_COPYIN:
16920 kind = GOMP_MAP_TO;
16921 break;
16922 case PRAGMA_OACC_CLAUSE_COPYOUT:
16923 kind = GOMP_MAP_FROM;
16924 break;
16925 case PRAGMA_OACC_CLAUSE_CREATE:
16926 kind = GOMP_MAP_ALLOC;
16927 break;
16928 case PRAGMA_OACC_CLAUSE_DELETE:
16929 kind = GOMP_MAP_RELEASE;
16930 break;
16931 case PRAGMA_OACC_CLAUSE_DETACH:
16932 kind = GOMP_MAP_DETACH;
16933 break;
16934 case PRAGMA_OACC_CLAUSE_DEVICE:
16935 kind = GOMP_MAP_FORCE_TO;
16936 break;
16937 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
16938 kind = GOMP_MAP_DEVICE_RESIDENT;
16939 break;
16940 case PRAGMA_OACC_CLAUSE_LINK:
16941 kind = GOMP_MAP_LINK;
16942 break;
16943 case PRAGMA_OACC_CLAUSE_NO_CREATE:
16944 kind = GOMP_MAP_IF_PRESENT;
16945 break;
16946 case PRAGMA_OACC_CLAUSE_PRESENT:
16947 kind = GOMP_MAP_FORCE_PRESENT;
16948 break;
16949 case PRAGMA_OACC_CLAUSE_SELF:
16950 /* "The 'host' clause is a synonym for the 'self' clause." */
16951 case PRAGMA_OACC_CLAUSE_HOST:
16952 kind = GOMP_MAP_FORCE_FROM;
16953 break;
16954 default:
16955 gcc_unreachable ();
16956 }
16957
16958 tree nl = list;
16959 bool readonly = false;
16960 location_t open_loc = c_parser_peek_token (parser)->location;
16961 matching_parens parens;
16962 if (parens.require_open (parser))
16963 {
16964 /* Turn on readonly modifier parsing for copyin clause. */
16965 if (c_kind == PRAGMA_OACC_CLAUSE_COPYIN)
16966 {
16967 c_token *token = c_parser_peek_token (parser);
16968 if (token->type == CPP_NAME
16969 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
16970 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
16971 {
16972 c_parser_consume_token (parser);
16973 c_parser_consume_token (parser);
16974 readonly = true;
16975 }
16976 }
16977 nl = c_parser_omp_variable_list (parser, clause_loc: open_loc, kind: OMP_CLAUSE_MAP, list,
16978 map_lvalue: false);
16979 parens.skip_until_found_close (parser);
16980 }
16981
16982 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
16983 {
16984 OMP_CLAUSE_SET_MAP_KIND (c, kind);
16985 if (readonly)
16986 OMP_CLAUSE_MAP_READONLY (c) = 1;
16987 }
16988
16989 return nl;
16990}
16991
16992/* OpenACC 2.0:
16993 deviceptr ( variable-list ) */
16994
16995static tree
16996c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
16997{
16998 tree vars, t;
16999
17000 /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
17001 c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
17002 variable-list must only allow for pointer variables. */
17003 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
17004 for (t = vars; t && t; t = TREE_CHAIN (t))
17005 {
17006 tree v = TREE_PURPOSE (t);
17007 location_t loc = EXPR_LOCATION (TREE_VALUE (t));
17008
17009 if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
17010 error_at (loc, "%qD is not a variable", v);
17011 else if (TREE_TYPE (v) == error_mark_node)
17012 ;
17013 else if (!POINTER_TYPE_P (TREE_TYPE (v)))
17014 error_at (loc, "%qD is not a pointer variable", v);
17015
17016 tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
17017 OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
17018 OMP_CLAUSE_DECL (u) = v;
17019 OMP_CLAUSE_CHAIN (u) = list;
17020 list = u;
17021 }
17022
17023 return list;
17024}
17025
17026/* OpenACC 2.0, OpenMP 3.0:
17027 collapse ( constant-expression ) */
17028
17029static tree
17030c_parser_omp_clause_collapse (c_parser *parser, tree list)
17031{
17032 tree c, num = error_mark_node;
17033 HOST_WIDE_INT n;
17034 location_t loc;
17035
17036 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
17037 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
17038
17039 loc = c_parser_peek_token (parser)->location;
17040 matching_parens parens;
17041 if (parens.require_open (parser))
17042 {
17043 num = c_parser_expr_no_commas (parser, NULL).value;
17044 parens.skip_until_found_close (parser);
17045 }
17046 if (num == error_mark_node)
17047 return list;
17048 mark_exp_read (num);
17049 num = c_fully_fold (num, false, NULL);
17050 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
17051 || !tree_fits_shwi_p (num)
17052 || (n = tree_to_shwi (num)) <= 0
17053 || (int) n != n)
17054 {
17055 error_at (loc,
17056 "collapse argument needs positive constant integer expression");
17057 return list;
17058 }
17059 c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
17060 OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
17061 OMP_CLAUSE_CHAIN (c) = list;
17062 return c;
17063}
17064
17065/* OpenMP 2.5:
17066 copyin ( variable-list ) */
17067
17068static tree
17069c_parser_omp_clause_copyin (c_parser *parser, tree list)
17070{
17071 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYIN, list);
17072}
17073
17074/* OpenMP 2.5:
17075 copyprivate ( variable-list ) */
17076
17077static tree
17078c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
17079{
17080 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_COPYPRIVATE, list);
17081}
17082
17083/* OpenMP 2.5:
17084 default ( none | shared )
17085
17086 OpenMP 5.1:
17087 default ( private | firstprivate )
17088
17089 OpenACC:
17090 default ( none | present ) */
17091
17092static tree
17093c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
17094{
17095 enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
17096 location_t loc = c_parser_peek_token (parser)->location;
17097 tree c;
17098
17099 matching_parens parens;
17100 if (!parens.require_open (parser))
17101 return list;
17102 if (c_parser_next_token_is (parser, type: CPP_NAME))
17103 {
17104 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17105
17106 switch (p[0])
17107 {
17108 case 'n':
17109 if (strcmp (s1: "none", s2: p) != 0)
17110 goto invalid_kind;
17111 kind = OMP_CLAUSE_DEFAULT_NONE;
17112 break;
17113
17114 case 'p':
17115 if (is_oacc)
17116 {
17117 if (strcmp (s1: "present", s2: p) != 0)
17118 goto invalid_kind;
17119 kind = OMP_CLAUSE_DEFAULT_PRESENT;
17120 }
17121 else
17122 {
17123 if (strcmp (s1: "private", s2: p) != 0)
17124 goto invalid_kind;
17125 kind = OMP_CLAUSE_DEFAULT_PRIVATE;
17126 }
17127 break;
17128
17129 case 'f':
17130 if (strcmp (s1: "firstprivate", s2: p) != 0 || is_oacc)
17131 goto invalid_kind;
17132 kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
17133 break;
17134
17135 case 's':
17136 if (strcmp (s1: "shared", s2: p) != 0 || is_oacc)
17137 goto invalid_kind;
17138 kind = OMP_CLAUSE_DEFAULT_SHARED;
17139 break;
17140
17141 default:
17142 goto invalid_kind;
17143 }
17144
17145 c_parser_consume_token (parser);
17146 }
17147 else
17148 {
17149 invalid_kind:
17150 if (is_oacc)
17151 c_parser_error (parser, gmsgid: "expected %<none%> or %<present%>");
17152 else
17153 c_parser_error (parser, gmsgid: "expected %<none%>, %<shared%>, "
17154 "%<private%> or %<firstprivate%>");
17155 }
17156 parens.skip_until_found_close (parser);
17157
17158 if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
17159 return list;
17160
17161 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEFAULT, name: "default");
17162 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
17163 OMP_CLAUSE_CHAIN (c) = list;
17164 OMP_CLAUSE_DEFAULT_KIND (c) = kind;
17165
17166 return c;
17167}
17168
17169/* OpenMP 2.5:
17170 firstprivate ( variable-list ) */
17171
17172static tree
17173c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
17174{
17175 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_FIRSTPRIVATE, list);
17176}
17177
17178/* OpenMP 3.1:
17179 final ( expression ) */
17180
17181static tree
17182c_parser_omp_clause_final (c_parser *parser, tree list)
17183{
17184 location_t loc = c_parser_peek_token (parser)->location;
17185 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
17186 {
17187 matching_parens parens;
17188 tree t, c;
17189 if (!parens.require_open (parser))
17190 t = error_mark_node;
17191 else
17192 {
17193 location_t eloc = c_parser_peek_token (parser)->location;
17194 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17195 t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
17196 t = c_objc_common_truthvalue_conversion (eloc, t);
17197 t = c_fully_fold (t, false, NULL);
17198 parens.skip_until_found_close (parser);
17199 }
17200
17201 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FINAL, name: "final");
17202
17203 c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
17204 OMP_CLAUSE_FINAL_EXPR (c) = t;
17205 OMP_CLAUSE_CHAIN (c) = list;
17206 list = c;
17207 }
17208 else
17209 c_parser_error (parser, gmsgid: "expected %<(%>");
17210
17211 return list;
17212}
17213
17214/* OpenMP 5.1:
17215 indirect [( expression )]
17216*/
17217
17218static tree
17219c_parser_omp_clause_indirect (c_parser *parser, tree list)
17220{
17221 location_t location = c_parser_peek_token (parser)->location;
17222 tree t;
17223
17224 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
17225 {
17226 matching_parens parens;
17227 if (!parens.require_open (parser))
17228 return list;
17229
17230 location_t loc = c_parser_peek_token (parser)->location;
17231 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17232 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17233 t = c_objc_common_truthvalue_conversion (loc, expr.value);
17234 t = c_fully_fold (t, false, NULL);
17235 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17236 || TREE_CODE (t) != INTEGER_CST)
17237 {
17238 c_parser_error (parser, gmsgid: "expected constant logical expression");
17239 return list;
17240 }
17241 parens.skip_until_found_close (parser);
17242 }
17243 else
17244 t = integer_one_node;
17245
17246 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INDIRECT, name: "indirect");
17247
17248 tree c = build_omp_clause (location, OMP_CLAUSE_INDIRECT);
17249 OMP_CLAUSE_INDIRECT_EXPR (c) = t;
17250 OMP_CLAUSE_CHAIN (c) = list;
17251
17252 return c;
17253}
17254
17255/* OpenACC, OpenMP 2.5:
17256 if ( expression )
17257
17258 OpenMP 4.5:
17259 if ( directive-name-modifier : expression )
17260
17261 directive-name-modifier:
17262 parallel | task | taskloop | target data | target | target update
17263 | target enter data | target exit data
17264
17265 OpenMP 5.0:
17266 directive-name-modifier:
17267 ... | simd | cancel */
17268
17269static tree
17270c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
17271{
17272 location_t location = c_parser_peek_token (parser)->location;
17273 enum tree_code if_modifier = ERROR_MARK;
17274
17275 matching_parens parens;
17276 if (!parens.require_open (parser))
17277 return list;
17278
17279 if (is_omp && c_parser_next_token_is (parser, type: CPP_NAME))
17280 {
17281 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17282 int n = 2;
17283 if (strcmp (s1: p, s2: "cancel") == 0)
17284 if_modifier = VOID_CST;
17285 else if (strcmp (s1: p, s2: "parallel") == 0)
17286 if_modifier = OMP_PARALLEL;
17287 else if (strcmp (s1: p, s2: "simd") == 0)
17288 if_modifier = OMP_SIMD;
17289 else if (strcmp (s1: p, s2: "task") == 0)
17290 if_modifier = OMP_TASK;
17291 else if (strcmp (s1: p, s2: "taskloop") == 0)
17292 if_modifier = OMP_TASKLOOP;
17293 else if (strcmp (s1: p, s2: "target") == 0)
17294 {
17295 if_modifier = OMP_TARGET;
17296 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17297 {
17298 p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
17299 if (strcmp (s1: "data", s2: p) == 0)
17300 if_modifier = OMP_TARGET_DATA;
17301 else if (strcmp (s1: "update", s2: p) == 0)
17302 if_modifier = OMP_TARGET_UPDATE;
17303 else if (strcmp (s1: "enter", s2: p) == 0)
17304 if_modifier = OMP_TARGET_ENTER_DATA;
17305 else if (strcmp (s1: "exit", s2: p) == 0)
17306 if_modifier = OMP_TARGET_EXIT_DATA;
17307 if (if_modifier != OMP_TARGET)
17308 {
17309 n = 3;
17310 c_parser_consume_token (parser);
17311 }
17312 else
17313 {
17314 location_t loc = c_parser_peek_2nd_token (parser)->location;
17315 error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
17316 "or %<exit%>");
17317 if_modifier = ERROR_MARK;
17318 }
17319 if (if_modifier == OMP_TARGET_ENTER_DATA
17320 || if_modifier == OMP_TARGET_EXIT_DATA)
17321 {
17322 if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
17323 {
17324 p = IDENTIFIER_POINTER
17325 (c_parser_peek_2nd_token (parser)->value);
17326 if (strcmp (s1: "data", s2: p) == 0)
17327 n = 4;
17328 }
17329 if (n == 4)
17330 c_parser_consume_token (parser);
17331 else
17332 {
17333 location_t loc
17334 = c_parser_peek_2nd_token (parser)->location;
17335 error_at (loc, "expected %<data%>");
17336 if_modifier = ERROR_MARK;
17337 }
17338 }
17339 }
17340 }
17341 if (if_modifier != ERROR_MARK)
17342 {
17343 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17344 {
17345 c_parser_consume_token (parser);
17346 c_parser_consume_token (parser);
17347 }
17348 else
17349 {
17350 if (n > 2)
17351 {
17352 location_t loc = c_parser_peek_2nd_token (parser)->location;
17353 error_at (loc, "expected %<:%>");
17354 }
17355 if_modifier = ERROR_MARK;
17356 }
17357 }
17358 }
17359
17360 location_t loc = c_parser_peek_token (parser)->location;
17361 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17362 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
17363 tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
17364 t = c_fully_fold (t, false, NULL);
17365 parens.skip_until_found_close (parser);
17366
17367 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17368 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
17369 {
17370 if (if_modifier != ERROR_MARK
17371 && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17372 {
17373 const char *p = NULL;
17374 switch (if_modifier)
17375 {
17376 case VOID_CST: p = "cancel"; break;
17377 case OMP_PARALLEL: p = "parallel"; break;
17378 case OMP_SIMD: p = "simd"; break;
17379 case OMP_TASK: p = "task"; break;
17380 case OMP_TASKLOOP: p = "taskloop"; break;
17381 case OMP_TARGET_DATA: p = "target data"; break;
17382 case OMP_TARGET: p = "target"; break;
17383 case OMP_TARGET_UPDATE: p = "target update"; break;
17384 case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
17385 case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
17386 default: gcc_unreachable ();
17387 }
17388 error_at (location, "too many %<if%> clauses with %qs modifier",
17389 p);
17390 return list;
17391 }
17392 else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
17393 {
17394 if (!is_omp)
17395 error_at (location, "too many %<if%> clauses");
17396 else
17397 error_at (location, "too many %<if%> clauses without modifier");
17398 return list;
17399 }
17400 else if (if_modifier == ERROR_MARK
17401 || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
17402 {
17403 error_at (location, "if any %<if%> clause has modifier, then all "
17404 "%<if%> clauses have to use modifier");
17405 return list;
17406 }
17407 }
17408
17409 c = build_omp_clause (location, OMP_CLAUSE_IF);
17410 OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
17411 OMP_CLAUSE_IF_EXPR (c) = t;
17412 OMP_CLAUSE_CHAIN (c) = list;
17413 return c;
17414}
17415
17416/* OpenMP 2.5:
17417 lastprivate ( variable-list )
17418
17419 OpenMP 5.0:
17420 lastprivate ( [ lastprivate-modifier : ] variable-list ) */
17421
17422static tree
17423c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
17424{
17425 /* The clauses location. */
17426 location_t loc = c_parser_peek_token (parser)->location;
17427
17428 if (c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
17429 {
17430 bool conditional = false;
17431 if (c_parser_next_token_is (parser, type: CPP_NAME)
17432 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
17433 {
17434 const char *p
17435 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17436 if (strcmp (s1: p, s2: "conditional") == 0)
17437 {
17438 conditional = true;
17439 c_parser_consume_token (parser);
17440 c_parser_consume_token (parser);
17441 }
17442 }
17443 tree nlist = c_parser_omp_variable_list (parser, clause_loc: loc,
17444 kind: OMP_CLAUSE_LASTPRIVATE, list);
17445 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
17446 if (conditional)
17447 for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
17448 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
17449 return nlist;
17450 }
17451 return list;
17452}
17453
17454/* OpenMP 3.1:
17455 mergeable */
17456
17457static tree
17458c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17459{
17460 tree c;
17461
17462 /* FIXME: Should we allow duplicates? */
17463 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_MERGEABLE, name: "mergeable");
17464
17465 c = build_omp_clause (c_parser_peek_token (parser)->location,
17466 OMP_CLAUSE_MERGEABLE);
17467 OMP_CLAUSE_CHAIN (c) = list;
17468
17469 return c;
17470}
17471
17472/* OpenMP 2.5:
17473 nowait */
17474
17475static tree
17476c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
17477{
17478 tree c;
17479 location_t loc = c_parser_peek_token (parser)->location;
17480
17481 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOWAIT, name: "nowait");
17482
17483 c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
17484 OMP_CLAUSE_CHAIN (c) = list;
17485 return c;
17486}
17487
17488/* OpenMP 2.5:
17489 num_threads ( expression ) */
17490
17491static tree
17492c_parser_omp_clause_num_threads (c_parser *parser, tree list)
17493{
17494 location_t num_threads_loc = c_parser_peek_token (parser)->location;
17495 matching_parens parens;
17496 if (parens.require_open (parser))
17497 {
17498 location_t expr_loc = c_parser_peek_token (parser)->location;
17499 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17500 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17501 tree c, t = expr.value;
17502 t = c_fully_fold (t, false, NULL);
17503
17504 parens.skip_until_found_close (parser);
17505
17506 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17507 {
17508 c_parser_error (parser, gmsgid: "expected integer expression");
17509 return list;
17510 }
17511
17512 /* Attempt to statically determine when the number isn't positive. */
17513 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17514 build_int_cst (TREE_TYPE (t), 0));
17515 protected_set_expr_location (c, expr_loc);
17516 if (c == boolean_true_node)
17517 {
17518 warning_at (expr_loc, OPT_Wopenmp,
17519 "%<num_threads%> value must be positive");
17520 t = integer_one_node;
17521 }
17522
17523 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_THREADS, name: "num_threads");
17524
17525 c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
17526 OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
17527 OMP_CLAUSE_CHAIN (c) = list;
17528 list = c;
17529 }
17530
17531 return list;
17532}
17533
17534/* OpenMP 4.5:
17535 num_tasks ( expression )
17536
17537 OpenMP 5.1:
17538 num_tasks ( strict : expression ) */
17539
17540static tree
17541c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
17542{
17543 location_t num_tasks_loc = c_parser_peek_token (parser)->location;
17544 matching_parens parens;
17545 if (parens.require_open (parser))
17546 {
17547 bool strict = false;
17548 if (c_parser_next_token_is (parser, type: CPP_NAME)
17549 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17550 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17551 s2: "strict") == 0)
17552 {
17553 strict = true;
17554 c_parser_consume_token (parser);
17555 c_parser_consume_token (parser);
17556 }
17557
17558 location_t expr_loc = c_parser_peek_token (parser)->location;
17559 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17560 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17561 tree c, t = expr.value;
17562 t = c_fully_fold (t, false, NULL);
17563
17564 parens.skip_until_found_close (parser);
17565
17566 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17567 {
17568 c_parser_error (parser, gmsgid: "expected integer expression");
17569 return list;
17570 }
17571
17572 /* Attempt to statically determine when the number isn't positive. */
17573 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17574 build_int_cst (TREE_TYPE (t), 0));
17575 if (CAN_HAVE_LOCATION_P (c))
17576 SET_EXPR_LOCATION (c, expr_loc);
17577 if (c == boolean_true_node)
17578 {
17579 warning_at (expr_loc, OPT_Wopenmp,
17580 "%<num_tasks%> value must be positive");
17581 t = integer_one_node;
17582 }
17583
17584 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TASKS, name: "num_tasks");
17585
17586 c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
17587 OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
17588 OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
17589 OMP_CLAUSE_CHAIN (c) = list;
17590 list = c;
17591 }
17592
17593 return list;
17594}
17595
17596/* OpenMP 4.5:
17597 grainsize ( expression )
17598
17599 OpenMP 5.1:
17600 grainsize ( strict : expression ) */
17601
17602static tree
17603c_parser_omp_clause_grainsize (c_parser *parser, tree list)
17604{
17605 location_t grainsize_loc = c_parser_peek_token (parser)->location;
17606 matching_parens parens;
17607 if (parens.require_open (parser))
17608 {
17609 bool strict = false;
17610 if (c_parser_next_token_is (parser, type: CPP_NAME)
17611 && c_parser_peek_2nd_token (parser)->type == CPP_COLON
17612 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
17613 s2: "strict") == 0)
17614 {
17615 strict = true;
17616 c_parser_consume_token (parser);
17617 c_parser_consume_token (parser);
17618 }
17619
17620 location_t expr_loc = c_parser_peek_token (parser)->location;
17621 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17622 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17623 tree c, t = expr.value;
17624 t = c_fully_fold (t, false, NULL);
17625
17626 parens.skip_until_found_close (parser);
17627
17628 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17629 {
17630 c_parser_error (parser, gmsgid: "expected integer expression");
17631 return list;
17632 }
17633
17634 /* Attempt to statically determine when the number isn't positive. */
17635 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
17636 build_int_cst (TREE_TYPE (t), 0));
17637 if (CAN_HAVE_LOCATION_P (c))
17638 SET_EXPR_LOCATION (c, expr_loc);
17639 if (c == boolean_true_node)
17640 {
17641 warning_at (expr_loc, OPT_Wopenmp,
17642 "%<grainsize%> value must be positive");
17643 t = integer_one_node;
17644 }
17645
17646 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_GRAINSIZE, name: "grainsize");
17647
17648 c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
17649 OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
17650 OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
17651 OMP_CLAUSE_CHAIN (c) = list;
17652 list = c;
17653 }
17654
17655 return list;
17656}
17657
17658/* OpenMP 4.5:
17659 priority ( expression ) */
17660
17661static tree
17662c_parser_omp_clause_priority (c_parser *parser, tree list)
17663{
17664 location_t priority_loc = c_parser_peek_token (parser)->location;
17665 matching_parens parens;
17666 if (parens.require_open (parser))
17667 {
17668 location_t expr_loc = c_parser_peek_token (parser)->location;
17669 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17670 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17671 tree c, t = expr.value;
17672 t = c_fully_fold (t, false, NULL);
17673
17674 parens.skip_until_found_close (parser);
17675
17676 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17677 {
17678 c_parser_error (parser, gmsgid: "expected integer expression");
17679 return list;
17680 }
17681
17682 /* Attempt to statically determine when the number isn't
17683 non-negative. */
17684 c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
17685 build_int_cst (TREE_TYPE (t), 0));
17686 if (CAN_HAVE_LOCATION_P (c))
17687 SET_EXPR_LOCATION (c, expr_loc);
17688 if (c == boolean_true_node)
17689 {
17690 warning_at (expr_loc, OPT_Wopenmp,
17691 "%<priority%> value must be non-negative");
17692 t = integer_one_node;
17693 }
17694
17695 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PRIORITY, name: "priority");
17696
17697 c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
17698 OMP_CLAUSE_PRIORITY_EXPR (c) = t;
17699 OMP_CLAUSE_CHAIN (c) = list;
17700 list = c;
17701 }
17702
17703 return list;
17704}
17705
17706/* OpenMP 4.5:
17707 hint ( expression ) */
17708
17709static tree
17710c_parser_omp_clause_hint (c_parser *parser, tree list)
17711{
17712 location_t hint_loc = c_parser_peek_token (parser)->location;
17713 matching_parens parens;
17714 if (parens.require_open (parser))
17715 {
17716 location_t expr_loc = c_parser_peek_token (parser)->location;
17717 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17718 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17719 tree c, t = expr.value;
17720 t = c_fully_fold (t, false, NULL);
17721 if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
17722 || TREE_CODE (t) != INTEGER_CST
17723 || tree_int_cst_sgn (t) == -1)
17724 {
17725 c_parser_error (parser, gmsgid: "expected constant integer expression "
17726 "with valid sync-hint value");
17727 return list;
17728 }
17729 parens.skip_until_found_close (parser);
17730 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_HINT, name: "hint");
17731
17732 c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
17733 OMP_CLAUSE_HINT_EXPR (c) = t;
17734 OMP_CLAUSE_CHAIN (c) = list;
17735 list = c;
17736 }
17737
17738 return list;
17739}
17740
17741/* OpenMP 5.1:
17742 filter ( integer-expression ) */
17743
17744static tree
17745c_parser_omp_clause_filter (c_parser *parser, tree list)
17746{
17747 location_t hint_loc = c_parser_peek_token (parser)->location;
17748 matching_parens parens;
17749 if (parens.require_open (parser))
17750 {
17751 location_t expr_loc = c_parser_peek_token (parser)->location;
17752 c_expr expr = c_parser_expr_no_commas (parser, NULL);
17753 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
17754 tree c, t = expr.value;
17755 t = c_fully_fold (t, false, NULL);
17756 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
17757 {
17758 c_parser_error (parser, gmsgid: "expected integer expression");
17759 return list;
17760 }
17761 parens.skip_until_found_close (parser);
17762 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FILTER, name: "filter");
17763
17764 c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
17765 OMP_CLAUSE_FILTER_EXPR (c) = t;
17766 OMP_CLAUSE_CHAIN (c) = list;
17767 list = c;
17768 }
17769
17770 return list;
17771}
17772
17773/* OpenMP 4.5:
17774 defaultmap ( tofrom : scalar )
17775
17776 OpenMP 5.0:
17777 defaultmap ( implicit-behavior [ : variable-category ] ) */
17778
17779static tree
17780c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
17781{
17782 location_t loc = c_parser_peek_token (parser)->location;
17783 tree c;
17784 const char *p;
17785 enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17786 enum omp_clause_defaultmap_kind category
17787 = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
17788
17789 matching_parens parens;
17790 if (!parens.require_open (parser))
17791 return list;
17792 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT))
17793 p = "default";
17794 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
17795 {
17796 invalid_behavior:
17797 c_parser_error (parser, gmsgid: "expected %<alloc%>, %<to%>, %<from%>, "
17798 "%<tofrom%>, %<firstprivate%>, %<none%> "
17799 "or %<default%>");
17800 goto out_err;
17801 }
17802 else
17803 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17804
17805 switch (p[0])
17806 {
17807 case 'a':
17808 if (strcmp (s1: "alloc", s2: p) == 0)
17809 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
17810 else
17811 goto invalid_behavior;
17812 break;
17813
17814 case 'd':
17815 if (strcmp (s1: "default", s2: p) == 0)
17816 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
17817 else
17818 goto invalid_behavior;
17819 break;
17820
17821 case 'f':
17822 if (strcmp (s1: "firstprivate", s2: p) == 0)
17823 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
17824 else if (strcmp (s1: "from", s2: p) == 0)
17825 behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
17826 else
17827 goto invalid_behavior;
17828 break;
17829
17830 case 'n':
17831 if (strcmp (s1: "none", s2: p) == 0)
17832 behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
17833 else
17834 goto invalid_behavior;
17835 break;
17836
17837 case 'p':
17838 if (strcmp (s1: "present", s2: p) == 0)
17839 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
17840 else
17841 goto invalid_behavior;
17842 break;
17843
17844 case 't':
17845 if (strcmp (s1: "tofrom", s2: p) == 0)
17846 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
17847 else if (strcmp (s1: "to", s2: p) == 0)
17848 behavior = OMP_CLAUSE_DEFAULTMAP_TO;
17849 else
17850 goto invalid_behavior;
17851 break;
17852
17853 default:
17854 goto invalid_behavior;
17855 }
17856 c_parser_consume_token (parser);
17857
17858 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
17859 {
17860 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
17861 goto out_err;
17862 if (!c_parser_next_token_is (parser, type: CPP_NAME))
17863 {
17864 invalid_category:
17865 c_parser_error (parser, gmsgid: "expected %<scalar%>, %<aggregate%>, "
17866 "%<pointer%> or %<all%>");
17867 goto out_err;
17868 }
17869 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
17870 switch (p[0])
17871 {
17872 case 'a':
17873 if (strcmp (s1: "aggregate", s2: p) == 0)
17874 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
17875 else if (strcmp (s1: "all", s2: p) == 0)
17876 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
17877 else
17878 goto invalid_category;
17879 break;
17880
17881 case 'p':
17882 if (strcmp (s1: "pointer", s2: p) == 0)
17883 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
17884 else
17885 goto invalid_category;
17886 break;
17887
17888 case 's':
17889 if (strcmp (s1: "scalar", s2: p) == 0)
17890 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
17891 else
17892 goto invalid_category;
17893 break;
17894
17895 default:
17896 goto invalid_category;
17897 }
17898
17899 c_parser_consume_token (parser);
17900 }
17901 parens.skip_until_found_close (parser);
17902
17903 for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
17904 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
17905 && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17906 || category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17907 || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
17908 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17909 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
17910 || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17911 == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL)))
17912 {
17913 enum omp_clause_defaultmap_kind cat = category;
17914 location_t loc = OMP_CLAUSE_LOCATION (c);
17915 if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
17916 || (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL
17917 && (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
17918 != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
17919 cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
17920 p = NULL;
17921 switch (cat)
17922 {
17923 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
17924 p = NULL;
17925 break;
17926 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
17927 p = "all";
17928 break;
17929 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
17930 p = "aggregate";
17931 break;
17932 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
17933 p = "pointer";
17934 break;
17935 case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
17936 p = "scalar";
17937 break;
17938 default:
17939 gcc_unreachable ();
17940 }
17941 if (p)
17942 error_at (loc, "too many %<defaultmap%> clauses with %qs category",
17943 p);
17944 else
17945 error_at (loc, "too many %<defaultmap%> clauses with unspecified "
17946 "category");
17947 break;
17948 }
17949
17950 c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
17951 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
17952 OMP_CLAUSE_CHAIN (c) = list;
17953 return c;
17954
17955 out_err:
17956 parens.skip_until_found_close (parser);
17957 return list;
17958}
17959
17960/* OpenACC 2.0:
17961 use_device ( variable-list )
17962
17963 OpenMP 4.5:
17964 use_device_ptr ( variable-list ) */
17965
17966static tree
17967c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
17968{
17969 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_PTR,
17970 list);
17971}
17972
17973/* OpenMP 5.0:
17974 use_device_addr ( variable-list ) */
17975
17976static tree
17977c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
17978{
17979 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE_DEVICE_ADDR,
17980 list);
17981}
17982
17983/* OpenMP 5.1:
17984 has_device_addr ( variable-list ) */
17985
17986static tree
17987c_parser_omp_clause_has_device_addr (c_parser *parser, tree list)
17988{
17989 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_HAS_DEVICE_ADDR,
17990 list);
17991}
17992
17993/* OpenMP 4.5:
17994 is_device_ptr ( variable-list ) */
17995
17996static tree
17997c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
17998{
17999 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_IS_DEVICE_PTR, list);
18000}
18001
18002/* OpenACC:
18003 num_gangs ( expression )
18004 num_workers ( expression )
18005 vector_length ( expression ) */
18006
18007static tree
18008c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
18009 tree list)
18010{
18011 location_t loc = c_parser_peek_token (parser)->location;
18012
18013 matching_parens parens;
18014 if (!parens.require_open (parser))
18015 return list;
18016
18017 location_t expr_loc = c_parser_peek_token (parser)->location;
18018 c_expr expr = c_parser_expression (parser);
18019 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
18020 tree c, t = expr.value;
18021 t = c_fully_fold (t, false, NULL);
18022
18023 parens.skip_until_found_close (parser);
18024
18025 if (t == error_mark_node)
18026 return list;
18027 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18028 {
18029 error_at (expr_loc, "%qs expression must be integral",
18030 omp_clause_code_name[code]);
18031 return list;
18032 }
18033
18034 /* Attempt to statically determine when the number isn't positive. */
18035 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
18036 build_int_cst (TREE_TYPE (t), 0));
18037 protected_set_expr_location (c, expr_loc);
18038 if (c == boolean_true_node)
18039 {
18040 warning_at (expr_loc, 0,
18041 "%qs value must be positive",
18042 omp_clause_code_name[code]);
18043 t = integer_one_node;
18044 }
18045
18046 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18047
18048 c = build_omp_clause (loc, code);
18049 OMP_CLAUSE_OPERAND (c, 0) = t;
18050 OMP_CLAUSE_CHAIN (c) = list;
18051 return c;
18052}
18053
18054/* OpenACC:
18055
18056 gang [( gang-arg-list )]
18057 worker [( [num:] int-expr )]
18058 vector [( [length:] int-expr )]
18059
18060 where gang-arg is one of:
18061
18062 [num:] int-expr
18063 static: size-expr
18064
18065 and size-expr may be:
18066
18067 *
18068 int-expr
18069*/
18070
18071static tree
18072c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
18073 omp_clause_code kind,
18074 const char *str, tree list)
18075{
18076 const char *id = "num";
18077 tree ops[2] = { NULL_TREE, NULL_TREE }, c;
18078
18079 if (kind == OMP_CLAUSE_VECTOR)
18080 id = "length";
18081
18082 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
18083 {
18084 c_parser_consume_token (parser);
18085
18086 do
18087 {
18088 c_token *next = c_parser_peek_token (parser);
18089 int idx = 0;
18090
18091 /* Gang static argument. */
18092 if (kind == OMP_CLAUSE_GANG
18093 && c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
18094 {
18095 c_parser_consume_token (parser);
18096
18097 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18098 goto cleanup_error;
18099
18100 idx = 1;
18101 if (ops[idx] != NULL_TREE)
18102 {
18103 c_parser_error (parser, gmsgid: "too many %<static%> arguments");
18104 goto cleanup_error;
18105 }
18106
18107 /* Check for the '*' argument. */
18108 if (c_parser_next_token_is (parser, type: CPP_MULT)
18109 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18110 || c_parser_peek_2nd_token (parser)->type
18111 == CPP_CLOSE_PAREN))
18112 {
18113 c_parser_consume_token (parser);
18114 ops[idx] = integer_minus_one_node;
18115
18116 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18117 {
18118 c_parser_consume_token (parser);
18119 continue;
18120 }
18121 else
18122 break;
18123 }
18124 }
18125 /* Worker num: argument and vector length: arguments. */
18126 else if (c_parser_next_token_is (parser, type: CPP_NAME)
18127 && strcmp (s1: id, IDENTIFIER_POINTER (next->value)) == 0
18128 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18129 {
18130 c_parser_consume_token (parser); /* id */
18131 c_parser_consume_token (parser); /* ':' */
18132 }
18133
18134 /* Now collect the actual argument. */
18135 if (ops[idx] != NULL_TREE)
18136 {
18137 c_parser_error (parser, gmsgid: "unexpected argument");
18138 goto cleanup_error;
18139 }
18140
18141 location_t expr_loc = c_parser_peek_token (parser)->location;
18142 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18143 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18144 tree expr = cexpr.value;
18145 if (expr == error_mark_node)
18146 goto cleanup_error;
18147
18148 expr = c_fully_fold (expr, false, NULL);
18149
18150 /* Attempt to statically determine when the number isn't a
18151 positive integer. */
18152
18153 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
18154 {
18155 c_parser_error (parser, gmsgid: "expected integer expression");
18156 return list;
18157 }
18158
18159 tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
18160 build_int_cst (TREE_TYPE (expr), 0));
18161 if (c == boolean_true_node)
18162 {
18163 warning_at (loc, 0,
18164 "%qs value must be positive", str);
18165 expr = integer_one_node;
18166 }
18167
18168 ops[idx] = expr;
18169
18170 if (kind == OMP_CLAUSE_GANG
18171 && c_parser_next_token_is (parser, type: CPP_COMMA))
18172 {
18173 c_parser_consume_token (parser);
18174 continue;
18175 }
18176 break;
18177 }
18178 while (1);
18179
18180 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
18181 goto cleanup_error;
18182 }
18183
18184 check_no_duplicate_clause (clauses: list, code: kind, name: str);
18185
18186 c = build_omp_clause (loc, kind);
18187
18188 if (ops[1])
18189 OMP_CLAUSE_OPERAND (c, 1) = ops[1];
18190
18191 OMP_CLAUSE_OPERAND (c, 0) = ops[0];
18192 OMP_CLAUSE_CHAIN (c) = list;
18193
18194 return c;
18195
18196 cleanup_error:
18197 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
18198 return list;
18199}
18200
18201/* OpenACC 2.5:
18202 auto
18203 finalize
18204 independent
18205 nohost
18206 seq */
18207
18208static tree
18209c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
18210 tree list)
18211{
18212 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18213
18214 tree c = build_omp_clause (loc, code);
18215 OMP_CLAUSE_CHAIN (c) = list;
18216
18217 return c;
18218}
18219
18220/* OpenACC:
18221 async [( int-expr )] */
18222
18223static tree
18224c_parser_oacc_clause_async (c_parser *parser, tree list)
18225{
18226 tree c, t;
18227 location_t loc = c_parser_peek_token (parser)->location;
18228
18229 t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18230
18231 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18232 {
18233 c_parser_consume_token (parser);
18234
18235 t = c_parser_expr_no_commas (parser, NULL).value;
18236 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
18237 c_parser_error (parser, gmsgid: "expected integer expression");
18238 else if (t == error_mark_node
18239 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
18240 return list;
18241 }
18242 else
18243 t = c_fully_fold (t, false, NULL);
18244
18245 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ASYNC, name: "async");
18246
18247 c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
18248 OMP_CLAUSE_ASYNC_EXPR (c) = t;
18249 OMP_CLAUSE_CHAIN (c) = list;
18250 list = c;
18251
18252 return list;
18253}
18254
18255/* OpenACC 2.0:
18256 tile ( size-expr-list ) */
18257
18258static tree
18259c_parser_oacc_clause_tile (c_parser *parser, tree list)
18260{
18261 tree c, expr = error_mark_node;
18262 location_t loc;
18263 tree tile = NULL_TREE;
18264
18265 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_TILE, name: "tile");
18266 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_COLLAPSE, name: "collapse");
18267
18268 loc = c_parser_peek_token (parser)->location;
18269 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
18270 return list;
18271
18272 do
18273 {
18274 if (tile && !c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>"))
18275 return list;
18276
18277 if (c_parser_next_token_is (parser, type: CPP_MULT)
18278 && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
18279 || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
18280 {
18281 c_parser_consume_token (parser);
18282 expr = integer_zero_node;
18283 }
18284 else
18285 {
18286 location_t expr_loc = c_parser_peek_token (parser)->location;
18287 c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
18288 cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
18289 expr = cexpr.value;
18290
18291 if (expr == error_mark_node)
18292 {
18293 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18294 msgid: "expected %<)%>");
18295 return list;
18296 }
18297
18298 expr = c_fully_fold (expr, false, NULL);
18299
18300 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
18301 || !tree_fits_shwi_p (expr)
18302 || tree_to_shwi (expr) <= 0)
18303 {
18304 error_at (expr_loc, "%<tile%> argument needs positive"
18305 " integral constant");
18306 expr = integer_zero_node;
18307 }
18308 }
18309
18310 tile = tree_cons (NULL_TREE, expr, tile);
18311 }
18312 while (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN));
18313
18314 /* Consume the trailing ')'. */
18315 c_parser_consume_token (parser);
18316
18317 c = build_omp_clause (loc, OMP_CLAUSE_TILE);
18318 tile = nreverse (tile);
18319 OMP_CLAUSE_TILE_LIST (c) = tile;
18320 OMP_CLAUSE_CHAIN (c) = list;
18321 return c;
18322}
18323
18324/* OpenACC:
18325 wait [( int-expr-list )] */
18326
18327static tree
18328c_parser_oacc_clause_wait (c_parser *parser, tree list)
18329{
18330 location_t clause_loc = c_parser_peek_token (parser)->location;
18331
18332 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18333 list = c_parser_oacc_wait_list (parser, clause_loc, list);
18334 else
18335 {
18336 tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
18337
18338 OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
18339 OMP_CLAUSE_CHAIN (c) = list;
18340 list = c;
18341 }
18342
18343 return list;
18344}
18345
18346/* OpenACC 2.7:
18347 self [( expression )] */
18348
18349static tree
18350c_parser_oacc_compute_clause_self (c_parser *parser, tree list)
18351{
18352 tree t;
18353 location_t location = c_parser_peek_token (parser)->location;
18354 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
18355 {
18356 matching_parens parens;
18357 parens.consume_open (parser);
18358
18359 location_t loc = c_parser_peek_token (parser)->location;
18360 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18361 expr = convert_lvalue_to_rvalue (loc, expr, true, true);
18362 t = c_objc_common_truthvalue_conversion (loc, expr.value);
18363 t = c_fully_fold (t, false, NULL);
18364 parens.skip_until_found_close (parser);
18365 }
18366 else
18367 t = truthvalue_true_node;
18368
18369 for (tree c = list; c; c = OMP_CLAUSE_CHAIN (c))
18370 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SELF)
18371 {
18372 error_at (location, "too many %<self%> clauses");
18373 return list;
18374 }
18375
18376 tree c = build_omp_clause (location, OMP_CLAUSE_SELF);
18377 OMP_CLAUSE_SELF_EXPR (c) = t;
18378 OMP_CLAUSE_CHAIN (c) = list;
18379 return c;
18380}
18381
18382/* OpenMP 5.0:
18383 order ( concurrent )
18384
18385 OpenMP 5.1:
18386 order ( order-modifier : concurrent )
18387
18388 order-modifier:
18389 reproducible
18390 unconstrained */
18391
18392static tree
18393c_parser_omp_clause_order (c_parser *parser, tree list)
18394{
18395 location_t loc = c_parser_peek_token (parser)->location;
18396 tree c;
18397 const char *p;
18398 bool unconstrained = false;
18399 bool reproducible = false;
18400
18401 matching_parens parens;
18402 if (!parens.require_open (parser))
18403 return list;
18404 if (c_parser_next_token_is (parser, type: CPP_NAME)
18405 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
18406 {
18407 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18408 if (strcmp (s1: p, s2: "unconstrained") == 0)
18409 unconstrained = true;
18410 else if (strcmp (s1: p, s2: "reproducible") == 0)
18411 reproducible = true;
18412 else
18413 {
18414 c_parser_error (parser, gmsgid: "expected %<reproducible%> or "
18415 "%<unconstrained%>");
18416 goto out_err;
18417 }
18418 c_parser_consume_token (parser);
18419 c_parser_consume_token (parser);
18420 }
18421 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18422 {
18423 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
18424 goto out_err;
18425 }
18426 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18427 if (strcmp (s1: p, s2: "concurrent") != 0)
18428 {
18429 c_parser_error (parser, gmsgid: "expected %<concurrent%>");
18430 goto out_err;
18431 }
18432 c_parser_consume_token (parser);
18433 parens.skip_until_found_close (parser);
18434 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDER, name: "order");
18435 c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
18436 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
18437 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
18438 OMP_CLAUSE_CHAIN (c) = list;
18439 return c;
18440
18441 out_err:
18442 parens.skip_until_found_close (parser);
18443 return list;
18444}
18445
18446
18447/* OpenMP 5.0:
18448 bind ( teams | parallel | thread ) */
18449
18450static tree
18451c_parser_omp_clause_bind (c_parser *parser, tree list)
18452{
18453 location_t loc = c_parser_peek_token (parser)->location;
18454 tree c;
18455 const char *p;
18456 enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18457
18458 matching_parens parens;
18459 if (!parens.require_open (parser))
18460 return list;
18461 if (!c_parser_next_token_is (parser, type: CPP_NAME))
18462 {
18463 invalid:
18464 c_parser_error (parser,
18465 gmsgid: "expected %<teams%>, %<parallel%> or %<thread%>");
18466 parens.skip_until_found_close (parser);
18467 return list;
18468 }
18469 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18470 if (strcmp (s1: p, s2: "teams") == 0)
18471 kind = OMP_CLAUSE_BIND_TEAMS;
18472 else if (strcmp (s1: p, s2: "parallel") == 0)
18473 kind = OMP_CLAUSE_BIND_PARALLEL;
18474 else if (strcmp (s1: p, s2: "thread") != 0)
18475 goto invalid;
18476 c_parser_consume_token (parser);
18477 parens.skip_until_found_close (parser);
18478 /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
18479 c = build_omp_clause (loc, OMP_CLAUSE_BIND);
18480 OMP_CLAUSE_BIND_KIND (c) = kind;
18481 OMP_CLAUSE_CHAIN (c) = list;
18482 return c;
18483}
18484
18485
18486/* OpenMP 2.5:
18487 ordered
18488
18489 OpenMP 4.5:
18490 ordered ( constant-expression ) */
18491
18492static tree
18493c_parser_omp_clause_ordered (c_parser *parser, tree list)
18494{
18495 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_ORDERED, name: "ordered");
18496
18497 tree c, num = NULL_TREE;
18498 HOST_WIDE_INT n;
18499 location_t loc = c_parser_peek_token (parser)->location;
18500 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
18501 {
18502 matching_parens parens;
18503 parens.consume_open (parser);
18504 num = c_parser_expr_no_commas (parser, NULL).value;
18505 parens.skip_until_found_close (parser);
18506 }
18507 if (num == error_mark_node)
18508 return list;
18509 if (num)
18510 {
18511 mark_exp_read (num);
18512 num = c_fully_fold (num, false, NULL);
18513 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
18514 || !tree_fits_shwi_p (num)
18515 || (n = tree_to_shwi (num)) <= 0
18516 || (int) n != n)
18517 {
18518 error_at (loc, "ordered argument needs positive "
18519 "constant integer expression");
18520 return list;
18521 }
18522 }
18523 c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
18524 OMP_CLAUSE_ORDERED_EXPR (c) = num;
18525 OMP_CLAUSE_CHAIN (c) = list;
18526 return c;
18527}
18528
18529/* OpenMP 2.5:
18530 private ( variable-list ) */
18531
18532static tree
18533c_parser_omp_clause_private (c_parser *parser, tree list)
18534{
18535 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_PRIVATE, list);
18536}
18537
18538/* OpenMP 2.5:
18539 reduction ( reduction-operator : variable-list )
18540
18541 reduction-operator:
18542 One of: + * - & ^ | && ||
18543
18544 OpenMP 3.1:
18545
18546 reduction-operator:
18547 One of: + * - & ^ | && || max min
18548
18549 OpenMP 4.0:
18550
18551 reduction-operator:
18552 One of: + * - & ^ | && ||
18553 identifier
18554
18555 OpenMP 5.0:
18556 reduction ( reduction-modifier, reduction-operator : variable-list )
18557 in_reduction ( reduction-operator : variable-list )
18558 task_reduction ( reduction-operator : variable-list ) */
18559
18560static tree
18561c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
18562 bool is_omp, tree list)
18563{
18564 location_t clause_loc = c_parser_peek_token (parser)->location;
18565 matching_parens parens;
18566 if (parens.require_open (parser))
18567 {
18568 bool task = false;
18569 bool inscan = false;
18570 enum tree_code code = ERROR_MARK;
18571 tree reduc_id = NULL_TREE;
18572
18573 if (kind == OMP_CLAUSE_REDUCTION && is_omp)
18574 {
18575 if (c_parser_next_token_is_keyword (parser, keyword: RID_DEFAULT)
18576 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18577 {
18578 c_parser_consume_token (parser);
18579 c_parser_consume_token (parser);
18580 }
18581 else if (c_parser_next_token_is (parser, type: CPP_NAME)
18582 && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
18583 {
18584 const char *p
18585 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18586 if (strcmp (s1: p, s2: "task") == 0)
18587 task = true;
18588 else if (strcmp (s1: p, s2: "inscan") == 0)
18589 inscan = true;
18590 if (task || inscan)
18591 {
18592 c_parser_consume_token (parser);
18593 c_parser_consume_token (parser);
18594 }
18595 }
18596 }
18597
18598 switch (c_parser_peek_token (parser)->type)
18599 {
18600 case CPP_PLUS:
18601 code = PLUS_EXPR;
18602 break;
18603 case CPP_MULT:
18604 code = MULT_EXPR;
18605 break;
18606 case CPP_MINUS:
18607 code = MINUS_EXPR;
18608 break;
18609 case CPP_AND:
18610 code = BIT_AND_EXPR;
18611 break;
18612 case CPP_XOR:
18613 code = BIT_XOR_EXPR;
18614 break;
18615 case CPP_OR:
18616 code = BIT_IOR_EXPR;
18617 break;
18618 case CPP_AND_AND:
18619 code = TRUTH_ANDIF_EXPR;
18620 break;
18621 case CPP_OR_OR:
18622 code = TRUTH_ORIF_EXPR;
18623 break;
18624 case CPP_NAME:
18625 {
18626 const char *p
18627 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
18628 if (strcmp (s1: p, s2: "min") == 0)
18629 {
18630 code = MIN_EXPR;
18631 break;
18632 }
18633 if (strcmp (s1: p, s2: "max") == 0)
18634 {
18635 code = MAX_EXPR;
18636 break;
18637 }
18638 reduc_id = c_parser_peek_token (parser)->value;
18639 break;
18640 }
18641 default:
18642 c_parser_error (parser,
18643 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
18644 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
18645 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
18646 return list;
18647 }
18648 c_parser_consume_token (parser);
18649 reduc_id = c_omp_reduction_id (code, reduc_id);
18650 if (c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
18651 {
18652 tree nl, c;
18653
18654 nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
18655 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
18656 {
18657 tree d = OMP_CLAUSE_DECL (c), type;
18658 if (TREE_CODE (d) != OMP_ARRAY_SECTION)
18659 type = TREE_TYPE (d);
18660 else
18661 {
18662 int cnt = 0;
18663 tree t;
18664 for (t = d;
18665 TREE_CODE (t) == OMP_ARRAY_SECTION;
18666 t = TREE_OPERAND (t, 0))
18667 cnt++;
18668 type = TREE_TYPE (t);
18669 while (cnt > 0)
18670 {
18671 if (TREE_CODE (type) != POINTER_TYPE
18672 && TREE_CODE (type) != ARRAY_TYPE)
18673 break;
18674 type = TREE_TYPE (type);
18675 cnt--;
18676 }
18677 }
18678 while (TREE_CODE (type) == ARRAY_TYPE)
18679 type = TREE_TYPE (type);
18680 OMP_CLAUSE_REDUCTION_CODE (c) = code;
18681 if (task)
18682 OMP_CLAUSE_REDUCTION_TASK (c) = 1;
18683 else if (inscan)
18684 OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
18685 if (code == ERROR_MARK
18686 || !(INTEGRAL_TYPE_P (type)
18687 || SCALAR_FLOAT_TYPE_P (type)
18688 || TREE_CODE (type) == COMPLEX_TYPE))
18689 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
18690 = c_omp_reduction_lookup (reduc_id,
18691 TYPE_MAIN_VARIANT (type));
18692 }
18693
18694 list = nl;
18695 }
18696 parens.skip_until_found_close (parser);
18697 }
18698 return list;
18699}
18700
18701/* OpenMP 2.5:
18702 schedule ( schedule-kind )
18703 schedule ( schedule-kind , expression )
18704
18705 schedule-kind:
18706 static | dynamic | guided | runtime | auto
18707
18708 OpenMP 4.5:
18709 schedule ( schedule-modifier : schedule-kind )
18710 schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
18711
18712 schedule-modifier:
18713 simd
18714 monotonic
18715 nonmonotonic */
18716
18717static tree
18718c_parser_omp_clause_schedule (c_parser *parser, tree list)
18719{
18720 tree c, t;
18721 location_t loc = c_parser_peek_token (parser)->location;
18722 int modifiers = 0, nmodifiers = 0;
18723
18724 matching_parens parens;
18725 if (!parens.require_open (parser))
18726 return list;
18727
18728 c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
18729
18730 location_t comma = UNKNOWN_LOCATION;
18731 while (c_parser_next_token_is (parser, type: CPP_NAME))
18732 {
18733 tree kind = c_parser_peek_token (parser)->value;
18734 const char *p = IDENTIFIER_POINTER (kind);
18735 if (strcmp (s1: "simd", s2: p) == 0)
18736 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
18737 else if (strcmp (s1: "monotonic", s2: p) == 0)
18738 modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
18739 else if (strcmp (s1: "nonmonotonic", s2: p) == 0)
18740 modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
18741 else
18742 break;
18743 comma = UNKNOWN_LOCATION;
18744 c_parser_consume_token (parser);
18745 if (nmodifiers++ == 0
18746 && c_parser_next_token_is (parser, type: CPP_COMMA))
18747 {
18748 comma = c_parser_peek_token (parser)->location;
18749 c_parser_consume_token (parser);
18750 }
18751 else
18752 {
18753 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
18754 break;
18755 }
18756 }
18757 if (comma != UNKNOWN_LOCATION)
18758 error_at (comma, "expected %<:%>");
18759
18760 if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
18761 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18762 == (OMP_CLAUSE_SCHEDULE_MONOTONIC
18763 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
18764 {
18765 error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
18766 "specified");
18767 modifiers = 0;
18768 }
18769
18770 if (c_parser_next_token_is (parser, type: CPP_NAME))
18771 {
18772 tree kind = c_parser_peek_token (parser)->value;
18773 const char *p = IDENTIFIER_POINTER (kind);
18774
18775 switch (p[0])
18776 {
18777 case 'd':
18778 if (strcmp (s1: "dynamic", s2: p) != 0)
18779 goto invalid_kind;
18780 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
18781 break;
18782
18783 case 'g':
18784 if (strcmp (s1: "guided", s2: p) != 0)
18785 goto invalid_kind;
18786 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
18787 break;
18788
18789 case 'r':
18790 if (strcmp (s1: "runtime", s2: p) != 0)
18791 goto invalid_kind;
18792 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
18793 break;
18794
18795 default:
18796 goto invalid_kind;
18797 }
18798 }
18799 else if (c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
18800 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
18801 else if (c_parser_next_token_is_keyword (parser, keyword: RID_AUTO))
18802 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
18803 else
18804 goto invalid_kind;
18805
18806 c_parser_consume_token (parser);
18807 if (c_parser_next_token_is (parser, type: CPP_COMMA))
18808 {
18809 location_t here;
18810 c_parser_consume_token (parser);
18811
18812 here = c_parser_peek_token (parser)->location;
18813 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18814 expr = convert_lvalue_to_rvalue (here, expr, false, true);
18815 t = expr.value;
18816 t = c_fully_fold (t, false, NULL);
18817
18818 if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
18819 error_at (here, "schedule %<runtime%> does not take "
18820 "a %<chunk_size%> parameter");
18821 else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
18822 error_at (here,
18823 "schedule %<auto%> does not take "
18824 "a %<chunk_size%> parameter");
18825 else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
18826 || TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE)
18827 {
18828 /* Attempt to statically determine when the number isn't
18829 positive. */
18830 tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
18831 build_int_cst (TREE_TYPE (t), 0));
18832 protected_set_expr_location (s, loc);
18833 if (s == boolean_true_node)
18834 {
18835 warning_at (loc, OPT_Wopenmp,
18836 "chunk size value must be positive");
18837 t = integer_one_node;
18838 }
18839 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
18840 }
18841 else
18842 c_parser_error (parser, gmsgid: "expected integer expression");
18843
18844 parens.skip_until_found_close (parser);
18845 }
18846 else
18847 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
18848 msgid: "expected %<,%> or %<)%>");
18849
18850 OMP_CLAUSE_SCHEDULE_KIND (c)
18851 = (enum omp_clause_schedule_kind)
18852 (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
18853
18854 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SCHEDULE, name: "schedule");
18855 OMP_CLAUSE_CHAIN (c) = list;
18856 return c;
18857
18858 invalid_kind:
18859 c_parser_error (parser, gmsgid: "invalid schedule kind");
18860 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, msgid: 0);
18861 return list;
18862}
18863
18864/* OpenMP 2.5:
18865 shared ( variable-list ) */
18866
18867static tree
18868c_parser_omp_clause_shared (c_parser *parser, tree list)
18869{
18870 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_SHARED, list);
18871}
18872
18873/* OpenMP 3.0:
18874 untied */
18875
18876static tree
18877c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18878{
18879 tree c;
18880
18881 /* FIXME: Should we allow duplicates? */
18882 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_UNTIED, name: "untied");
18883
18884 c = build_omp_clause (c_parser_peek_token (parser)->location,
18885 OMP_CLAUSE_UNTIED);
18886 OMP_CLAUSE_CHAIN (c) = list;
18887
18888 return c;
18889}
18890
18891/* OpenMP 4.0:
18892 inbranch
18893 notinbranch */
18894
18895static tree
18896c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
18897 enum omp_clause_code code, tree list)
18898{
18899 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18900
18901 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18902 OMP_CLAUSE_CHAIN (c) = list;
18903
18904 return c;
18905}
18906
18907/* OpenMP 4.0:
18908 parallel
18909 for
18910 sections
18911 taskgroup */
18912
18913static tree
18914c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
18915 enum omp_clause_code code, tree list)
18916{
18917 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18918 OMP_CLAUSE_CHAIN (c) = list;
18919
18920 return c;
18921}
18922
18923/* OpenMP 4.5:
18924 nogroup */
18925
18926static tree
18927c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
18928{
18929 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOGROUP, name: "nogroup");
18930 tree c = build_omp_clause (c_parser_peek_token (parser)->location,
18931 OMP_CLAUSE_NOGROUP);
18932 OMP_CLAUSE_CHAIN (c) = list;
18933 return c;
18934}
18935
18936/* OpenMP 4.5:
18937 simd
18938 threads */
18939
18940static tree
18941c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
18942 enum omp_clause_code code, tree list)
18943{
18944 check_no_duplicate_clause (clauses: list, code, name: omp_clause_code_name[code]);
18945 tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
18946 OMP_CLAUSE_CHAIN (c) = list;
18947 return c;
18948}
18949
18950/* OpenMP 4.0:
18951 num_teams ( expression )
18952
18953 OpenMP 5.1:
18954 num_teams ( expression : expression ) */
18955
18956static tree
18957c_parser_omp_clause_num_teams (c_parser *parser, tree list)
18958{
18959 location_t num_teams_loc = c_parser_peek_token (parser)->location;
18960 matching_parens parens;
18961 if (parens.require_open (parser))
18962 {
18963 location_t upper_loc = c_parser_peek_token (parser)->location;
18964 location_t lower_loc = UNKNOWN_LOCATION;
18965 c_expr expr = c_parser_expr_no_commas (parser, NULL);
18966 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
18967 tree c, upper = expr.value, lower = NULL_TREE;
18968 upper = c_fully_fold (upper, false, NULL);
18969
18970 if (c_parser_next_token_is (parser, type: CPP_COLON))
18971 {
18972 c_parser_consume_token (parser);
18973 lower_loc = upper_loc;
18974 lower = upper;
18975 upper_loc = c_parser_peek_token (parser)->location;
18976 expr = c_parser_expr_no_commas (parser, NULL);
18977 expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
18978 upper = expr.value;
18979 upper = c_fully_fold (upper, false, NULL);
18980 }
18981
18982 parens.skip_until_found_close (parser);
18983
18984 if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
18985 || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
18986 {
18987 c_parser_error (parser, gmsgid: "expected integer expression");
18988 return list;
18989 }
18990
18991 /* Attempt to statically determine when the number isn't positive. */
18992 c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
18993 build_int_cst (TREE_TYPE (upper), 0));
18994 protected_set_expr_location (c, upper_loc);
18995 if (c == boolean_true_node)
18996 {
18997 warning_at (upper_loc, OPT_Wopenmp,
18998 "%<num_teams%> value must be positive");
18999 upper = integer_one_node;
19000 }
19001 if (lower)
19002 {
19003 c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
19004 build_int_cst (TREE_TYPE (lower), 0));
19005 protected_set_expr_location (c, lower_loc);
19006 if (c == boolean_true_node)
19007 {
19008 warning_at (lower_loc, OPT_Wopenmp,
19009 "%<num_teams%> value must be positive");
19010 lower = NULL_TREE;
19011 }
19012 else if (TREE_CODE (lower) == INTEGER_CST
19013 && TREE_CODE (upper) == INTEGER_CST
19014 && tree_int_cst_lt (t1: upper, t2: lower))
19015 {
19016 warning_at (lower_loc, OPT_Wopenmp,
19017 "%<num_teams%> lower bound %qE bigger than upper "
19018 "bound %qE", lower, upper);
19019 lower = NULL_TREE;
19020 }
19021 }
19022
19023 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NUM_TEAMS, name: "num_teams");
19024
19025 c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
19026 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
19027 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
19028 OMP_CLAUSE_CHAIN (c) = list;
19029 list = c;
19030 }
19031
19032 return list;
19033}
19034
19035/* OpenMP 4.0:
19036 thread_limit ( expression ) */
19037
19038static tree
19039c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
19040{
19041 location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
19042 matching_parens parens;
19043 if (parens.require_open (parser))
19044 {
19045 location_t expr_loc = c_parser_peek_token (parser)->location;
19046 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19047 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19048 tree c, t = expr.value;
19049 t = c_fully_fold (t, false, NULL);
19050
19051 parens.skip_until_found_close (parser);
19052
19053 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
19054 {
19055 c_parser_error (parser, gmsgid: "expected integer expression");
19056 return list;
19057 }
19058
19059 /* Attempt to statically determine when the number isn't positive. */
19060 c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
19061 build_int_cst (TREE_TYPE (t), 0));
19062 protected_set_expr_location (c, expr_loc);
19063 if (c == boolean_true_node)
19064 {
19065 warning_at (expr_loc, OPT_Wopenmp,
19066 "%<thread_limit%> value must be positive");
19067 t = integer_one_node;
19068 }
19069
19070 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_THREAD_LIMIT,
19071 name: "thread_limit");
19072
19073 c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
19074 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
19075 OMP_CLAUSE_CHAIN (c) = list;
19076 list = c;
19077 }
19078
19079 return list;
19080}
19081
19082/* OpenMP 4.0:
19083 aligned ( variable-list )
19084 aligned ( variable-list : constant-expression ) */
19085
19086static tree
19087c_parser_omp_clause_aligned (c_parser *parser, tree list)
19088{
19089 location_t clause_loc = c_parser_peek_token (parser)->location;
19090 tree nl, c;
19091
19092 matching_parens parens;
19093 if (!parens.require_open (parser))
19094 return list;
19095
19096 nl = c_parser_omp_variable_list (parser, clause_loc,
19097 kind: OMP_CLAUSE_ALIGNED, list);
19098
19099 if (c_parser_next_token_is (parser, type: CPP_COLON))
19100 {
19101 c_parser_consume_token (parser);
19102 location_t expr_loc = c_parser_peek_token (parser)->location;
19103 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19104 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19105 tree alignment = expr.value;
19106 alignment = c_fully_fold (alignment, false, NULL);
19107 if (TREE_CODE (alignment) != INTEGER_CST
19108 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
19109 || tree_int_cst_sgn (alignment) != 1)
19110 {
19111 error_at (clause_loc, "%<aligned%> clause alignment expression must "
19112 "be positive constant integer expression");
19113 alignment = NULL_TREE;
19114 }
19115
19116 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19117 OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
19118 }
19119
19120 parens.skip_until_found_close (parser);
19121 return nl;
19122}
19123
19124/* OpenMP 5.0:
19125 allocate ( variable-list )
19126 allocate ( expression : variable-list )
19127
19128 OpenMP 5.1:
19129 allocate ( allocator-modifier : variable-list )
19130 allocate ( allocator-modifier , allocator-modifier : variable-list )
19131
19132 allocator-modifier:
19133 allocator ( expression )
19134 align ( expression ) */
19135
19136static tree
19137c_parser_omp_clause_allocate (c_parser *parser, tree list)
19138{
19139 location_t clause_loc = c_parser_peek_token (parser)->location;
19140 tree nl, c;
19141 tree allocator = NULL_TREE;
19142 tree align = NULL_TREE;
19143
19144 matching_parens parens;
19145 if (!parens.require_open (parser))
19146 return list;
19147
19148 if ((c_parser_next_token_is_not (parser, type: CPP_NAME)
19149 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
19150 || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
19151 && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
19152 {
19153 bool has_modifiers = false;
19154 tree orig_type = NULL_TREE;
19155 if (c_parser_next_token_is (parser, type: CPP_NAME)
19156 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19157 {
19158 unsigned int n = 3;
19159 const char *p
19160 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19161 if ((strcmp (s1: p, s2: "allocator") == 0 || strcmp (s1: p, s2: "align") == 0)
19162 && c_parser_check_balanced_raw_token_sequence (parser, n: &n)
19163 && (c_parser_peek_nth_token_raw (parser, n)->type
19164 == CPP_CLOSE_PAREN))
19165 {
19166 if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19167 == CPP_COLON)
19168 has_modifiers = true;
19169 else if (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19170 == CPP_COMMA
19171 && (c_parser_peek_nth_token_raw (parser, n: n + 2)->type
19172 == CPP_NAME)
19173 && (c_parser_peek_nth_token_raw (parser, n: n + 3)->type
19174 == CPP_OPEN_PAREN))
19175 {
19176 c_token *tok = c_parser_peek_nth_token_raw (parser, n: n + 2);
19177 const char *q = IDENTIFIER_POINTER (tok->value);
19178 n += 4;
19179 if ((strcmp (s1: q, s2: "allocator") == 0
19180 || strcmp (s1: q, s2: "align") == 0)
19181 && c_parser_check_balanced_raw_token_sequence (parser,
19182 n: &n)
19183 && (c_parser_peek_nth_token_raw (parser, n)->type
19184 == CPP_CLOSE_PAREN)
19185 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19186 == CPP_COLON))
19187 has_modifiers = true;
19188 }
19189 }
19190 if (has_modifiers)
19191 {
19192 c_parser_consume_token (parser);
19193 matching_parens parens2;
19194 parens2.require_open (parser);
19195 location_t expr_loc = c_parser_peek_token (parser)->location;
19196 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19197 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19198 if (expr.value == error_mark_node)
19199 ;
19200 else if (strcmp (s1: p, s2: "allocator") == 0)
19201 {
19202 allocator = expr.value;
19203 allocator = c_fully_fold (allocator, false, NULL);
19204 orig_type = expr.original_type
19205 ? expr.original_type : TREE_TYPE (allocator);
19206 orig_type = TYPE_MAIN_VARIANT (orig_type);
19207 }
19208 else
19209 {
19210 align = expr.value;
19211 align = c_fully_fold (align, false, NULL);
19212 }
19213 parens2.skip_until_found_close (parser);
19214 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19215 {
19216 c_parser_consume_token (parser);
19217 c_token *tok = c_parser_peek_token (parser);
19218 const char *q = "";
19219 if (c_parser_next_token_is (parser, type: CPP_NAME))
19220 q = IDENTIFIER_POINTER (tok->value);
19221 if (strcmp (s1: q, s2: "allocator") != 0 && strcmp (s1: q, s2: "align") != 0)
19222 {
19223 c_parser_error (parser, gmsgid: "expected %<allocator%> or "
19224 "%<align%>");
19225 parens.skip_until_found_close (parser);
19226 return list;
19227 }
19228 else if (strcmp (s1: p, s2: q) == 0)
19229 {
19230 error_at (tok->location, "duplicate %qs modifier", p);
19231 parens.skip_until_found_close (parser);
19232 return list;
19233 }
19234 c_parser_consume_token (parser);
19235 if (!parens2.require_open (parser))
19236 {
19237 parens.skip_until_found_close (parser);
19238 return list;
19239 }
19240 expr_loc = c_parser_peek_token (parser)->location;
19241 expr = c_parser_expr_no_commas (parser, NULL);
19242 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19243 true);
19244 if (strcmp (s1: q, s2: "allocator") == 0)
19245 {
19246 allocator = expr.value;
19247 allocator = c_fully_fold (allocator, false, NULL);
19248 orig_type = expr.original_type
19249 ? expr.original_type : TREE_TYPE (allocator);
19250 orig_type = TYPE_MAIN_VARIANT (orig_type);
19251 }
19252 else
19253 {
19254 align = expr.value;
19255 align = c_fully_fold (align, false, NULL);
19256 }
19257 parens2.skip_until_found_close (parser);
19258 }
19259 }
19260 }
19261 if (!has_modifiers)
19262 {
19263 location_t expr_loc = c_parser_peek_token (parser)->location;
19264 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19265 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19266 allocator = expr.value;
19267 allocator = c_fully_fold (allocator, false, NULL);
19268 orig_type = expr.original_type
19269 ? expr.original_type : TREE_TYPE (allocator);
19270 orig_type = TYPE_MAIN_VARIANT (orig_type);
19271 }
19272 if (allocator
19273 && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
19274 || TREE_CODE (orig_type) != ENUMERAL_TYPE
19275 || (TYPE_NAME (orig_type)
19276 != get_identifier ("omp_allocator_handle_t"))))
19277 {
19278 error_at (clause_loc, "%<allocate%> clause allocator expression "
19279 "has type %qT rather than "
19280 "%<omp_allocator_handle_t%>",
19281 TREE_TYPE (allocator));
19282 allocator = NULL_TREE;
19283 }
19284 if (align
19285 && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
19286 || !tree_fits_uhwi_p (align)
19287 || !integer_pow2p (align)))
19288 {
19289 error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
19290 "argument needs to be positive constant "
19291 "power of two integer expression");
19292 align = NULL_TREE;
19293 }
19294 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19295 {
19296 parens.skip_until_found_close (parser);
19297 return list;
19298 }
19299 }
19300
19301 nl = c_parser_omp_variable_list (parser, clause_loc,
19302 kind: OMP_CLAUSE_ALLOCATE, list);
19303
19304 if (allocator || align)
19305 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19306 {
19307 OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
19308 OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
19309 }
19310
19311 parens.skip_until_found_close (parser);
19312 return nl;
19313}
19314
19315/* OpenMP 4.0:
19316 linear ( variable-list )
19317 linear ( variable-list : expression )
19318
19319 OpenMP 4.5:
19320 linear ( modifier ( variable-list ) )
19321 linear ( modifier ( variable-list ) : expression )
19322
19323 modifier:
19324 val
19325
19326 OpenMP 5.2:
19327 linear ( variable-list : modifiers-list )
19328
19329 modifiers:
19330 val
19331 step ( expression ) */
19332
19333static tree
19334c_parser_omp_clause_linear (c_parser *parser, tree list)
19335{
19336 location_t clause_loc = c_parser_peek_token (parser)->location;
19337 tree nl, c, step;
19338 enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
19339 bool old_linear_modifier = false;
19340
19341 matching_parens parens;
19342 if (!parens.require_open (parser))
19343 return list;
19344
19345 if (c_parser_next_token_is (parser, type: CPP_NAME))
19346 {
19347 c_token *tok = c_parser_peek_token (parser);
19348 const char *p = IDENTIFIER_POINTER (tok->value);
19349 if (strcmp (s1: "val", s2: p) == 0)
19350 kind = OMP_CLAUSE_LINEAR_VAL;
19351 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
19352 kind = OMP_CLAUSE_LINEAR_DEFAULT;
19353 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19354 {
19355 old_linear_modifier = true;
19356 c_parser_consume_token (parser);
19357 c_parser_consume_token (parser);
19358 }
19359 }
19360
19361 nl = c_parser_omp_variable_list (parser, clause_loc,
19362 kind: OMP_CLAUSE_LINEAR, list);
19363
19364 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19365 parens.skip_until_found_close (parser);
19366
19367 if (c_parser_next_token_is (parser, type: CPP_COLON))
19368 {
19369 c_parser_consume_token (parser);
19370 location_t expr_loc = c_parser_peek_token (parser)->location;
19371 bool has_modifiers = false;
19372 if (kind == OMP_CLAUSE_LINEAR_DEFAULT
19373 && c_parser_next_token_is (parser, type: CPP_NAME))
19374 {
19375 c_token *tok = c_parser_peek_token (parser);
19376 const char *p = IDENTIFIER_POINTER (tok->value);
19377 unsigned int pos = 0;
19378 if (strcmp (s1: "val", s2: p) == 0)
19379 pos = 2;
19380 else if (strcmp (s1: "step", s2: p) == 0
19381 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
19382 {
19383 pos = 3;
19384 if (c_parser_check_balanced_raw_token_sequence (parser, n: &pos)
19385 && (c_parser_peek_nth_token_raw (parser, n: pos)->type
19386 == CPP_CLOSE_PAREN))
19387 ++pos;
19388 else
19389 pos = 0;
19390 }
19391 if (pos)
19392 {
19393 tok = c_parser_peek_nth_token_raw (parser, n: pos);
19394 if (tok->type == CPP_COMMA || tok->type == CPP_CLOSE_PAREN)
19395 has_modifiers = true;
19396 }
19397 }
19398 if (has_modifiers)
19399 {
19400 step = NULL_TREE;
19401 while (c_parser_next_token_is (parser, type: CPP_NAME))
19402 {
19403 c_token *tok = c_parser_peek_token (parser);
19404 const char *p = IDENTIFIER_POINTER (tok->value);
19405 if (strcmp (s1: "val", s2: p) == 0)
19406 {
19407 if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
19408 error_at (tok->location, "multiple linear modifiers");
19409 kind = OMP_CLAUSE_LINEAR_DEFAULT;
19410 c_parser_consume_token (parser);
19411 }
19412 else if (strcmp (s1: "step", s2: p) == 0)
19413 {
19414 c_parser_consume_token (parser);
19415 matching_parens parens2;
19416 if (parens2.require_open (parser))
19417 {
19418 if (step)
19419 error_at (tok->location,
19420 "multiple %<step%> modifiers");
19421 expr_loc = c_parser_peek_token (parser)->location;
19422 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19423 expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
19424 true);
19425 step = c_fully_fold (expr.value, false, NULL);
19426 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19427 {
19428 error_at (clause_loc, "%<linear%> clause step "
19429 "expression must be integral");
19430 step = integer_one_node;
19431 }
19432 parens2.skip_until_found_close (parser);
19433 }
19434 else
19435 break;
19436 }
19437 else
19438 break;
19439 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19440 {
19441 c_parser_consume_token (parser);
19442 continue;
19443 }
19444 break;
19445 }
19446 if (!step)
19447 step = integer_one_node;
19448 }
19449 else
19450 {
19451 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19452 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19453 step = c_fully_fold (expr.value, false, NULL);
19454 if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
19455 {
19456 error_at (clause_loc, "%<linear%> clause step expression must "
19457 "be integral");
19458 step = integer_one_node;
19459 }
19460 }
19461
19462 }
19463 else
19464 step = integer_one_node;
19465
19466 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19467 {
19468 OMP_CLAUSE_LINEAR_STEP (c) = step;
19469 OMP_CLAUSE_LINEAR_KIND (c) = kind;
19470 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (c) = old_linear_modifier;
19471 }
19472
19473 parens.skip_until_found_close (parser);
19474 return nl;
19475}
19476
19477/* OpenMP 5.0:
19478 nontemporal ( variable-list ) */
19479
19480static tree
19481c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
19482{
19483 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_NONTEMPORAL, list);
19484}
19485
19486/* OpenMP 4.0:
19487 safelen ( constant-expression ) */
19488
19489static tree
19490c_parser_omp_clause_safelen (c_parser *parser, tree list)
19491{
19492 location_t clause_loc = c_parser_peek_token (parser)->location;
19493 tree c, t;
19494
19495 matching_parens parens;
19496 if (!parens.require_open (parser))
19497 return list;
19498
19499 location_t expr_loc = c_parser_peek_token (parser)->location;
19500 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19501 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19502 t = expr.value;
19503 t = c_fully_fold (t, false, NULL);
19504 if (TREE_CODE (t) != INTEGER_CST
19505 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19506 || tree_int_cst_sgn (t) != 1)
19507 {
19508 error_at (clause_loc, "%<safelen%> clause expression must "
19509 "be positive constant integer expression");
19510 t = NULL_TREE;
19511 }
19512
19513 parens.skip_until_found_close (parser);
19514 if (t == NULL_TREE || t == error_mark_node)
19515 return list;
19516
19517 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SAFELEN, name: "safelen");
19518
19519 c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
19520 OMP_CLAUSE_SAFELEN_EXPR (c) = t;
19521 OMP_CLAUSE_CHAIN (c) = list;
19522 return c;
19523}
19524
19525/* OpenMP 4.0:
19526 simdlen ( constant-expression ) */
19527
19528static tree
19529c_parser_omp_clause_simdlen (c_parser *parser, tree list)
19530{
19531 location_t clause_loc = c_parser_peek_token (parser)->location;
19532 tree c, t;
19533
19534 matching_parens parens;
19535 if (!parens.require_open (parser))
19536 return list;
19537
19538 location_t expr_loc = c_parser_peek_token (parser)->location;
19539 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19540 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
19541 t = expr.value;
19542 t = c_fully_fold (t, false, NULL);
19543 if (TREE_CODE (t) != INTEGER_CST
19544 || !INTEGRAL_TYPE_P (TREE_TYPE (t))
19545 || tree_int_cst_sgn (t) != 1)
19546 {
19547 error_at (clause_loc, "%<simdlen%> clause expression must "
19548 "be positive constant integer expression");
19549 t = NULL_TREE;
19550 }
19551
19552 parens.skip_until_found_close (parser);
19553 if (t == NULL_TREE || t == error_mark_node)
19554 return list;
19555
19556 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_SIMDLEN, name: "simdlen");
19557
19558 c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
19559 OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
19560 OMP_CLAUSE_CHAIN (c) = list;
19561 return c;
19562}
19563
19564/* OpenMP 4.5:
19565 vec:
19566 identifier [+/- integer]
19567 vec , identifier [+/- integer]
19568*/
19569
19570static tree
19571c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
19572 tree list, bool depend_p)
19573{
19574 tree vec = NULL;
19575 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
19576 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
19577 {
19578 c_parser_error (parser, gmsgid: "expected identifier");
19579 return list;
19580 }
19581
19582 if (!depend_p)
19583 {
19584 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19585 if (strcmp (s1: p, s2: "omp_cur_iteration") == 0
19586 && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
19587 && c_parser_peek_nth_token (parser, n: 3)->type == CPP_NUMBER
19588 && c_parser_peek_nth_token (parser, n: 4)->type == CPP_CLOSE_PAREN)
19589 {
19590 tree val = c_parser_peek_nth_token (parser, n: 3)->value;
19591 if (integer_onep (val))
19592 {
19593 c_parser_consume_token (parser);
19594 c_parser_consume_token (parser);
19595 c_parser_consume_token (parser);
19596 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19597 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19598 OMP_CLAUSE_CHAIN (u) = list;
19599 return u;
19600 }
19601 }
19602 }
19603
19604
19605
19606 while (c_parser_next_token_is (parser, type: CPP_NAME)
19607 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
19608 {
19609 tree t = lookup_name (c_parser_peek_token (parser)->value);
19610 tree addend = NULL;
19611
19612 if (t == NULL_TREE)
19613 {
19614 undeclared_variable (c_parser_peek_token (parser)->location,
19615 c_parser_peek_token (parser)->value);
19616 t = error_mark_node;
19617 }
19618
19619 c_parser_consume_token (parser);
19620
19621 bool neg = false;
19622 if (c_parser_next_token_is (parser, type: CPP_MINUS))
19623 neg = true;
19624 else if (!c_parser_next_token_is (parser, type: CPP_PLUS))
19625 {
19626 addend = integer_zero_node;
19627 neg = false;
19628 goto add_to_vector;
19629 }
19630 c_parser_consume_token (parser);
19631
19632 if (c_parser_next_token_is_not (parser, type: CPP_NUMBER))
19633 {
19634 c_parser_error (parser, gmsgid: "expected integer");
19635 return list;
19636 }
19637
19638 addend = c_parser_peek_token (parser)->value;
19639 if (TREE_CODE (addend) != INTEGER_CST)
19640 {
19641 c_parser_error (parser, gmsgid: "expected integer");
19642 return list;
19643 }
19644 c_parser_consume_token (parser);
19645
19646 add_to_vector:
19647 if (t != error_mark_node)
19648 {
19649 vec = tree_cons (addend, t, vec);
19650 if (neg)
19651 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
19652 }
19653
19654 if (c_parser_next_token_is_not (parser, type: CPP_COMMA)
19655 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
19656 || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
19657 break;
19658
19659 c_parser_consume_token (parser);
19660 }
19661
19662 if (vec == NULL_TREE)
19663 return list;
19664
19665 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19666 OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
19667 OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
19668 OMP_CLAUSE_DECL (u) = nreverse (vec);
19669 OMP_CLAUSE_CHAIN (u) = list;
19670 return u;
19671}
19672
19673/* OpenMP 5.0:
19674 iterators ( iterators-definition )
19675
19676 iterators-definition:
19677 iterator-specifier
19678 iterator-specifier , iterators-definition
19679
19680 iterator-specifier:
19681 identifier = range-specification
19682 iterator-type identifier = range-specification
19683
19684 range-specification:
19685 begin : end
19686 begin : end : step */
19687
19688static tree
19689c_parser_omp_iterators (c_parser *parser)
19690{
19691 tree ret = NULL_TREE, *last = &ret;
19692 c_parser_consume_token (parser);
19693
19694 push_scope ();
19695
19696 matching_parens parens;
19697 if (!parens.require_open (parser))
19698 return error_mark_node;
19699
19700 do
19701 {
19702 tree iter_type = NULL_TREE, type_expr = NULL_TREE;
19703 if (c_parser_next_tokens_start_typename (parser, la: cla_prefer_id))
19704 {
19705 struct c_type_name *type = c_parser_type_name (parser);
19706 if (type != NULL)
19707 iter_type = groktypename (type, &type_expr, NULL);
19708 }
19709 if (iter_type == NULL_TREE)
19710 iter_type = integer_type_node;
19711
19712 location_t loc = c_parser_peek_token (parser)->location;
19713 if (!c_parser_next_token_is (parser, type: CPP_NAME))
19714 {
19715 c_parser_error (parser, gmsgid: "expected identifier");
19716 break;
19717 }
19718
19719 tree id = c_parser_peek_token (parser)->value;
19720 c_parser_consume_token (parser);
19721
19722 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
19723 break;
19724
19725 location_t eloc = c_parser_peek_token (parser)->location;
19726 c_expr expr = c_parser_expr_no_commas (parser, NULL);
19727 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19728 tree begin = expr.value;
19729
19730 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19731 break;
19732
19733 eloc = c_parser_peek_token (parser)->location;
19734 expr = c_parser_expr_no_commas (parser, NULL);
19735 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19736 tree end = expr.value;
19737
19738 tree step = integer_one_node;
19739 if (c_parser_next_token_is (parser, type: CPP_COLON))
19740 {
19741 c_parser_consume_token (parser);
19742 eloc = c_parser_peek_token (parser)->location;
19743 expr = c_parser_expr_no_commas (parser, NULL);
19744 expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
19745 step = expr.value;
19746 }
19747
19748 tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
19749 DECL_ARTIFICIAL (iter_var) = 1;
19750 DECL_CONTEXT (iter_var) = current_function_decl;
19751 pushdecl (iter_var);
19752
19753 *last = make_tree_vec (6);
19754 TREE_VEC_ELT (*last, 0) = iter_var;
19755 TREE_VEC_ELT (*last, 1) = begin;
19756 TREE_VEC_ELT (*last, 2) = end;
19757 TREE_VEC_ELT (*last, 3) = step;
19758 last = &TREE_CHAIN (*last);
19759
19760 if (c_parser_next_token_is (parser, type: CPP_COMMA))
19761 {
19762 c_parser_consume_token (parser);
19763 continue;
19764 }
19765 break;
19766 }
19767 while (1);
19768
19769 parens.skip_until_found_close (parser);
19770 return ret ? ret : error_mark_node;
19771}
19772
19773/* OpenMP 5.0:
19774 affinity ( [aff-modifier :] variable-list )
19775 aff-modifier:
19776 iterator ( iterators-definition ) */
19777
19778static tree
19779c_parser_omp_clause_affinity (c_parser *parser, tree list)
19780{
19781 location_t clause_loc = c_parser_peek_token (parser)->location;
19782 tree nl, iterators = NULL_TREE;
19783
19784 matching_parens parens;
19785 if (!parens.require_open (parser))
19786 return list;
19787
19788 if (c_parser_next_token_is (parser, type: CPP_NAME))
19789 {
19790 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19791 bool parse_iter = ((strcmp (s1: "iterator", s2: p) == 0)
19792 && (c_parser_peek_2nd_token (parser)->type
19793 == CPP_OPEN_PAREN));
19794 if (parse_iter)
19795 {
19796 unsigned n = 3;
19797 parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, n: &n)
19798 && (c_parser_peek_nth_token_raw (parser, n)->type
19799 == CPP_CLOSE_PAREN)
19800 && (c_parser_peek_nth_token_raw (parser, n: n + 1)->type
19801 == CPP_COLON));
19802 }
19803 if (parse_iter)
19804 {
19805 iterators = c_parser_omp_iterators (parser);
19806 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19807 {
19808 if (iterators)
19809 pop_scope ();
19810 parens.skip_until_found_close (parser);
19811 return list;
19812 }
19813 }
19814 }
19815 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_AFFINITY,
19816 list);
19817 if (iterators)
19818 {
19819 tree block = pop_scope ();
19820 if (iterators != error_mark_node)
19821 {
19822 TREE_VEC_ELT (iterators, 5) = block;
19823 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19824 OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
19825 OMP_CLAUSE_DECL (c));
19826 }
19827 }
19828
19829 parens.skip_until_found_close (parser);
19830 return nl;
19831}
19832
19833
19834/* OpenMP 4.0:
19835 depend ( depend-kind: variable-list )
19836
19837 depend-kind:
19838 in | out | inout
19839
19840 OpenMP 4.5:
19841 depend ( source )
19842
19843 depend ( sink : vec )
19844
19845 OpenMP 5.0:
19846 depend ( depend-modifier , depend-kind: variable-list )
19847
19848 depend-kind:
19849 in | out | inout | mutexinoutset | depobj | inoutset
19850
19851 depend-modifier:
19852 iterator ( iterators-definition ) */
19853
19854static tree
19855c_parser_omp_clause_depend (c_parser *parser, tree list)
19856{
19857 location_t clause_loc = c_parser_peek_token (parser)->location;
19858 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
19859 enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
19860 tree nl, c, iterators = NULL_TREE;
19861
19862 matching_parens parens;
19863 if (!parens.require_open (parser))
19864 return list;
19865
19866 do
19867 {
19868 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
19869 goto invalid_kind;
19870
19871 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19872 if (strcmp (s1: "iterator", s2: p) == 0 && iterators == NULL_TREE)
19873 {
19874 iterators = c_parser_omp_iterators (parser);
19875 c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<,%>");
19876 continue;
19877 }
19878 if (strcmp (s1: "in", s2: p) == 0)
19879 kind = OMP_CLAUSE_DEPEND_IN;
19880 else if (strcmp (s1: "inout", s2: p) == 0)
19881 kind = OMP_CLAUSE_DEPEND_INOUT;
19882 else if (strcmp (s1: "inoutset", s2: p) == 0)
19883 kind = OMP_CLAUSE_DEPEND_INOUTSET;
19884 else if (strcmp (s1: "mutexinoutset", s2: p) == 0)
19885 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
19886 else if (strcmp (s1: "out", s2: p) == 0)
19887 kind = OMP_CLAUSE_DEPEND_OUT;
19888 else if (strcmp (s1: "depobj", s2: p) == 0)
19889 kind = OMP_CLAUSE_DEPEND_DEPOBJ;
19890 else if (strcmp (s1: "sink", s2: p) == 0)
19891 dkind = OMP_CLAUSE_DOACROSS_SINK;
19892 else if (strcmp (s1: "source", s2: p) == 0)
19893 dkind = OMP_CLAUSE_DOACROSS_SOURCE;
19894 else
19895 goto invalid_kind;
19896 break;
19897 }
19898 while (1);
19899
19900 c_parser_consume_token (parser);
19901
19902 if (iterators
19903 && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
19904 || dkind == OMP_CLAUSE_DOACROSS_SINK))
19905 {
19906 pop_scope ();
19907 error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
19908 dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
19909 iterators = NULL_TREE;
19910 }
19911
19912 if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
19913 {
19914 c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
19915 OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
19916 OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
19917 OMP_CLAUSE_DECL (c) = NULL_TREE;
19918 OMP_CLAUSE_CHAIN (c) = list;
19919 parens.skip_until_found_close (parser);
19920 return c;
19921 }
19922
19923 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19924 goto resync_fail;
19925
19926 if (dkind == OMP_CLAUSE_DOACROSS_SINK)
19927 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: true);
19928 else
19929 {
19930 nl = c_parser_omp_variable_list (parser, clause_loc,
19931 kind: OMP_CLAUSE_DEPEND, list);
19932
19933 if (iterators)
19934 {
19935 tree block = pop_scope ();
19936 if (iterators == error_mark_node)
19937 iterators = NULL_TREE;
19938 else
19939 TREE_VEC_ELT (iterators, 5) = block;
19940 }
19941
19942 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
19943 {
19944 OMP_CLAUSE_DEPEND_KIND (c) = kind;
19945 if (iterators)
19946 OMP_CLAUSE_DECL (c)
19947 = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
19948 }
19949 }
19950
19951 parens.skip_until_found_close (parser);
19952 return nl;
19953
19954 invalid_kind:
19955 c_parser_error (parser, gmsgid: "invalid depend kind");
19956 resync_fail:
19957 parens.skip_until_found_close (parser);
19958 if (iterators)
19959 pop_scope ();
19960 return list;
19961}
19962
19963/* OpenMP 5.2:
19964 doacross ( source : )
19965 doacross ( source : omp_cur_iteration )
19966
19967 doacross ( sink : vec )
19968 doacross ( sink : omp_cur_iteration - logical_iteration ) */
19969
19970static tree
19971c_parser_omp_clause_doacross (c_parser *parser, tree list)
19972{
19973 location_t clause_loc = c_parser_peek_token (parser)->location;
19974 enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
19975 tree nl;
19976 const char *p;
19977
19978 matching_parens parens;
19979 if (!parens.require_open (parser))
19980 return list;
19981
19982 if (c_parser_next_token_is_not (parser, type: CPP_NAME))
19983 goto invalid_kind;
19984
19985 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
19986 if (strcmp (s1: "sink", s2: p) == 0)
19987 kind = OMP_CLAUSE_DOACROSS_SINK;
19988 else if (strcmp (s1: "source", s2: p) == 0)
19989 kind = OMP_CLAUSE_DOACROSS_SOURCE;
19990 else
19991 goto invalid_kind;
19992
19993 c_parser_consume_token (parser);
19994
19995 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
19996 goto resync_fail;
19997
19998 if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
19999 {
20000 if (c_parser_next_token_is (parser, type: CPP_NAME)
20001 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
20002 s2: "omp_cur_iteration") == 0)
20003 c_parser_consume_token (parser);
20004 nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
20005 OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
20006 OMP_CLAUSE_DECL (nl) = NULL_TREE;
20007 OMP_CLAUSE_CHAIN (nl) = list;
20008 }
20009 else
20010 nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, depend_p: false);
20011
20012 parens.skip_until_found_close (parser);
20013 return nl;
20014
20015 invalid_kind:
20016 c_parser_error (parser, gmsgid: "invalid doacross kind");
20017 resync_fail:
20018 parens.skip_until_found_close (parser);
20019 return list;
20020}
20021
20022/* OpenMP 4.0:
20023 map ( map-kind: variable-list )
20024 map ( variable-list )
20025
20026 map-kind:
20027 alloc | to | from | tofrom
20028
20029 OpenMP 4.5:
20030 map-kind:
20031 alloc | to | from | tofrom | release | delete
20032
20033 map ( always [,] map-kind: variable-list )
20034
20035 OpenMP 5.0:
20036 map ( [map-type-modifier[,] ...] map-kind: variable-list )
20037
20038 map-type-modifier:
20039 always | close */
20040
20041static tree
20042c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
20043{
20044 location_t clause_loc = c_parser_peek_token (parser)->location;
20045 tree nl, c;
20046 enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
20047
20048 matching_parens parens;
20049 if (!parens.require_open (parser))
20050 return list;
20051
20052 int pos = 1;
20053 int map_kind_pos = 0;
20054 while (c_parser_peek_nth_token_raw (parser, n: pos)->type == CPP_NAME)
20055 {
20056 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COLON)
20057 {
20058 map_kind_pos = pos;
20059 break;
20060 }
20061
20062 if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type == CPP_COMMA)
20063 pos++;
20064 else if (c_parser_peek_nth_token_raw (parser, n: pos + 1)->type
20065 == CPP_OPEN_PAREN)
20066 {
20067 unsigned int npos = pos + 2;
20068 if (c_parser_check_balanced_raw_token_sequence (parser, n: &npos)
20069 && (c_parser_peek_nth_token_raw (parser, n: npos)->type
20070 == CPP_CLOSE_PAREN)
20071 && (c_parser_peek_nth_token_raw (parser, n: npos + 1)->type
20072 == CPP_COMMA))
20073 pos = npos + 1;
20074 }
20075
20076 pos++;
20077 }
20078
20079 int always_modifier = 0;
20080 int close_modifier = 0;
20081 int present_modifier = 0;
20082 int mapper_modifier = 0;
20083 tree mapper_name = NULL_TREE;
20084 for (int pos = 1; pos < map_kind_pos; ++pos)
20085 {
20086 c_token *tok = c_parser_peek_token (parser);
20087
20088 if (tok->type == CPP_COMMA)
20089 {
20090 c_parser_consume_token (parser);
20091 continue;
20092 }
20093
20094 const char *p = IDENTIFIER_POINTER (tok->value);
20095 if (strcmp (s1: "always", s2: p) == 0)
20096 {
20097 if (always_modifier)
20098 {
20099 c_parser_error (parser, gmsgid: "too many %<always%> modifiers");
20100 parens.skip_until_found_close (parser);
20101 return list;
20102 }
20103 always_modifier++;
20104 c_parser_consume_token (parser);
20105 }
20106 else if (strcmp (s1: "close", s2: p) == 0)
20107 {
20108 if (close_modifier)
20109 {
20110 c_parser_error (parser, gmsgid: "too many %<close%> modifiers");
20111 parens.skip_until_found_close (parser);
20112 return list;
20113 }
20114 close_modifier++;
20115 c_parser_consume_token (parser);
20116 }
20117 else if (strcmp (s1: "mapper", s2: p) == 0)
20118 {
20119 c_parser_consume_token (parser);
20120
20121 matching_parens mparens;
20122 if (mparens.require_open (parser))
20123 {
20124 if (mapper_modifier)
20125 {
20126 c_parser_error (parser, gmsgid: "too many %<mapper%> modifiers");
20127 /* Assume it's a well-formed mapper modifier, even if it
20128 seems to be in the wrong place. */
20129 c_parser_consume_token (parser);
20130 mparens.require_close (parser);
20131 parens.skip_until_found_close (parser);
20132 return list;
20133 }
20134
20135 tok = c_parser_peek_token (parser);
20136
20137 switch (tok->type)
20138 {
20139 case CPP_NAME:
20140 {
20141 mapper_name = tok->value;
20142 c_parser_consume_token (parser);
20143 if (declare_mapper_p)
20144 {
20145 error_at (tok->location,
20146 "in %<declare mapper%> directives, parameter "
20147 "to %<mapper%> modifier must be %<default%>");
20148 }
20149 }
20150 break;
20151
20152 case CPP_KEYWORD:
20153 if (tok->keyword == RID_DEFAULT)
20154 {
20155 c_parser_consume_token (parser);
20156 break;
20157 }
20158 /* Fallthrough. */
20159
20160 default:
20161 error_at (tok->location,
20162 "expected identifier or %<default%>");
20163 return list;
20164 }
20165
20166 if (!mparens.require_close (parser))
20167 {
20168 parens.skip_until_found_close (parser);
20169 return list;
20170 }
20171
20172 mapper_modifier++;
20173 pos += 3;
20174 }
20175 }
20176 else if (strcmp (s1: "present", s2: p) == 0)
20177 {
20178 if (present_modifier)
20179 {
20180 c_parser_error (parser, gmsgid: "too many %<present%> modifiers");
20181 parens.skip_until_found_close (parser);
20182 return list;
20183 }
20184 present_modifier++;
20185 c_parser_consume_token (parser);
20186 }
20187 else
20188 {
20189 c_parser_error (parser, gmsgid: "%<map%> clause with map-type modifier other "
20190 "than %<always%>, %<close%>, %<mapper%> or "
20191 "%<present%>");
20192 parens.skip_until_found_close (parser);
20193 return list;
20194 }
20195 }
20196
20197 if (c_parser_next_token_is (parser, type: CPP_NAME)
20198 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20199 {
20200 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20201 int always_present_modifier = always_modifier && present_modifier;
20202
20203 if (strcmp (s1: "alloc", s2: p) == 0)
20204 kind = present_modifier ? GOMP_MAP_PRESENT_ALLOC : GOMP_MAP_ALLOC;
20205 else if (strcmp (s1: "to", s2: p) == 0)
20206 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TO
20207 : present_modifier ? GOMP_MAP_PRESENT_TO
20208 : always_modifier ? GOMP_MAP_ALWAYS_TO
20209 : GOMP_MAP_TO);
20210 else if (strcmp (s1: "from", s2: p) == 0)
20211 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_FROM
20212 : present_modifier ? GOMP_MAP_PRESENT_FROM
20213 : always_modifier ? GOMP_MAP_ALWAYS_FROM
20214 : GOMP_MAP_FROM);
20215 else if (strcmp (s1: "tofrom", s2: p) == 0)
20216 kind = (always_present_modifier ? GOMP_MAP_ALWAYS_PRESENT_TOFROM
20217 : present_modifier ? GOMP_MAP_PRESENT_TOFROM
20218 : always_modifier ? GOMP_MAP_ALWAYS_TOFROM
20219 : GOMP_MAP_TOFROM);
20220 else if (strcmp (s1: "release", s2: p) == 0)
20221 kind = GOMP_MAP_RELEASE;
20222 else if (strcmp (s1: "delete", s2: p) == 0)
20223 kind = GOMP_MAP_DELETE;
20224 else
20225 {
20226 c_parser_error (parser, gmsgid: "invalid map kind");
20227 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
20228 msgid: "expected %<)%>");
20229 return list;
20230 }
20231 c_parser_consume_token (parser);
20232 c_parser_consume_token (parser);
20233 }
20234
20235 nl = c_parser_omp_variable_list (parser, clause_loc, kind: OMP_CLAUSE_MAP, list,
20236 map_lvalue: true);
20237
20238 tree last_new = NULL_TREE;
20239
20240 for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20241 {
20242 OMP_CLAUSE_SET_MAP_KIND (c, kind);
20243 last_new = c;
20244 }
20245
20246 if (mapper_name)
20247 {
20248 tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20249 OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
20250 OMP_CLAUSE_DECL (name) = mapper_name;
20251 OMP_CLAUSE_CHAIN (name) = nl;
20252 nl = name;
20253
20254 gcc_assert (last_new);
20255
20256 name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
20257 OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
20258 OMP_CLAUSE_DECL (name) = null_pointer_node;
20259 OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
20260 OMP_CLAUSE_CHAIN (last_new) = name;
20261 }
20262
20263 parens.skip_until_found_close (parser);
20264 return nl;
20265}
20266
20267/* OpenMP 4.0:
20268 device ( expression )
20269
20270 OpenMP 5.0:
20271 device ( [device-modifier :] integer-expression )
20272
20273 device-modifier:
20274 ancestor | device_num */
20275
20276static tree
20277c_parser_omp_clause_device (c_parser *parser, tree list)
20278{
20279 location_t clause_loc = c_parser_peek_token (parser)->location;
20280 location_t expr_loc;
20281 c_expr expr;
20282 tree c, t;
20283 bool ancestor = false;
20284
20285 matching_parens parens;
20286 if (!parens.require_open (parser))
20287 return list;
20288
20289 if (c_parser_next_token_is (parser, type: CPP_NAME)
20290 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20291 {
20292 c_token *tok = c_parser_peek_token (parser);
20293 const char *p = IDENTIFIER_POINTER (tok->value);
20294 if (strcmp (s1: "ancestor", s2: p) == 0)
20295 {
20296 /* A requires directive with the reverse_offload clause must be
20297 specified. */
20298 if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
20299 {
20300 error_at (tok->location, "%<ancestor%> device modifier not "
20301 "preceded by %<requires%> directive "
20302 "with %<reverse_offload%> clause");
20303 parens.skip_until_found_close (parser);
20304 return list;
20305 }
20306 ancestor = true;
20307 }
20308 else if (strcmp (s1: "device_num", s2: p) == 0)
20309 ;
20310 else
20311 {
20312 error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
20313 parens.skip_until_found_close (parser);
20314 return list;
20315 }
20316 c_parser_consume_token (parser);
20317 c_parser_consume_token (parser);
20318 }
20319
20320 expr_loc = c_parser_peek_token (parser)->location;
20321 expr = c_parser_expr_no_commas (parser, NULL);
20322 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20323 t = expr.value;
20324 t = c_fully_fold (t, false, NULL);
20325
20326 parens.skip_until_found_close (parser);
20327
20328 if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
20329 {
20330 c_parser_error (parser, gmsgid: "expected integer expression");
20331 return list;
20332 }
20333 if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
20334 {
20335 error_at (expr_loc, "the %<device%> clause expression must evaluate to "
20336 "%<1%>");
20337 return list;
20338 }
20339
20340 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE, name: "device");
20341
20342 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
20343
20344 OMP_CLAUSE_DEVICE_ID (c) = t;
20345 OMP_CLAUSE_CHAIN (c) = list;
20346 OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
20347
20348 list = c;
20349 return list;
20350}
20351
20352/* OpenMP 4.0:
20353 dist_schedule ( static )
20354 dist_schedule ( static , expression ) */
20355
20356static tree
20357c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
20358{
20359 tree c, t = NULL_TREE;
20360 location_t loc = c_parser_peek_token (parser)->location;
20361
20362 matching_parens parens;
20363 if (!parens.require_open (parser))
20364 return list;
20365
20366 if (!c_parser_next_token_is_keyword (parser, keyword: RID_STATIC))
20367 {
20368 c_parser_error (parser, gmsgid: "invalid dist_schedule kind");
20369 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
20370 msgid: "expected %<)%>");
20371 return list;
20372 }
20373
20374 c_parser_consume_token (parser);
20375 if (c_parser_next_token_is (parser, type: CPP_COMMA))
20376 {
20377 c_parser_consume_token (parser);
20378
20379 location_t expr_loc = c_parser_peek_token (parser)->location;
20380 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20381 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
20382 t = expr.value;
20383 t = c_fully_fold (t, false, NULL);
20384 parens.skip_until_found_close (parser);
20385 }
20386 else
20387 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
20388 msgid: "expected %<,%> or %<)%>");
20389
20390 /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
20391 "dist_schedule"); */
20392 if (omp_find_clause (clauses: list, kind: OMP_CLAUSE_DIST_SCHEDULE))
20393 warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule");
20394 if (t == error_mark_node)
20395 return list;
20396
20397 c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
20398 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
20399 OMP_CLAUSE_CHAIN (c) = list;
20400 return c;
20401}
20402
20403/* OpenMP 4.0:
20404 proc_bind ( proc-bind-kind )
20405
20406 proc-bind-kind:
20407 primary | master | close | spread
20408 where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
20409
20410static tree
20411c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
20412{
20413 location_t clause_loc = c_parser_peek_token (parser)->location;
20414 enum omp_clause_proc_bind_kind kind;
20415 tree c;
20416
20417 matching_parens parens;
20418 if (!parens.require_open (parser))
20419 return list;
20420
20421 if (c_parser_next_token_is (parser, type: CPP_NAME))
20422 {
20423 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20424 if (strcmp (s1: "primary", s2: p) == 0)
20425 kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
20426 else if (strcmp (s1: "master", s2: p) == 0)
20427 kind = OMP_CLAUSE_PROC_BIND_MASTER;
20428 else if (strcmp (s1: "close", s2: p) == 0)
20429 kind = OMP_CLAUSE_PROC_BIND_CLOSE;
20430 else if (strcmp (s1: "spread", s2: p) == 0)
20431 kind = OMP_CLAUSE_PROC_BIND_SPREAD;
20432 else
20433 goto invalid_kind;
20434 }
20435 else
20436 goto invalid_kind;
20437
20438 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PROC_BIND, name: "proc_bind");
20439 c_parser_consume_token (parser);
20440 parens.skip_until_found_close (parser);
20441 c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
20442 OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
20443 OMP_CLAUSE_CHAIN (c) = list;
20444 return c;
20445
20446 invalid_kind:
20447 c_parser_error (parser, gmsgid: "invalid proc_bind kind");
20448 parens.skip_until_found_close (parser);
20449 return list;
20450}
20451
20452/* OpenMP 5.0:
20453 device_type ( host | nohost | any ) */
20454
20455static tree
20456c_parser_omp_clause_device_type (c_parser *parser, tree list)
20457{
20458 location_t clause_loc = c_parser_peek_token (parser)->location;
20459 enum omp_clause_device_type_kind kind;
20460 tree c;
20461
20462 matching_parens parens;
20463 if (!parens.require_open (parser))
20464 return list;
20465
20466 if (c_parser_next_token_is (parser, type: CPP_NAME))
20467 {
20468 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
20469 if (strcmp (s1: "host", s2: p) == 0)
20470 kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
20471 else if (strcmp (s1: "nohost", s2: p) == 0)
20472 kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
20473 else if (strcmp (s1: "any", s2: p) == 0)
20474 kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
20475 else
20476 goto invalid_kind;
20477 }
20478 else
20479 goto invalid_kind;
20480
20481 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_DEVICE_TYPE,
20482 name: "device_type");
20483 c_parser_consume_token (parser);
20484 parens.skip_until_found_close (parser);
20485 c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
20486 OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
20487 OMP_CLAUSE_CHAIN (c) = list;
20488 return c;
20489
20490 invalid_kind:
20491 c_parser_error (parser, gmsgid: "expected %<host%>, %<nohost%> or %<any%>");
20492 parens.skip_until_found_close (parser);
20493 return list;
20494}
20495
20496/* OpenMP 4.0:
20497 from ( variable-list )
20498 to ( variable-list )
20499
20500 OpenMP 5.1:
20501 from ( [present :] variable-list )
20502 to ( [present :] variable-list ) */
20503
20504static tree
20505c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
20506 tree list)
20507{
20508 location_t loc = c_parser_peek_token (parser)->location;
20509 matching_parens parens;
20510 if (!parens.require_open (parser))
20511 return list;
20512
20513 bool present = false;
20514 c_token *token = c_parser_peek_token (parser);
20515
20516 if (token->type == CPP_NAME
20517 && strcmp (IDENTIFIER_POINTER (token->value), s2: "present") == 0
20518 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
20519 {
20520 present = true;
20521 c_parser_consume_token (parser);
20522 c_parser_consume_token (parser);
20523 }
20524
20525 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind, list);
20526 parens.skip_until_found_close (parser);
20527
20528 if (present)
20529 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20530 OMP_CLAUSE_MOTION_PRESENT (c) = 1;
20531
20532 return nl;
20533}
20534
20535/* OpenMP 4.0:
20536 uniform ( variable-list ) */
20537
20538static tree
20539c_parser_omp_clause_uniform (c_parser *parser, tree list)
20540{
20541 /* The clauses location. */
20542 location_t loc = c_parser_peek_token (parser)->location;
20543
20544 matching_parens parens;
20545 if (parens.require_open (parser))
20546 {
20547 list = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_UNIFORM,
20548 list);
20549 parens.skip_until_found_close (parser);
20550 }
20551 return list;
20552}
20553
20554/* OpenMP 5.1
20555 full */
20556
20557static tree
20558c_parser_omp_clause_full (c_parser *parser, tree list)
20559{
20560 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_FULL, name: "full");
20561
20562 location_t loc = c_parser_peek_token (parser)->location;
20563 tree c = build_omp_clause (loc, OMP_CLAUSE_FULL);
20564 OMP_CLAUSE_CHAIN (c) = list;
20565 return c;
20566}
20567
20568/* OpenMP 5.1
20569 partial ( constant-expression ) */
20570
20571static tree
20572c_parser_omp_clause_partial (c_parser *parser, tree list)
20573{
20574 tree num = NULL_TREE;
20575 location_t loc = c_parser_peek_token (parser)->location;
20576
20577 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_PARTIAL, name: "partial");
20578
20579 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
20580 {
20581 matching_parens parens;
20582 parens.consume_open (parser);
20583 num = c_parser_expr_no_commas (parser, NULL).value;
20584 parens.skip_until_found_close (parser);
20585
20586 if (num == error_mark_node)
20587 return list;
20588
20589 mark_exp_read (num);
20590 num = c_fully_fold (num, false, NULL);
20591 HOST_WIDE_INT n;
20592 if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
20593 || !tree_fits_shwi_p (num)
20594 || (n = tree_to_shwi (num)) <= 0
20595 || (int) n != n)
20596 {
20597 error_at (loc, "%<partial%> argument needs positive constant "
20598 "integer expression");
20599 return list;
20600 }
20601 }
20602
20603 tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL);
20604 OMP_CLAUSE_PARTIAL_EXPR (c) = num;
20605 OMP_CLAUSE_CHAIN (c) = list;
20606 return c;
20607}
20608
20609/* OpenMP 5.1
20610 novariants ( scalar-expression ) */
20611
20612static tree
20613c_parser_omp_clause_novariants (c_parser *parser, tree list)
20614{
20615 matching_parens parens;
20616 if (!parens.require_open (parser))
20617 return list;
20618
20619 location_t loc = c_parser_peek_token (parser)->location;
20620 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20621 tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20622 t = c_objc_common_truthvalue_conversion (loc, t);
20623 t = c_fully_fold (t, false, NULL);
20624 parens.skip_until_found_close (parser);
20625
20626 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOVARIANTS, name: "novariants");
20627
20628 tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
20629 OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
20630 OMP_CLAUSE_CHAIN (c) = list;
20631 list = c;
20632
20633 return list;
20634}
20635
20636/* OpenMP 5.1
20637 nocontext ( scalar-expression ) */
20638
20639static tree
20640c_parser_omp_clause_nocontext (c_parser *parser, tree list)
20641{
20642 matching_parens parens;
20643 if (!parens.require_open (parser))
20644 return list;
20645
20646 location_t loc = c_parser_peek_token (parser)->location;
20647 c_expr expr = c_parser_expr_no_commas (parser, NULL);
20648 tree t = convert_lvalue_to_rvalue (loc, expr, true, true).value;
20649 t = c_objc_common_truthvalue_conversion (loc, t);
20650 t = c_fully_fold (t, false, NULL);
20651 parens.skip_until_found_close (parser);
20652
20653 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_NOCONTEXT, name: "nocontext");
20654
20655 tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
20656 OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
20657 OMP_CLAUSE_CHAIN (c) = list;
20658 list = c;
20659
20660 return list;
20661}
20662
20663/* OpenMP 5.0:
20664 detach ( event-handle ) */
20665
20666static tree
20667c_parser_omp_clause_detach (c_parser *parser, tree list)
20668{
20669 matching_parens parens;
20670 location_t clause_loc = c_parser_peek_token (parser)->location;
20671
20672 if (!parens.require_open (parser))
20673 return list;
20674
20675 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
20676 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
20677 {
20678 c_parser_error (parser, gmsgid: "expected identifier");
20679 parens.skip_until_found_close (parser);
20680 return list;
20681 }
20682
20683 tree t = lookup_name (c_parser_peek_token (parser)->value);
20684 if (t == NULL_TREE)
20685 {
20686 undeclared_variable (c_parser_peek_token (parser)->location,
20687 c_parser_peek_token (parser)->value);
20688 parens.skip_until_found_close (parser);
20689 return list;
20690 }
20691 c_parser_consume_token (parser);
20692
20693 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
20694 if (!INTEGRAL_TYPE_P (type)
20695 || TREE_CODE (type) != ENUMERAL_TYPE
20696 || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
20697 {
20698 error_at (clause_loc, "%<detach%> clause event handle "
20699 "has type %qT rather than "
20700 "%<omp_event_handle_t%>",
20701 type);
20702 parens.skip_until_found_close (parser);
20703 return list;
20704 }
20705
20706 tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
20707 OMP_CLAUSE_DECL (u) = t;
20708 OMP_CLAUSE_CHAIN (u) = list;
20709 parens.skip_until_found_close (parser);
20710 return u;
20711}
20712
20713/* OpenMP 5.0:
20714 destroy ( variable-list ) */
20715
20716static tree
20717c_parser_omp_clause_destroy (c_parser *parser, tree list)
20718{
20719 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_DESTROY, list);
20720 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
20721 TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
20722 return nl;
20723}
20724
20725/* OpenMP 5.1:
20726 prefer_type ( const-int-expr-or-string-literal-list )
20727
20728 OpenMP 6.0:
20729 prefer_type ( { preference-selector-list }, { ... } )
20730
20731 with preference-selector being:
20732 fr ( identifier-or-string-literal-list )
20733 attr ( string-list )
20734
20735 Data format:
20736 For the foreign runtime identifiers, string values are converted to
20737 their integer value; unknown string or integer values are set to
20738 GOMP_INTEROP_IFR_KNOWN.
20739
20740 Each item (a) GOMP_INTEROP_IFR_SEPARATOR
20741 (b) for any 'fr', its integer value.
20742 Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
20743 (c) GOMP_INTEROP_IFR_SEPARATOR
20744 (d) list of \0-terminated non-empty strings for 'attr'
20745 (e) '\0'
20746 Tailing '\0'. */
20747
20748static tree
20749c_parser_omp_modifier_prefer_type (c_parser *parser)
20750{
20751 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
20752 return error_mark_node;
20753
20754 std::string str;
20755
20756 /* Old Format: const-int-expr-or-string-literal-list */
20757 if (!c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
20758 while (true)
20759 {
20760 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20761 if (c_parser_next_token_is (parser, type: CPP_STRING))
20762 {
20763 c_expr cval = c_parser_string_literal (parser, translate: false, wide_ok: false);
20764 if (cval.value == error_mark_node)
20765 return error_mark_node;
20766 if ((size_t) TREE_STRING_LENGTH (cval.value)
20767 != strlen (TREE_STRING_POINTER (cval.value)) + 1)
20768 {
20769 error_at (cval.get_location (), "string literal must "
20770 "not contain %<\\0%>");
20771 parser->error = true;
20772 return error_mark_node;
20773 }
20774
20775 char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (cval.value));
20776 if (c == GOMP_INTEROP_IFR_UNKNOWN)
20777 warning_at (cval.get_location (), OPT_Wopenmp,
20778 "unknown foreign runtime identifier %qs",
20779 TREE_STRING_POINTER (cval.value));
20780 str += c;
20781 }
20782 else
20783 {
20784 c_expr cval = c_parser_expr_no_commas (parser, NULL);
20785 tree value = c_fully_fold (cval.value, false, NULL);
20786 if (INTEGRAL_TYPE_P (TREE_TYPE (value))
20787 && TREE_CODE (value) != INTEGER_CST)
20788 value = convert_lvalue_to_rvalue (cval.get_start (), cval,
20789 false, true).value;
20790 if (TREE_CODE (value) != INTEGER_CST
20791 || !tree_fits_shwi_p (value))
20792 {
20793 c_parser_error (parser, gmsgid: "expected string literal or constant "
20794 "integer expression");
20795 return error_mark_node;
20796 }
20797 HOST_WIDE_INT n = tree_to_shwi (value);
20798 if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
20799 {
20800 warning_at (cval.get_location (), OPT_Wopenmp,
20801 "unknown foreign runtime identifier %qwd", n);
20802 n = GOMP_INTEROP_IFR_UNKNOWN;
20803 }
20804 str += (char) n;
20805 }
20806 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20807 str += '\0';
20808 if (c_parser_next_token_is (parser, type: CPP_COMMA))
20809 {
20810 c_parser_consume_token (parser);
20811 continue;
20812 }
20813 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN,
20814 msgid: "expected %<,%> or %<)%>"))
20815 return error_mark_node;
20816 str += '\0';
20817 tree res = build_string (str.length (), str.data ());
20818 TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
20819 str.length ());
20820 return res;
20821 }
20822
20823 /* New format. */
20824 std::string str2;
20825 while (true)
20826 {
20827 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
20828 return error_mark_node;
20829 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20830 str2.clear ();
20831 bool has_fr = false;
20832 while (true)
20833 {
20834 c_token *tok = c_parser_peek_token (parser);
20835 if (tok->type != CPP_NAME
20836 || (strcmp(s1: "fr", IDENTIFIER_POINTER (tok->value)) != 0
20837 && strcmp(s1: "attr", IDENTIFIER_POINTER (tok->value)) != 0))
20838 {
20839 c_parser_error (parser, gmsgid: "expected %<fr%> or %<attr%> preference "
20840 "selector");
20841 return error_mark_node;
20842 }
20843 c_parser_consume_token (parser);
20844 bool is_fr = IDENTIFIER_POINTER (tok->value)[0] == 'f';
20845 if (is_fr && has_fr)
20846 {
20847 c_parser_error (parser, gmsgid: "duplicated %<fr%> preference selector");
20848 return error_mark_node;
20849 }
20850 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
20851 return error_mark_node;
20852 while (true)
20853 {
20854 if (c_parser_next_token_is (parser, type: CPP_STRING))
20855 {
20856 c_expr cval = c_parser_string_literal (parser, translate: false, wide_ok: false);
20857 tree value = cval.value;
20858 if (value == error_mark_node)
20859 return error_mark_node;
20860 if ((size_t) TREE_STRING_LENGTH (value)
20861 != strlen (TREE_STRING_POINTER (value)) + 1)
20862 {
20863 error_at (cval.get_location (), "string literal must "
20864 "not contain %<\\0%>");
20865 parser->error = true;
20866 return error_mark_node;
20867 }
20868 if (!is_fr)
20869 {
20870 if (!startswith (TREE_STRING_POINTER (value), prefix: "ompx_"))
20871 {
20872 error_at (cval.get_location (),
20873 "%<attr%> string literal must start with "
20874 "%<ompx_%>");
20875 parser->error = true;
20876 return error_mark_node;
20877 }
20878 if (strchr (TREE_STRING_POINTER (value), c: ','))
20879 {
20880 error_at (cval.get_location (),
20881 "%<attr%> string literal must not contain "
20882 "a comma");
20883 parser->error = true;
20884 return error_mark_node;
20885 }
20886 str2 += TREE_STRING_POINTER (value);
20887 str2 += '\0';
20888 }
20889 else
20890 {
20891 if (*TREE_STRING_POINTER (value) == '\0')
20892 {
20893 c_parser_error (parser, gmsgid: "non-empty string literal expected");
20894 return error_mark_node;
20895 }
20896 char c = omp_get_fr_id_from_name (TREE_STRING_POINTER (value));
20897 if (c == GOMP_INTEROP_IFR_UNKNOWN)
20898 warning_at (cval.get_location (), OPT_Wopenmp,
20899 "unknown foreign runtime identifier %qs",
20900 TREE_STRING_POINTER (value));
20901 str += c;
20902 has_fr = true;
20903 }
20904 }
20905 else if (!is_fr)
20906 {
20907 c_parser_error (parser, gmsgid: "expected string literal");
20908 return error_mark_node;
20909 }
20910 else
20911 {
20912 c_expr cval = c_parser_expr_no_commas (parser, NULL);
20913 tree value = c_fully_fold (cval.value, false, NULL);
20914 if (INTEGRAL_TYPE_P (TREE_TYPE (value))
20915 && TREE_CODE (value) != INTEGER_CST)
20916 value = convert_lvalue_to_rvalue (cval.get_start (), cval,
20917 false, true).value;
20918
20919 if (TREE_CODE (value) != INTEGER_CST
20920 || !tree_fits_shwi_p (value))
20921 {
20922 c_parser_error (parser, gmsgid: "expected string literal or "
20923 "constant integer expression");
20924 return error_mark_node;
20925 }
20926 HOST_WIDE_INT n = tree_to_shwi (value);
20927 if (n < 1 || n > GOMP_INTEROP_IFR_LAST)
20928 {
20929 warning_at (cval.get_location (), OPT_Wopenmp,
20930 "unknown foreign runtime identifier %qwd", n);
20931 n = GOMP_INTEROP_IFR_UNKNOWN;
20932 }
20933 str += (char) n;
20934 has_fr = true;
20935 }
20936 if (!is_fr
20937 && c_parser_next_token_is (parser, type: CPP_COMMA))
20938 {
20939 c_parser_consume_token (parser);
20940 continue;
20941 }
20942 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN,
20943 msgid: is_fr ? G_("expected %<)%>")
20944 : G_("expected %<)%> or %<,%>")))
20945 return error_mark_node;
20946 break;
20947 }
20948 if (c_parser_next_token_is (parser, type: CPP_COMMA))
20949 {
20950 c_parser_consume_token (parser);
20951 continue;
20952 }
20953 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
20954 break;
20955 c_parser_error (parser, gmsgid: "expected %<,%> or %<}%>");
20956 return error_mark_node;
20957 }
20958 str += (char) GOMP_INTEROP_IFR_SEPARATOR;
20959 str += str2;
20960 str += '\0';
20961 c_parser_consume_token (parser);
20962 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
20963 break;
20964 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<)%> or %<,%>"))
20965 return error_mark_node;
20966 }
20967 c_parser_consume_token (parser);
20968 str += '\0';
20969 tree res = build_string (str.length (), str.data ());
20970 TREE_TYPE (res) = build_array_type_nelts (unsigned_char_type_node,
20971 str.length ());
20972 return res;
20973}
20974
20975/* OpenMP 5.1
20976 modifiers of the 'init' clause, used by the 'init' and the
20977 'append_args' clauses.
20978
20979 Modifiers:
20980 target
20981 targetsync
20982 prefer_type (preference-specification)
20983
20984 Returns 'false' if an error has been issued. */
20985
20986static bool
20987c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target,
20988 bool *targetsync, tree *prefer_type_tree)
20989{
20990 *target = false;
20991 *targetsync = false;
20992 *prefer_type_tree = NULL_TREE;
20993
20994 do
20995 {
20996 c_token *tok = c_parser_peek_token (parser);
20997 if (tok->type != CPP_NAME)
20998 goto fail;
20999 const char *p = IDENTIFIER_POINTER (tok->value);
21000 if (strcmp (s1: "targetsync", s2: p) == 0)
21001 {
21002 if (*targetsync)
21003 error_at (tok->location, "duplicate %<targetsync%> modifier");
21004 *targetsync = true;
21005 c_parser_consume_token (parser);
21006 }
21007 else if (strcmp (s1: "target", s2: p) == 0)
21008 {
21009 if (*target)
21010 error_at (tok->location, "duplicate %<target%> modifier");
21011 *target = true;
21012 c_parser_consume_token (parser);
21013 }
21014 else if (strcmp (s1: "prefer_type", s2: p) == 0)
21015 {
21016 if (*prefer_type_tree != NULL_TREE)
21017 error_at (tok->location, "duplicate %<prefer_type%> modifier");
21018 c_parser_consume_token (parser);
21019 *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser);
21020 if (*prefer_type_tree == error_mark_node)
21021 return false;
21022 }
21023 else
21024 goto fail;
21025 tok = c_parser_peek_token (parser);
21026 if (tok->type == CPP_COMMA)
21027 {
21028 c_parser_consume_token (parser);
21029 continue;
21030 }
21031 /* Unknown token - either done or an error; handle it in the caller. */
21032 return true;
21033 }
21034 while (true);
21035
21036fail:
21037 c_parser_error (parser,
21038 gmsgid: "expected %<prefer_type%>, %<target%>, or %<targetsync%>");
21039 return false;
21040}
21041
21042/* OpenMP 5.1:
21043 init ( [init-modifier-list : ] variable-list )
21044
21045 Modifiers:
21046 target
21047 targetsync
21048 prefer_type (preference-specification) */
21049
21050static tree
21051c_parser_omp_clause_init (c_parser *parser, tree list)
21052{
21053 location_t loc = c_parser_peek_token (parser)->location;
21054
21055 matching_parens parens;
21056 if (!parens.require_open (parser))
21057 return list;
21058
21059 bool target = false;
21060 bool targetsync = false;
21061 tree prefer_type_tree = NULL_TREE;
21062
21063 if (!c_parser_omp_clause_init_modifiers (parser, target: &target, targetsync: &targetsync,
21064 prefer_type_tree: &prefer_type_tree)
21065 || !c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
21066 {
21067 if (prefer_type_tree != error_mark_node)
21068 parens.skip_until_found_close (parser);
21069 return list;
21070 }
21071
21072 if (!target && !targetsync)
21073 error_at (loc,
21074 "missing required %<target%> and/or %<targetsync%> modifier");
21075
21076 tree nl = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_INIT, list,
21077 map_lvalue: false);
21078 parens.skip_until_found_close (parser);
21079
21080 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21081 {
21082 TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
21083 if (target)
21084 OMP_CLAUSE_INIT_TARGET (c) = 1;
21085 if (targetsync)
21086 OMP_CLAUSE_INIT_TARGETSYNC (c) = 1;
21087 if (prefer_type_tree)
21088 OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree;
21089 }
21090 return nl;
21091}
21092
21093/* OpenMP 5.0:
21094 use ( variable-list ) */
21095
21096static tree
21097c_parser_omp_clause_use (c_parser *parser, tree list)
21098{
21099 return c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_USE, list);
21100}
21101
21102/* OpenMP 6.0:
21103 interop ( variable-list ) */
21104
21105static tree
21106c_parser_omp_clause_interop (c_parser *parser, tree list)
21107{
21108 check_no_duplicate_clause (clauses: list, code: OMP_CLAUSE_INTEROP, name: "interop");
21109 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_INTEROP, list);
21110 for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
21111 {
21112 TREE_USED (OMP_CLAUSE_DECL (c)) = 1;
21113 DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1;
21114 }
21115 return nl;
21116}
21117
21118/* Parse all OpenACC clauses. The set clauses allowed by the directive
21119 is a bitmask in MASK. Return the list of clauses found. */
21120
21121static tree
21122c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
21123 const char *where, bool finish_p = true,
21124 bool target_p = false)
21125{
21126 tree clauses = NULL;
21127 bool first = true;
21128
21129 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
21130 {
21131 location_t here;
21132 pragma_omp_clause c_kind;
21133 const char *c_name;
21134 tree prev = clauses;
21135
21136 if (!first && c_parser_next_token_is (parser, type: CPP_COMMA))
21137 c_parser_consume_token (parser);
21138
21139 here = c_parser_peek_token (parser)->location;
21140 c_kind = c_parser_omp_clause_name (parser);
21141
21142 switch (c_kind)
21143 {
21144 case PRAGMA_OACC_CLAUSE_ASYNC:
21145 clauses = c_parser_oacc_clause_async (parser, list: clauses);
21146 c_name = "async";
21147 break;
21148 case PRAGMA_OACC_CLAUSE_AUTO:
21149 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_AUTO,
21150 list: clauses);
21151 c_name = "auto";
21152 break;
21153 case PRAGMA_OACC_CLAUSE_ATTACH:
21154 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21155 c_name = "attach";
21156 break;
21157 case PRAGMA_OACC_CLAUSE_COLLAPSE:
21158 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
21159 c_name = "collapse";
21160 break;
21161 case PRAGMA_OACC_CLAUSE_COPY:
21162 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21163 c_name = "copy";
21164 break;
21165 case PRAGMA_OACC_CLAUSE_COPYIN:
21166 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21167 c_name = "copyin";
21168 break;
21169 case PRAGMA_OACC_CLAUSE_COPYOUT:
21170 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21171 c_name = "copyout";
21172 break;
21173 case PRAGMA_OACC_CLAUSE_CREATE:
21174 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21175 c_name = "create";
21176 break;
21177 case PRAGMA_OACC_CLAUSE_DELETE:
21178 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21179 c_name = "delete";
21180 break;
21181 case PRAGMA_OMP_CLAUSE_DEFAULT:
21182 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: true);
21183 c_name = "default";
21184 break;
21185 case PRAGMA_OACC_CLAUSE_DETACH:
21186 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21187 c_name = "detach";
21188 break;
21189 case PRAGMA_OACC_CLAUSE_DEVICE:
21190 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21191 c_name = "device";
21192 break;
21193 case PRAGMA_OACC_CLAUSE_DEVICEPTR:
21194 clauses = c_parser_oacc_data_clause_deviceptr (parser, list: clauses);
21195 c_name = "deviceptr";
21196 break;
21197 case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
21198 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21199 c_name = "device_resident";
21200 break;
21201 case PRAGMA_OACC_CLAUSE_FINALIZE:
21202 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_FINALIZE,
21203 list: clauses);
21204 c_name = "finalize";
21205 break;
21206 case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
21207 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
21208 c_name = "firstprivate";
21209 break;
21210 case PRAGMA_OACC_CLAUSE_GANG:
21211 c_name = "gang";
21212 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_GANG,
21213 str: c_name, list: clauses);
21214 break;
21215 case PRAGMA_OACC_CLAUSE_HOST:
21216 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21217 c_name = "host";
21218 break;
21219 case PRAGMA_OACC_CLAUSE_IF:
21220 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: false);
21221 c_name = "if";
21222 break;
21223 case PRAGMA_OACC_CLAUSE_IF_PRESENT:
21224 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_IF_PRESENT,
21225 list: clauses);
21226 c_name = "if_present";
21227 break;
21228 case PRAGMA_OACC_CLAUSE_INDEPENDENT:
21229 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_INDEPENDENT,
21230 list: clauses);
21231 c_name = "independent";
21232 break;
21233 case PRAGMA_OACC_CLAUSE_LINK:
21234 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21235 c_name = "link";
21236 break;
21237 case PRAGMA_OACC_CLAUSE_NO_CREATE:
21238 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21239 c_name = "no_create";
21240 break;
21241 case PRAGMA_OACC_CLAUSE_NOHOST:
21242 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_NOHOST,
21243 list: clauses);
21244 c_name = "nohost";
21245 break;
21246 case PRAGMA_OACC_CLAUSE_NUM_GANGS:
21247 clauses = c_parser_oacc_single_int_clause (parser,
21248 code: OMP_CLAUSE_NUM_GANGS,
21249 list: clauses);
21250 c_name = "num_gangs";
21251 break;
21252 case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
21253 clauses = c_parser_oacc_single_int_clause (parser,
21254 code: OMP_CLAUSE_NUM_WORKERS,
21255 list: clauses);
21256 c_name = "num_workers";
21257 break;
21258 case PRAGMA_OACC_CLAUSE_PRESENT:
21259 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21260 c_name = "present";
21261 break;
21262 case PRAGMA_OACC_CLAUSE_PRIVATE:
21263 clauses = c_parser_omp_clause_private (parser, list: clauses);
21264 c_name = "private";
21265 break;
21266 case PRAGMA_OACC_CLAUSE_REDUCTION:
21267 clauses
21268 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
21269 is_omp: false, list: clauses);
21270 c_name = "reduction";
21271 break;
21272 case PRAGMA_OACC_CLAUSE_SELF:
21273 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST)) == 0)
21274 /* OpenACC compute construct */
21275 clauses = c_parser_oacc_compute_clause_self (parser, list: clauses);
21276 else
21277 /* OpenACC 'update' directive */
21278 clauses = c_parser_oacc_data_clause (parser, c_kind, list: clauses);
21279 c_name = "self";
21280 break;
21281 case PRAGMA_OACC_CLAUSE_SEQ:
21282 clauses = c_parser_oacc_simple_clause (loc: here, code: OMP_CLAUSE_SEQ,
21283 list: clauses);
21284 c_name = "seq";
21285 break;
21286 case PRAGMA_OACC_CLAUSE_TILE:
21287 clauses = c_parser_oacc_clause_tile (parser, list: clauses);
21288 c_name = "tile";
21289 break;
21290 case PRAGMA_OACC_CLAUSE_USE_DEVICE:
21291 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
21292 c_name = "use_device";
21293 break;
21294 case PRAGMA_OACC_CLAUSE_VECTOR:
21295 c_name = "vector";
21296 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_VECTOR,
21297 str: c_name, list: clauses);
21298 break;
21299 case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
21300 clauses = c_parser_oacc_single_int_clause (parser,
21301 code: OMP_CLAUSE_VECTOR_LENGTH,
21302 list: clauses);
21303 c_name = "vector_length";
21304 break;
21305 case PRAGMA_OACC_CLAUSE_WAIT:
21306 clauses = c_parser_oacc_clause_wait (parser, list: clauses);
21307 c_name = "wait";
21308 break;
21309 case PRAGMA_OACC_CLAUSE_WORKER:
21310 c_name = "worker";
21311 clauses = c_parser_oacc_shape_clause (parser, loc: here, kind: OMP_CLAUSE_WORKER,
21312 str: c_name, list: clauses);
21313 break;
21314 default:
21315 c_parser_error (parser, gmsgid: "expected an OpenACC clause");
21316 goto saw_error;
21317 }
21318
21319 first = false;
21320
21321 if (((mask >> c_kind) & 1) == 0)
21322 {
21323 /* Remove the invalid clause(s) from the list to avoid
21324 confusing the rest of the compiler. */
21325 clauses = prev;
21326 error_at (here, "%qs is not valid for %qs", c_name, where);
21327 }
21328 }
21329
21330 saw_error:
21331 c_parser_skip_to_pragma_eol (parser);
21332
21333 if (finish_p)
21334 return c_finish_omp_clauses (clauses, target_p ? C_ORT_ACC_TARGET
21335 : C_ORT_ACC);
21336
21337 return clauses;
21338}
21339
21340/* Parse all OpenMP clauses. The set clauses allowed by the directive
21341 is a bitmask in MASK. Return the list of clauses found.
21342 FINISH_P set if c_finish_omp_clauses should be called.
21343 NESTED non-zero if clauses should be terminated by closing paren instead
21344 of end of pragma. If it is 2, additionally commas are required in between
21345 the clauses. */
21346
21347static tree
21348c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
21349 const char *where, bool finish_p = true,
21350 int nested = 0)
21351{
21352 tree clauses = NULL;
21353 bool first = true;
21354
21355 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
21356 {
21357 location_t here;
21358 pragma_omp_clause c_kind;
21359 const char *c_name;
21360 tree prev = clauses;
21361
21362 if (nested && c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
21363 break;
21364
21365 if (!first || nested != 2)
21366 {
21367 if (c_parser_next_token_is (parser, type: CPP_COMMA))
21368 c_parser_consume_token (parser);
21369 else if (nested == 2)
21370 error_at (c_parser_peek_token (parser)->location,
21371 "clauses in %<simd%> trait should be separated "
21372 "by %<,%>");
21373 }
21374
21375 here = c_parser_peek_token (parser)->location;
21376 c_kind = c_parser_omp_clause_name (parser);
21377
21378 switch (c_kind)
21379 {
21380 case PRAGMA_OMP_CLAUSE_BIND:
21381 clauses = c_parser_omp_clause_bind (parser, list: clauses);
21382 c_name = "bind";
21383 break;
21384 case PRAGMA_OMP_CLAUSE_COLLAPSE:
21385 clauses = c_parser_omp_clause_collapse (parser, list: clauses);
21386 c_name = "collapse";
21387 break;
21388 case PRAGMA_OMP_CLAUSE_COPYIN:
21389 clauses = c_parser_omp_clause_copyin (parser, list: clauses);
21390 c_name = "copyin";
21391 break;
21392 case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
21393 clauses = c_parser_omp_clause_copyprivate (parser, list: clauses);
21394 c_name = "copyprivate";
21395 break;
21396 case PRAGMA_OMP_CLAUSE_DEFAULT:
21397 clauses = c_parser_omp_clause_default (parser, list: clauses, is_oacc: false);
21398 c_name = "default";
21399 break;
21400 case PRAGMA_OMP_CLAUSE_DETACH:
21401 clauses = c_parser_omp_clause_detach (parser, list: clauses);
21402 c_name = "detach";
21403 break;
21404 case PRAGMA_OMP_CLAUSE_FILTER:
21405 clauses = c_parser_omp_clause_filter (parser, list: clauses);
21406 c_name = "filter";
21407 break;
21408 case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
21409 clauses = c_parser_omp_clause_firstprivate (parser, list: clauses);
21410 c_name = "firstprivate";
21411 break;
21412 case PRAGMA_OMP_CLAUSE_FINAL:
21413 clauses = c_parser_omp_clause_final (parser, list: clauses);
21414 c_name = "final";
21415 break;
21416 case PRAGMA_OMP_CLAUSE_GRAINSIZE:
21417 clauses = c_parser_omp_clause_grainsize (parser, list: clauses);
21418 c_name = "grainsize";
21419 break;
21420 case PRAGMA_OMP_CLAUSE_HINT:
21421 clauses = c_parser_omp_clause_hint (parser, list: clauses);
21422 c_name = "hint";
21423 break;
21424 case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
21425 clauses = c_parser_omp_clause_defaultmap (parser, list: clauses);
21426 c_name = "defaultmap";
21427 break;
21428 case PRAGMA_OMP_CLAUSE_IF:
21429 clauses = c_parser_omp_clause_if (parser, list: clauses, is_omp: true);
21430 c_name = "if";
21431 break;
21432 case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
21433 clauses
21434 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_IN_REDUCTION,
21435 is_omp: true, list: clauses);
21436 c_name = "in_reduction";
21437 break;
21438 case PRAGMA_OMP_CLAUSE_INDIRECT:
21439 clauses = c_parser_omp_clause_indirect (parser, list: clauses);
21440 c_name = "indirect";
21441 break;
21442 case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
21443 clauses = c_parser_omp_clause_lastprivate (parser, list: clauses);
21444 c_name = "lastprivate";
21445 break;
21446 case PRAGMA_OMP_CLAUSE_MERGEABLE:
21447 clauses = c_parser_omp_clause_mergeable (parser, list: clauses);
21448 c_name = "mergeable";
21449 break;
21450 case PRAGMA_OMP_CLAUSE_NOWAIT:
21451 clauses = c_parser_omp_clause_nowait (parser, list: clauses);
21452 c_name = "nowait";
21453 break;
21454 case PRAGMA_OMP_CLAUSE_NUM_TASKS:
21455 clauses = c_parser_omp_clause_num_tasks (parser, list: clauses);
21456 c_name = "num_tasks";
21457 break;
21458 case PRAGMA_OMP_CLAUSE_NUM_THREADS:
21459 clauses = c_parser_omp_clause_num_threads (parser, list: clauses);
21460 c_name = "num_threads";
21461 break;
21462 case PRAGMA_OMP_CLAUSE_ORDER:
21463 clauses = c_parser_omp_clause_order (parser, list: clauses);
21464 c_name = "order";
21465 break;
21466 case PRAGMA_OMP_CLAUSE_ORDERED:
21467 clauses = c_parser_omp_clause_ordered (parser, list: clauses);
21468 c_name = "ordered";
21469 break;
21470 case PRAGMA_OMP_CLAUSE_PRIORITY:
21471 clauses = c_parser_omp_clause_priority (parser, list: clauses);
21472 c_name = "priority";
21473 break;
21474 case PRAGMA_OMP_CLAUSE_PRIVATE:
21475 clauses = c_parser_omp_clause_private (parser, list: clauses);
21476 c_name = "private";
21477 break;
21478 case PRAGMA_OMP_CLAUSE_REDUCTION:
21479 clauses
21480 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_REDUCTION,
21481 is_omp: true, list: clauses);
21482 c_name = "reduction";
21483 break;
21484 case PRAGMA_OMP_CLAUSE_SCHEDULE:
21485 clauses = c_parser_omp_clause_schedule (parser, list: clauses);
21486 c_name = "schedule";
21487 break;
21488 case PRAGMA_OMP_CLAUSE_SHARED:
21489 clauses = c_parser_omp_clause_shared (parser, list: clauses);
21490 c_name = "shared";
21491 break;
21492 case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
21493 clauses
21494 = c_parser_omp_clause_reduction (parser, kind: OMP_CLAUSE_TASK_REDUCTION,
21495 is_omp: true, list: clauses);
21496 c_name = "task_reduction";
21497 break;
21498 case PRAGMA_OMP_CLAUSE_UNTIED:
21499 clauses = c_parser_omp_clause_untied (parser, list: clauses);
21500 c_name = "untied";
21501 break;
21502 case PRAGMA_OMP_CLAUSE_INBRANCH:
21503 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_INBRANCH,
21504 list: clauses);
21505 c_name = "inbranch";
21506 break;
21507 case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
21508 clauses = c_parser_omp_clause_nontemporal (parser, list: clauses);
21509 c_name = "nontemporal";
21510 break;
21511 case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
21512 clauses = c_parser_omp_clause_branch (parser, code: OMP_CLAUSE_NOTINBRANCH,
21513 list: clauses);
21514 c_name = "notinbranch";
21515 break;
21516 case PRAGMA_OMP_CLAUSE_PARALLEL:
21517 clauses
21518 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_PARALLEL,
21519 list: clauses);
21520 c_name = "parallel";
21521 if (!first)
21522 {
21523 clause_not_first:
21524 error_at (here, "%qs must be the first clause of %qs",
21525 c_name, where);
21526 clauses = prev;
21527 }
21528 break;
21529 case PRAGMA_OMP_CLAUSE_FOR:
21530 clauses
21531 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_FOR,
21532 list: clauses);
21533 c_name = "for";
21534 if (!first)
21535 goto clause_not_first;
21536 break;
21537 case PRAGMA_OMP_CLAUSE_SECTIONS:
21538 clauses
21539 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_SECTIONS,
21540 list: clauses);
21541 c_name = "sections";
21542 if (!first)
21543 goto clause_not_first;
21544 break;
21545 case PRAGMA_OMP_CLAUSE_TASKGROUP:
21546 clauses
21547 = c_parser_omp_clause_cancelkind (parser, code: OMP_CLAUSE_TASKGROUP,
21548 list: clauses);
21549 c_name = "taskgroup";
21550 if (!first)
21551 goto clause_not_first;
21552 break;
21553 case PRAGMA_OMP_CLAUSE_LINK:
21554 clauses
21555 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_LINK, list: clauses);
21556 c_name = "link";
21557 break;
21558 case PRAGMA_OMP_CLAUSE_TO:
21559 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
21560 {
21561 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
21562 list: clauses);
21563 for (tree c = nl; c != clauses; c = OMP_CLAUSE_CHAIN (c))
21564 OMP_CLAUSE_ENTER_TO (c) = 1;
21565 clauses = nl;
21566 }
21567 else
21568 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_TO,
21569 list: clauses);
21570 c_name = "to";
21571 break;
21572 case PRAGMA_OMP_CLAUSE_FROM:
21573 clauses = c_parser_omp_clause_from_to (parser, kind: OMP_CLAUSE_FROM,
21574 list: clauses);
21575 c_name = "from";
21576 break;
21577 case PRAGMA_OMP_CLAUSE_UNIFORM:
21578 clauses = c_parser_omp_clause_uniform (parser, list: clauses);
21579 c_name = "uniform";
21580 break;
21581 case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
21582 clauses = c_parser_omp_clause_num_teams (parser, list: clauses);
21583 c_name = "num_teams";
21584 break;
21585 case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
21586 clauses = c_parser_omp_clause_thread_limit (parser, list: clauses);
21587 c_name = "thread_limit";
21588 break;
21589 case PRAGMA_OMP_CLAUSE_ALIGNED:
21590 clauses = c_parser_omp_clause_aligned (parser, list: clauses);
21591 c_name = "aligned";
21592 break;
21593 case PRAGMA_OMP_CLAUSE_ALLOCATE:
21594 clauses = c_parser_omp_clause_allocate (parser, list: clauses);
21595 c_name = "allocate";
21596 break;
21597 case PRAGMA_OMP_CLAUSE_LINEAR:
21598 clauses = c_parser_omp_clause_linear (parser, list: clauses);
21599 c_name = "linear";
21600 break;
21601 case PRAGMA_OMP_CLAUSE_AFFINITY:
21602 clauses = c_parser_omp_clause_affinity (parser, list: clauses);
21603 c_name = "affinity";
21604 break;
21605 case PRAGMA_OMP_CLAUSE_DEPEND:
21606 clauses = c_parser_omp_clause_depend (parser, list: clauses);
21607 c_name = "depend";
21608 break;
21609 case PRAGMA_OMP_CLAUSE_DOACROSS:
21610 clauses = c_parser_omp_clause_doacross (parser, list: clauses);
21611 c_name = "doacross";
21612 break;
21613 case PRAGMA_OMP_CLAUSE_DESTROY:
21614 clauses = c_parser_omp_clause_destroy (parser, list: clauses);
21615 c_name = "destroy";
21616 break;
21617 case PRAGMA_OMP_CLAUSE_INIT:
21618 clauses = c_parser_omp_clause_init (parser, list: clauses);
21619 c_name = "init";
21620 break;
21621 case PRAGMA_OMP_CLAUSE_USE:
21622 clauses = c_parser_omp_clause_use (parser, list: clauses);
21623 c_name = "use";
21624 break;
21625 case PRAGMA_OMP_CLAUSE_INTEROP:
21626 clauses = c_parser_omp_clause_interop (parser, list: clauses);
21627 c_name = "interop";
21628 break;
21629 case PRAGMA_OMP_CLAUSE_MAP:
21630 clauses = c_parser_omp_clause_map (parser, list: clauses, declare_mapper_p: false);
21631 c_name = "map";
21632 break;
21633 case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
21634 clauses = c_parser_omp_clause_use_device_ptr (parser, list: clauses);
21635 c_name = "use_device_ptr";
21636 break;
21637 case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
21638 clauses = c_parser_omp_clause_use_device_addr (parser, list: clauses);
21639 c_name = "use_device_addr";
21640 break;
21641 case PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR:
21642 clauses = c_parser_omp_clause_has_device_addr (parser, list: clauses);
21643 c_name = "has_device_addr";
21644 break;
21645 case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
21646 clauses = c_parser_omp_clause_is_device_ptr (parser, list: clauses);
21647 c_name = "is_device_ptr";
21648 break;
21649 case PRAGMA_OMP_CLAUSE_DEVICE:
21650 clauses = c_parser_omp_clause_device (parser, list: clauses);
21651 c_name = "device";
21652 break;
21653 case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
21654 clauses = c_parser_omp_clause_dist_schedule (parser, list: clauses);
21655 c_name = "dist_schedule";
21656 break;
21657 case PRAGMA_OMP_CLAUSE_PROC_BIND:
21658 clauses = c_parser_omp_clause_proc_bind (parser, list: clauses);
21659 c_name = "proc_bind";
21660 break;
21661 case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
21662 clauses = c_parser_omp_clause_device_type (parser, list: clauses);
21663 c_name = "device_type";
21664 break;
21665 case PRAGMA_OMP_CLAUSE_SAFELEN:
21666 clauses = c_parser_omp_clause_safelen (parser, list: clauses);
21667 c_name = "safelen";
21668 break;
21669 case PRAGMA_OMP_CLAUSE_SIMDLEN:
21670 clauses = c_parser_omp_clause_simdlen (parser, list: clauses);
21671 c_name = "simdlen";
21672 break;
21673 case PRAGMA_OMP_CLAUSE_NOGROUP:
21674 clauses = c_parser_omp_clause_nogroup (parser, list: clauses);
21675 c_name = "nogroup";
21676 break;
21677 case PRAGMA_OMP_CLAUSE_THREADS:
21678 clauses
21679 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_THREADS,
21680 list: clauses);
21681 c_name = "threads";
21682 break;
21683 case PRAGMA_OMP_CLAUSE_SIMD:
21684 clauses
21685 = c_parser_omp_clause_orderedkind (parser, code: OMP_CLAUSE_SIMD,
21686 list: clauses);
21687 c_name = "simd";
21688 break;
21689 case PRAGMA_OMP_CLAUSE_ENTER:
21690 clauses
21691 = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
21692 list: clauses);
21693 c_name = "enter";
21694 break;
21695 case PRAGMA_OMP_CLAUSE_FULL:
21696 c_name = "full";
21697 clauses = c_parser_omp_clause_full (parser, list: clauses);
21698 break;
21699 case PRAGMA_OMP_CLAUSE_PARTIAL:
21700 c_name = "partial";
21701 clauses = c_parser_omp_clause_partial (parser, list: clauses);
21702 break;
21703 case PRAGMA_OMP_CLAUSE_NOVARIANTS:
21704 c_name = "novariants";
21705 clauses = c_parser_omp_clause_novariants (parser, list: clauses);
21706 break;
21707 case PRAGMA_OMP_CLAUSE_NOCONTEXT:
21708 c_name = "nocontext";
21709 clauses = c_parser_omp_clause_nocontext (parser, list: clauses);
21710 break;
21711 default:
21712 c_parser_error (parser, gmsgid: "expected an OpenMP clause");
21713 goto saw_error;
21714 }
21715
21716 first = false;
21717
21718 if (((mask >> c_kind) & 1) == 0)
21719 {
21720 /* Remove the invalid clause(s) from the list to avoid
21721 confusing the rest of the compiler. */
21722 clauses = prev;
21723 error_at (here, "%qs is not valid for %qs", c_name, where);
21724 }
21725 }
21726
21727 saw_error:
21728 if (!nested)
21729 c_parser_skip_to_pragma_eol (parser);
21730
21731 if (finish_p)
21732 {
21733 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
21734 return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
21735 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE)) != 0)
21736 return c_finish_omp_clauses (clauses, C_ORT_OMP_INTEROP);
21737 return c_finish_omp_clauses (clauses, C_ORT_OMP);
21738 }
21739
21740 return clauses;
21741}
21742
21743/* OpenACC 2.0, OpenMP 2.5:
21744 structured-block:
21745 statement
21746
21747 In practice, we're also interested in adding the statement to an
21748 outer node. So it is convenient if we work around the fact that
21749 c_parser_statement calls add_stmt. */
21750
21751static tree
21752c_parser_omp_structured_block (c_parser *parser, bool *if_p)
21753{
21754 tree stmt = push_stmt_list ();
21755 parser->omp_attrs_forbidden_p = true;
21756 c_parser_statement (parser, if_p);
21757 return pop_stmt_list (stmt);
21758}
21759
21760/* OpenACC 2.0:
21761 # pragma acc cache (variable-list) new-line
21762
21763 OpenACC 2.7:
21764 # pragma acc cache (readonly: variable-list) new-line
21765
21766 LOC is the location of the #pragma token.
21767*/
21768
21769static tree
21770c_parser_oacc_cache (location_t loc, c_parser *parser)
21771{
21772 tree stmt, clauses = NULL_TREE;
21773 bool readonly = false;
21774 location_t open_loc = c_parser_peek_token (parser)->location;
21775 matching_parens parens;
21776 if (parens.require_open (parser))
21777 {
21778 c_token *token = c_parser_peek_token (parser);
21779 if (token->type == CPP_NAME
21780 && !strcmp (IDENTIFIER_POINTER (token->value), s2: "readonly")
21781 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
21782 {
21783 c_parser_consume_token (parser);
21784 c_parser_consume_token (parser);
21785 readonly = true;
21786 }
21787 clauses = c_parser_omp_variable_list (parser, clause_loc: open_loc,
21788 kind: OMP_CLAUSE__CACHE_, NULL_TREE);
21789 parens.skip_until_found_close (parser);
21790 }
21791
21792 if (readonly)
21793 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
21794 OMP_CLAUSE__CACHE__READONLY (c) = 1;
21795
21796 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
21797
21798 c_parser_skip_to_pragma_eol (parser);
21799
21800 stmt = make_node (OACC_CACHE);
21801 TREE_TYPE (stmt) = void_type_node;
21802 OACC_CACHE_CLAUSES (stmt) = clauses;
21803 SET_EXPR_LOCATION (stmt, loc);
21804 add_stmt (stmt);
21805
21806 return stmt;
21807}
21808
21809/* OpenACC 2.0:
21810 # pragma acc data oacc-data-clause[optseq] new-line
21811 structured-block
21812
21813 LOC is the location of the #pragma token.
21814*/
21815
21816#define OACC_DATA_CLAUSE_MASK \
21817 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
21818 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
21819 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
21820 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
21821 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
21822 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
21823 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
21824 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
21825 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
21826 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
21827
21828static tree
21829c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
21830{
21831 tree stmt, clauses, block;
21832
21833 clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
21834 where: "#pragma acc data");
21835
21836 block = c_begin_omp_parallel ();
21837 add_stmt (c_parser_omp_structured_block (parser, if_p));
21838
21839 stmt = c_finish_oacc_data (loc, clauses, block);
21840
21841 return stmt;
21842}
21843
21844/* OpenACC 2.0:
21845 # pragma acc declare oacc-data-clause[optseq] new-line
21846*/
21847
21848#define OACC_DECLARE_CLAUSE_MASK \
21849 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
21850 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
21851 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
21852 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
21853 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
21854 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
21855 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
21856 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
21857
21858static void
21859c_parser_oacc_declare (c_parser *parser)
21860{
21861 location_t pragma_loc = c_parser_peek_token (parser)->location;
21862 tree clauses, stmt, t, decl;
21863
21864 bool error = false;
21865
21866 c_parser_consume_pragma (parser);
21867
21868 clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
21869 where: "#pragma acc declare");
21870 if (!clauses)
21871 {
21872 error_at (pragma_loc,
21873 "no valid clauses specified in %<#pragma acc declare%>");
21874 return;
21875 }
21876
21877 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
21878 {
21879 location_t loc = OMP_CLAUSE_LOCATION (t);
21880 decl = OMP_CLAUSE_DECL (t);
21881 if (!DECL_P (decl))
21882 {
21883 error_at (loc, "array section in %<#pragma acc declare%>");
21884 error = true;
21885 continue;
21886 }
21887
21888 switch (OMP_CLAUSE_MAP_KIND (t))
21889 {
21890 case GOMP_MAP_FIRSTPRIVATE_POINTER:
21891 case GOMP_MAP_ALLOC:
21892 case GOMP_MAP_TO:
21893 case GOMP_MAP_FORCE_DEVICEPTR:
21894 case GOMP_MAP_DEVICE_RESIDENT:
21895 break;
21896
21897 case GOMP_MAP_LINK:
21898 if (!global_bindings_p ()
21899 && (TREE_STATIC (decl)
21900 || !DECL_EXTERNAL (decl)))
21901 {
21902 error_at (loc,
21903 "%qD must be a global variable in "
21904 "%<#pragma acc declare link%>",
21905 decl);
21906 error = true;
21907 continue;
21908 }
21909 break;
21910
21911 default:
21912 if (global_bindings_p ())
21913 {
21914 error_at (loc, "invalid OpenACC clause at file scope");
21915 error = true;
21916 continue;
21917 }
21918 if (DECL_EXTERNAL (decl))
21919 {
21920 error_at (loc,
21921 "invalid use of %<extern%> variable %qD "
21922 "in %<#pragma acc declare%>", decl);
21923 error = true;
21924 continue;
21925 }
21926 else if (TREE_PUBLIC (decl))
21927 {
21928 error_at (loc,
21929 "invalid use of %<global%> variable %qD "
21930 "in %<#pragma acc declare%>", decl);
21931 error = true;
21932 continue;
21933 }
21934 break;
21935 }
21936
21937 if (!c_check_in_current_scope (decl))
21938 {
21939 error_at (loc,
21940 "%qD must be a variable declared in the same scope as "
21941 "%<#pragma acc declare%>", decl);
21942 error = true;
21943 continue;
21944 }
21945
21946 if (lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (decl))
21947 || lookup_attribute (attr_name: "omp declare target link",
21948 DECL_ATTRIBUTES (decl)))
21949 {
21950 error_at (loc, "variable %qD used more than once with "
21951 "%<#pragma acc declare%>", decl);
21952 error = true;
21953 continue;
21954 }
21955
21956 if (!error)
21957 {
21958 tree id;
21959
21960 if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
21961 id = get_identifier ("omp declare target link");
21962 else
21963 id = get_identifier ("omp declare target");
21964
21965 DECL_ATTRIBUTES (decl)
21966 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
21967
21968 if (global_bindings_p ())
21969 {
21970 symtab_node *node = symtab_node::get (decl);
21971 if (node != NULL)
21972 {
21973 node->offloadable = 1;
21974 if (ENABLE_OFFLOADING)
21975 {
21976 g->have_offload = true;
21977 if (is_a <varpool_node *> (p: node))
21978 vec_safe_push (v&: offload_vars, obj: decl);
21979 }
21980 }
21981 }
21982 }
21983 }
21984
21985 if (error || global_bindings_p ())
21986 return;
21987
21988 stmt = make_node (OACC_DECLARE);
21989 TREE_TYPE (stmt) = void_type_node;
21990 OACC_DECLARE_CLAUSES (stmt) = clauses;
21991 SET_EXPR_LOCATION (stmt, pragma_loc);
21992
21993 add_stmt (stmt);
21994
21995 return;
21996}
21997
21998/* OpenACC 2.0:
21999 # pragma acc enter data oacc-enter-data-clause[optseq] new-line
22000
22001 or
22002
22003 # pragma acc exit data oacc-exit-data-clause[optseq] new-line
22004
22005
22006 LOC is the location of the #pragma token.
22007*/
22008
22009#define OACC_ENTER_DATA_CLAUSE_MASK \
22010 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22011 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22012 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22013 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22014 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22015 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22016
22017#define OACC_EXIT_DATA_CLAUSE_MASK \
22018 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22019 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22020 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22021 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
22022 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
22023 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
22024 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22025
22026static void
22027c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
22028{
22029 location_t loc = c_parser_peek_token (parser)->location;
22030 tree clauses, stmt;
22031 const char *p = "";
22032
22033 c_parser_consume_pragma (parser);
22034
22035 if (c_parser_next_token_is (parser, type: CPP_NAME))
22036 {
22037 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22038 c_parser_consume_token (parser);
22039 }
22040
22041 if (strcmp (s1: p, s2: "data") != 0)
22042 {
22043 error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
22044 enter ? "enter" : "exit");
22045 parser->error = true;
22046 c_parser_skip_to_pragma_eol (parser);
22047 return;
22048 }
22049
22050 if (enter)
22051 clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
22052 where: "#pragma acc enter data");
22053 else
22054 clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
22055 where: "#pragma acc exit data");
22056
22057 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
22058 {
22059 error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
22060 enter ? "enter" : "exit");
22061 return;
22062 }
22063
22064 stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
22065 TREE_TYPE (stmt) = void_type_node;
22066 OMP_STANDALONE_CLAUSES (stmt) = clauses;
22067 SET_EXPR_LOCATION (stmt, loc);
22068 add_stmt (stmt);
22069}
22070
22071
22072/* OpenACC 2.0:
22073 # pragma acc host_data oacc-data-clause[optseq] new-line
22074 structured-block
22075*/
22076
22077#define OACC_HOST_DATA_CLAUSE_MASK \
22078 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
22079 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22080 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
22081
22082static tree
22083c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
22084{
22085 tree stmt, clauses, block;
22086
22087 clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
22088 where: "#pragma acc host_data", finish_p: false);
22089 if (!omp_find_clause (clauses, kind: OMP_CLAUSE_USE_DEVICE_PTR))
22090 {
22091 error_at (loc, "%<host_data%> construct requires %<use_device%> clause");
22092 return error_mark_node;
22093 }
22094 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22095 block = c_begin_omp_parallel ();
22096 add_stmt (c_parser_omp_structured_block (parser, if_p));
22097 stmt = c_finish_oacc_host_data (loc, clauses, block);
22098 return stmt;
22099}
22100
22101
22102/* OpenACC 2.0:
22103
22104 # pragma acc loop oacc-loop-clause[optseq] new-line
22105 structured-block
22106
22107 LOC is the location of the #pragma token.
22108*/
22109
22110#define OACC_LOOP_CLAUSE_MASK \
22111 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
22112 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22113 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22114 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22115 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22116 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22117 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
22118 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
22119 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22120 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
22121static tree
22122c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
22123 omp_clause_mask mask, tree *cclauses, bool *if_p)
22124{
22125 bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
22126
22127 strcat (dest: p_name, src: " loop");
22128 mask |= OACC_LOOP_CLAUSE_MASK;
22129
22130 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
22131 /*finish_p=*/cclauses == NULL,
22132 /*target=*/target_p: is_parallel);
22133 if (cclauses)
22134 {
22135 clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
22136 if (*cclauses)
22137 *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC_TARGET);
22138 if (clauses)
22139 clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
22140 }
22141
22142 tree block = c_begin_compound_stmt (true);
22143 tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
22144 if_p);
22145 block = c_end_compound_stmt (loc, block, true);
22146 add_stmt (block);
22147
22148 return stmt;
22149}
22150
22151/* OpenACC 2.0:
22152 # pragma acc kernels oacc-kernels-clause[optseq] new-line
22153 structured-block
22154
22155 or
22156
22157 # pragma acc parallel oacc-parallel-clause[optseq] new-line
22158 structured-block
22159
22160 OpenACC 2.6:
22161
22162 # pragma acc serial oacc-serial-clause[optseq] new-line
22163 structured-block
22164
22165 LOC is the location of the #pragma token.
22166*/
22167
22168#define OACC_KERNELS_CLAUSE_MASK \
22169 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22170 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22171 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22172 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22173 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22174 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22175 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22176 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22177 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22178 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22179 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22180 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22181 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22182 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22183 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22184 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22185
22186#define OACC_PARALLEL_CLAUSE_MASK \
22187 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22188 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22189 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22190 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22191 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22192 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22193 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22194 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22195 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22196 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22197 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22198 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22199 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
22200 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
22201 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22202 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22203 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22204 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
22205 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22206
22207#define OACC_SERIAL_CLAUSE_MASK \
22208 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22209 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
22210 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
22211 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
22212 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
22213 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
22214 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
22215 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
22216 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22217 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
22218 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
22219 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
22220 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
22221 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
22222 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22223 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22224
22225static tree
22226c_parser_oacc_compute (location_t loc, c_parser *parser,
22227 enum pragma_kind p_kind, char *p_name, bool *if_p)
22228{
22229 omp_clause_mask mask;
22230 enum tree_code code;
22231 switch (p_kind)
22232 {
22233 case PRAGMA_OACC_KERNELS:
22234 strcat (dest: p_name, src: " kernels");
22235 mask = OACC_KERNELS_CLAUSE_MASK;
22236 code = OACC_KERNELS;
22237 break;
22238 case PRAGMA_OACC_PARALLEL:
22239 strcat (dest: p_name, src: " parallel");
22240 mask = OACC_PARALLEL_CLAUSE_MASK;
22241 code = OACC_PARALLEL;
22242 break;
22243 case PRAGMA_OACC_SERIAL:
22244 strcat (dest: p_name, src: " serial");
22245 mask = OACC_SERIAL_CLAUSE_MASK;
22246 code = OACC_SERIAL;
22247 break;
22248 default:
22249 gcc_unreachable ();
22250 }
22251
22252 if (c_parser_next_token_is (parser, type: CPP_NAME))
22253 {
22254 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22255 if (strcmp (s1: p, s2: "loop") == 0)
22256 {
22257 c_parser_consume_token (parser);
22258 tree block = c_begin_omp_parallel ();
22259 tree clauses;
22260 c_parser_oacc_loop (loc, parser, p_name, mask, cclauses: &clauses, if_p);
22261 return c_finish_omp_construct (loc, code, block, clauses);
22262 }
22263 }
22264
22265 tree clauses = c_parser_oacc_all_clauses (parser, mask, where: p_name,
22266 /*finish_p=*/true,
22267 /*target=*/target_p: true);
22268
22269 tree block = c_begin_omp_parallel ();
22270 add_stmt (c_parser_omp_structured_block (parser, if_p));
22271
22272 return c_finish_omp_construct (loc, code, block, clauses);
22273}
22274
22275/* OpenACC 2.0:
22276 # pragma acc routine oacc-routine-clause[optseq] new-line
22277 function-definition
22278
22279 # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
22280*/
22281
22282#define OACC_ROUTINE_CLAUSE_MASK \
22283 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
22284 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
22285 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
22286 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
22287 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
22288
22289/* Parse an OpenACC routine directive. For named directives, we apply
22290 immediately to the named function. For unnamed ones we then parse
22291 a declaration or definition, which must be for a function. */
22292
22293static void
22294c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
22295{
22296 gcc_checking_assert (context == pragma_external);
22297
22298 oacc_routine_data data;
22299 data.error_seen = false;
22300 data.fndecl_seen = false;
22301 data.loc = c_parser_peek_token (parser)->location;
22302
22303 c_parser_consume_pragma (parser);
22304
22305 /* Look for optional '( name )'. */
22306 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
22307 {
22308 c_parser_consume_token (parser); /* '(' */
22309
22310 tree decl = NULL_TREE;
22311 c_token *name_token = c_parser_peek_token (parser);
22312 location_t name_loc = name_token->location;
22313 if (name_token->type == CPP_NAME
22314 && (name_token->id_kind == C_ID_ID
22315 || name_token->id_kind == C_ID_TYPENAME))
22316 {
22317 decl = lookup_name (name_token->value);
22318 if (!decl)
22319 error_at (name_loc,
22320 "%qE has not been declared", name_token->value);
22321 c_parser_consume_token (parser);
22322 }
22323 else
22324 c_parser_error (parser, gmsgid: "expected function name");
22325
22326 if (!decl
22327 || !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
22328 {
22329 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
22330 return;
22331 }
22332
22333 data.clauses
22334 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22335 where: "#pragma acc routine");
22336 /* The clauses are in reverse order; fix that to make later diagnostic
22337 emission easier. */
22338 data.clauses = nreverse (data.clauses);
22339
22340 if (TREE_CODE (decl) != FUNCTION_DECL)
22341 {
22342 error_at (name_loc, "%qD does not refer to a function", decl);
22343 return;
22344 }
22345
22346 c_finish_oacc_routine (&data, decl, false);
22347 }
22348 else /* No optional '( name )'. */
22349 {
22350 data.clauses
22351 = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
22352 where: "#pragma acc routine");
22353 /* The clauses are in reverse order; fix that to make later diagnostic
22354 emission easier. */
22355 data.clauses = nreverse (data.clauses);
22356
22357 /* Emit a helpful diagnostic if there's another pragma following this
22358 one. Also don't allow a static assertion declaration, as in the
22359 following we'll just parse a *single* "declaration or function
22360 definition", and the static assertion counts an one. */
22361 if (c_parser_next_token_is (parser, type: CPP_PRAGMA)
22362 || c_parser_next_token_is_keyword (parser, keyword: RID_STATIC_ASSERT))
22363 {
22364 error_at (data.loc,
22365 "%<#pragma acc routine%> not immediately followed by"
22366 " function declaration or definition");
22367 /* ..., and then just keep going. */
22368 return;
22369 }
22370
22371 /* We only have to consider the pragma_external case here. */
22372 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
22373 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
22374 {
22375 int ext = disable_extension_diagnostics ();
22376 do
22377 c_parser_consume_token (parser);
22378 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
22379 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
22380 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
22381 simple_ok: false, NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
22382 restore_extension_diagnostics (flags: ext);
22383 }
22384 else
22385 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
22386 simple_ok: false, NULL, NULL, have_attrs: false, NULL, oacc_routine_data: &data);
22387 }
22388}
22389
22390/* Finalize an OpenACC routine pragma, applying it to FNDECL.
22391 IS_DEFN is true if we're applying it to the definition. */
22392
22393static void
22394c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
22395 bool is_defn)
22396{
22397 /* Keep going if we're in error reporting mode. */
22398 if (data->error_seen
22399 || fndecl == error_mark_node)
22400 return;
22401
22402 if (data->fndecl_seen)
22403 {
22404 error_at (data->loc,
22405 "%<#pragma acc routine%> not immediately followed by"
22406 " a single function declaration or definition");
22407 data->error_seen = true;
22408 return;
22409 }
22410 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
22411 {
22412 error_at (data->loc,
22413 "%<#pragma acc routine%> not immediately followed by"
22414 " function declaration or definition");
22415 data->error_seen = true;
22416 return;
22417 }
22418
22419 int compatible
22420 = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
22421 "#pragma acc routine");
22422 if (compatible < 0)
22423 {
22424 data->error_seen = true;
22425 return;
22426 }
22427 if (compatible > 0)
22428 {
22429 }
22430 else
22431 {
22432 if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
22433 {
22434 error_at (data->loc,
22435 TREE_USED (fndecl)
22436 ? G_("%<#pragma acc routine%> must be applied before use")
22437 : G_("%<#pragma acc routine%> must be applied before"
22438 " definition"));
22439 data->error_seen = true;
22440 return;
22441 }
22442
22443 /* Set the routine's level of parallelism. */
22444 tree dims = oacc_build_routine_dims (clauses: data->clauses);
22445 oacc_replace_fn_attrib (fn: fndecl, dims);
22446
22447 /* Add an "omp declare target" attribute. */
22448 DECL_ATTRIBUTES (fndecl)
22449 = tree_cons (get_identifier ("omp declare target"),
22450 data->clauses, DECL_ATTRIBUTES (fndecl));
22451 }
22452
22453 /* Remember that we've used this "#pragma acc routine". */
22454 data->fndecl_seen = true;
22455}
22456
22457/* OpenACC 2.0:
22458 # pragma acc update oacc-update-clause[optseq] new-line
22459*/
22460
22461#define OACC_UPDATE_CLAUSE_MASK \
22462 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
22463 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
22464 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
22465 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
22466 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
22467 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SELF) \
22468 | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
22469
22470static void
22471c_parser_oacc_update (c_parser *parser)
22472{
22473 location_t loc = c_parser_peek_token (parser)->location;
22474
22475 c_parser_consume_pragma (parser);
22476
22477 tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
22478 where: "#pragma acc update");
22479 if (omp_find_clause (clauses, kind: OMP_CLAUSE_MAP) == NULL_TREE)
22480 {
22481 error_at (loc,
22482 "%<#pragma acc update%> must contain at least one "
22483 "%<device%> or %<host%> or %<self%> clause");
22484 return;
22485 }
22486
22487 if (parser->error)
22488 return;
22489
22490 tree stmt = make_node (OACC_UPDATE);
22491 TREE_TYPE (stmt) = void_type_node;
22492 OACC_UPDATE_CLAUSES (stmt) = clauses;
22493 SET_EXPR_LOCATION (stmt, loc);
22494 add_stmt (stmt);
22495}
22496
22497/* OpenACC 2.0:
22498 # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
22499
22500 LOC is the location of the #pragma token.
22501*/
22502
22503#define OACC_WAIT_CLAUSE_MASK \
22504 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
22505
22506static tree
22507c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
22508{
22509 tree clauses, list = NULL_TREE, stmt = NULL_TREE;
22510
22511 if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
22512 list = c_parser_oacc_wait_list (parser, clause_loc: loc, list);
22513
22514 strcpy (dest: p_name, src: " wait");
22515 clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, where: p_name);
22516 stmt = c_finish_oacc_wait (loc, list, clauses);
22517 add_stmt (stmt);
22518
22519 return stmt;
22520}
22521
22522struct c_omp_loc_tree
22523{
22524 location_t loc;
22525 tree var;
22526};
22527
22528/* Check whether the expression used in the allocator clause is declared or
22529 modified between the variable declaration and its allocate directive. */
22530static tree
22531c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
22532{
22533 tree var = ((struct c_omp_loc_tree *) data)->var;
22534 location_t loc = ((struct c_omp_loc_tree *) data)->loc;
22535 if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
22536 {
22537 if (linemap_location_before_p (set: line_table, DECL_SOURCE_LOCATION (var),
22538 DECL_SOURCE_LOCATION (*tp)))
22539 {
22540 error_at (loc, "variable %qD used in the %<allocator%> clause must "
22541 "be declared before %qD", *tp, var);
22542 inform (DECL_SOURCE_LOCATION (*tp), "declared here");
22543 inform (DECL_SOURCE_LOCATION (var),
22544 "to be allocated variable declared here");
22545 return *tp;
22546 }
22547 else
22548 {
22549 gcc_assert (cur_stmt_list
22550 && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
22551
22552 tree_stmt_iterator l = tsi_last (cur_stmt_list);
22553 while (!tsi_end_p (i: l))
22554 {
22555 if (linemap_location_before_p (set: line_table, EXPR_LOCATION (*l),
22556 DECL_SOURCE_LOCATION (var)))
22557 break;
22558 if (TREE_CODE (*l) == MODIFY_EXPR
22559 && TREE_OPERAND (*l, 0) == *tp)
22560 {
22561 error_at (loc,
22562 "variable %qD used in the %<allocator%> clause "
22563 "must not be modified between declaration of %qD "
22564 "and its %<allocate%> directive", *tp, var);
22565 inform (EXPR_LOCATION (*l), "modified here");
22566 inform (DECL_SOURCE_LOCATION (var),
22567 "to be allocated variable declared here");
22568 return *tp;
22569 }
22570 --l;
22571 }
22572 }
22573 }
22574 return NULL_TREE;
22575}
22576
22577/* OpenMP 5.x:
22578 # pragma omp allocate (list) clauses
22579
22580 OpenMP 5.0 clause:
22581 allocator (omp_allocator_handle_t expression)
22582
22583 OpenMP 5.1 additional clause:
22584 align (constant-expression)] */
22585
22586static void
22587c_parser_omp_allocate (c_parser *parser)
22588{
22589 tree alignment = NULL_TREE;
22590 tree allocator = NULL_TREE;
22591 c_parser_consume_pragma (parser);
22592 location_t loc = c_parser_peek_token (parser)->location;
22593 location_t allocator_loc = UNKNOWN_LOCATION;
22594 tree nl = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ALLOCATE, NULL_TREE);
22595 do
22596 {
22597 if (c_parser_next_token_is (parser, type: CPP_COMMA)
22598 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22599 c_parser_consume_token (parser);
22600 if (!c_parser_next_token_is (parser, type: CPP_NAME))
22601 break;
22602 matching_parens parens;
22603 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22604 c_parser_consume_token (parser);
22605 location_t expr_loc = c_parser_peek_token (parser)->location;
22606 if (strcmp (s1: "align", s2: p) != 0 && strcmp (s1: "allocator", s2: p) != 0)
22607 {
22608 error_at (c_parser_peek_token (parser)->location,
22609 "expected %<allocator%> or %<align%>");
22610 break;
22611 }
22612 if (!parens.require_open (parser))
22613 break;
22614
22615 c_expr expr = c_parser_expr_no_commas (parser, NULL);
22616 expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
22617 expr_loc = c_parser_peek_token (parser)->location;
22618 if (expr.value == error_mark_node)
22619 ;
22620 else if (p[2] == 'i' && alignment)
22621 {
22622 error_at (expr_loc, "too many %qs clauses", "align");
22623 break;
22624 }
22625 else if (p[2] == 'i')
22626 {
22627 alignment = c_fully_fold (expr.value, false, NULL);
22628 if (TREE_CODE (alignment) != INTEGER_CST
22629 || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
22630 || tree_int_cst_sgn (alignment) != 1
22631 || !integer_pow2p (alignment))
22632 {
22633 error_at (expr_loc, "%<align%> clause argument needs to be "
22634 "positive constant power of two integer "
22635 "expression");
22636 alignment = NULL_TREE;
22637 }
22638 }
22639 else if (allocator)
22640 {
22641 error_at (expr_loc, "too many %qs clauses", "allocator");
22642 break;
22643 }
22644 else
22645 {
22646 allocator = c_fully_fold (expr.value, false, NULL);
22647 allocator_loc = expr_loc;
22648 tree orig_type
22649 = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
22650 orig_type = TYPE_MAIN_VARIANT (orig_type);
22651 if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
22652 || TREE_CODE (orig_type) != ENUMERAL_TYPE
22653 || TYPE_NAME (orig_type)
22654 != get_identifier ("omp_allocator_handle_t"))
22655 {
22656 error_at (expr_loc,
22657 "%<allocator%> clause allocator expression has type "
22658 "%qT rather than %<omp_allocator_handle_t%>",
22659 TREE_TYPE (allocator));
22660 allocator = NULL_TREE;
22661 }
22662 }
22663 parens.skip_until_found_close (parser);
22664 } while (true);
22665 c_parser_skip_to_pragma_eol (parser);
22666
22667 c_mark_decl_jump_unsafe_in_current_scope ();
22668 for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
22669 {
22670 tree var = OMP_CLAUSE_DECL (c);
22671 if (TREE_CODE (var) == PARM_DECL)
22672 {
22673 error_at (OMP_CLAUSE_LOCATION (nl),
22674 "function parameter %qD may not appear as list item in an "
22675 "%<allocate%> directive", var);
22676 continue;
22677 }
22678 if (!parser->in_omp_decl_attribute && !c_check_in_current_scope (var))
22679 {
22680 error_at (OMP_CLAUSE_LOCATION (nl),
22681 "%<allocate%> directive must be in the same scope as %qD",
22682 var);
22683 inform (DECL_SOURCE_LOCATION (var), "declared here");
22684 continue;
22685 }
22686 if (lookup_attribute (attr_name: "omp allocate", DECL_ATTRIBUTES (var)))
22687 {
22688 error_at (OMP_CLAUSE_LOCATION (nl),
22689 "%qD already appeared as list item in an "
22690 "%<allocate%> directive", var);
22691 continue;
22692 }
22693 if (TREE_STATIC (var))
22694 {
22695 if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
22696 {
22697 error_at (loc,
22698 "%<allocator%> clause required for "
22699 "static variable %qD", var);
22700 continue;
22701 }
22702 else if (allocator
22703 && (wi::to_widest (t: allocator) < 1
22704 || wi::to_widest (t: allocator) > GOMP_OMP_PREDEF_ALLOC_MAX)
22705 && (wi::to_widest (t: allocator) < GOMP_OMPX_PREDEF_ALLOC_MIN
22706 || wi::to_widest (t: allocator) > GOMP_OMPX_PREDEF_ALLOC_MAX))
22707 {
22708 error_at (allocator_loc,
22709 "%<allocator%> clause requires a predefined allocator as "
22710 "%qD is static", var);
22711 }
22712 }
22713 if (allocator)
22714 {
22715 struct c_omp_loc_tree data
22716 = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), .var: var};
22717 walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
22718 }
22719 DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
22720 build_tree_list (allocator, alignment),
22721 DECL_ATTRIBUTES (var));
22722 }
22723}
22724
22725/* OpenMP 2.5:
22726 # pragma omp atomic new-line
22727 expression-stmt
22728
22729 expression-stmt:
22730 x binop= expr | x++ | ++x | x-- | --x
22731 binop:
22732 +, *, -, /, &, ^, |, <<, >>
22733
22734 where x is an lvalue expression with scalar type.
22735
22736 OpenMP 3.1:
22737 # pragma omp atomic new-line
22738 update-stmt
22739
22740 # pragma omp atomic read new-line
22741 read-stmt
22742
22743 # pragma omp atomic write new-line
22744 write-stmt
22745
22746 # pragma omp atomic update new-line
22747 update-stmt
22748
22749 # pragma omp atomic capture new-line
22750 capture-stmt
22751
22752 # pragma omp atomic capture new-line
22753 capture-block
22754
22755 read-stmt:
22756 v = x
22757 write-stmt:
22758 x = expr
22759 update-stmt:
22760 expression-stmt | x = x binop expr
22761 capture-stmt:
22762 v = expression-stmt
22763 capture-block:
22764 { v = x; update-stmt; } | { update-stmt; v = x; }
22765
22766 OpenMP 4.0:
22767 update-stmt:
22768 expression-stmt | x = x binop expr | x = expr binop x
22769 capture-stmt:
22770 v = update-stmt
22771 capture-block:
22772 { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
22773
22774 OpenMP 5.1:
22775 # pragma omp atomic compare new-line
22776 conditional-update-atomic
22777
22778 # pragma omp atomic compare capture new-line
22779 conditional-update-capture-atomic
22780
22781 conditional-update-atomic:
22782 cond-expr-stmt | cond-update-stmt
22783 cond-expr-stmt:
22784 x = expr ordop x ? expr : x;
22785 x = x ordop expr ? expr : x;
22786 x = x == e ? d : x;
22787 cond-update-stmt:
22788 if (expr ordop x) { x = expr; }
22789 if (x ordop expr) { x = expr; }
22790 if (x == e) { x = d; }
22791 ordop:
22792 <, >
22793 conditional-update-capture-atomic:
22794 v = cond-expr-stmt
22795 { v = x; cond-expr-stmt }
22796 { cond-expr-stmt v = x; }
22797 { v = x; cond-update-stmt }
22798 { cond-update-stmt v = x; }
22799 if (x == e) { x = d; } else { v = x; }
22800 { r = x == e; if (r) { x = d; } }
22801 { r = x == e; if (r) { x = d; } else { v = x; } }
22802
22803 where x, r and v are lvalue expressions with scalar type,
22804 expr, e and d are expressions with scalar type and e might be
22805 the same as v.
22806
22807 LOC is the location of the #pragma token. */
22808
22809static void
22810c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
22811{
22812 tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
22813 tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
22814 tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
22815 enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
22816 enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
22817 struct c_expr expr;
22818 location_t eloc;
22819 bool structured_block = false;
22820 bool swapped = false;
22821 bool non_lvalue_p;
22822 tree clauses = NULL_TREE;
22823 bool capture = false;
22824 bool compare = false;
22825 bool weak = false;
22826 enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22827 bool no_semicolon = false;
22828 bool extra_scope = false;
22829
22830 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
22831 {
22832 if (c_parser_next_token_is (parser, type: CPP_COMMA)
22833 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
22834 c_parser_consume_token (parser);
22835
22836 if (c_parser_next_token_is (parser, type: CPP_NAME))
22837 {
22838 const char *p
22839 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22840 location_t cloc = c_parser_peek_token (parser)->location;
22841 enum tree_code new_code = ERROR_MARK;
22842 enum omp_memory_order new_memory_order
22843 = OMP_MEMORY_ORDER_UNSPECIFIED;
22844 bool new_capture = false;
22845 bool new_compare = false;
22846 bool new_weak = false;
22847 enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22848
22849 if (!strcmp (s1: p, s2: "read"))
22850 new_code = OMP_ATOMIC_READ;
22851 else if (!strcmp (s1: p, s2: "write"))
22852 new_code = NOP_EXPR;
22853 else if (!strcmp (s1: p, s2: "update"))
22854 new_code = OMP_ATOMIC;
22855 else if (openacc && !strcmp (s1: p, s2: "capture"))
22856 new_code = OMP_ATOMIC_CAPTURE_NEW;
22857 else if (openacc)
22858 {
22859 p = NULL;
22860 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
22861 "or %<capture%> clause");
22862 }
22863 else if (!strcmp (s1: p, s2: "capture"))
22864 new_capture = true;
22865 else if (!strcmp (s1: p, s2: "compare"))
22866 new_compare = true;
22867 else if (!strcmp (s1: p, s2: "weak"))
22868 new_weak = true;
22869 else if (!strcmp (s1: p, s2: "fail"))
22870 {
22871 matching_parens parens;
22872
22873 c_parser_consume_token (parser);
22874 if (!parens.require_open (parser))
22875 continue;
22876
22877 if (c_parser_next_token_is (parser, type: CPP_NAME))
22878 {
22879 const char *q
22880 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
22881
22882 if (!strcmp (s1: q, s2: "seq_cst"))
22883 new_fail = OMP_MEMORY_ORDER_SEQ_CST;
22884 else if (!strcmp (s1: q, s2: "acquire"))
22885 new_fail = OMP_MEMORY_ORDER_ACQUIRE;
22886 else if (!strcmp (s1: q, s2: "relaxed"))
22887 new_fail = OMP_MEMORY_ORDER_RELAXED;
22888 }
22889
22890 if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
22891 {
22892 c_parser_consume_token (parser);
22893 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
22894 error_at (cloc, "too many %qs clauses", "fail");
22895 else
22896 fail = new_fail;
22897 }
22898 else
22899 c_parser_error (parser, gmsgid: "expected %<seq_cst%>, %<acquire%> "
22900 "or %<relaxed%>");
22901 parens.skip_until_found_close (parser);
22902 continue;
22903 }
22904 else if (!strcmp (s1: p, s2: "seq_cst"))
22905 new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
22906 else if (!strcmp (s1: p, s2: "acq_rel"))
22907 new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
22908 else if (!strcmp (s1: p, s2: "release"))
22909 new_memory_order = OMP_MEMORY_ORDER_RELEASE;
22910 else if (!strcmp (s1: p, s2: "acquire"))
22911 new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
22912 else if (!strcmp (s1: p, s2: "relaxed"))
22913 new_memory_order = OMP_MEMORY_ORDER_RELAXED;
22914 else if (!strcmp (s1: p, s2: "hint"))
22915 {
22916 c_parser_consume_token (parser);
22917 clauses = c_parser_omp_clause_hint (parser, list: clauses);
22918 continue;
22919 }
22920 else
22921 {
22922 p = NULL;
22923 error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
22924 "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
22925 "%<seq_cst%>, %<acq_rel%>, %<release%>, "
22926 "%<relaxed%> or %<hint%> clause");
22927 }
22928 if (p)
22929 {
22930 if (new_code != ERROR_MARK)
22931 {
22932 /* OpenACC permits 'update capture'. */
22933 if (openacc
22934 && code == OMP_ATOMIC
22935 && new_code == OMP_ATOMIC_CAPTURE_NEW)
22936 code = new_code;
22937 else if (code != ERROR_MARK)
22938 error_at (cloc, "too many atomic clauses");
22939 else
22940 code = new_code;
22941 }
22942 else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
22943 {
22944 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
22945 error_at (cloc, "too many memory order clauses");
22946 else
22947 memory_order = new_memory_order;
22948 }
22949 else if (new_capture)
22950 {
22951 if (capture)
22952 error_at (cloc, "too many %qs clauses", "capture");
22953 else
22954 capture = true;
22955 }
22956 else if (new_compare)
22957 {
22958 if (compare)
22959 error_at (cloc, "too many %qs clauses", "compare");
22960 else
22961 compare = true;
22962 }
22963 else if (new_weak)
22964 {
22965 if (weak)
22966 error_at (cloc, "too many %qs clauses", "weak");
22967 else
22968 weak = true;
22969 }
22970 c_parser_consume_token (parser);
22971 continue;
22972 }
22973 }
22974 break;
22975 }
22976 c_parser_skip_to_pragma_eol (parser);
22977
22978 if (code == ERROR_MARK)
22979 code = OMP_ATOMIC;
22980 if (capture)
22981 {
22982 if (code != OMP_ATOMIC)
22983 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
22984 "clauses", "capture");
22985 else
22986 code = OMP_ATOMIC_CAPTURE_NEW;
22987 }
22988 if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
22989 {
22990 error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
22991 "clauses", "compare");
22992 compare = false;
22993 }
22994 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
22995 {
22996 error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
22997 fail = OMP_MEMORY_ORDER_UNSPECIFIED;
22998 }
22999 if (weak && !compare)
23000 {
23001 error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
23002 weak = false;
23003 }
23004 if (openacc)
23005 memory_order = OMP_MEMORY_ORDER_RELAXED;
23006 else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
23007 {
23008 omp_requires_mask
23009 = (enum omp_requires) (omp_requires_mask
23010 | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
23011 switch ((enum omp_memory_order)
23012 (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
23013 {
23014 case OMP_MEMORY_ORDER_UNSPECIFIED:
23015 case OMP_MEMORY_ORDER_RELAXED:
23016 memory_order = OMP_MEMORY_ORDER_RELAXED;
23017 break;
23018 case OMP_MEMORY_ORDER_SEQ_CST:
23019 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23020 break;
23021 case OMP_MEMORY_ORDER_ACQUIRE:
23022 if (code == NOP_EXPR) /* atomic write */
23023 {
23024 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23025 "%<acquire%> clause implicitly provided by a "
23026 "%<requires%> directive");
23027 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23028 }
23029 else
23030 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23031 break;
23032 case OMP_MEMORY_ORDER_RELEASE:
23033 if (code == OMP_ATOMIC_READ)
23034 {
23035 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23036 "%<release%> clause implicitly provided by a "
23037 "%<requires%> directive");
23038 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23039 }
23040 else
23041 memory_order = OMP_MEMORY_ORDER_RELEASE;
23042 break;
23043 case OMP_MEMORY_ORDER_ACQ_REL:
23044 switch (code)
23045 {
23046 case OMP_ATOMIC_READ:
23047 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23048 break;
23049 case NOP_EXPR: /* atomic write */
23050 memory_order = OMP_MEMORY_ORDER_RELEASE;
23051 break;
23052 default:
23053 memory_order = OMP_MEMORY_ORDER_ACQ_REL;
23054 break;
23055 }
23056 break;
23057 default:
23058 gcc_unreachable ();
23059 }
23060 }
23061 else
23062 switch (code)
23063 {
23064 case OMP_ATOMIC_READ:
23065 if (memory_order == OMP_MEMORY_ORDER_RELEASE)
23066 {
23067 error_at (loc, "%<#pragma omp atomic read%> incompatible with "
23068 "%<release%> clause");
23069 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23070 }
23071 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23072 memory_order = OMP_MEMORY_ORDER_ACQUIRE;
23073 break;
23074 case NOP_EXPR: /* atomic write */
23075 if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
23076 {
23077 error_at (loc, "%<#pragma omp atomic write%> incompatible with "
23078 "%<acquire%> clause");
23079 memory_order = OMP_MEMORY_ORDER_SEQ_CST;
23080 }
23081 else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
23082 memory_order = OMP_MEMORY_ORDER_RELEASE;
23083 break;
23084 default:
23085 break;
23086 }
23087 if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
23088 memory_order
23089 = (enum omp_memory_order) (memory_order
23090 | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
23091
23092 switch (code)
23093 {
23094 case OMP_ATOMIC_READ:
23095 case NOP_EXPR: /* atomic write */
23096 v = c_parser_cast_expression (parser, NULL).value;
23097 non_lvalue_p = !lvalue_p (v);
23098 v = c_fully_fold (v, false, NULL, true);
23099 if (v == error_mark_node)
23100 goto saw_error;
23101 if (non_lvalue_p)
23102 v = non_lvalue (v);
23103 loc = c_parser_peek_token (parser)->location;
23104 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23105 goto saw_error;
23106 if (code == NOP_EXPR)
23107 {
23108 eloc = c_parser_peek_token (parser)->location;
23109 expr = c_parser_expression (parser);
23110 expr = default_function_array_read_conversion (eloc, expr);
23111 /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
23112 opcode. */
23113 code = OMP_ATOMIC;
23114 lhs = v;
23115 v = NULL_TREE;
23116 rhs = c_fully_fold (expr.value, false, NULL);
23117 if (rhs == error_mark_node)
23118 goto saw_error;
23119 }
23120 else
23121 {
23122 lhs = c_parser_cast_expression (parser, NULL).value;
23123 non_lvalue_p = !lvalue_p (lhs);
23124 lhs = c_fully_fold (lhs, false, NULL, true);
23125 if (lhs == error_mark_node)
23126 goto saw_error;
23127 if (non_lvalue_p)
23128 lhs = non_lvalue (lhs);
23129 }
23130 goto done;
23131 case OMP_ATOMIC_CAPTURE_NEW:
23132 if (c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
23133 {
23134 c_parser_consume_token (parser);
23135 structured_block = true;
23136 }
23137 else if (compare
23138 && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23139 break;
23140 else
23141 {
23142 v = c_parser_cast_expression (parser, NULL).value;
23143 non_lvalue_p = !lvalue_p (v);
23144 v = c_fully_fold (v, false, NULL, true);
23145 if (v == error_mark_node)
23146 goto saw_error;
23147 if (non_lvalue_p)
23148 v = non_lvalue (v);
23149 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23150 goto saw_error;
23151 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23152 {
23153 eloc = c_parser_peek_token (parser)->location;
23154 error_at (eloc, "expected expression");
23155 goto saw_error;
23156 }
23157 }
23158 break;
23159 default:
23160 break;
23161 }
23162
23163 /* For structured_block case we don't know yet whether
23164 old or new x should be captured. */
23165restart:
23166 if (compare && c_parser_next_token_is_keyword (parser, keyword: RID_IF))
23167 {
23168 c_parser_consume_token (parser);
23169
23170 matching_parens parens;
23171 if (!parens.require_open (parser))
23172 goto saw_error;
23173 eloc = c_parser_peek_token (parser)->location;
23174 c_expr cmp_expr;
23175 if (r)
23176 {
23177 cmp_expr = c_parser_cast_expression (parser, NULL);
23178 cmp_expr = default_function_array_conversion (eloc, cmp_expr);
23179 }
23180 else
23181 cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
23182 parens.skip_until_found_close (parser);
23183 if (cmp_expr.value == error_mark_node)
23184 goto saw_error;
23185 if (r)
23186 {
23187 if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
23188 goto bad_if;
23189 cmp_expr.value = rhs1;
23190 rhs1 = NULL_TREE;
23191 gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
23192 }
23193 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23194 ;
23195 else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23196 {
23197 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23198 "expected %<==%> comparison in %<if%> condition");
23199 goto saw_error;
23200 }
23201 else if (TREE_CODE (cmp_expr.value) != GT_EXPR
23202 && TREE_CODE (cmp_expr.value) != LT_EXPR)
23203 {
23204 error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
23205 "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
23206 "condition");
23207 goto saw_error;
23208 }
23209 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
23210 goto saw_error;
23211
23212 extra_scope = true;
23213 eloc = c_parser_peek_token (parser)->location;
23214 expr = c_parser_cast_expression (parser, NULL);
23215 lhs = expr.value;
23216 expr = default_function_array_conversion (eloc, expr);
23217 unfolded_lhs = expr.value;
23218 lhs = c_fully_fold (lhs, false, NULL, true);
23219 orig_lhs = lhs;
23220 if (lhs == error_mark_node)
23221 goto saw_error;
23222 if (!lvalue_p (unfolded_lhs))
23223 lhs = non_lvalue (lhs);
23224 if (!c_parser_next_token_is (parser, type: CPP_EQ))
23225 {
23226 c_parser_error (parser, gmsgid: "expected %<=%>");
23227 goto saw_error;
23228 }
23229 c_parser_consume_token (parser);
23230 eloc = c_parser_peek_token (parser)->location;
23231 expr = c_parser_expr_no_commas (parser, NULL);
23232 rhs1 = expr.value;
23233
23234 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
23235 goto saw_error;
23236
23237 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
23238 goto saw_error;
23239
23240 extra_scope = false;
23241 no_semicolon = true;
23242
23243 if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
23244 {
23245 if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23246 {
23247 opcode = COND_EXPR;
23248 rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23249 false, NULL, true);
23250 rhs1 = c_fully_fold (rhs1, false, NULL, true);
23251 }
23252 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
23253 {
23254 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23255 ? MIN_EXPR : MAX_EXPR);
23256 rhs = c_fully_fold (rhs1, false, NULL, true);
23257 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
23258 false, NULL, true);
23259 }
23260 else
23261 goto bad_if;
23262 }
23263 else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
23264 goto bad_if;
23265 else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
23266 && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
23267 {
23268 opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
23269 ? MAX_EXPR : MIN_EXPR);
23270 rhs = c_fully_fold (rhs1, false, NULL, true);
23271 rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
23272 false, NULL, true);
23273 }
23274 else
23275 {
23276 bad_if:
23277 c_parser_error (parser,
23278 gmsgid: "invalid form of %<#pragma omp atomic compare%>");
23279 goto saw_error;
23280 }
23281
23282 if (c_parser_next_token_is_keyword (parser, keyword: RID_ELSE))
23283 {
23284 if (code != OMP_ATOMIC_CAPTURE_NEW
23285 || (structured_block && r == NULL_TREE)
23286 || TREE_CODE (cmp_expr.value) != EQ_EXPR)
23287 {
23288 eloc = c_parser_peek_token (parser)->location;
23289 error_at (eloc, "unexpected %<else%>");
23290 goto saw_error;
23291 }
23292
23293 c_parser_consume_token (parser);
23294
23295 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
23296 goto saw_error;
23297
23298 extra_scope = true;
23299 v = c_parser_cast_expression (parser, NULL).value;
23300 non_lvalue_p = !lvalue_p (v);
23301 v = c_fully_fold (v, false, NULL, true);
23302 if (v == error_mark_node)
23303 goto saw_error;
23304 if (non_lvalue_p)
23305 v = non_lvalue (v);
23306 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23307 goto saw_error;
23308
23309 expr = c_parser_expr_no_commas (parser, NULL);
23310
23311 if (!c_tree_equal (expr.value, unfolded_lhs))
23312 goto bad_if;
23313
23314 if (!c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
23315 goto saw_error;
23316
23317 if (!c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>"))
23318 goto saw_error;
23319
23320 extra_scope = false;
23321 code = OMP_ATOMIC_CAPTURE_OLD;
23322 if (r == NULL_TREE)
23323 /* Signal to c_finish_omp_atomic that in
23324 if (x == e) { x = d; } else { v = x; }
23325 case the store to v should be conditional. */
23326 r = void_list_node;
23327 }
23328 else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23329 {
23330 c_parser_require_keyword (parser, keyword: RID_ELSE, msgid: "expected %<else%>");
23331 goto saw_error;
23332 }
23333 else if (code == OMP_ATOMIC_CAPTURE_NEW
23334 && r != NULL_TREE
23335 && v == NULL_TREE)
23336 code = OMP_ATOMIC;
23337 goto stmt_done;
23338 }
23339 eloc = c_parser_peek_token (parser)->location;
23340 expr = c_parser_cast_expression (parser, NULL);
23341 lhs = expr.value;
23342 expr = default_function_array_conversion (eloc, expr);
23343 unfolded_lhs = expr.value;
23344 lhs = c_fully_fold (lhs, false, NULL, true);
23345 orig_lhs = lhs;
23346 switch (TREE_CODE (lhs))
23347 {
23348 invalid_compare:
23349 error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
23350 /* FALLTHRU */
23351 case ERROR_MARK:
23352 saw_error:
23353 c_parser_skip_to_end_of_block_or_statement (parser);
23354 if (extra_scope && c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
23355 c_parser_consume_token (parser);
23356 if (structured_block)
23357 {
23358 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
23359 c_parser_consume_token (parser);
23360 else if (code == OMP_ATOMIC_CAPTURE_NEW)
23361 {
23362 c_parser_skip_to_end_of_block_or_statement (parser);
23363 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
23364 c_parser_consume_token (parser);
23365 }
23366 }
23367 return;
23368
23369 case POSTINCREMENT_EXPR:
23370 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23371 code = OMP_ATOMIC_CAPTURE_OLD;
23372 /* FALLTHROUGH */
23373 case PREINCREMENT_EXPR:
23374 lhs = TREE_OPERAND (lhs, 0);
23375 unfolded_lhs = NULL_TREE;
23376 opcode = PLUS_EXPR;
23377 rhs = integer_one_node;
23378 if (compare)
23379 goto invalid_compare;
23380 break;
23381
23382 case POSTDECREMENT_EXPR:
23383 if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
23384 code = OMP_ATOMIC_CAPTURE_OLD;
23385 /* FALLTHROUGH */
23386 case PREDECREMENT_EXPR:
23387 lhs = TREE_OPERAND (lhs, 0);
23388 unfolded_lhs = NULL_TREE;
23389 opcode = MINUS_EXPR;
23390 rhs = integer_one_node;
23391 if (compare)
23392 goto invalid_compare;
23393 break;
23394
23395 case COMPOUND_EXPR:
23396 if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
23397 && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
23398 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
23399 && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
23400 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
23401 (TREE_OPERAND (lhs, 1), 0), 0))))
23402 /* Undo effects of boolean_increment for post {in,de}crement. */
23403 lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
23404 /* FALLTHRU */
23405 case MODIFY_EXPR:
23406 if (TREE_CODE (lhs) == MODIFY_EXPR
23407 && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
23408 {
23409 /* Undo effects of boolean_increment. */
23410 if (integer_onep (TREE_OPERAND (lhs, 1)))
23411 {
23412 /* This is pre or post increment. */
23413 rhs = TREE_OPERAND (lhs, 1);
23414 lhs = TREE_OPERAND (lhs, 0);
23415 unfolded_lhs = NULL_TREE;
23416 opcode = NOP_EXPR;
23417 if (code == OMP_ATOMIC_CAPTURE_NEW
23418 && !structured_block
23419 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23420 code = OMP_ATOMIC_CAPTURE_OLD;
23421 if (compare)
23422 goto invalid_compare;
23423 break;
23424 }
23425 if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
23426 && TREE_OPERAND (lhs, 0)
23427 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
23428 {
23429 /* This is pre or post decrement. */
23430 rhs = TREE_OPERAND (lhs, 1);
23431 lhs = TREE_OPERAND (lhs, 0);
23432 unfolded_lhs = NULL_TREE;
23433 opcode = NOP_EXPR;
23434 if (code == OMP_ATOMIC_CAPTURE_NEW
23435 && !structured_block
23436 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
23437 code = OMP_ATOMIC_CAPTURE_OLD;
23438 if (compare)
23439 goto invalid_compare;
23440 break;
23441 }
23442 }
23443 /* FALLTHRU */
23444 default:
23445 if (!lvalue_p (unfolded_lhs))
23446 lhs = non_lvalue (lhs);
23447 if (compare && !c_parser_next_token_is (parser, type: CPP_EQ))
23448 {
23449 c_parser_error (parser, gmsgid: "expected %<=%>");
23450 goto saw_error;
23451 }
23452 switch (c_parser_peek_token (parser)->type)
23453 {
23454 case CPP_MULT_EQ:
23455 opcode = MULT_EXPR;
23456 break;
23457 case CPP_DIV_EQ:
23458 opcode = TRUNC_DIV_EXPR;
23459 break;
23460 case CPP_PLUS_EQ:
23461 opcode = PLUS_EXPR;
23462 break;
23463 case CPP_MINUS_EQ:
23464 opcode = MINUS_EXPR;
23465 break;
23466 case CPP_LSHIFT_EQ:
23467 opcode = LSHIFT_EXPR;
23468 break;
23469 case CPP_RSHIFT_EQ:
23470 opcode = RSHIFT_EXPR;
23471 break;
23472 case CPP_AND_EQ:
23473 opcode = BIT_AND_EXPR;
23474 break;
23475 case CPP_OR_EQ:
23476 opcode = BIT_IOR_EXPR;
23477 break;
23478 case CPP_XOR_EQ:
23479 opcode = BIT_XOR_EXPR;
23480 break;
23481 case CPP_EQ:
23482 c_parser_consume_token (parser);
23483 eloc = c_parser_peek_token (parser)->location;
23484 expr = c_parser_expr_no_commas (parser, NULL, omp_atomic_lhs: unfolded_lhs);
23485 rhs1 = expr.value;
23486 switch (TREE_CODE (rhs1))
23487 {
23488 case MULT_EXPR:
23489 case TRUNC_DIV_EXPR:
23490 case RDIV_EXPR:
23491 case PLUS_EXPR:
23492 case MINUS_EXPR:
23493 case LSHIFT_EXPR:
23494 case RSHIFT_EXPR:
23495 case BIT_AND_EXPR:
23496 case BIT_IOR_EXPR:
23497 case BIT_XOR_EXPR:
23498 if (compare)
23499 break;
23500 if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
23501 {
23502 opcode = TREE_CODE (rhs1);
23503 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23504 true);
23505 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23506 true);
23507 goto stmt_done;
23508 }
23509 if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
23510 {
23511 opcode = TREE_CODE (rhs1);
23512 rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
23513 true);
23514 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23515 true);
23516 swapped = !commutative_tree_code (opcode);
23517 goto stmt_done;
23518 }
23519 break;
23520 case COND_EXPR:
23521 if (!compare)
23522 break;
23523 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
23524 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
23525 && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
23526 break;
23527 if (!TREE_OPERAND (rhs1, 1))
23528 break;
23529 if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
23530 break;
23531 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23532 unfolded_lhs))
23533 {
23534 if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23535 {
23536 opcode = COND_EXPR;
23537 rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23538 0), 1),
23539 false, NULL, true);
23540 rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
23541 NULL, true);
23542 goto stmt_done;
23543 }
23544 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23545 TREE_OPERAND (rhs1, 1)))
23546 {
23547 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23548 ? MIN_EXPR : MAX_EXPR);
23549 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23550 true);
23551 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23552 0), 0),
23553 false, NULL, true);
23554 goto stmt_done;
23555 }
23556 }
23557 else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
23558 break;
23559 else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
23560 unfolded_lhs))
23561 {
23562 if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
23563 TREE_OPERAND (rhs1, 1)))
23564 {
23565 opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
23566 ? MAX_EXPR : MIN_EXPR);
23567 rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
23568 true);
23569 rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
23570 0), 1),
23571 false, NULL, true);
23572 goto stmt_done;
23573 }
23574 }
23575 break;
23576 case EQ_EXPR:
23577 if (!compare
23578 || code != OMP_ATOMIC_CAPTURE_NEW
23579 || !structured_block
23580 || v
23581 || r)
23582 break;
23583 if (c_parser_next_token_is (parser, type: CPP_SEMICOLON)
23584 && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
23585 {
23586 r = lhs;
23587 lhs = NULL_TREE;
23588 c_parser_consume_token (parser);
23589 goto restart;
23590 }
23591 break;
23592 case ERROR_MARK:
23593 goto saw_error;
23594 default:
23595 break;
23596 }
23597 if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
23598 {
23599 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
23600 {
23601 code = OMP_ATOMIC_CAPTURE_OLD;
23602 v = lhs;
23603 lhs = NULL_TREE;
23604 expr = default_function_array_read_conversion (eloc, expr);
23605 unfolded_lhs1 = expr.value;
23606 lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
23607 rhs1 = NULL_TREE;
23608 c_parser_consume_token (parser);
23609 goto restart;
23610 }
23611 if (structured_block && !compare)
23612 {
23613 opcode = NOP_EXPR;
23614 expr = default_function_array_read_conversion (eloc, expr);
23615 rhs = c_fully_fold (expr.value, false, NULL, true);
23616 rhs1 = NULL_TREE;
23617 goto stmt_done;
23618 }
23619 }
23620 c_parser_error (parser, gmsgid: "invalid form of %<#pragma omp atomic%>");
23621 goto saw_error;
23622 default:
23623 c_parser_error (parser,
23624 gmsgid: "invalid operator for %<#pragma omp atomic%>");
23625 goto saw_error;
23626 }
23627
23628 /* Arrange to pass the location of the assignment operator to
23629 c_finish_omp_atomic. */
23630 loc = c_parser_peek_token (parser)->location;
23631 c_parser_consume_token (parser);
23632 eloc = c_parser_peek_token (parser)->location;
23633 expr = c_parser_expression (parser);
23634 expr = default_function_array_read_conversion (eloc, expr);
23635 rhs = expr.value;
23636 rhs = c_fully_fold (rhs, false, NULL, true);
23637 break;
23638 }
23639stmt_done:
23640 if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
23641 {
23642 if (!no_semicolon
23643 && !c_parser_require (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>"))
23644 goto saw_error;
23645 no_semicolon = false;
23646 v = c_parser_cast_expression (parser, NULL).value;
23647 non_lvalue_p = !lvalue_p (v);
23648 v = c_fully_fold (v, false, NULL, true);
23649 if (v == error_mark_node)
23650 goto saw_error;
23651 if (non_lvalue_p)
23652 v = non_lvalue (v);
23653 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
23654 goto saw_error;
23655 eloc = c_parser_peek_token (parser)->location;
23656 expr = c_parser_cast_expression (parser, NULL);
23657 lhs1 = expr.value;
23658 expr = default_function_array_read_conversion (eloc, expr);
23659 unfolded_lhs1 = expr.value;
23660 lhs1 = c_fully_fold (lhs1, false, NULL, true);
23661 if (lhs1 == error_mark_node)
23662 goto saw_error;
23663 if (!lvalue_p (unfolded_lhs1))
23664 lhs1 = non_lvalue (lhs1);
23665 }
23666 if (structured_block)
23667 {
23668 if (!no_semicolon)
23669 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
23670 c_parser_require (parser, type: CPP_CLOSE_BRACE, msgid: "expected %<}%>");
23671 }
23672done:
23673 if (weak && opcode != COND_EXPR)
23674 {
23675 error_at (loc, "%<weak%> clause requires atomic equality comparison");
23676 weak = false;
23677 }
23678 if (unfolded_lhs && unfolded_lhs1
23679 && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
23680 {
23681 error ("%<#pragma omp atomic capture%> uses two different "
23682 "expressions for memory");
23683 stmt = error_mark_node;
23684 }
23685 else
23686 stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
23687 swapped, memory_order, weak);
23688 if (stmt != error_mark_node)
23689 add_stmt (stmt);
23690
23691 if (!structured_block && !no_semicolon)
23692 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
23693}
23694
23695
23696/* OpenMP 2.5:
23697 # pragma omp barrier new-line
23698*/
23699
23700static void
23701c_parser_omp_barrier (c_parser *parser)
23702{
23703 location_t loc = c_parser_peek_token (parser)->location;
23704 c_parser_consume_pragma (parser);
23705 c_parser_skip_to_pragma_eol (parser);
23706
23707 c_finish_omp_barrier (loc);
23708}
23709
23710/* OpenMP 2.5:
23711 # pragma omp critical [(name)] new-line
23712 structured-block
23713
23714 OpenMP 4.5:
23715 # pragma omp critical [(name) [hint(expression)]] new-line
23716
23717 LOC is the location of the #pragma itself. */
23718
23719#define OMP_CRITICAL_CLAUSE_MASK \
23720 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
23721
23722static tree
23723c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
23724{
23725 tree stmt, name = NULL_TREE, clauses = NULL_TREE;
23726
23727 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
23728 {
23729 c_parser_consume_token (parser);
23730 if (c_parser_next_token_is (parser, type: CPP_NAME))
23731 {
23732 name = c_parser_peek_token (parser)->value;
23733 c_parser_consume_token (parser);
23734 c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>");
23735 }
23736 else
23737 c_parser_error (parser, gmsgid: "expected identifier");
23738
23739 if (c_parser_next_token_is (parser, type: CPP_COMMA)
23740 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23741 c_parser_consume_token (parser);
23742 }
23743 clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
23744 where: "#pragma omp critical");
23745 stmt = c_parser_omp_structured_block (parser, if_p);
23746 return c_finish_omp_critical (loc, stmt, name, clauses);
23747}
23748
23749/* OpenMP 5.0:
23750 # pragma omp depobj ( depobj ) depobj-clause new-line
23751
23752 depobj-clause:
23753 depend (dependence-type : locator)
23754 destroy
23755 update (dependence-type)
23756
23757 OpenMP 5.2 additionally:
23758 destroy ( depobj )
23759
23760 dependence-type:
23761 in
23762 out
23763 inout
23764 mutexinout */
23765
23766static void
23767c_parser_omp_depobj (c_parser *parser)
23768{
23769 location_t loc = c_parser_peek_token (parser)->location;
23770 c_parser_consume_pragma (parser);
23771 matching_parens parens;
23772 if (!parens.require_open (parser))
23773 {
23774 c_parser_skip_to_pragma_eol (parser);
23775 return;
23776 }
23777
23778 tree depobj = c_parser_expr_no_commas (parser, NULL).value;
23779 if (depobj != error_mark_node)
23780 {
23781 if (!lvalue_p (depobj))
23782 {
23783 error_at (EXPR_LOC_OR_LOC (depobj, loc),
23784 "%<depobj%> expression is not lvalue expression");
23785 depobj = error_mark_node;
23786 }
23787 else
23788 {
23789 tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
23790 depobj, false);
23791 if (addr == error_mark_node)
23792 depobj = error_mark_node;
23793 else
23794 depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
23795 addr, RO_UNARY_STAR);
23796 }
23797 }
23798
23799 parens.skip_until_found_close (parser);
23800 tree clause = NULL_TREE;
23801 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
23802 if (c_parser_next_token_is (parser, type: CPP_COMMA))
23803 c_parser_consume_token (parser);
23804 location_t c_loc = c_parser_peek_token (parser)->location;
23805 if (c_parser_next_token_is (parser, type: CPP_NAME))
23806 {
23807 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23808
23809 c_parser_consume_token (parser);
23810 if (!strcmp (s1: "depend", s2: p))
23811 {
23812 clause = c_parser_omp_clause_depend (parser, NULL_TREE);
23813 clause = c_finish_omp_clauses (clause, C_ORT_OMP);
23814 if (!clause)
23815 clause = error_mark_node;
23816 }
23817 else if (!strcmp (s1: "destroy", s2: p))
23818 {
23819 matching_parens c_parens;
23820 kind = OMP_CLAUSE_DEPEND_LAST;
23821 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN)
23822 && c_parens.require_open (parser))
23823 {
23824 tree destobj = c_parser_expr_no_commas (parser, NULL).value;
23825 if (!lvalue_p (destobj))
23826 error_at (EXPR_LOC_OR_LOC (destobj, c_loc),
23827 "%<destroy%> expression is not lvalue expression");
23828 else if (depobj != error_mark_node
23829 && !operand_equal_p (destobj, depobj,
23830 flags: OEP_MATCH_SIDE_EFFECTS
23831 | OEP_LEXICOGRAPHIC))
23832 warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp,
23833 "the %<destroy%> expression %qE should be the same "
23834 "as the %<depobj%> argument %qE", destobj, depobj);
23835 c_parens.skip_until_found_close (parser);
23836 }
23837 }
23838 else if (!strcmp (s1: "update", s2: p))
23839 {
23840 matching_parens c_parens;
23841 if (c_parens.require_open (parser))
23842 {
23843 location_t c2_loc = c_parser_peek_token (parser)->location;
23844 if (c_parser_next_token_is (parser, type: CPP_NAME))
23845 {
23846 const char *p2
23847 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23848
23849 c_parser_consume_token (parser);
23850 if (!strcmp (s1: "in", s2: p2))
23851 kind = OMP_CLAUSE_DEPEND_IN;
23852 else if (!strcmp (s1: "out", s2: p2))
23853 kind = OMP_CLAUSE_DEPEND_OUT;
23854 else if (!strcmp (s1: "inout", s2: p2))
23855 kind = OMP_CLAUSE_DEPEND_INOUT;
23856 else if (!strcmp (s1: "mutexinoutset", s2: p2))
23857 kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
23858 else if (!strcmp (s1: "inoutset", s2: p2))
23859 kind = OMP_CLAUSE_DEPEND_INOUTSET;
23860 }
23861 if (kind == OMP_CLAUSE_DEPEND_INVALID)
23862 {
23863 clause = error_mark_node;
23864 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
23865 "%<mutexinoutset%> or %<inoutset%>");
23866 }
23867 c_parens.skip_until_found_close (parser);
23868 }
23869 else
23870 clause = error_mark_node;
23871 }
23872 }
23873 if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
23874 {
23875 clause = error_mark_node;
23876 error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
23877 }
23878 c_parser_skip_to_pragma_eol (parser);
23879
23880 c_finish_omp_depobj (loc, depobj, kind, clause);
23881}
23882
23883
23884/* OpenMP 2.5:
23885 # pragma omp flush flush-vars[opt] new-line
23886
23887 flush-vars:
23888 ( variable-list )
23889
23890 OpenMP 5.0:
23891 # pragma omp flush memory-order-clause new-line */
23892
23893static void
23894c_parser_omp_flush (c_parser *parser)
23895{
23896 location_t loc = c_parser_peek_token (parser)->location;
23897 c_parser_consume_pragma (parser);
23898 enum memmodel mo = MEMMODEL_LAST;
23899 if (c_parser_next_token_is (parser, type: CPP_COMMA)
23900 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
23901 c_parser_consume_token (parser);
23902 if (c_parser_next_token_is (parser, type: CPP_NAME))
23903 {
23904 const char *p
23905 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
23906
23907 if (!strcmp (s1: p, s2: "seq_cst"))
23908 mo = MEMMODEL_SEQ_CST;
23909 else if (!strcmp (s1: p, s2: "acq_rel"))
23910 mo = MEMMODEL_ACQ_REL;
23911 else if (!strcmp (s1: p, s2: "release"))
23912 mo = MEMMODEL_RELEASE;
23913 else if (!strcmp (s1: p, s2: "acquire"))
23914 mo = MEMMODEL_ACQUIRE;
23915 else
23916 error_at (c_parser_peek_token (parser)->location,
23917 "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
23918 "%<acquire%>");
23919 c_parser_consume_token (parser);
23920 }
23921 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
23922 {
23923 if (mo != MEMMODEL_LAST)
23924 error_at (c_parser_peek_token (parser)->location,
23925 "%<flush%> list specified together with memory order "
23926 "clause");
23927 c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
23928 }
23929 else if (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
23930 c_parser_error (parser, gmsgid: "expected %<(%> or end of line");
23931 c_parser_skip_to_pragma_eol (parser);
23932
23933 c_finish_omp_flush (loc, mo);
23934}
23935
23936/* Return true if next tokens contain a standard attribute that contains
23937 omp::directive (DIRECTIVE). */
23938
23939static bool
23940c_parser_omp_section_scan (c_parser *parser, const char *directive,
23941 bool tentative)
23942{
23943 if (!c_parser_nth_token_starts_std_attributes (parser, n: 1))
23944 return false;
23945 unsigned int n = 3;
23946 if (!c_parser_check_balanced_raw_token_sequence (parser, n: &n))
23947 return false;
23948 c_token *token = c_parser_peek_nth_token_raw (parser, n);
23949 if (token->type != CPP_CLOSE_SQUARE)
23950 return false;
23951 token = c_parser_peek_nth_token_raw (parser, n: n + 1);
23952 if (token->type != CPP_CLOSE_SQUARE)
23953 return false;
23954 if (n < 9)
23955 return false;
23956 if (c_parser_peek_nth_token_raw (parser, n: 3)->type == CPP_NAME
23957 && c_parser_peek_nth_token_raw (parser, n: 4)->type == CPP_OPEN_PAREN
23958 && c_parser_peek_nth_token_raw (parser, n: 5)->type == CPP_NAME)
23959 {
23960 tree first = c_parser_peek_nth_token_raw (parser, n: 3)->value;
23961 tree second = c_parser_peek_nth_token_raw (parser, n: 5)->value;
23962 if (strcmp (IDENTIFIER_POINTER (first), s2: "directive")
23963 && strcmp (IDENTIFIER_POINTER (first), s2: "__directive__"))
23964 return false;
23965 if (strcmp (IDENTIFIER_POINTER (second), s2: directive))
23966 return false;
23967 }
23968 if (tentative)
23969 return true;
23970 location_t first_loc = c_parser_peek_token (parser)->location;
23971 location_t last_loc = c_parser_peek_nth_token_raw (parser, n: n + 1)->location;
23972 location_t middle_loc = UNKNOWN_LOCATION;
23973 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
23974 bool seen = false;
23975 int cnt = 0;
23976 for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
23977 if (is_attribute_namespace_p (attr_ns: "omp", attr)
23978 && is_attribute_p (attr_name: "directive", ident: get_attribute_name (attr)))
23979 {
23980 for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
23981 {
23982 tree d = TREE_VALUE (a);
23983 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
23984 c_token *first = C_TOKEN_VEC_TOKENS (d)->address ();
23985 cnt++;
23986 if (first->type == CPP_NAME
23987 && strcmp (IDENTIFIER_POINTER (first->value),
23988 s2: directive) == 0)
23989 {
23990 seen = true;
23991 if (middle_loc == UNKNOWN_LOCATION)
23992 middle_loc = first->location;
23993 }
23994 }
23995 }
23996 if (!seen)
23997 return false;
23998 if (cnt != 1 || TREE_CHAIN (std_attrs))
23999 {
24000 error_at (make_location (caret: first_loc, start: last_loc, finish: middle_loc),
24001 "%<[[omp::directive(%s)]]%> must be the only specified "
24002 "attribute on a statement", directive);
24003 return false;
24004 }
24005 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
24006 return true;
24007}
24008
24009/* Parse an OpenMP structured block sequence. KIND is the corresponding
24010 separating directive. */
24011
24012static tree
24013c_parser_omp_structured_block_sequence (c_parser *parser,
24014 enum pragma_kind kind)
24015{
24016 tree stmt = push_stmt_list ();
24017 c_parser_statement (parser, NULL);
24018 do
24019 {
24020 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24021 break;
24022 if (c_parser_next_token_is (parser, type: CPP_EOF))
24023 break;
24024
24025 if (kind != PRAGMA_NONE
24026 && c_parser_peek_token (parser)->pragma_kind == kind)
24027 break;
24028
24029 if (kind != PRAGMA_NONE
24030 && c_parser_omp_section_scan (parser,
24031 directive: kind == PRAGMA_OMP_SCAN
24032 ? "scan" : "section", tentative: false))
24033 break;
24034
24035 c_parser_statement (parser, NULL);
24036 }
24037 while (1);
24038 return pop_stmt_list (stmt);
24039}
24040
24041/* OpenMP 5.0:
24042
24043 scan-loop-body:
24044 { structured-block scan-directive structured-block } */
24045
24046static void
24047c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
24048{
24049 tree substmt;
24050 location_t loc;
24051 tree clauses = NULL_TREE;
24052 bool found_scan = false;
24053
24054 loc = c_parser_peek_token (parser)->location;
24055 if (!open_brace_parsed
24056 && !c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
24057 {
24058 /* Avoid skipping until the end of the block. */
24059 parser->error = false;
24060 return;
24061 }
24062
24063 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SCAN)
24064 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_OMP_SCAN);
24065 else
24066 {
24067 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
24068 "%<#pragma omp scan%> with zero preceding executable "
24069 "statements");
24070 substmt = build_empty_stmt (loc);
24071 }
24072 substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
24073 SET_EXPR_LOCATION (substmt, loc);
24074 add_stmt (substmt);
24075
24076 loc = c_parser_peek_token (parser)->location;
24077 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
24078 {
24079 enum omp_clause_code clause = OMP_CLAUSE_ERROR;
24080 found_scan = true;
24081
24082 c_parser_consume_pragma (parser);
24083
24084 if (c_parser_next_token_is (parser, type: CPP_COMMA))
24085 c_parser_consume_token (parser);
24086
24087 if (c_parser_next_token_is (parser, type: CPP_NAME))
24088 {
24089 const char *p
24090 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24091 if (strcmp (s1: p, s2: "inclusive") == 0)
24092 clause = OMP_CLAUSE_INCLUSIVE;
24093 else if (strcmp (s1: p, s2: "exclusive") == 0)
24094 clause = OMP_CLAUSE_EXCLUSIVE;
24095 }
24096 if (clause != OMP_CLAUSE_ERROR)
24097 {
24098 c_parser_consume_token (parser);
24099 clauses = c_parser_omp_var_list_parens (parser, kind: clause, NULL_TREE);
24100 }
24101 else
24102 c_parser_error (parser, gmsgid: "expected %<inclusive%> or "
24103 "%<exclusive%> clause");
24104 c_parser_skip_to_pragma_eol (parser);
24105 }
24106 else
24107 error ("expected %<#pragma omp scan%>");
24108
24109 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
24110 if (!c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
24111 substmt = c_parser_omp_structured_block_sequence (parser, kind: PRAGMA_NONE);
24112 else
24113 {
24114 if (found_scan)
24115 warning_at (loc, OPT_Wopenmp,
24116 "%<#pragma omp scan%> with zero succeeding executable "
24117 "statements");
24118 substmt = build_empty_stmt (loc);
24119 }
24120 substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
24121 SET_EXPR_LOCATION (substmt, loc);
24122 add_stmt (substmt);
24123
24124 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
24125 msgid: "expected %<}%>");
24126}
24127
24128
24129/* Check if the next tokens can start a canonical loop. Return true if yes,
24130 otherwise diagnose an error if ERROR_P is true, and return false. */
24131static bool
24132c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser,
24133 enum tree_code code,
24134 bool error_p)
24135{
24136 if (code == OACC_LOOP)
24137 {
24138 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
24139 return true;
24140 if (error_p)
24141 c_parser_error (parser, gmsgid: "for statement expected");
24142 }
24143 else
24144 {
24145 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
24146 return true;
24147
24148 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
24149 switch (c_parser_peek_token (parser)->pragma_kind)
24150 {
24151 case PRAGMA_OMP_UNROLL:
24152 case PRAGMA_OMP_TILE:
24153 return true;
24154 default:
24155 break;
24156 }
24157
24158 /* Skip standard attributes on next for in case they are
24159 [[omp::directive (unroll partial (4))]] or
24160 [[omp::directive (tile sizes (1, 2, 3))]] etc. */
24161 size_t n = c_parser_skip_std_attribute_spec_seq (parser, n: 1);
24162 c_token *token = c_parser_peek_nth_token_raw (parser, n);
24163 /* TOKEN is a raw token that hasn't been converted to a keyword yet,
24164 we have to do the lookup explicitly. */
24165 if (token->type == CPP_NAME
24166 && C_IS_RESERVED_WORD (token->value)
24167 && C_RID_CODE (token->value) == RID_FOR)
24168 return true;
24169 if (error_p)
24170 c_parser_error (parser, gmsgid: "loop nest expected");
24171 }
24172
24173 return false;
24174}
24175
24176static tree c_parser_omp_tile (location_t, c_parser *, bool *);
24177static tree c_parser_omp_unroll (location_t, c_parser *, bool *);
24178
24179/* This function parses a single level of a loop nest, invoking itself
24180 recursively if necessary.
24181
24182 loop-nest :: for (...) loop-body
24183 loop-body :: loop-nest
24184 | { [intervening-code] loop-body [intervening-code] }
24185 | final-loop-body
24186 intervening-code :: structured-block-sequence
24187 final-loop-body :: structured-block
24188
24189 For a collapsed loop nest, only a single OMP_FOR is built, pulling out
24190 all the iterator information from the inner loops into the
24191 parser->omp_for_parse_state structure.
24192
24193 The iterator decl, init, cond, and incr are stored in vectors.
24194
24195 Initialization code for iterator variables is collected into
24196 parser->omp_for_parse_state->pre_body and ends up inserted directly
24197 into the OMP_FOR structure. */
24198
24199static tree
24200c_parser_omp_loop_nest (c_parser *parser, bool *if_p)
24201{
24202 tree decl = NULL_TREE, cond = NULL_TREE, incr = NULL_TREE, init = NULL_TREE;
24203 tree body = NULL_TREE;
24204 matching_parens parens;
24205 bool moreloops;
24206 unsigned char save_in_statement;
24207 tree loop_scope;
24208 location_t loc;
24209 struct omp_for_parse_data *omp_for_parse_state
24210 = parser->omp_for_parse_state;
24211 gcc_assert (omp_for_parse_state);
24212 int depth = omp_for_parse_state->depth;
24213
24214 /* Arrange for C23 standard attribute syntax to be parsed as regular
24215 pragmas. */
24216 if (c_parser_nth_token_starts_std_attributes (parser, n: 1))
24217 {
24218 tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
24219 c_parser_handle_statement_omp_attributes (parser, attrs&: std_attrs, NULL);
24220 if (std_attrs)
24221 error_at (c_parser_peek_token (parser)->location,
24222 "attributes other than OpenMP directives "
24223 "are not allowed on %<for%> in loop nest");
24224 }
24225
24226 loc = c_parser_peek_token (parser)->location;
24227
24228 /* Handle loop transformations first. */
24229 if (c_parser_next_token_is (parser, type: CPP_PRAGMA))
24230 {
24231 tree transform = NULL_TREE, sizes, body = NULL_TREE;
24232 int count = 0;
24233 switch (c_parser_peek_token (parser)->pragma_kind)
24234 {
24235 case PRAGMA_OMP_UNROLL:
24236 c_parser_consume_pragma (parser);
24237 body = push_stmt_list ();
24238 transform = c_parser_omp_unroll (loc, parser, if_p);
24239 body = pop_stmt_list (body);
24240 if (transform == NULL_TREE || transform == error_mark_node)
24241 {
24242 transform = error_mark_node;
24243 break;
24244 }
24245 gcc_assert (TREE_CODE (transform) == OMP_UNROLL);
24246 if (omp_find_clause (OMP_FOR_CLAUSES (transform),
24247 kind: OMP_CLAUSE_PARTIAL))
24248 {
24249 if (omp_for_parse_state->count - depth > 1)
24250 {
24251 error_at (loc, "%<unroll%> construct with %<partial%> "
24252 "clause generates just one loop with "
24253 "canonical form but %d loops are needed",
24254 omp_for_parse_state->count - depth);
24255 transform = error_mark_node;
24256 }
24257 else
24258 count = 1;
24259 }
24260 else
24261 {
24262 error_at (loc, "generated loop of %<unroll%> construct "
24263 "without %<partial%> clause does not have "
24264 "canonical form");
24265 transform = error_mark_node;
24266 }
24267 break;
24268 case PRAGMA_OMP_TILE:
24269 c_parser_consume_pragma (parser);
24270 body = push_stmt_list ();
24271 transform = c_parser_omp_tile (loc, parser, if_p);
24272 body = pop_stmt_list (body);
24273 if (transform == NULL_TREE || transform == error_mark_node)
24274 {
24275 transform = error_mark_node;
24276 break;
24277 }
24278 gcc_assert (TREE_CODE (transform) == OMP_TILE);
24279 sizes = omp_find_clause (OMP_FOR_CLAUSES (transform),
24280 kind: OMP_CLAUSE_SIZES);
24281 gcc_assert (sizes);
24282 count = list_length (OMP_CLAUSE_SIZES_LIST (sizes));
24283 if (depth + count < omp_for_parse_state->count)
24284 {
24285 error_at (loc, "%<tile%> construct generates %d loops "
24286 "with canonical form but %d loops are needed",
24287 count, omp_for_parse_state->count - depth);
24288 transform = error_mark_node;
24289 }
24290 break;
24291 default:
24292 c_parser_pragma (parser, context: pragma_stmt, NULL, void_list_node);
24293 break;
24294 }
24295 if (transform == NULL_TREE)
24296 error_at (loc, "expected %<for%> loop or OpenMP loop "
24297 "transformation construct");
24298 if (transform == NULL_TREE || transform == error_mark_node)
24299 {
24300 omp_for_parse_state->fail = true;
24301 return NULL_TREE;
24302 }
24303 for (count = omp_for_parse_state->count; depth < count; ++depth)
24304 {
24305 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE;
24306 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE;
24307 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE;
24308 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE;
24309 }
24310 omp_for_parse_state->want_nested_loop = false;
24311 return body;
24312 }
24313
24314 /* We have already matched the FOR token but not consumed it yet. */
24315 gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
24316 c_parser_consume_token (parser);
24317
24318 /* Forbid break/continue in the loop initializer, condition, and
24319 increment expressions. */
24320 save_in_statement = in_statement;
24321 in_statement = IN_OMP_BLOCK;
24322
24323 /* We are not in intervening code now. */
24324 omp_for_parse_state->in_intervening_code = false;
24325
24326 if (!parens.require_open (parser))
24327 {
24328 omp_for_parse_state->fail = true;
24329 return NULL_TREE;
24330 }
24331
24332 /* An implicit scope block surrounds each level of FOR loop, for
24333 declarations of iteration variables at this loop depth. */
24334 loop_scope = c_begin_compound_stmt (true);
24335
24336 /* Parse the initialization declaration or expression. */
24337 if (c_parser_next_tokens_start_declaration (parser))
24338 {
24339 /* This is a declaration, which must be added to the pre_body code. */
24340 tree this_pre_body = push_stmt_list ();
24341 c_in_omp_for = true;
24342 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
24343 simple_ok: false);
24344 c_in_omp_for = false;
24345 this_pre_body = pop_stmt_list (this_pre_body);
24346 append_to_statement_list_force (this_pre_body,
24347 &(omp_for_parse_state->pre_body));
24348 decl = check_for_loop_decls (omp_for_parse_state->for_loc, flag_isoc99);
24349 if (decl == NULL)
24350 goto error_init;
24351 if (DECL_INITIAL (decl) == error_mark_node)
24352 decl = error_mark_node;
24353 init = decl;
24354 }
24355 else if (c_parser_next_token_is (parser, type: CPP_NAME)
24356 && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
24357 {
24358 struct c_expr decl_exp;
24359 struct c_expr init_exp;
24360 location_t init_loc;
24361
24362 decl_exp = c_parser_postfix_expression (parser);
24363 decl = decl_exp.value;
24364
24365 c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>");
24366
24367 init_loc = c_parser_peek_token (parser)->location;
24368 init_exp = c_parser_expr_no_commas (parser, NULL);
24369 init_exp = default_function_array_read_conversion (init_loc,
24370 init_exp);
24371 c_in_omp_for = true;
24372 init = build_modify_expr (init_loc, decl, decl_exp.original_type,
24373 NOP_EXPR, init_loc, init_exp.value,
24374 init_exp.original_type);
24375 c_in_omp_for = false;
24376 init = c_process_expr_stmt (init_loc, init);
24377
24378 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
24379 }
24380 else
24381 {
24382 error_init:
24383 c_parser_error (parser,
24384 gmsgid: "expected iteration declaration or initialization");
24385 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN,
24386 msgid: "expected %<)%>");
24387 omp_for_parse_state->fail = true;
24388 goto parse_next;
24389 }
24390
24391 /* Parse the loop condition. */
24392 if (c_parser_next_token_is_not (parser, type: CPP_SEMICOLON))
24393 {
24394 location_t cond_loc = c_parser_peek_token (parser)->location;
24395 c_in_omp_for = true;
24396 struct c_expr cond_expr
24397 = c_parser_binary_expression (parser, NULL, NULL_TREE);
24398 c_in_omp_for = false;
24399
24400 cond = cond_expr.value;
24401 cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
24402 switch (cond_expr.original_code)
24403 {
24404 case GT_EXPR:
24405 case GE_EXPR:
24406 case LT_EXPR:
24407 case LE_EXPR:
24408 break;
24409 case NE_EXPR:
24410 if (omp_for_parse_state->code != OACC_LOOP)
24411 break;
24412 /* FALLTHRU. */
24413 default:
24414 /* Can't be cond = error_mark_node, because we want to preserve
24415 the location until c_finish_omp_for. */
24416 cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
24417 break;
24418 }
24419 protected_set_expr_location (cond, cond_loc);
24420 }
24421 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
24422
24423 /* Parse the increment expression. */
24424 if (c_parser_next_token_is_not (parser, type: CPP_CLOSE_PAREN))
24425 {
24426 location_t incr_loc = c_parser_peek_token (parser)->location;
24427
24428 incr = c_process_expr_stmt (incr_loc,
24429 c_parser_expression (parser).value);
24430 }
24431 parens.skip_until_found_close (parser);
24432
24433 if (decl == NULL || decl == error_mark_node || init == error_mark_node)
24434 omp_for_parse_state->fail = true;
24435 else
24436 {
24437 TREE_VEC_ELT (omp_for_parse_state->declv, depth) = decl;
24438 TREE_VEC_ELT (omp_for_parse_state->initv, depth) = init;
24439 TREE_VEC_ELT (omp_for_parse_state->condv, depth) = cond;
24440 TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = incr;
24441 }
24442
24443parse_next:
24444 moreloops = depth < omp_for_parse_state->count - 1;
24445 omp_for_parse_state->want_nested_loop = moreloops;
24446 if (moreloops
24447 && c_parser_omp_next_tokens_can_be_canon_loop (parser,
24448 code: omp_for_parse_state->code,
24449 error_p: false))
24450 {
24451 omp_for_parse_state->depth++;
24452 body = c_parser_omp_loop_nest (parser, if_p);
24453 omp_for_parse_state->depth--;
24454 }
24455 else if (moreloops && c_parser_next_token_is (parser, type: CPP_OPEN_BRACE))
24456 {
24457 /* This is the open brace in the loop-body grammar production. Rather
24458 than trying to special-case braces, just parse it as a compound
24459 statement and handle the nested loop-body case there. Note that
24460 when we see a further open brace inside the compound statement
24461 loop-body, we don't know whether it is the start of intervening
24462 code that is a compound statement, or a level of braces
24463 surrounding a nested loop-body. Use the WANT_NESTED_LOOP state
24464 bit to ensure we have only one nested loop at each level. */
24465 omp_for_parse_state->in_intervening_code = true;
24466 body = c_parser_compound_statement (parser, NULL);
24467 omp_for_parse_state->in_intervening_code = false;
24468 if (omp_for_parse_state->want_nested_loop)
24469 {
24470 /* We have already parsed the whole loop body and not found a
24471 nested loop. */
24472 error_at (omp_for_parse_state->for_loc,
24473 "not enough nested loops");
24474 omp_for_parse_state->fail = true;
24475 }
24476 if_p = NULL;
24477 }
24478 else
24479 {
24480 /* This is the final-loop-body case in the grammar: we have
24481 something that is not a FOR and not an open brace. */
24482 if (moreloops)
24483 {
24484 /* If we were expecting a nested loop, give an error and mark
24485 that parsing has failed, and try to recover by parsing the
24486 body as regular code without further collapsing. */
24487 error_at (omp_for_parse_state->for_loc,
24488 "not enough nested loops");
24489 omp_for_parse_state->fail = true;
24490 }
24491 in_statement = IN_OMP_FOR;
24492 parser->omp_for_parse_state = NULL;
24493 body = push_stmt_list ();
24494 if (omp_for_parse_state->inscan)
24495 c_parser_omp_scan_loop_body (parser, open_brace_parsed: false);
24496 else
24497 add_stmt (c_parser_c99_block_statement (parser, if_p));
24498 body = pop_stmt_list (body);
24499 parser->omp_for_parse_state = omp_for_parse_state;
24500 }
24501 in_statement = save_in_statement;
24502 omp_for_parse_state->want_nested_loop = false;
24503 omp_for_parse_state->in_intervening_code = true;
24504
24505 /* Pop and return the implicit scope surrounding this level of loop.
24506 If the iteration variable at this depth was bound in the for loop,
24507 pull out and save the binding. Later in c_parser_omp_for_loop,
24508 these bindings will be moved to the scope surrounding the entire
24509 OMP_FOR. That keeps the gimplifier happy later on, and meanwhile
24510 we have already resolved all references to the iteration variable
24511 in its true scope. */
24512 if (body)
24513 add_stmt (body);
24514 body = c_end_compound_stmt (loc, loop_scope, true);
24515 if (decl && TREE_CODE (body) == BIND_EXPR)
24516 {
24517 tree t = BIND_EXPR_VARS (body);
24518 tree prev = NULL_TREE, next = NULL_TREE;
24519 while (t)
24520 {
24521 next = DECL_CHAIN (t);
24522 if (t == decl)
24523 {
24524 if (prev)
24525 DECL_CHAIN (prev) = next;
24526 else
24527 {
24528 BIND_EXPR_VARS (body) = next;
24529 BLOCK_VARS (BIND_EXPR_BLOCK (body)) = next;
24530 }
24531 DECL_CHAIN (t) = omp_for_parse_state->bindings;
24532 omp_for_parse_state->bindings = t;
24533 break;
24534 }
24535 else
24536 {
24537 prev = t;
24538 t = next;
24539 }
24540 }
24541 if (BIND_EXPR_VARS (body) == NULL_TREE)
24542 body = BIND_EXPR_BODY (body);
24543 }
24544
24545 return body;
24546}
24547
24548/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
24549 The real trick here is to determine the loop control variable early
24550 so that we can push a new decl if necessary to make it private.
24551 LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
24552 respectively. */
24553
24554static tree
24555c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
24556 tree clauses, tree *cclauses, bool *if_p)
24557{
24558 tree body, stmt, cl;
24559 tree ret = NULL_TREE;
24560 tree ordered_cl = NULL_TREE;
24561 int i, collapse = 1, ordered = 0, count;
24562 bool oacc_tiling = false;
24563 bool inscan = false;
24564 struct omp_for_parse_data data;
24565 struct omp_for_parse_data *save_data = parser->omp_for_parse_state;
24566
24567 for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
24568 if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
24569 collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
24570 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
24571 {
24572 oacc_tiling = true;
24573 collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
24574 }
24575 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES)
24576 collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl));
24577 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
24578 && OMP_CLAUSE_ORDERED_EXPR (cl))
24579 {
24580 ordered_cl = cl;
24581 ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
24582 }
24583 else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
24584 && OMP_CLAUSE_REDUCTION_INSCAN (cl)
24585 && (code == OMP_SIMD || code == OMP_FOR))
24586 inscan = true;
24587
24588 if (ordered && ordered < collapse)
24589 {
24590 error_at (OMP_CLAUSE_LOCATION (ordered_cl),
24591 "%<ordered%> clause parameter is less than %<collapse%>");
24592 OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
24593 = build_int_cst (NULL_TREE, collapse);
24594 ordered = collapse;
24595 }
24596
24597 gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0));
24598 count = ordered ? ordered : collapse;
24599
24600 if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, error_p: true))
24601 return NULL;
24602
24603 /* Initialize parse state for recursive descent. */
24604 data.declv = make_tree_vec (count);
24605 data.initv = make_tree_vec (count);
24606 data.condv = make_tree_vec (count);
24607 data.incrv = make_tree_vec (count);
24608 data.pre_body = NULL_TREE;
24609 data.bindings = NULL_TREE;
24610 data.for_loc = c_parser_peek_token (parser)->location;
24611 data.count = count;
24612 data.depth = 0;
24613 data.want_nested_loop = true;
24614 data.ordered = ordered > 0;
24615 data.in_intervening_code = false;
24616 data.perfect_nesting_fail = false;
24617 data.fail = false;
24618 data.inscan = inscan;
24619 data.saw_intervening_code = false;
24620 data.code = code;
24621 parser->omp_for_parse_state = &data;
24622
24623 body = c_parser_omp_loop_nest (parser, if_p);
24624
24625 /* Add saved bindings for iteration variables that were declared in
24626 the nested for loop to the scope surrounding the entire loop. */
24627 for (tree t = data.bindings; t; )
24628 {
24629 tree n = TREE_CHAIN (t);
24630 TREE_CHAIN (t) = NULL_TREE;
24631 pushdecl (t);
24632 t = n;
24633 }
24634
24635 /* Only bother calling c_finish_omp_for if we haven't already generated
24636 an error from the initialization parsing. */
24637 if (!data.fail)
24638 {
24639 c_in_omp_for = true;
24640 stmt = c_finish_omp_for (loc, code, data.declv, NULL, data.initv,
24641 data.condv, data.incrv,
24642 body, data.pre_body, true);
24643 c_in_omp_for = false;
24644
24645 /* Check for iterators appearing in lb, b or incr expressions. */
24646 if (stmt && !c_omp_check_loop_iv (stmt, data.declv, NULL))
24647 stmt = NULL_TREE;
24648
24649 /* Check for errors involving lb/ub/incr expressions referencing
24650 variables declared in intervening code. */
24651 if (data.saw_intervening_code
24652 && stmt
24653 && !c_omp_check_loop_binding_exprs (stmt, NULL))
24654 stmt = NULL_TREE;
24655
24656 if (stmt)
24657 {
24658 add_stmt (stmt);
24659
24660 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
24661 {
24662 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
24663 if (init == NULL_TREE)
24664 break;
24665 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
24666 tree decl = TREE_OPERAND (init, 0);
24667 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
24668 gcc_assert (COMPARISON_CLASS_P (cond));
24669 gcc_assert (TREE_OPERAND (cond, 0) == decl);
24670
24671 tree op0 = TREE_OPERAND (init, 1);
24672 if (!OMP_FOR_NON_RECTANGULAR (stmt)
24673 || TREE_CODE (op0) != TREE_VEC)
24674 TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
24675 else
24676 {
24677 TREE_VEC_ELT (op0, 1)
24678 = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
24679 TREE_VEC_ELT (op0, 2)
24680 = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
24681 }
24682
24683 tree op1 = TREE_OPERAND (cond, 1);
24684 if (!OMP_FOR_NON_RECTANGULAR (stmt)
24685 || TREE_CODE (op1) != TREE_VEC)
24686 TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
24687 else
24688 {
24689 TREE_VEC_ELT (op1, 1)
24690 = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
24691 TREE_VEC_ELT (op1, 2)
24692 = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
24693 }
24694 }
24695
24696 if (cclauses != NULL
24697 && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
24698 {
24699 tree *c;
24700 for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
24701 if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
24702 && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
24703 c = &OMP_CLAUSE_CHAIN (*c);
24704 else
24705 {
24706 for (i = 0; i < count; i++)
24707 if (TREE_VEC_ELT (data.declv, i) == OMP_CLAUSE_DECL (*c))
24708 break;
24709 if (i == count)
24710 c = &OMP_CLAUSE_CHAIN (*c);
24711 else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
24712 {
24713 error_at (loc,
24714 "iteration variable %qD should not be firstprivate",
24715 OMP_CLAUSE_DECL (*c));
24716 *c = OMP_CLAUSE_CHAIN (*c);
24717 }
24718 else
24719 {
24720 /* Move lastprivate (decl) clause to
24721 OMP_FOR_CLAUSES. */
24722 tree l = *c;
24723 *c = OMP_CLAUSE_CHAIN (*c);
24724 if (code == OMP_SIMD)
24725 {
24726 OMP_CLAUSE_CHAIN (l)
24727 = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24728 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
24729 }
24730 else
24731 {
24732 OMP_CLAUSE_CHAIN (l) = clauses;
24733 clauses = l;
24734 }
24735 }
24736 }
24737 }
24738 OMP_FOR_CLAUSES (stmt) = clauses;
24739 }
24740 ret = stmt;
24741 }
24742
24743 parser->omp_for_parse_state = save_data;
24744 return ret;
24745}
24746
24747/* Helper function for OpenMP parsing, split clauses and call
24748 finish_omp_clauses on each of the set of clauses afterwards. */
24749
24750static void
24751omp_split_clauses (location_t loc, enum tree_code code,
24752 omp_clause_mask mask, tree clauses, tree *cclauses)
24753{
24754 int i;
24755 c_omp_split_clauses (loc, code, mask, clauses, cclauses);
24756 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
24757 if (cclauses[i])
24758 cclauses[i] = c_finish_omp_clauses (cclauses[i],
24759 i == C_OMP_CLAUSE_SPLIT_TARGET
24760 ? C_ORT_OMP_TARGET : C_ORT_OMP);
24761}
24762
24763/* OpenMP 5.0:
24764 #pragma omp loop loop-clause[optseq] new-line
24765 for-loop
24766
24767 LOC is the location of the #pragma token.
24768*/
24769
24770#define OMP_LOOP_CLAUSE_MASK \
24771 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24772 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24773 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24774 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24775 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
24776 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24777
24778static tree
24779c_parser_omp_loop (location_t loc, c_parser *parser,
24780 char *p_name, omp_clause_mask mask, tree *cclauses,
24781 bool *if_p)
24782{
24783 tree block, clauses, ret;
24784
24785 strcat (dest: p_name, src: " loop");
24786 mask |= OMP_LOOP_CLAUSE_MASK;
24787
24788 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
24789 if (cclauses)
24790 {
24791 omp_split_clauses (loc, code: OMP_LOOP, mask, clauses, cclauses);
24792 clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
24793 }
24794
24795 block = c_begin_compound_stmt (true);
24796 ret = c_parser_omp_for_loop (loc, parser, code: OMP_LOOP, clauses, cclauses, if_p);
24797 block = c_end_compound_stmt (loc, block, true);
24798 add_stmt (block);
24799
24800 return ret;
24801}
24802
24803/* OpenMP 4.0:
24804 #pragma omp simd simd-clause[optseq] new-line
24805 for-loop
24806
24807 LOC is the location of the #pragma token.
24808*/
24809
24810#define OMP_SIMD_CLAUSE_MASK \
24811 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
24812 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
24813 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24814 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
24815 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24816 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24817 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24818 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24819 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
24820 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
24821 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24822
24823static tree
24824c_parser_omp_simd (location_t loc, c_parser *parser,
24825 char *p_name, omp_clause_mask mask, tree *cclauses,
24826 bool *if_p)
24827{
24828 tree block, clauses, ret;
24829
24830 strcat (dest: p_name, src: " simd");
24831 mask |= OMP_SIMD_CLAUSE_MASK;
24832
24833 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
24834 if (cclauses)
24835 {
24836 omp_split_clauses (loc, code: OMP_SIMD, mask, clauses, cclauses);
24837 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
24838 }
24839
24840 block = c_begin_compound_stmt (true);
24841 ret = c_parser_omp_for_loop (loc, parser, code: OMP_SIMD, clauses, cclauses, if_p);
24842 block = c_end_compound_stmt (loc, block, true);
24843 add_stmt (block);
24844
24845 return ret;
24846}
24847
24848/* OpenMP 2.5:
24849 #pragma omp for for-clause[optseq] new-line
24850 for-loop
24851
24852 OpenMP 4.0:
24853 #pragma omp for simd for-simd-clause[optseq] new-line
24854 for-loop
24855
24856 LOC is the location of the #pragma token.
24857*/
24858
24859#define OMP_FOR_CLAUSE_MASK \
24860 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
24861 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
24862 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
24863 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
24864 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
24865 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
24866 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
24867 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
24868 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
24869 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
24870 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
24871
24872static tree
24873c_parser_omp_for (location_t loc, c_parser *parser,
24874 char *p_name, omp_clause_mask mask, tree *cclauses,
24875 bool *if_p)
24876{
24877 tree block, clauses, ret;
24878
24879 strcat (dest: p_name, src: " for");
24880 mask |= OMP_FOR_CLAUSE_MASK;
24881 /* parallel for{, simd} disallows nowait clause, but for
24882 target {teams distribute ,}parallel for{, simd} it should be accepted. */
24883 if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
24884 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
24885 /* Composite distribute parallel for{, simd} disallows ordered clause. */
24886 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
24887 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
24888
24889 if (c_parser_next_token_is (parser, type: CPP_NAME))
24890 {
24891 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24892
24893 if (strcmp (s1: p, s2: "simd") == 0)
24894 {
24895 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
24896 if (cclauses == NULL)
24897 cclauses = cclauses_buf;
24898
24899 c_parser_consume_token (parser);
24900 if (!flag_openmp) /* flag_openmp_simd */
24901 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
24902 if_p);
24903 block = c_begin_compound_stmt (true);
24904 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
24905 block = c_end_compound_stmt (loc, block, true);
24906 if (ret == NULL_TREE)
24907 return ret;
24908 ret = make_node (OMP_FOR);
24909 TREE_TYPE (ret) = void_type_node;
24910 OMP_FOR_BODY (ret) = block;
24911 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24912 SET_EXPR_LOCATION (ret, loc);
24913 add_stmt (ret);
24914 return ret;
24915 }
24916 }
24917 if (!flag_openmp) /* flag_openmp_simd */
24918 {
24919 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24920 return NULL_TREE;
24921 }
24922
24923 /* Composite distribute parallel for disallows linear clause. */
24924 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
24925 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
24926
24927 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
24928 if (cclauses)
24929 {
24930 omp_split_clauses (loc, code: OMP_FOR, mask, clauses, cclauses);
24931 clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
24932 }
24933
24934 block = c_begin_compound_stmt (true);
24935 ret = c_parser_omp_for_loop (loc, parser, code: OMP_FOR, clauses, cclauses, if_p);
24936 block = c_end_compound_stmt (loc, block, true);
24937 add_stmt (block);
24938
24939 return ret;
24940}
24941
24942static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
24943 omp_clause_mask, tree *, bool *);
24944
24945/* OpenMP 2.5:
24946 # pragma omp master new-line
24947 structured-block
24948
24949 LOC is the location of the #pragma token.
24950*/
24951
24952static tree
24953c_parser_omp_master (location_t loc, c_parser *parser,
24954 char *p_name, omp_clause_mask mask, tree *cclauses,
24955 bool *if_p)
24956{
24957 tree block, clauses, ret;
24958
24959 strcat (dest: p_name, src: " master");
24960
24961 if (c_parser_next_token_is (parser, type: CPP_NAME))
24962 {
24963 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
24964
24965 if (strcmp (s1: p, s2: "taskloop") == 0)
24966 {
24967 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
24968 if (cclauses == NULL)
24969 cclauses = cclauses_buf;
24970
24971 c_parser_consume_token (parser);
24972 if (!flag_openmp) /* flag_openmp_simd */
24973 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
24974 if_p);
24975 block = c_begin_compound_stmt (true);
24976 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
24977 if_p);
24978 block = c_end_compound_stmt (loc, block, true);
24979 if (ret == NULL_TREE)
24980 return ret;
24981 ret = c_finish_omp_master (loc, block);
24982 OMP_MASTER_COMBINED (ret) = 1;
24983 return ret;
24984 }
24985 }
24986 if (!flag_openmp) /* flag_openmp_simd */
24987 {
24988 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
24989 return NULL_TREE;
24990 }
24991
24992 if (cclauses)
24993 {
24994 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: false);
24995 omp_split_clauses (loc, code: OMP_MASTER, mask, clauses, cclauses);
24996 }
24997 else
24998 c_parser_skip_to_pragma_eol (parser);
24999
25000 return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
25001 if_p));
25002}
25003
25004/* OpenMP 5.1:
25005 # pragma omp masked masked-clauses new-line
25006 structured-block
25007
25008 LOC is the location of the #pragma token.
25009*/
25010
25011#define OMP_MASKED_CLAUSE_MASK \
25012 (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
25013
25014static tree
25015c_parser_omp_masked (location_t loc, c_parser *parser,
25016 char *p_name, omp_clause_mask mask, tree *cclauses,
25017 bool *if_p)
25018{
25019 tree block, clauses, ret;
25020
25021 strcat (dest: p_name, src: " masked");
25022 mask |= OMP_MASKED_CLAUSE_MASK;
25023
25024 if (c_parser_next_token_is (parser, type: CPP_NAME))
25025 {
25026 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25027
25028 if (strcmp (s1: p, s2: "taskloop") == 0)
25029 {
25030 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25031 if (cclauses == NULL)
25032 cclauses = cclauses_buf;
25033
25034 c_parser_consume_token (parser);
25035 if (!flag_openmp) /* flag_openmp_simd */
25036 return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25037 if_p);
25038 block = c_begin_compound_stmt (true);
25039 ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
25040 if_p);
25041 block = c_end_compound_stmt (loc, block, true);
25042 if (ret == NULL_TREE)
25043 return ret;
25044 ret = c_finish_omp_masked (loc, block,
25045 cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
25046 OMP_MASKED_COMBINED (ret) = 1;
25047 return ret;
25048 }
25049 }
25050 if (!flag_openmp) /* flag_openmp_simd */
25051 {
25052 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25053 return NULL_TREE;
25054 }
25055
25056 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25057 if (cclauses)
25058 {
25059 omp_split_clauses (loc, code: OMP_MASKED, mask, clauses, cclauses);
25060 clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
25061 }
25062
25063 return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
25064 if_p),
25065 clauses);
25066}
25067
25068/* OpenMP 5.1:
25069 # pragma omp interop clauses[opt] new-line */
25070
25071#define OMP_INTEROP_CLAUSE_MASK \
25072 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25073 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DESTROY) \
25074 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25075 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INIT) \
25076 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
25077 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE))
25078
25079static void
25080c_parser_omp_interop (c_parser *parser)
25081{
25082 location_t loc = c_parser_peek_token (parser)->location;
25083 c_parser_consume_pragma (parser);
25084 tree clauses = c_parser_omp_all_clauses (parser,
25085 OMP_INTEROP_CLAUSE_MASK,
25086 where: "#pragma omp interop");
25087 tree stmt = make_node (OMP_INTEROP);
25088 TREE_TYPE (stmt) = void_type_node;
25089 OMP_INTEROP_CLAUSES (stmt) = clauses;
25090 SET_EXPR_LOCATION (stmt, loc);
25091 add_stmt (stmt);
25092}
25093
25094/* OpenMP 2.5:
25095 # pragma omp ordered new-line
25096 structured-block
25097
25098 OpenMP 4.5:
25099 # pragma omp ordered ordered-clauses new-line
25100 structured-block
25101
25102 # pragma omp ordered depend-clauses new-line
25103
25104 OpenMP 5.2
25105 # pragma omp ordered doacross-clauses new-line */
25106
25107#define OMP_ORDERED_CLAUSE_MASK \
25108 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
25109 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
25110
25111#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
25112 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25113 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
25114
25115static bool
25116c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
25117 bool *if_p)
25118{
25119 location_t loc = c_parser_peek_token (parser)->location;
25120 c_parser_consume_pragma (parser);
25121
25122 if (context != pragma_stmt && context != pragma_compound)
25123 {
25124 c_parser_error (parser, gmsgid: "expected declaration specifiers");
25125 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25126 return false;
25127 }
25128
25129 int n = 1;
25130 if (c_parser_next_token_is (parser, type: CPP_COMMA))
25131 n = 2;
25132
25133 if (c_parser_peek_nth_token (parser, n)->type == CPP_NAME)
25134 {
25135 const char *p
25136 = IDENTIFIER_POINTER (c_parser_peek_nth_token (parser, n)->value);
25137
25138 if (!strcmp (s1: "depend", s2: p) || !strcmp (s1: "doacross", s2: p))
25139 {
25140 if (!flag_openmp) /* flag_openmp_simd */
25141 {
25142 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25143 return false;
25144 }
25145 if (context == pragma_stmt)
25146 {
25147 error_at (loc,
25148 "%<#pragma omp ordered%> with %qs clause may "
25149 "only be used in compound statements", p);
25150 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25151 return true;
25152 }
25153
25154 tree clauses
25155 = c_parser_omp_all_clauses (parser,
25156 OMP_ORDERED_DEPEND_CLAUSE_MASK,
25157 where: "#pragma omp ordered");
25158 c_finish_omp_ordered (loc, clauses, NULL_TREE);
25159 return false;
25160 }
25161 }
25162
25163 tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
25164 where: "#pragma omp ordered");
25165
25166 if (!flag_openmp /* flag_openmp_simd */
25167 && omp_find_clause (clauses, kind: OMP_CLAUSE_SIMD) == NULL_TREE)
25168 return false;
25169
25170 c_finish_omp_ordered (loc, clauses,
25171 c_parser_omp_structured_block (parser, if_p));
25172 return true;
25173}
25174
25175/* OpenMP 2.5:
25176
25177 section-scope:
25178 { section-sequence }
25179
25180 section-sequence:
25181 section-directive[opt] structured-block
25182 section-sequence section-directive structured-block
25183
25184 OpenMP 5.1 allows structured-block-sequence instead of structured-block.
25185
25186 SECTIONS_LOC is the location of the #pragma omp sections. */
25187
25188static tree
25189c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
25190{
25191 tree stmt, substmt;
25192 bool error_suppress = false;
25193 location_t loc;
25194
25195 loc = c_parser_peek_token (parser)->location;
25196 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
25197 {
25198 /* Avoid skipping until the end of the block. */
25199 parser->error = false;
25200 return NULL_TREE;
25201 }
25202
25203 stmt = push_stmt_list ();
25204
25205 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION
25206 && !c_parser_omp_section_scan (parser, directive: "section", tentative: true))
25207 {
25208 substmt = c_parser_omp_structured_block_sequence (parser,
25209 kind: PRAGMA_OMP_SECTION);
25210 substmt = build1 (OMP_SECTION, void_type_node, substmt);
25211 SET_EXPR_LOCATION (substmt, loc);
25212 add_stmt (substmt);
25213 }
25214
25215 while (1)
25216 {
25217 if (c_parser_next_token_is (parser, type: CPP_CLOSE_BRACE))
25218 break;
25219 if (c_parser_next_token_is (parser, type: CPP_EOF))
25220 break;
25221
25222 loc = c_parser_peek_token (parser)->location;
25223 c_parser_omp_section_scan (parser, directive: "section", tentative: false);
25224 if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
25225 {
25226 c_parser_consume_pragma (parser);
25227 c_parser_skip_to_pragma_eol (parser);
25228 error_suppress = false;
25229 }
25230 else if (!error_suppress)
25231 {
25232 error_at (loc, "expected %<#pragma omp section%> or %<}%>");
25233 error_suppress = true;
25234 }
25235
25236 substmt = c_parser_omp_structured_block_sequence (parser,
25237 kind: PRAGMA_OMP_SECTION);
25238 substmt = build1 (OMP_SECTION, void_type_node, substmt);
25239 SET_EXPR_LOCATION (substmt, loc);
25240 add_stmt (substmt);
25241 }
25242 c_parser_skip_until_found (parser, type: CPP_CLOSE_BRACE,
25243 msgid: "expected %<#pragma omp section%> or %<}%>");
25244
25245 substmt = pop_stmt_list (stmt);
25246
25247 stmt = make_node (OMP_SECTIONS);
25248 SET_EXPR_LOCATION (stmt, sections_loc);
25249 TREE_TYPE (stmt) = void_type_node;
25250 OMP_SECTIONS_BODY (stmt) = substmt;
25251
25252 return add_stmt (stmt);
25253}
25254
25255/* OpenMP 2.5:
25256 # pragma omp sections sections-clause[optseq] newline
25257 sections-scope
25258
25259 LOC is the location of the #pragma token.
25260*/
25261
25262#define OMP_SECTIONS_CLAUSE_MASK \
25263 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25264 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25265 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25266 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25267 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25268 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25269
25270static tree
25271c_parser_omp_sections (location_t loc, c_parser *parser,
25272 char *p_name, omp_clause_mask mask, tree *cclauses)
25273{
25274 tree block, clauses, ret;
25275
25276 strcat (dest: p_name, src: " sections");
25277 mask |= OMP_SECTIONS_CLAUSE_MASK;
25278 if (cclauses)
25279 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
25280
25281 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25282 if (cclauses)
25283 {
25284 omp_split_clauses (loc, code: OMP_SECTIONS, mask, clauses, cclauses);
25285 clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
25286 }
25287
25288 block = c_begin_compound_stmt (true);
25289 ret = c_parser_omp_sections_scope (sections_loc: loc, parser);
25290 if (ret)
25291 OMP_SECTIONS_CLAUSES (ret) = clauses;
25292 block = c_end_compound_stmt (loc, block, true);
25293 add_stmt (block);
25294
25295 return ret;
25296}
25297
25298/* OpenMP 2.5:
25299 # pragma omp parallel parallel-clause[optseq] new-line
25300 structured-block
25301 # pragma omp parallel for parallel-for-clause[optseq] new-line
25302 structured-block
25303 # pragma omp parallel sections parallel-sections-clause[optseq] new-line
25304 structured-block
25305
25306 OpenMP 4.0:
25307 # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
25308 structured-block
25309
25310 LOC is the location of the #pragma token.
25311*/
25312
25313#define OMP_PARALLEL_CLAUSE_MASK \
25314 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25315 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25316 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25317 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25318 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25319 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
25320 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25321 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
25322 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25323 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
25324
25325static tree
25326c_parser_omp_parallel (location_t loc, c_parser *parser,
25327 char *p_name, omp_clause_mask mask, tree *cclauses,
25328 bool *if_p)
25329{
25330 tree stmt, clauses, block;
25331
25332 strcat (dest: p_name, src: " parallel");
25333 mask |= OMP_PARALLEL_CLAUSE_MASK;
25334 /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
25335 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
25336 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
25337 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
25338
25339 if (c_parser_next_token_is_keyword (parser, keyword: RID_FOR))
25340 {
25341 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25342 if (cclauses == NULL)
25343 cclauses = cclauses_buf;
25344
25345 c_parser_consume_token (parser);
25346 if (!flag_openmp) /* flag_openmp_simd */
25347 return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25348 block = c_begin_omp_parallel ();
25349 tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
25350 stmt
25351 = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25352 block);
25353 if (ret == NULL_TREE)
25354 return ret;
25355 OMP_PARALLEL_COMBINED (stmt) = 1;
25356 return stmt;
25357 }
25358 /* When combined with distribute, parallel has to be followed by for.
25359 #pragma omp target parallel is allowed though. */
25360 else if (cclauses
25361 && (mask & (OMP_CLAUSE_MASK_1
25362 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
25363 {
25364 error_at (loc, "expected %<for%> after %qs", p_name);
25365 c_parser_skip_to_pragma_eol (parser);
25366 return NULL_TREE;
25367 }
25368 else if (c_parser_next_token_is (parser, type: CPP_NAME))
25369 {
25370 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25371 if (cclauses == NULL && strcmp (s1: p, s2: "masked") == 0)
25372 {
25373 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25374 cclauses = cclauses_buf;
25375
25376 c_parser_consume_token (parser);
25377 if (!flag_openmp) /* flag_openmp_simd */
25378 return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25379 if_p);
25380 block = c_begin_omp_parallel ();
25381 tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
25382 if_p);
25383 stmt = c_finish_omp_parallel (loc,
25384 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25385 block);
25386 if (ret == NULL)
25387 return ret;
25388 /* masked does have just filter clause, but during gimplification
25389 isn't represented by a gimplification omp context, so for
25390 #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
25391 so that
25392 #pragma omp parallel masked
25393 #pragma omp taskloop simd lastprivate (x)
25394 isn't confused with
25395 #pragma omp parallel masked taskloop simd lastprivate (x) */
25396 if (OMP_MASKED_COMBINED (ret))
25397 OMP_PARALLEL_COMBINED (stmt) = 1;
25398 return stmt;
25399 }
25400 else if (cclauses == NULL && strcmp (s1: p, s2: "master") == 0)
25401 {
25402 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25403 cclauses = cclauses_buf;
25404
25405 c_parser_consume_token (parser);
25406 if (!flag_openmp) /* flag_openmp_simd */
25407 return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25408 if_p);
25409 block = c_begin_omp_parallel ();
25410 tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
25411 if_p);
25412 stmt = c_finish_omp_parallel (loc,
25413 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25414 block);
25415 if (ret == NULL)
25416 return ret;
25417 /* master doesn't have any clauses and during gimplification
25418 isn't represented by a gimplification omp context, so for
25419 #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
25420 so that
25421 #pragma omp parallel master
25422 #pragma omp taskloop simd lastprivate (x)
25423 isn't confused with
25424 #pragma omp parallel master taskloop simd lastprivate (x) */
25425 if (OMP_MASTER_COMBINED (ret))
25426 OMP_PARALLEL_COMBINED (stmt) = 1;
25427 return stmt;
25428 }
25429 else if (strcmp (s1: p, s2: "loop") == 0)
25430 {
25431 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25432 if (cclauses == NULL)
25433 cclauses = cclauses_buf;
25434
25435 c_parser_consume_token (parser);
25436 if (!flag_openmp) /* flag_openmp_simd */
25437 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25438 if_p);
25439 block = c_begin_omp_parallel ();
25440 tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
25441 if_p);
25442 stmt
25443 = c_finish_omp_parallel (loc,
25444 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25445 block);
25446 if (ret == NULL_TREE)
25447 return ret;
25448 OMP_PARALLEL_COMBINED (stmt) = 1;
25449 return stmt;
25450 }
25451 else if (!flag_openmp) /* flag_openmp_simd */
25452 {
25453 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25454 return NULL_TREE;
25455 }
25456 else if (cclauses == NULL && strcmp (s1: p, s2: "sections") == 0)
25457 {
25458 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25459 cclauses = cclauses_buf;
25460
25461 c_parser_consume_token (parser);
25462 block = c_begin_omp_parallel ();
25463 c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
25464 stmt = c_finish_omp_parallel (loc,
25465 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
25466 block);
25467 OMP_PARALLEL_COMBINED (stmt) = 1;
25468 return stmt;
25469 }
25470 }
25471 else if (!flag_openmp) /* flag_openmp_simd */
25472 {
25473 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25474 return NULL_TREE;
25475 }
25476
25477 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25478 if (cclauses)
25479 {
25480 omp_split_clauses (loc, code: OMP_PARALLEL, mask, clauses, cclauses);
25481 clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
25482 }
25483
25484 block = c_begin_omp_parallel ();
25485 parser->omp_attrs_forbidden_p = true;
25486 c_parser_statement (parser, if_p);
25487 stmt = c_finish_omp_parallel (loc, clauses, block);
25488
25489 return stmt;
25490}
25491
25492/* OpenMP 2.5:
25493 # pragma omp single single-clause[optseq] new-line
25494 structured-block
25495
25496 LOC is the location of the #pragma.
25497*/
25498
25499#define OMP_SINGLE_CLAUSE_MASK \
25500 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25501 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25502 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
25503 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25504 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25505
25506static tree
25507c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
25508{
25509 tree stmt = make_node (OMP_SINGLE);
25510 SET_EXPR_LOCATION (stmt, loc);
25511 TREE_TYPE (stmt) = void_type_node;
25512
25513 OMP_SINGLE_CLAUSES (stmt)
25514 = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
25515 where: "#pragma omp single");
25516 OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25517
25518 return add_stmt (stmt);
25519}
25520
25521/* OpenMP 5.1:
25522 # pragma omp scope scope-clause[optseq] new-line
25523 structured-block
25524
25525 LOC is the location of the #pragma.
25526*/
25527
25528#define OMP_SCOPE_CLAUSE_MASK \
25529 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25530 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25531 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25532 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25533 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25534
25535static tree
25536c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
25537{
25538 tree stmt = make_node (OMP_SCOPE);
25539 SET_EXPR_LOCATION (stmt, loc);
25540 TREE_TYPE (stmt) = void_type_node;
25541
25542 OMP_SCOPE_CLAUSES (stmt)
25543 = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
25544 where: "#pragma omp scope");
25545 OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
25546
25547 return add_stmt (stmt);
25548}
25549
25550/* Parse a function dispatch structured block:
25551
25552 lvalue-expression = target-call ( [expression-list] );
25553 or
25554 target-call ( [expression-list] );
25555
25556 Adapted from c_parser_expr_no_commas and c_parser_postfix_expression
25557 (CPP_NAME/C_ID_ID) for the function name.
25558*/
25559static tree
25560c_parser_omp_dispatch_body (c_parser *parser)
25561{
25562 struct c_expr lhs, rhs, ret;
25563 location_t expr_loc = c_parser_peek_token (parser)->location;
25564 source_range tok_range = c_parser_peek_token (parser)->get_range ();
25565
25566 lhs = c_parser_conditional_expression (parser, NULL, NULL);
25567 if (TREE_CODE (lhs.value) == CALL_EXPR)
25568 return lhs.value;
25569
25570 location_t op_location = c_parser_peek_token (parser)->location;
25571 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
25572 return error_mark_node;
25573
25574 /* Parse function name. */
25575 if (!c_parser_next_token_is (parser, type: CPP_NAME))
25576 {
25577 c_parser_error (parser, gmsgid: "expected a function name");
25578 return error_mark_node;
25579 }
25580 expr_loc = c_parser_peek_token (parser)->location;
25581 tree id = c_parser_peek_token (parser)->value;
25582 c_parser_consume_token (parser);
25583 if (!c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
25584 {
25585 c_parser_error (parser, gmsgid: "expected a function name");
25586 return error_mark_node;
25587 }
25588
25589 rhs.value = build_external_ref (expr_loc, id, true, &rhs.original_type);
25590 set_c_expr_source_range (expr: &rhs, src_range: tok_range);
25591
25592 /* Parse argument list. */
25593 rhs = c_parser_postfix_expression_after_primary (
25594 parser, EXPR_LOC_OR_LOC (rhs.value, expr_loc), expr: rhs);
25595 if (TREE_CODE (rhs.value) != CALL_EXPR)
25596 {
25597 error_at (EXPR_LOC_OR_LOC (rhs.value, expr_loc),
25598 "expected target-function call");
25599 return error_mark_node;
25600 }
25601
25602 /* Build assignment. */
25603 rhs = convert_lvalue_to_rvalue (expr_loc, rhs, true, true);
25604 ret.value
25605 = build_modify_expr (op_location, lhs.value, lhs.original_type, NOP_EXPR,
25606 expr_loc, rhs.value, rhs.original_type);
25607 ret.m_decimal = 0;
25608 set_c_expr_source_range (expr: &ret, start: lhs.get_start (), finish: rhs.get_finish ());
25609 ret.original_code = MODIFY_EXPR;
25610 ret.original_type = NULL;
25611 return ret.value;
25612}
25613
25614/* OpenMP 5.1:
25615 # pragma omp dispatch dispatch-clause[optseq] new-line
25616 expression-stmt
25617
25618 LOC is the location of the #pragma.
25619*/
25620
25621#define OMP_DISPATCH_CLAUSE_MASK \
25622 ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
25623 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25624 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
25625 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
25626 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
25627 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \
25628 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
25629 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25630
25631static tree
25632c_parser_omp_dispatch (location_t loc, c_parser *parser)
25633{
25634 tree stmt = make_node (OMP_DISPATCH);
25635 SET_EXPR_LOCATION (stmt, loc);
25636 TREE_TYPE (stmt) = void_type_node;
25637
25638 OMP_DISPATCH_CLAUSES (stmt)
25639 = c_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
25640 where: "#pragma omp dispatch");
25641
25642 // Extract depend clauses and create taskwait
25643 tree depend_clauses = NULL_TREE;
25644 tree *depend_clauses_ptr = &depend_clauses;
25645 for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
25646 {
25647 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
25648 {
25649 *depend_clauses_ptr = c;
25650 depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
25651 }
25652 }
25653 if (depend_clauses != NULL_TREE)
25654 {
25655 tree stmt = make_node (OMP_TASK);
25656 TREE_TYPE (stmt) = void_node;
25657 OMP_TASK_CLAUSES (stmt) = depend_clauses;
25658 OMP_TASK_BODY (stmt) = NULL_TREE;
25659 SET_EXPR_LOCATION (stmt, loc);
25660 add_stmt (stmt);
25661 }
25662
25663 // Parse body as expression statement
25664 loc = c_parser_peek_token (parser)->location;
25665 tree dispatch_body = c_parser_omp_dispatch_body (parser);
25666 if (dispatch_body == error_mark_node)
25667 {
25668 inform (loc, "%<#pragma omp dispatch%> must be followed by a function "
25669 "call with optional assignment");
25670 c_parser_skip_to_end_of_block_or_statement (parser);
25671 return NULL_TREE;
25672 }
25673
25674 // Walk the tree to find the dispatch function call and wrap it into an IFN
25675 gcc_assert (TREE_CODE (dispatch_body) == CALL_EXPR
25676 || TREE_CODE (dispatch_body) == MODIFY_EXPR);
25677 tree *dispatch_call = TREE_CODE (dispatch_body) == MODIFY_EXPR
25678 ? &TREE_OPERAND (dispatch_body, 1)
25679 : &dispatch_body;
25680 while (TREE_CODE (*dispatch_call) == FLOAT_EXPR
25681 || TREE_CODE (*dispatch_call) == CONVERT_EXPR
25682 || TREE_CODE (*dispatch_call) == NOP_EXPR)
25683 dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
25684 *dispatch_call = build_call_expr_internal_loc (
25685 loc, IFN_GOMP_DISPATCH,
25686 TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*dispatch_call))), 1, *dispatch_call);
25687
25688 c_parser_skip_until_found (parser, type: CPP_SEMICOLON, msgid: "expected %<;%>");
25689 OMP_DISPATCH_BODY (stmt) = dispatch_body;
25690
25691 return add_stmt (stmt);
25692}
25693
25694/* OpenMP 3.0:
25695 # pragma omp task task-clause[optseq] new-line
25696
25697 LOC is the location of the #pragma.
25698*/
25699
25700#define OMP_TASK_CLAUSE_MASK \
25701 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
25702 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
25703 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
25704 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25705 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25706 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25707 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
25708 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
25709 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25710 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
25711 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25712 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
25713 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
25714 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
25715
25716static tree
25717c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
25718{
25719 tree clauses, block;
25720
25721 clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
25722 where: "#pragma omp task");
25723
25724 block = c_begin_omp_task ();
25725 parser->omp_attrs_forbidden_p = true;
25726 c_parser_statement (parser, if_p);
25727 return c_finish_omp_task (loc, clauses, block);
25728}
25729
25730/* OpenMP 3.0:
25731 # pragma omp taskwait new-line
25732
25733 OpenMP 5.0:
25734 # pragma omp taskwait taskwait-clause[optseq] new-line
25735*/
25736
25737#define OMP_TASKWAIT_CLAUSE_MASK \
25738 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
25739 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
25740
25741static void
25742c_parser_omp_taskwait (c_parser *parser)
25743{
25744 location_t loc = c_parser_peek_token (parser)->location;
25745 c_parser_consume_pragma (parser);
25746
25747 tree clauses
25748 = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
25749 where: "#pragma omp taskwait");
25750
25751 if (clauses)
25752 {
25753 tree stmt = make_node (OMP_TASK);
25754 TREE_TYPE (stmt) = void_node;
25755 OMP_TASK_CLAUSES (stmt) = clauses;
25756 OMP_TASK_BODY (stmt) = NULL_TREE;
25757 SET_EXPR_LOCATION (stmt, loc);
25758 add_stmt (stmt);
25759 }
25760 else
25761 c_finish_omp_taskwait (loc);
25762}
25763
25764/* OpenMP 3.1:
25765 # pragma omp taskyield new-line
25766*/
25767
25768static void
25769c_parser_omp_taskyield (c_parser *parser)
25770{
25771 location_t loc = c_parser_peek_token (parser)->location;
25772 c_parser_consume_pragma (parser);
25773 c_parser_skip_to_pragma_eol (parser);
25774
25775 c_finish_omp_taskyield (loc);
25776}
25777
25778/* OpenMP 4.0:
25779 # pragma omp taskgroup new-line
25780
25781 OpenMP 5.0:
25782 # pragma omp taskgroup taskgroup-clause[optseq] new-line
25783*/
25784
25785#define OMP_TASKGROUP_CLAUSE_MASK \
25786 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25787 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
25788
25789static tree
25790c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
25791{
25792 tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
25793 where: "#pragma omp taskgroup");
25794
25795 tree body = c_parser_omp_structured_block (parser, if_p);
25796 return c_finish_omp_taskgroup (loc, body, clauses);
25797}
25798
25799/* OpenMP 4.0:
25800 # pragma omp cancel cancel-clause[optseq] new-line
25801
25802 LOC is the location of the #pragma.
25803*/
25804
25805#define OMP_CANCEL_CLAUSE_MASK \
25806 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25807 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25808 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25809 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
25810 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
25811
25812static void
25813c_parser_omp_cancel (c_parser *parser)
25814{
25815 location_t loc = c_parser_peek_token (parser)->location;
25816
25817 c_parser_consume_pragma (parser);
25818 tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
25819 where: "#pragma omp cancel");
25820
25821 c_finish_omp_cancel (loc, clauses);
25822}
25823
25824/* OpenMP 4.0:
25825 # pragma omp cancellation point cancelpt-clause[optseq] new-line
25826
25827 LOC is the location of the #pragma.
25828*/
25829
25830#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
25831 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
25832 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
25833 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
25834 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
25835
25836static bool
25837c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
25838{
25839 location_t loc = c_parser_peek_token (parser)->location;
25840 tree clauses;
25841 bool point_seen = false;
25842
25843 c_parser_consume_pragma (parser);
25844 if (c_parser_next_token_is (parser, type: CPP_NAME))
25845 {
25846 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25847 if (strcmp (s1: p, s2: "point") == 0)
25848 {
25849 c_parser_consume_token (parser);
25850 point_seen = true;
25851 }
25852 }
25853 if (!point_seen)
25854 {
25855 c_parser_error (parser, gmsgid: "expected %<point%>");
25856 c_parser_skip_to_pragma_eol (parser);
25857 return false;
25858 }
25859
25860 if (context != pragma_compound)
25861 {
25862 if (context == pragma_stmt)
25863 error_at (loc,
25864 "%<#pragma %s%> may only be used in compound statements",
25865 "omp cancellation point");
25866 else
25867 c_parser_error (parser, gmsgid: "expected declaration specifiers");
25868 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25869 return true;
25870 }
25871
25872 clauses
25873 = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
25874 where: "#pragma omp cancellation point");
25875
25876 c_finish_omp_cancellation_point (loc, clauses);
25877 return true;
25878}
25879
25880/* OpenMP 4.0:
25881 #pragma omp distribute distribute-clause[optseq] new-line
25882 for-loop */
25883
25884#define OMP_DISTRIBUTE_CLAUSE_MASK \
25885 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25886 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25887 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
25888 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
25889 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25890 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
25891 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
25892
25893static tree
25894c_parser_omp_distribute (location_t loc, c_parser *parser,
25895 char *p_name, omp_clause_mask mask, tree *cclauses,
25896 bool *if_p)
25897{
25898 tree clauses, block, ret;
25899
25900 strcat (dest: p_name, src: " distribute");
25901 mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
25902
25903 if (c_parser_next_token_is (parser, type: CPP_NAME))
25904 {
25905 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25906 bool simd = false;
25907 bool parallel = false;
25908
25909 if (strcmp (s1: p, s2: "simd") == 0)
25910 simd = true;
25911 else
25912 parallel = strcmp (s1: p, s2: "parallel") == 0;
25913 if (parallel || simd)
25914 {
25915 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25916 if (cclauses == NULL)
25917 cclauses = cclauses_buf;
25918 c_parser_consume_token (parser);
25919 if (!flag_openmp) /* flag_openmp_simd */
25920 {
25921 if (simd)
25922 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25923 if_p);
25924 else
25925 return c_parser_omp_parallel (loc, parser, p_name, mask,
25926 cclauses, if_p);
25927 }
25928 block = c_begin_compound_stmt (true);
25929 if (simd)
25930 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
25931 if_p);
25932 else
25933 ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
25934 if_p);
25935 block = c_end_compound_stmt (loc, block, true);
25936 if (ret == NULL)
25937 return ret;
25938 ret = make_node (OMP_DISTRIBUTE);
25939 TREE_TYPE (ret) = void_type_node;
25940 OMP_FOR_BODY (ret) = block;
25941 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
25942 SET_EXPR_LOCATION (ret, loc);
25943 add_stmt (ret);
25944 return ret;
25945 }
25946 }
25947 if (!flag_openmp) /* flag_openmp_simd */
25948 {
25949 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
25950 return NULL_TREE;
25951 }
25952
25953 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
25954 if (cclauses)
25955 {
25956 omp_split_clauses (loc, code: OMP_DISTRIBUTE, mask, clauses, cclauses);
25957 clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
25958 }
25959
25960 block = c_begin_compound_stmt (true);
25961 ret = c_parser_omp_for_loop (loc, parser, code: OMP_DISTRIBUTE, clauses, NULL,
25962 if_p);
25963 block = c_end_compound_stmt (loc, block, true);
25964 add_stmt (block);
25965
25966 return ret;
25967}
25968
25969/* OpenMP 4.0:
25970 # pragma omp teams teams-clause[optseq] new-line
25971 structured-block */
25972
25973#define OMP_TEAMS_CLAUSE_MASK \
25974 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
25975 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
25976 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
25977 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
25978 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
25979 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
25980 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
25981 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
25982
25983static tree
25984c_parser_omp_teams (location_t loc, c_parser *parser,
25985 char *p_name, omp_clause_mask mask, tree *cclauses,
25986 bool *if_p)
25987{
25988 tree clauses, block, ret;
25989
25990 strcat (dest: p_name, src: " teams");
25991 mask |= OMP_TEAMS_CLAUSE_MASK;
25992
25993 if (c_parser_next_token_is (parser, type: CPP_NAME))
25994 {
25995 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
25996 if (strcmp (s1: p, s2: "distribute") == 0)
25997 {
25998 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
25999 if (cclauses == NULL)
26000 cclauses = cclauses_buf;
26001
26002 c_parser_consume_token (parser);
26003 if (!flag_openmp) /* flag_openmp_simd */
26004 return c_parser_omp_distribute (loc, parser, p_name, mask,
26005 cclauses, if_p);
26006 block = c_begin_omp_parallel ();
26007 ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
26008 if_p);
26009 block = c_end_compound_stmt (loc, block, true);
26010 if (ret == NULL)
26011 return ret;
26012 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26013 ret = make_node (OMP_TEAMS);
26014 TREE_TYPE (ret) = void_type_node;
26015 OMP_TEAMS_CLAUSES (ret) = clauses;
26016 OMP_TEAMS_BODY (ret) = block;
26017 OMP_TEAMS_COMBINED (ret) = 1;
26018 SET_EXPR_LOCATION (ret, loc);
26019 return add_stmt (ret);
26020 }
26021 else if (strcmp (s1: p, s2: "loop") == 0)
26022 {
26023 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
26024 if (cclauses == NULL)
26025 cclauses = cclauses_buf;
26026
26027 c_parser_consume_token (parser);
26028 if (!flag_openmp) /* flag_openmp_simd */
26029 return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
26030 if_p);
26031 block = c_begin_omp_parallel ();
26032 ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
26033 block = c_end_compound_stmt (loc, block, true);
26034 if (ret == NULL)
26035 return ret;
26036 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26037 ret = make_node (OMP_TEAMS);
26038 TREE_TYPE (ret) = void_type_node;
26039 OMP_TEAMS_CLAUSES (ret) = clauses;
26040 OMP_TEAMS_BODY (ret) = block;
26041 OMP_TEAMS_COMBINED (ret) = 1;
26042 SET_EXPR_LOCATION (ret, loc);
26043 return add_stmt (ret);
26044 }
26045 }
26046 if (!flag_openmp) /* flag_openmp_simd */
26047 {
26048 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26049 return NULL_TREE;
26050 }
26051
26052 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
26053 if (cclauses)
26054 {
26055 omp_split_clauses (loc, code: OMP_TEAMS, mask, clauses, cclauses);
26056 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26057 }
26058
26059 tree stmt = make_node (OMP_TEAMS);
26060 TREE_TYPE (stmt) = void_type_node;
26061 OMP_TEAMS_CLAUSES (stmt) = clauses;
26062 block = c_begin_omp_parallel ();
26063 add_stmt (c_parser_omp_structured_block (parser, if_p));
26064 OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26065 SET_EXPR_LOCATION (stmt, loc);
26066
26067 return add_stmt (stmt);
26068}
26069
26070/* OpenMP 4.0:
26071 # pragma omp target data target-data-clause[optseq] new-line
26072 structured-block */
26073
26074#define OMP_TARGET_DATA_CLAUSE_MASK \
26075 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26076 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26077 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26078 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
26079 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
26080
26081static tree
26082c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
26083{
26084 if (flag_openmp)
26085 omp_requires_mask
26086 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26087
26088 tree clauses
26089 = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
26090 where: "#pragma omp target data");
26091 c_omp_adjust_map_clauses (clauses, false);
26092 int map_seen = 0;
26093 for (tree *pc = &clauses; *pc;)
26094 {
26095 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26096 switch (OMP_CLAUSE_MAP_KIND (*pc))
26097 {
26098 case GOMP_MAP_TO:
26099 case GOMP_MAP_ALWAYS_TO:
26100 case GOMP_MAP_PRESENT_TO:
26101 case GOMP_MAP_ALWAYS_PRESENT_TO:
26102 case GOMP_MAP_FROM:
26103 case GOMP_MAP_ALWAYS_FROM:
26104 case GOMP_MAP_PRESENT_FROM:
26105 case GOMP_MAP_ALWAYS_PRESENT_FROM:
26106 case GOMP_MAP_TOFROM:
26107 case GOMP_MAP_ALWAYS_TOFROM:
26108 case GOMP_MAP_PRESENT_TOFROM:
26109 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26110 case GOMP_MAP_ALLOC:
26111 case GOMP_MAP_PRESENT_ALLOC:
26112 map_seen = 3;
26113 break;
26114 case GOMP_MAP_FIRSTPRIVATE_POINTER:
26115 case GOMP_MAP_ALWAYS_POINTER:
26116 case GOMP_MAP_ATTACH_DETACH:
26117 case GOMP_MAP_ATTACH:
26118 break;
26119 default:
26120 map_seen |= 1;
26121 error_at (OMP_CLAUSE_LOCATION (*pc),
26122 "%<#pragma omp target data%> with map-type other "
26123 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26124 "on %<map%> clause");
26125 *pc = OMP_CLAUSE_CHAIN (*pc);
26126 continue;
26127 }
26128 else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
26129 || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
26130 map_seen = 3;
26131 pc = &OMP_CLAUSE_CHAIN (*pc);
26132 }
26133
26134 if (map_seen != 3)
26135 {
26136 if (map_seen == 0)
26137 error_at (loc,
26138 "%<#pragma omp target data%> must contain at least "
26139 "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
26140 "clause");
26141 return NULL_TREE;
26142 }
26143
26144 tree stmt = make_node (OMP_TARGET_DATA);
26145 TREE_TYPE (stmt) = void_type_node;
26146 OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
26147 keep_next_level ();
26148 tree block = c_begin_compound_stmt (true);
26149 add_stmt (c_parser_omp_structured_block (parser, if_p));
26150 OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26151
26152 SET_EXPR_LOCATION (stmt, loc);
26153 return add_stmt (stmt);
26154}
26155
26156/* OpenMP 4.0:
26157 # pragma omp target update target-update-clause[optseq] new-line */
26158
26159#define OMP_TARGET_UPDATE_CLAUSE_MASK \
26160 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
26161 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
26162 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26163 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26164 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26165 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26166
26167static bool
26168c_parser_omp_target_update (location_t loc, c_parser *parser,
26169 enum pragma_context context)
26170{
26171 if (context == pragma_stmt)
26172 {
26173 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26174 "omp target update");
26175 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26176 return true;
26177 }
26178
26179 tree clauses
26180 = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
26181 where: "#pragma omp target update");
26182 if (omp_find_clause (clauses, kind: OMP_CLAUSE_TO) == NULL_TREE
26183 && omp_find_clause (clauses, kind: OMP_CLAUSE_FROM) == NULL_TREE)
26184 {
26185 error_at (loc,
26186 "%<#pragma omp target update%> must contain at least one "
26187 "%<from%> or %<to%> clauses");
26188 return false;
26189 }
26190
26191 if (flag_openmp)
26192 omp_requires_mask
26193 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26194
26195 tree stmt = make_node (OMP_TARGET_UPDATE);
26196 TREE_TYPE (stmt) = void_type_node;
26197 OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
26198 SET_EXPR_LOCATION (stmt, loc);
26199 add_stmt (stmt);
26200 return false;
26201}
26202
26203/* OpenMP 4.5:
26204 # pragma omp target enter data target-data-clause[optseq] new-line */
26205
26206#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
26207 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26208 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26209 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26210 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26211 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26212
26213static bool
26214c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
26215 enum pragma_context context)
26216{
26217 bool data_seen = false;
26218 if (c_parser_next_token_is (parser, type: CPP_NAME))
26219 {
26220 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26221 if (strcmp (s1: p, s2: "data") == 0)
26222 {
26223 c_parser_consume_token (parser);
26224 data_seen = true;
26225 }
26226 }
26227 if (!data_seen)
26228 {
26229 c_parser_error (parser, gmsgid: "expected %<data%>");
26230 c_parser_skip_to_pragma_eol (parser);
26231 return false;
26232 }
26233
26234 if (context == pragma_stmt)
26235 {
26236 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26237 "omp target enter data");
26238 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26239 return true;
26240 }
26241
26242 if (flag_openmp)
26243 omp_requires_mask
26244 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26245
26246 tree clauses
26247 = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
26248 where: "#pragma omp target enter data");
26249 c_omp_adjust_map_clauses (clauses, false);
26250 int map_seen = 0;
26251 for (tree *pc = &clauses; *pc;)
26252 {
26253 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26254 switch (OMP_CLAUSE_MAP_KIND (*pc))
26255 {
26256 case GOMP_MAP_TO:
26257 case GOMP_MAP_ALWAYS_TO:
26258 case GOMP_MAP_PRESENT_TO:
26259 case GOMP_MAP_ALWAYS_PRESENT_TO:
26260 case GOMP_MAP_ALLOC:
26261 case GOMP_MAP_PRESENT_ALLOC:
26262 map_seen = 3;
26263 break;
26264 case GOMP_MAP_TOFROM:
26265 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_TO);
26266 map_seen = 3;
26267 break;
26268 case GOMP_MAP_ALWAYS_TOFROM:
26269 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_TO);
26270 map_seen = 3;
26271 break;
26272 case GOMP_MAP_PRESENT_TOFROM:
26273 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_TO);
26274 map_seen = 3;
26275 break;
26276 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26277 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_TO);
26278 map_seen = 3;
26279 break;
26280 case GOMP_MAP_FIRSTPRIVATE_POINTER:
26281 case GOMP_MAP_ALWAYS_POINTER:
26282 case GOMP_MAP_ATTACH_DETACH:
26283 case GOMP_MAP_ATTACH:
26284 break;
26285 default:
26286 map_seen |= 1;
26287 error_at (OMP_CLAUSE_LOCATION (*pc),
26288 "%<#pragma omp target enter data%> with map-type other "
26289 "than %<to%>, %<tofrom%> or %<alloc%> on %<map%> clause");
26290 *pc = OMP_CLAUSE_CHAIN (*pc);
26291 continue;
26292 }
26293 pc = &OMP_CLAUSE_CHAIN (*pc);
26294 }
26295
26296 if (map_seen != 3)
26297 {
26298 if (map_seen == 0)
26299 error_at (loc,
26300 "%<#pragma omp target enter data%> must contain at least "
26301 "one %<map%> clause");
26302 return true;
26303 }
26304
26305 tree stmt = make_node (OMP_TARGET_ENTER_DATA);
26306 TREE_TYPE (stmt) = void_type_node;
26307 OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
26308 SET_EXPR_LOCATION (stmt, loc);
26309 add_stmt (stmt);
26310 return true;
26311}
26312
26313/* OpenMP 4.5:
26314 # pragma omp target exit data target-data-clause[optseq] new-line */
26315
26316#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
26317 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26318 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26319 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26320 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26321 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
26322
26323static bool
26324c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
26325 enum pragma_context context)
26326{
26327 bool data_seen = false;
26328 if (c_parser_next_token_is (parser, type: CPP_NAME))
26329 {
26330 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26331 if (strcmp (s1: p, s2: "data") == 0)
26332 {
26333 c_parser_consume_token (parser);
26334 data_seen = true;
26335 }
26336 }
26337 if (!data_seen)
26338 {
26339 c_parser_error (parser, gmsgid: "expected %<data%>");
26340 c_parser_skip_to_pragma_eol (parser);
26341 return false;
26342 }
26343
26344 if (context == pragma_stmt)
26345 {
26346 error_at (loc, "%<#pragma %s%> may only be used in compound statements",
26347 "omp target exit data");
26348 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26349 return true;
26350 }
26351
26352 if (flag_openmp)
26353 omp_requires_mask
26354 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26355
26356 tree clauses
26357 = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
26358 where: "#pragma omp target exit data", finish_p: false);
26359 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_EXIT_DATA);
26360 c_omp_adjust_map_clauses (clauses, false);
26361 int map_seen = 0;
26362 for (tree *pc = &clauses; *pc;)
26363 {
26364 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26365 switch (OMP_CLAUSE_MAP_KIND (*pc))
26366 {
26367 case GOMP_MAP_FROM:
26368 case GOMP_MAP_ALWAYS_FROM:
26369 case GOMP_MAP_PRESENT_FROM:
26370 case GOMP_MAP_ALWAYS_PRESENT_FROM:
26371 case GOMP_MAP_RELEASE:
26372 case GOMP_MAP_DELETE:
26373 map_seen = 3;
26374 break;
26375 case GOMP_MAP_TOFROM:
26376 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_FROM);
26377 map_seen = 3;
26378 break;
26379 case GOMP_MAP_ALWAYS_TOFROM:
26380 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_FROM);
26381 map_seen = 3;
26382 break;
26383 case GOMP_MAP_PRESENT_TOFROM:
26384 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_PRESENT_FROM);
26385 map_seen = 3;
26386 break;
26387 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26388 OMP_CLAUSE_SET_MAP_KIND (*pc, GOMP_MAP_ALWAYS_PRESENT_FROM);
26389 map_seen = 3;
26390 break;
26391 case GOMP_MAP_FIRSTPRIVATE_POINTER:
26392 case GOMP_MAP_ALWAYS_POINTER:
26393 case GOMP_MAP_ATTACH_DETACH:
26394 case GOMP_MAP_DETACH:
26395 break;
26396 default:
26397 map_seen |= 1;
26398 error_at (OMP_CLAUSE_LOCATION (*pc),
26399 "%<#pragma omp target exit data%> with map-type other "
26400 "than %<from%>, %<tofrom%>, %<release%> or %<delete%> "
26401 "on %<map%> clause");
26402 *pc = OMP_CLAUSE_CHAIN (*pc);
26403 continue;
26404 }
26405 pc = &OMP_CLAUSE_CHAIN (*pc);
26406 }
26407
26408 if (map_seen != 3)
26409 {
26410 if (map_seen == 0)
26411 error_at (loc,
26412 "%<#pragma omp target exit data%> must contain at least one "
26413 "%<map%> clause");
26414 return true;
26415 }
26416
26417 tree stmt = make_node (OMP_TARGET_EXIT_DATA);
26418 TREE_TYPE (stmt) = void_type_node;
26419 OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
26420 SET_EXPR_LOCATION (stmt, loc);
26421 add_stmt (stmt);
26422 return true;
26423}
26424
26425/* OpenMP 4.0:
26426 # pragma omp target target-clause[optseq] new-line
26427 structured-block */
26428
26429#define OMP_TARGET_CLAUSE_MASK \
26430 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
26431 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
26432 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
26433 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
26434 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
26435 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
26436 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
26437 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
26438 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
26439 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
26440 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
26441 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
26442 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
26443
26444static bool
26445c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
26446{
26447 location_t loc = c_parser_peek_token (parser)->location;
26448 c_parser_consume_pragma (parser);
26449 tree *pc = NULL, stmt, block, body, clauses;
26450
26451 if (context != pragma_stmt && context != pragma_compound)
26452 {
26453 c_parser_error (parser, gmsgid: "expected declaration specifiers");
26454 c_parser_skip_to_pragma_eol (parser);
26455 return false;
26456 }
26457
26458 if (flag_openmp)
26459 omp_requires_mask
26460 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
26461
26462 if (c_parser_next_token_is (parser, type: CPP_NAME))
26463 {
26464 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
26465 enum tree_code ccode = ERROR_MARK;
26466
26467 if (strcmp (s1: p, s2: "teams") == 0)
26468 ccode = OMP_TEAMS;
26469 else if (strcmp (s1: p, s2: "parallel") == 0)
26470 ccode = OMP_PARALLEL;
26471 else if (strcmp (s1: p, s2: "simd") == 0)
26472 ccode = OMP_SIMD;
26473 if (ccode != ERROR_MARK)
26474 {
26475 tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
26476 char p_name[sizeof ("#pragma omp target teams distribute "
26477 "parallel for simd")];
26478
26479 c_parser_consume_token (parser);
26480 strcpy (dest: p_name, src: "#pragma omp target");
26481 if (!flag_openmp) /* flag_openmp_simd */
26482 {
26483 tree stmt;
26484 switch (ccode)
26485 {
26486 case OMP_TEAMS:
26487 stmt = c_parser_omp_teams (loc, parser, p_name,
26488 OMP_TARGET_CLAUSE_MASK,
26489 cclauses, if_p);
26490 break;
26491 case OMP_PARALLEL:
26492 stmt = c_parser_omp_parallel (loc, parser, p_name,
26493 OMP_TARGET_CLAUSE_MASK,
26494 cclauses, if_p);
26495 break;
26496 case OMP_SIMD:
26497 stmt = c_parser_omp_simd (loc, parser, p_name,
26498 OMP_TARGET_CLAUSE_MASK,
26499 cclauses, if_p);
26500 break;
26501 default:
26502 gcc_unreachable ();
26503 }
26504 return stmt != NULL_TREE;
26505 }
26506 keep_next_level ();
26507 tree block = c_begin_compound_stmt (true), ret;
26508 switch (ccode)
26509 {
26510 case OMP_TEAMS:
26511 ret = c_parser_omp_teams (loc, parser, p_name,
26512 OMP_TARGET_CLAUSE_MASK, cclauses,
26513 if_p);
26514 break;
26515 case OMP_PARALLEL:
26516 ret = c_parser_omp_parallel (loc, parser, p_name,
26517 OMP_TARGET_CLAUSE_MASK, cclauses,
26518 if_p);
26519 break;
26520 case OMP_SIMD:
26521 ret = c_parser_omp_simd (loc, parser, p_name,
26522 OMP_TARGET_CLAUSE_MASK, cclauses,
26523 if_p);
26524 break;
26525 default:
26526 gcc_unreachable ();
26527 }
26528 block = c_end_compound_stmt (loc, block, true);
26529 if (ret == NULL_TREE)
26530 return false;
26531 if (ccode == OMP_TEAMS)
26532 /* For combined target teams, ensure the num_teams and
26533 thread_limit clause expressions are evaluated on the host,
26534 before entering the target construct. */
26535 for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
26536 c; c = OMP_CLAUSE_CHAIN (c))
26537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
26538 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
26539 for (int i = 0;
26540 i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
26541 if (OMP_CLAUSE_OPERAND (c, i)
26542 && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
26543 {
26544 tree expr = OMP_CLAUSE_OPERAND (c, i);
26545 tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
26546 expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
26547 expr, NULL_TREE, NULL_TREE);
26548 add_stmt (expr);
26549 OMP_CLAUSE_OPERAND (c, i) = expr;
26550 tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
26551 OMP_CLAUSE_FIRSTPRIVATE);
26552 OMP_CLAUSE_DECL (tc) = tmp;
26553 OMP_CLAUSE_CHAIN (tc)
26554 = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26555 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
26556 }
26557 tree stmt = make_node (OMP_TARGET);
26558 TREE_TYPE (stmt) = void_type_node;
26559 OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
26560 c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
26561 OMP_TARGET_BODY (stmt) = block;
26562 OMP_TARGET_COMBINED (stmt) = 1;
26563 SET_EXPR_LOCATION (stmt, loc);
26564 add_stmt (stmt);
26565 pc = &OMP_TARGET_CLAUSES (stmt);
26566 goto check_clauses;
26567 }
26568 else if (!flag_openmp) /* flag_openmp_simd */
26569 {
26570 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26571 return false;
26572 }
26573 else if (strcmp (s1: p, s2: "data") == 0)
26574 {
26575 c_parser_consume_token (parser);
26576 c_parser_omp_target_data (loc, parser, if_p);
26577 return true;
26578 }
26579 else if (strcmp (s1: p, s2: "enter") == 0)
26580 {
26581 c_parser_consume_token (parser);
26582 return c_parser_omp_target_enter_data (loc, parser, context);
26583 }
26584 else if (strcmp (s1: p, s2: "exit") == 0)
26585 {
26586 c_parser_consume_token (parser);
26587 return c_parser_omp_target_exit_data (loc, parser, context);
26588 }
26589 else if (strcmp (s1: p, s2: "update") == 0)
26590 {
26591 c_parser_consume_token (parser);
26592 return c_parser_omp_target_update (loc, parser, context);
26593 }
26594 }
26595 if (!flag_openmp) /* flag_openmp_simd */
26596 {
26597 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
26598 return false;
26599 }
26600
26601 stmt = make_node (OMP_TARGET);
26602 TREE_TYPE (stmt) = void_type_node;
26603
26604 clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
26605 where: "#pragma omp target", finish_p: false);
26606 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
26607 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
26608 {
26609 tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
26610 OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
26611 OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
26612 OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
26613 OMP_CLAUSE_CHAIN (c) = nc;
26614 }
26615 clauses = c_omp_instantiate_mappers (clauses);
26616 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
26617 c_omp_adjust_map_clauses (clauses, true);
26618
26619 keep_next_level ();
26620 block = c_begin_compound_stmt (true);
26621 body = c_parser_omp_structured_block (parser, if_p);
26622
26623 c_omp_scan_mapper_bindings (loc, &clauses, body);
26624
26625 add_stmt (body);
26626 OMP_TARGET_CLAUSES (stmt) = clauses;
26627 pc = &OMP_TARGET_CLAUSES (stmt);
26628 OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
26629
26630 SET_EXPR_LOCATION (stmt, loc);
26631 add_stmt (stmt);
26632
26633check_clauses:
26634 while (*pc)
26635 {
26636 if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
26637 switch (OMP_CLAUSE_MAP_KIND (*pc))
26638 {
26639 case GOMP_MAP_TO:
26640 case GOMP_MAP_ALWAYS_TO:
26641 case GOMP_MAP_PRESENT_TO:
26642 case GOMP_MAP_ALWAYS_PRESENT_TO:
26643 case GOMP_MAP_FROM:
26644 case GOMP_MAP_ALWAYS_FROM:
26645 case GOMP_MAP_PRESENT_FROM:
26646 case GOMP_MAP_ALWAYS_PRESENT_FROM:
26647 case GOMP_MAP_TOFROM:
26648 case GOMP_MAP_ALWAYS_TOFROM:
26649 case GOMP_MAP_PRESENT_TOFROM:
26650 case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
26651 case GOMP_MAP_ALLOC:
26652 case GOMP_MAP_PRESENT_ALLOC:
26653 case GOMP_MAP_FIRSTPRIVATE_POINTER:
26654 case GOMP_MAP_ALWAYS_POINTER:
26655 case GOMP_MAP_POINTER:
26656 case GOMP_MAP_ATTACH_DETACH:
26657 case GOMP_MAP_ATTACH:
26658 break;
26659 default:
26660 error_at (OMP_CLAUSE_LOCATION (*pc),
26661 "%<#pragma omp target%> with map-type other "
26662 "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
26663 "on %<map%> clause");
26664 *pc = OMP_CLAUSE_CHAIN (*pc);
26665 continue;
26666 }
26667 pc = &OMP_CLAUSE_CHAIN (*pc);
26668 }
26669 cfun->has_omp_target = true;
26670 return true;
26671}
26672
26673/* OpenMP 4.0:
26674 # pragma omp declare simd declare-simd-clauses[optseq] new-line
26675
26676 OpenMP 5.0:
26677 # pragma omp declare variant (identifier) match(context-selector) new-line
26678
26679 OpenMP 5.1
26680 # pragma omp declare variant (identifier) match(context-selector) \
26681 adjust_args(adjust-op:argument-list) append_args(interop-list) new-line
26682 */
26683
26684#define OMP_DECLARE_SIMD_CLAUSE_MASK \
26685 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
26686 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
26687 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
26688 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
26689 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
26690 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
26691
26692static void
26693c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
26694{
26695 c_token *token = c_parser_peek_token (parser);
26696 gcc_assert (token->type == CPP_NAME);
26697 tree kind = token->value;
26698 gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
26699 || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
26700
26701 auto_vec<c_token> clauses;
26702 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
26703 {
26704 c_token *token = c_parser_peek_token (parser);
26705 if (token->type == CPP_EOF)
26706 {
26707 c_parser_skip_to_pragma_eol (parser);
26708 return;
26709 }
26710 clauses.safe_push (obj: *token);
26711 c_parser_consume_token (parser);
26712 }
26713 clauses.safe_push (obj: *c_parser_peek_token (parser));
26714 c_parser_skip_to_pragma_eol (parser);
26715
26716 while (c_parser_next_token_is (parser, type: CPP_PRAGMA))
26717 {
26718 if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
26719 || c_parser_peek_2nd_token (parser)->type != CPP_NAME
26720 || c_parser_peek_2nd_token (parser)->value != kind)
26721 {
26722 error ("%<#pragma omp declare %s%> must be followed by "
26723 "function declaration or definition or another "
26724 "%<#pragma omp declare %s%>",
26725 IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
26726 return;
26727 }
26728 c_parser_consume_pragma (parser);
26729 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
26730 {
26731 c_token *token = c_parser_peek_token (parser);
26732 if (token->type == CPP_EOF)
26733 {
26734 c_parser_skip_to_pragma_eol (parser);
26735 return;
26736 }
26737 clauses.safe_push (obj: *token);
26738 c_parser_consume_token (parser);
26739 }
26740 clauses.safe_push (obj: *c_parser_peek_token (parser));
26741 c_parser_skip_to_pragma_eol (parser);
26742 }
26743
26744 /* Make sure nothing tries to read past the end of the tokens. */
26745 c_token eof_token;
26746 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
26747 eof_token.type = CPP_EOF;
26748 clauses.safe_push (obj: eof_token);
26749 clauses.safe_push (obj: eof_token);
26750
26751 switch (context)
26752 {
26753 case pragma_external:
26754 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26755 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26756 {
26757 int ext = disable_extension_diagnostics ();
26758 do
26759 c_parser_consume_token (parser);
26760 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26761 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26762 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
26763 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses);
26764 restore_extension_diagnostics (flags: ext);
26765 }
26766 else
26767 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: false, start_attr_ok: true,
26768 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses);
26769 break;
26770 case pragma_struct:
26771 case pragma_param:
26772 case pragma_stmt:
26773 error ("%<#pragma omp declare %s%> must be followed by "
26774 "function declaration or definition",
26775 IDENTIFIER_POINTER (kind));
26776 break;
26777 case pragma_compound:
26778 bool have_std_attrs;
26779 tree std_attrs;
26780 have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, n: 1);
26781 if (have_std_attrs)
26782 std_attrs = c_parser_std_attribute_specifier_sequence (parser);
26783 else
26784 std_attrs = NULL_TREE;
26785 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26786 && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
26787 {
26788 int ext = disable_extension_diagnostics ();
26789 do
26790 c_parser_consume_token (parser);
26791 while (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26792 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
26793 if (c_parser_next_tokens_start_declaration (parser)
26794 || c_parser_nth_token_starts_std_attributes (parser, n: 1))
26795 {
26796 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true,
26797 start_attr_ok: true, simple_ok: false, NULL, omp_declare_simd_clauses: &clauses,
26798 have_attrs: have_std_attrs, attrs: std_attrs);
26799 restore_extension_diagnostics (flags: ext);
26800 break;
26801 }
26802 restore_extension_diagnostics (flags: ext);
26803 }
26804 else if (c_parser_next_tokens_start_declaration (parser))
26805 {
26806 c_parser_declaration_or_fndef (parser, fndef_ok: true, static_assert_ok: true, empty_ok: true, nested: true, start_attr_ok: true,
26807 simple_ok: false, NULL, omp_declare_simd_clauses: &clauses, have_attrs: have_std_attrs,
26808 attrs: std_attrs);
26809 break;
26810 }
26811 error ("%<#pragma omp declare %s%> must be followed by "
26812 "function declaration or definition",
26813 IDENTIFIER_POINTER (kind));
26814 break;
26815 default:
26816 gcc_unreachable ();
26817 }
26818}
26819
26820/* OpenMP 5.0:
26821
26822 trait-selector:
26823 trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
26824
26825 trait-score:
26826 score(score-expression)
26827
26828 Note that this function returns a list of trait selectors for the
26829 trait-selector-set SET. */
26830
26831static tree
26832c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
26833 tree parms)
26834{
26835 tree ret = NULL_TREE;
26836 do
26837 {
26838 tree selector;
26839 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26840 || c_parser_next_token_is (parser, type: CPP_NAME))
26841 selector = c_parser_peek_token (parser)->value;
26842 else
26843 {
26844 c_parser_error (parser, gmsgid: "expected trait selector name");
26845 return error_mark_node;
26846 }
26847 enum omp_ts_code sel
26848 = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
26849
26850 if (sel == OMP_TRAIT_INVALID)
26851 {
26852 /* Per the spec, "Implementations can ignore specified selectors
26853 that are not those described in this section"; however, we
26854 must record such selectors because they cause match failures. */
26855 warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
26856 "unknown selector %qs for context selector set %qs",
26857 IDENTIFIER_POINTER (selector), omp_tss_map[set]);
26858 c_parser_consume_token (parser);
26859 ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
26860 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
26861 c_parser_balanced_token_sequence (parser);
26862 if (c_parser_next_token_is (parser, type: CPP_COMMA))
26863 {
26864 c_parser_consume_token (parser);
26865 continue;
26866 }
26867 else
26868 break;
26869 }
26870
26871 c_parser_consume_token (parser);
26872
26873 tree properties = NULL_TREE;
26874 tree scoreval = NULL_TREE;
26875 enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
26876 bool allow_score = omp_ts_map[sel].allow_score;
26877 tree t;
26878
26879 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
26880 {
26881 if (property_kind == OMP_TRAIT_PROPERTY_NONE)
26882 {
26883 error_at (c_parser_peek_token (parser)->location,
26884 "selector %qs does not accept any properties",
26885 IDENTIFIER_POINTER (selector));
26886 return error_mark_node;
26887 }
26888
26889 matching_parens parens;
26890 parens.require_open (parser);
26891
26892 c_token *token = c_parser_peek_token (parser);
26893 if (c_parser_next_token_is (parser, type: CPP_NAME)
26894 && strcmp (IDENTIFIER_POINTER (token->value), s2: "score") == 0
26895 && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
26896 {
26897 c_parser_consume_token (parser);
26898
26899 matching_parens parens2;
26900 parens2.require_open (parser);
26901 tree score = c_parser_expr_no_commas (parser, NULL).value;
26902 parens2.skip_until_found_close (parser);
26903 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
26904 if (!allow_score)
26905 error_at (token->location,
26906 "%<score%> cannot be specified in traits "
26907 "in the %qs trait-selector-set",
26908 omp_tss_map[set]);
26909 else if (score != error_mark_node)
26910 {
26911 mark_exp_read (score);
26912 score = c_fully_fold (score, false, NULL);
26913 if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
26914 || TREE_CODE (score) != INTEGER_CST)
26915 error_at (token->location, "%<score%> argument must "
26916 "be constant integer expression");
26917 else if (tree_int_cst_sgn (score) < 0)
26918 error_at (token->location, "%<score%> argument must "
26919 "be non-negative");
26920 else
26921 scoreval = score;
26922 }
26923 token = c_parser_peek_token (parser);
26924 }
26925
26926 switch (property_kind)
26927 {
26928 case OMP_TRAIT_PROPERTY_ID:
26929 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26930 || c_parser_next_token_is (parser, type: CPP_NAME))
26931 {
26932 tree prop = c_parser_peek_token (parser)->value;
26933 c_parser_consume_token (parser);
26934 properties = make_trait_property (prop, NULL_TREE,
26935 properties);
26936 }
26937 else
26938 {
26939 c_parser_error (parser, gmsgid: "expected identifier");
26940 return error_mark_node;
26941 }
26942 break;
26943 case OMP_TRAIT_PROPERTY_NAME_LIST:
26944 do
26945 {
26946 tree prop = OMP_TP_NAMELIST_NODE;
26947 tree value = NULL_TREE;
26948 if (c_parser_next_token_is (parser, type: CPP_KEYWORD)
26949 || c_parser_next_token_is (parser, type: CPP_NAME))
26950 {
26951 value = c_parser_peek_token (parser)->value;
26952 c_parser_consume_token (parser);
26953 }
26954 else if (c_parser_next_token_is (parser, type: CPP_STRING))
26955 value = c_parser_string_literal (parser, translate: false,
26956 wide_ok: false).value;
26957 else
26958 {
26959 c_parser_error (parser, gmsgid: "expected identifier or "
26960 "string literal");
26961 return error_mark_node;
26962 }
26963
26964 properties = make_trait_property (prop, value, properties);
26965
26966 if (c_parser_next_token_is (parser, type: CPP_COMMA))
26967 c_parser_consume_token (parser);
26968 else
26969 break;
26970 }
26971 while (1);
26972 break;
26973 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
26974 case OMP_TRAIT_PROPERTY_BOOL_EXPR:
26975 {
26976 c_expr texpr = c_parser_expr_no_commas (parser, NULL);
26977 texpr = convert_lvalue_to_rvalue (token->location, texpr,
26978 true, true);
26979 t = texpr.value;
26980 }
26981 if (t == error_mark_node)
26982 return error_mark_node;
26983 mark_exp_read (t);
26984 if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
26985 {
26986 t = c_objc_common_truthvalue_conversion (token->location,
26987 t,
26988 boolean_type_node);
26989 if (t == error_mark_node)
26990 return error_mark_node;
26991 }
26992 else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
26993 {
26994 error_at (token->location,
26995 "property must be integer expression");
26996 return error_mark_node;
26997 }
26998 t = c_fully_fold (t, false, NULL);
26999 properties = make_trait_property (NULL_TREE, t, properties);
27000 break;
27001 case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
27002 if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
27003 {
27004 if (parms == NULL_TREE)
27005 {
27006 error_at (token->location, "properties for %<simd%> "
27007 "selector may not be specified in "
27008 "%<metadirective%>");
27009 return error_mark_node;
27010 }
27011 tree c;
27012 c = c_parser_omp_all_clauses (parser,
27013 OMP_DECLARE_SIMD_CLAUSE_MASK,
27014 where: "simd", finish_p: true, nested: 2);
27015 c = c_omp_declare_simd_clauses_to_numbers (parms
27016 == error_mark_node
27017 ? NULL_TREE : parms,
27018 c);
27019 properties = c;
27020 }
27021 else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
27022 {
27023 /* FIXME: The "requires" selector was added in OpenMP 5.1.
27024 Currently only the now-deprecated syntax
27025 from OpenMP 5.0 is supported. */
27026 sorry_at (token->location,
27027 "%<requires%> selector is not supported yet");
27028 return error_mark_node;
27029 }
27030 else
27031 gcc_unreachable ();
27032 break;
27033 default:
27034 gcc_unreachable ();
27035 }
27036
27037 parens.skip_until_found_close (parser);
27038 properties = nreverse (properties);
27039 }
27040 else if (property_kind != OMP_TRAIT_PROPERTY_NONE
27041 && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
27042 && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
27043 {
27044 c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>");
27045 return error_mark_node;
27046 }
27047
27048 ret = make_trait_selector (sel, scoreval, properties, ret);
27049
27050 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27051 c_parser_consume_token (parser);
27052 else
27053 break;
27054 }
27055 while (1);
27056
27057 return nreverse (ret);
27058}
27059
27060/* OpenMP 5.0:
27061
27062 trait-set-selector[,trait-set-selector[,...]]
27063
27064 trait-set-selector:
27065 trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
27066
27067 trait-set-selector-name:
27068 constructor
27069 device
27070 implementation
27071 user */
27072
27073static tree
27074c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
27075{
27076 tree ret = NULL_TREE;
27077 do
27078 {
27079 const char *setp = "";
27080 if (c_parser_next_token_is (parser, type: CPP_NAME))
27081 setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27082 enum omp_tss_code set = omp_lookup_tss_code (setp);
27083
27084 if (set == OMP_TRAIT_SET_INVALID)
27085 {
27086 c_parser_error (parser, gmsgid: "expected context selector set name");
27087 return error_mark_node;
27088 }
27089
27090 c_parser_consume_token (parser);
27091
27092 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
27093 return error_mark_node;
27094
27095 matching_braces braces;
27096 if (!braces.require_open (parser))
27097 return error_mark_node;
27098
27099 tree selectors = c_parser_omp_context_selector (parser, set, parms);
27100 if (selectors == error_mark_node)
27101 {
27102 c_parser_skip_to_closing_brace (parser);
27103 ret = error_mark_node;
27104 }
27105 else if (ret != error_mark_node)
27106 ret = make_trait_set_selector (set, selectors, ret);
27107
27108 braces.require_close (parser);
27109
27110 if (c_parser_next_token_is (parser, type: CPP_COMMA))
27111 c_parser_consume_token (parser);
27112 else
27113 break;
27114 }
27115 while (1);
27116
27117 if (ret == error_mark_node)
27118 return ret;
27119 return nreverse (ret);
27120}
27121
27122/* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
27123 that into "omp declare variant base" attribute. */
27124
27125static void
27126c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
27127{
27128 matching_parens parens;
27129 if (!parens.require_open (parser))
27130 {
27131 fail:
27132 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
27133 return;
27134 }
27135
27136 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
27137 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
27138 {
27139 c_parser_error (parser, gmsgid: "expected identifier");
27140 goto fail;
27141 }
27142
27143 c_token *token = c_parser_peek_token (parser);
27144 tree variant = lookup_name (token->value);
27145
27146 if (variant == NULL_TREE)
27147 {
27148 undeclared_variable (token->location, token->value);
27149 variant = error_mark_node;
27150 }
27151
27152 c_parser_consume_token (parser);
27153
27154 parens.require_close (parser);
27155
27156 tree append_args_tree = NULL_TREE;
27157 tree append_args_last;
27158 vec<tree> adjust_args_list = vNULL;
27159 bool has_match = false, has_adjust_args = false;
27160 location_t adjust_args_loc = UNKNOWN_LOCATION;
27161 location_t append_args_loc = UNKNOWN_LOCATION;
27162 location_t match_loc = UNKNOWN_LOCATION;
27163 tree need_device_ptr_list = NULL_TREE;
27164 tree ctx = error_mark_node;
27165
27166 do
27167 {
27168 if (c_parser_next_token_is (parser, type: CPP_COMMA)
27169 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
27170 c_parser_consume_token (parser);
27171
27172 const char *clause = "";
27173 location_t loc = c_parser_peek_token (parser)->location;
27174 if (c_parser_next_token_is (parser, type: CPP_NAME))
27175 clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27176
27177 enum clause
27178 {
27179 match,
27180 adjust_args,
27181 append_args
27182 } ccode;
27183
27184 if (strcmp (s1: clause, s2: "match") == 0)
27185 {
27186 ccode = match;
27187 match_loc = loc;
27188 }
27189 else if (strcmp (s1: clause, s2: "adjust_args") == 0)
27190 {
27191 ccode = adjust_args;
27192 adjust_args_loc = loc;
27193 }
27194 else if (strcmp (s1: clause, s2: "append_args") == 0)
27195 {
27196 ccode = append_args;
27197 append_args_loc = loc;
27198 }
27199 else
27200 {
27201 c_parser_error (parser, gmsgid: "expected %<match%>, %<adjust_args%> or "
27202 "%<append_args%> clause");
27203 goto fail;
27204 }
27205
27206 c_parser_consume_token (parser);
27207
27208 if (!parens.require_open (parser))
27209 goto fail;
27210
27211 if (parms == NULL_TREE)
27212 parms = error_mark_node;
27213
27214 if (ccode == match)
27215 {
27216 if (has_match)
27217 error_at (match_loc, "too many %<match%> clauses");
27218 has_match = true;
27219 ctx = c_parser_omp_context_selector_specification (parser, parms);
27220 if (ctx == error_mark_node)
27221 goto fail;
27222 ctx = omp_check_context_selector (loc: match_loc, ctx,
27223 directive: OMP_CTX_DECLARE_VARIANT);
27224 if (ctx != error_mark_node && variant != error_mark_node)
27225 {
27226 if (TREE_CODE (variant) != FUNCTION_DECL)
27227 {
27228 error_at (token->location, "variant %qD is not a function",
27229 variant);
27230 variant = error_mark_node;
27231 }
27232 else if (fndecl_built_in_p (node: variant)
27233 && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27234 s2: "__builtin_", n: strlen (s: "__builtin_"))
27235 == 0
27236 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27237 s2: "__sync_", n: strlen (s: "__sync_"))
27238 == 0
27239 || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
27240 s2: "__atomic_", n: strlen (s: "__atomic_"))
27241 == 0))
27242 {
27243 error_at (token->location, "variant %qD is a built-in",
27244 variant);
27245 variant = error_mark_node;
27246 }
27247 }
27248 }
27249 else if (ccode == adjust_args)
27250 {
27251 has_adjust_args = true;
27252 if (c_parser_next_token_is (parser, type: CPP_NAME)
27253 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
27254 {
27255 const char *p
27256 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27257 if (strcmp (s1: p, s2: "need_device_ptr") == 0
27258 || strcmp (s1: p, s2: "nothing") == 0)
27259 {
27260 c_parser_consume_token (parser); // need_device_ptr
27261 c_parser_consume_token (parser); // :
27262
27263 loc = c_parser_peek_token (parser)->location;
27264 tree list
27265 = c_parser_omp_variable_list (parser, clause_loc: loc, kind: OMP_CLAUSE_ERROR,
27266 NULL_TREE);
27267
27268 tree arg;
27269 if (variant != error_mark_node)
27270 for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
27271 {
27272 tree decl = TREE_PURPOSE (c);
27273 location_t arg_loc = EXPR_LOCATION (TREE_VALUE (c));
27274 int idx;
27275 for (arg = parms, idx = 0; arg != NULL;
27276 arg = TREE_CHAIN (arg), idx++)
27277 if (arg == decl)
27278 break;
27279 if (arg == NULL_TREE)
27280 {
27281 error_at (arg_loc,
27282 "%qD is not a function argument",
27283 decl);
27284 goto fail;
27285 }
27286 if (adjust_args_list.contains (search: arg))
27287 {
27288 error_at (arg_loc,
27289 "%qD is specified more than once",
27290 decl);
27291 goto fail;
27292 }
27293 if (strcmp (s1: p, s2: "need_device_ptr") == 0
27294 && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
27295 {
27296 error_at (loc, "%qD is not of pointer type", decl);
27297 goto fail;
27298 }
27299 adjust_args_list.safe_push (obj: arg);
27300 if (strcmp (s1: p, s2: "need_device_ptr") == 0)
27301 {
27302 need_device_ptr_list = chainon (
27303 need_device_ptr_list,
27304 build_tree_list (
27305 NULL_TREE,
27306 build_int_cst (
27307 integer_type_node,
27308 idx))); // Store 0-based argument index,
27309 // as in gimplify_call_expr
27310 }
27311 }
27312 }
27313 else
27314 {
27315 error_at (c_parser_peek_token (parser)->location,
27316 "expected %<nothing%> or %<need_device_ptr%>");
27317 if (strcmp (s1: p, s2: "need_device_addr") == 0)
27318 inform (c_parser_peek_token (parser)->location,
27319 "%<need_device_addr%> is not valid for C");
27320 goto fail;
27321 }
27322 }
27323 else
27324 {
27325 error_at (c_parser_peek_token (parser)->location,
27326 "expected %<nothing%> or %<need_device_ptr%> "
27327 "followed by %<:%>");
27328 goto fail;
27329 }
27330 }
27331 else if (ccode == append_args)
27332 {
27333 if (append_args_tree)
27334 {
27335 error_at (append_args_loc, "too many %qs clauses", "append_args");
27336 append_args_tree = NULL_TREE;
27337 }
27338 do
27339 {
27340 location_t loc = c_parser_peek_token (parser)->location;
27341 if (!c_parser_next_token_is (parser, type: CPP_NAME)
27342 || strcmp (s1: "interop",
27343 IDENTIFIER_POINTER (
27344 c_parser_peek_token (parser)->value)))
27345 {
27346 error_at (loc, "expected %<interop%>");
27347 goto fail;
27348 }
27349 c_parser_consume_token (parser);
27350
27351 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
27352 goto fail;
27353 bool target = false;
27354 bool targetsync = false;
27355 tree prefer_type_tree = NULL_TREE;
27356 if (!c_parser_omp_clause_init_modifiers (parser, target: &target,
27357 targetsync: &targetsync,
27358 prefer_type_tree: &prefer_type_tree)
27359 || !c_parser_require (parser, type: CPP_CLOSE_PAREN,
27360 msgid: "expected %<)%> or %<,%>"))
27361 goto fail;
27362 if (!target && !targetsync)
27363 error_at (loc,
27364 "missing required %<target%> and/or "
27365 "%<targetsync%> modifier");
27366 tree t = build_tree_list (target ? boolean_true_node
27367 : boolean_false_node,
27368 targetsync ? boolean_true_node
27369 : boolean_false_node);
27370 t = build1_loc (loc, code: NOP_EXPR, void_type_node, arg1: t);
27371 t = build_tree_list (t, prefer_type_tree);
27372 if (append_args_tree)
27373 {
27374 TREE_CHAIN (append_args_last) = t;
27375 append_args_last = t;
27376 }
27377 else
27378 append_args_tree = append_args_last = t;
27379 if (c_parser_next_token_is (parser, type: CPP_CLOSE_PAREN))
27380 break;
27381 if (!c_parser_require (parser, type: CPP_COMMA, msgid: "expected %<)%> or %<,%>"))
27382 goto fail;
27383 }
27384 while (true);
27385 }
27386
27387 parens.require_close (parser);
27388 } while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL));
27389 c_parser_skip_to_pragma_eol (parser);
27390
27391 if ((ctx != error_mark_node && variant != error_mark_node)
27392 && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27393 OMP_TRAIT_CONSTRUCT_SIMD))
27394 {
27395 bool fail = false;
27396 if (append_args_tree)
27397 {
27398 int nappend_args = 0;
27399 int nbase_args = 0;
27400 for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27401 t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
27402 nbase_args++;
27403 for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
27404 nappend_args++;
27405
27406 /* Store as purpose = arg number after which to append
27407 and value = list of interop items. */
27408 append_args_tree = build_tree_list (build_int_cst (integer_type_node,
27409 nbase_args),
27410 append_args_tree);
27411 tree args, arg;
27412 args = arg = TYPE_ARG_TYPES (TREE_TYPE (variant));
27413 for (int j = 0; j < nbase_args && arg; j++, arg = TREE_CHAIN (arg))
27414 args = arg;
27415 for (int i = 0; i < nappend_args && arg; i++)
27416 arg = TREE_CHAIN (arg);
27417 tree saved_args;
27418 if (nbase_args && args)
27419 {
27420 saved_args = TREE_CHAIN (args);
27421 TREE_CHAIN (args) = arg;
27422 }
27423 else
27424 {
27425 saved_args = args;
27426 TYPE_ARG_TYPES (TREE_TYPE (variant)) = arg;
27427 TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 1;
27428 }
27429 if (!comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
27430 fail = true;
27431 if (nbase_args && args)
27432 TREE_CHAIN (args) = saved_args;
27433 else
27434 {
27435 TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_args;
27436 TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 0;
27437 }
27438 arg = saved_args;
27439 if (!fail)
27440 for (int i = 0; i < nappend_args; i++, arg = TREE_CHAIN (arg))
27441 if (!arg || !c_omp_interop_t_p (TREE_VALUE (arg)))
27442 {
27443 error_at (DECL_SOURCE_LOCATION (variant),
27444 "argument %d of %qD must be of %<omp_interop_t%>",
27445 nbase_args + i + 1, variant);
27446 inform (append_args_loc, "%<append_args%> specified here");
27447 break;
27448 }
27449 }
27450 else
27451 {
27452 if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
27453 {
27454 if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE
27455 && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE)
27456 {
27457 if (!append_args_tree)
27458 TYPE_ARG_TYPES (TREE_TYPE (variant))
27459 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27460 else
27461 {
27462 tree new_args = NULL_TREE;
27463 tree arg, last_arg = NULL_TREE;
27464 for (arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
27465 arg && arg != void_type_node; arg = TREE_CHAIN (arg))
27466 {
27467 if (new_args == NULL_TREE)
27468 new_args = last_arg = copy_node (arg);
27469 else
27470 {
27471 TREE_CHAIN (last_arg) = copy_node (arg);
27472 last_arg = TREE_CHAIN (last_arg);
27473 }
27474 }
27475 for (tree t3 = append_args_tree; t3; t3 = TREE_CHAIN (t3))
27476 {
27477 tree type = lookup_name (get_identifier ("omp_interop_t"));
27478 type = type ? TREE_TYPE (type) : ptr_type_node;
27479 last_arg = tree_cons (NULL_TREE, type, last_arg);
27480 }
27481 TREE_CHAIN (last_arg) = arg;
27482 TYPE_ARG_TYPES (TREE_TYPE (variant)) = new_args;
27483 }
27484 }
27485 }
27486 else
27487 fail = true;
27488 }
27489 if (fail)
27490 {
27491 error_at (token->location,
27492 "variant %qD and base %qD have incompatible types",
27493 variant, fndecl);
27494 variant = error_mark_node;
27495 }
27496 }
27497 if (ctx != error_mark_node && variant != error_mark_node)
27498 {
27499 C_DECL_USED (variant) = 1;
27500 tree construct = omp_get_context_selector_list (ctx,
27501 OMP_TRAIT_SET_CONSTRUCT);
27502 omp_mark_declare_variant (loc: match_loc, variant, construct);
27503 if (omp_context_selector_matches (ctx, NULL_TREE, false))
27504 {
27505 tree attr = tree_cons (get_identifier ("omp declare variant base"),
27506 build_tree_list (variant, ctx),
27507 DECL_ATTRIBUTES (fndecl));
27508 DECL_ATTRIBUTES (fndecl) = attr;
27509 }
27510 }
27511
27512 if (has_adjust_args || append_args_tree)
27513 {
27514 if (!has_match)
27515 {
27516 error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
27517 "an %qs clause requires a %<match%> clause",
27518 has_adjust_args ? "adjust_args" : "append_args");
27519 }
27520 else if (ctx != error_mark_node && variant != error_mark_node)
27521 {
27522 tree attr = lookup_attribute (attr_name: "omp declare variant base",
27523 DECL_ATTRIBUTES (fndecl));
27524 if (attr != NULL_TREE)
27525 {
27526 tree ctx = TREE_VALUE (TREE_VALUE (attr));
27527 if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
27528 OMP_TRAIT_CONSTRUCT_DISPATCH))
27529 error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
27530 "an %qs clause can only be specified if the "
27531 "%<dispatch%> selector of the %<construct%> selector "
27532 "set appears in the %<match%> clause",
27533 has_adjust_args ? "adjust_args" : "append_args");
27534 }
27535 }
27536 }
27537
27538 if ((ctx != error_mark_node && variant != error_mark_node)
27539 && (need_device_ptr_list || append_args_tree))
27540 {
27541 tree variant_decl = tree_strip_nop_conversions (variant);
27542 tree t = build_tree_list (need_device_ptr_list,
27543 NULL_TREE /* need_device_addr */);
27544 TREE_CHAIN (t) = append_args_tree;
27545 DECL_ATTRIBUTES (variant_decl)
27546 = tree_cons (get_identifier ("omp declare variant variant args"), t,
27547 DECL_ATTRIBUTES (variant_decl));
27548 }
27549}
27550
27551/* Finalize #pragma omp declare simd or #pragma omp declare variant
27552 clauses after FNDECL has been parsed, and put that into "omp declare simd"
27553 or "omp declare variant base" attribute. */
27554
27555static void
27556c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
27557 vec<c_token> *pclauses)
27558{
27559 vec<c_token> &clauses = *pclauses;
27560
27561 /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
27562 indicates error has been reported and CPP_PRAGMA that
27563 c_finish_omp_declare_simd has already processed the tokens. */
27564 if (clauses.exists () && clauses[0].type == CPP_EOF)
27565 return;
27566 const char *kind = "simd";
27567 if (clauses.exists ()
27568 && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
27569 kind = IDENTIFIER_POINTER (clauses[0].value);
27570 gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
27571 if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
27572 {
27573 error ("%<#pragma omp declare %s%> not immediately followed by "
27574 "a function declaration or definition", kind);
27575 clauses[0].type = CPP_EOF;
27576 return;
27577 }
27578 if (clauses.exists () && clauses[0].type != CPP_NAME)
27579 {
27580 error_at (DECL_SOURCE_LOCATION (fndecl),
27581 "%<#pragma omp declare %s%> not immediately followed by "
27582 "a single function declaration or definition", kind);
27583 clauses[0].type = CPP_EOF;
27584 return;
27585 }
27586
27587 if (parms == NULL_TREE)
27588 parms = DECL_ARGUMENTS (fndecl);
27589
27590 unsigned int tokens_avail = parser->tokens_avail;
27591 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27592
27593 parser->tokens = clauses.address ();
27594 parser->tokens_avail = clauses.length ();
27595
27596 /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
27597 while (parser->tokens_avail > 3)
27598 {
27599 c_token *token = c_parser_peek_token (parser);
27600 gcc_assert (token->type == CPP_NAME);
27601 kind = IDENTIFIER_POINTER (token->value);
27602 c_parser_consume_token (parser);
27603 parser->in_pragma = true;
27604
27605 if (strcmp (s1: kind, s2: "simd") == 0)
27606 {
27607 tree c;
27608 c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
27609 where: "#pragma omp declare simd");
27610 c = c_omp_declare_simd_clauses_to_numbers (parms, c);
27611 if (c != NULL_TREE)
27612 c = tree_cons (NULL_TREE, c, NULL_TREE);
27613 c = build_tree_list (get_identifier ("omp declare simd"), c);
27614 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
27615 DECL_ATTRIBUTES (fndecl) = c;
27616 }
27617 else
27618 {
27619 gcc_assert (strcmp (kind, "variant") == 0);
27620 c_finish_omp_declare_variant (parser, fndecl, parms);
27621 }
27622 }
27623
27624 parser->tokens = &parser->tokens_buf[0];
27625 parser->tokens_avail = tokens_avail;
27626 if (clauses.exists ())
27627 clauses[0].type = CPP_PRAGMA;
27628}
27629
27630/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
27631 a threadprivate, groupprivate, allocate or declare target directive,
27632 return true and parse it for DECL. */
27633
27634bool
27635c_maybe_parse_omp_decl (tree decl, tree d)
27636{
27637 gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
27638 vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
27639 c_token *first = toks->address ();
27640 c_token *last = first + toks->length ();
27641 const char *directive[3] = {};
27642 for (int j = 0; j < 3; j++)
27643 {
27644 tree id = NULL_TREE;
27645 if (first + j == last)
27646 break;
27647 if (first[j].type == CPP_NAME)
27648 id = first[j].value;
27649 else if (first[j].type == CPP_KEYWORD)
27650 id = ridpointers[(int) first[j].keyword];
27651 else
27652 break;
27653 directive[j] = IDENTIFIER_POINTER (id);
27654 }
27655 const c_omp_directive *dir = NULL;
27656 if (directive[0])
27657 dir = c_omp_categorize_directive (directive[0], directive[1],
27658 directive[2]);
27659 if (dir == NULL)
27660 {
27661 error_at (first->location,
27662 "unknown OpenMP directive name in "
27663 "%qs attribute argument", "omp::decl");
27664 return false;
27665 }
27666 if (dir->id != PRAGMA_OMP_THREADPRIVATE
27667 /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
27668 && dir->id != PRAGMA_OMP_ALLOCATE
27669 && (dir->id != PRAGMA_OMP_DECLARE
27670 || strcmp (s1: directive[1], s2: "target") != 0))
27671 return false;
27672
27673 if (!flag_openmp && !dir->simd)
27674 return true;
27675
27676 c_parser *parser = the_parser;
27677 unsigned int tokens_avail = parser->tokens_avail;
27678 gcc_assert (parser->tokens == &parser->tokens_buf[0]);
27679 toks = NULL;
27680 vec_safe_reserve (v&: toks, nelems: last - first + 2, exact: true);
27681 c_token tok = {};
27682 tok.type = CPP_PRAGMA;
27683 tok.keyword = RID_MAX;
27684 tok.pragma_kind = pragma_kind (dir->id);
27685 tok.location = first->location;
27686 toks->quick_push (obj: tok);
27687 while (++first < last)
27688 toks->quick_push (obj: *first);
27689 tok = {};
27690 tok.type = CPP_PRAGMA_EOL;
27691 tok.keyword = RID_MAX;
27692 tok.location = last[-1].location;
27693 toks->quick_push (obj: tok);
27694 tok = {};
27695 tok.type = CPP_EOF;
27696 tok.keyword = RID_MAX;
27697 tok.location = last[-1].location;
27698 toks->quick_push (obj: tok);
27699 parser->in_omp_decl_attribute = decl;
27700 gcc_assert (!parser->in_omp_attribute_pragma);
27701 parser->in_omp_attribute_pragma = ggc_alloc<omp_attribute_pragma_state> ();
27702 parser->in_omp_attribute_pragma->token_vec = toks;
27703 parser->in_omp_attribute_pragma->save_tokens = parser->tokens;
27704 parser->in_omp_attribute_pragma->save_tokens_avail = tokens_avail;
27705 parser->tokens = toks->address ();
27706 parser->tokens_avail = toks->length ();
27707 c_parser_pragma (parser, context: pragma_external, NULL, NULL_TREE);
27708 parser->in_omp_decl_attribute = NULL_TREE;
27709 return true;
27710}
27711
27712/* OpenMP 4.0:
27713 # pragma omp declare target new-line
27714 declarations and definitions
27715 # pragma omp end declare target new-line
27716
27717 OpenMP 4.5:
27718 # pragma omp declare target ( extended-list ) new-line
27719
27720 # pragma omp declare target declare-target-clauses[seq] new-line */
27721
27722#define OMP_DECLARE_TARGET_CLAUSE_MASK \
27723 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
27724 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ENTER) \
27725 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
27726 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27727 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
27728
27729static void
27730c_parser_omp_declare_target (c_parser *parser)
27731{
27732 tree clauses = NULL_TREE;
27733 int device_type = 0;
27734 bool indirect = false;
27735 bool only_device_type_or_indirect = true;
27736 if (flag_openmp)
27737 omp_requires_mask
27738 = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
27739 if (c_parser_next_token_is (parser, type: CPP_NAME)
27740 || (c_parser_next_token_is (parser, type: CPP_COMMA)
27741 && c_parser_peek_2nd_token (parser)->type == CPP_NAME))
27742 clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
27743 where: "#pragma omp declare target");
27744 else if (parser->in_omp_decl_attribute
27745 || c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
27746 {
27747 clauses = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ENTER,
27748 list: clauses);
27749 clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
27750 c_parser_skip_to_pragma_eol (parser);
27751 }
27752 else
27753 {
27754 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27755 c_parser_skip_to_pragma_eol (parser);
27756 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: -1, .indirect: 0 };
27757 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
27758 return;
27759 }
27760 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27761 {
27762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
27763 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
27764 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27765 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
27766 }
27767 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27768 {
27769 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE
27770 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27771 continue;
27772 tree t = OMP_CLAUSE_DECL (c), id;
27773 tree at1 = lookup_attribute (attr_name: "omp declare target", DECL_ATTRIBUTES (t));
27774 tree at2 = lookup_attribute (attr_name: "omp declare target link",
27775 DECL_ATTRIBUTES (t));
27776 only_device_type_or_indirect = false;
27777 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
27778 {
27779 id = get_identifier ("omp declare target link");
27780 std::swap (a&: at1, b&: at2);
27781 }
27782 else
27783 id = get_identifier ("omp declare target");
27784 if (at2)
27785 {
27786 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ENTER)
27787 error_at (OMP_CLAUSE_LOCATION (c),
27788 "%qD specified both in declare target %<link%> and %qs"
27789 " clauses", t, OMP_CLAUSE_ENTER_TO (c) ? "to" : "enter");
27790 else
27791 error_at (OMP_CLAUSE_LOCATION (c),
27792 "%qD specified both in declare target %<link%> and "
27793 "%<to%> or %<enter%> clauses", t);
27794 continue;
27795 }
27796 if (!at1)
27797 {
27798 DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27799 if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
27800 continue;
27801
27802 symtab_node *node = symtab_node::get (decl: t);
27803 if (node != NULL)
27804 {
27805 node->offloadable = 1;
27806 if (ENABLE_OFFLOADING)
27807 {
27808 g->have_offload = true;
27809 if (is_a <varpool_node *> (p: node))
27810 vec_safe_push (v&: offload_vars, obj: t);
27811 }
27812 }
27813 }
27814 if (TREE_CODE (t) != FUNCTION_DECL)
27815 continue;
27816 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
27817 {
27818 tree at3 = lookup_attribute (attr_name: "omp declare target host",
27819 DECL_ATTRIBUTES (t));
27820 if (at3 == NULL_TREE)
27821 {
27822 id = get_identifier ("omp declare target host");
27823 DECL_ATTRIBUTES (t)
27824 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27825 }
27826 }
27827 if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
27828 {
27829 tree at3 = lookup_attribute (attr_name: "omp declare target nohost",
27830 DECL_ATTRIBUTES (t));
27831 if (at3 == NULL_TREE)
27832 {
27833 id = get_identifier ("omp declare target nohost");
27834 DECL_ATTRIBUTES (t)
27835 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27836 }
27837 }
27838 if (indirect)
27839 {
27840 tree at4 = lookup_attribute (attr_name: "omp declare target indirect",
27841 DECL_ATTRIBUTES (t));
27842 if (at4 == NULL_TREE)
27843 {
27844 id = get_identifier ("omp declare target indirect");
27845 DECL_ATTRIBUTES (t)
27846 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
27847 }
27848 }
27849 }
27850 if ((device_type || indirect) && only_device_type_or_indirect)
27851 error_at (OMP_CLAUSE_LOCATION (clauses),
27852 "directive with only %<device_type%> or %<indirect%> clauses");
27853 if (indirect && device_type && device_type != OMP_CLAUSE_DEVICE_TYPE_ANY)
27854 error_at (OMP_CLAUSE_LOCATION (clauses),
27855 "%<device_type%> clause must specify 'any' when used with "
27856 "an %<indirect%> clause");
27857}
27858
27859/* OpenMP 5.1
27860 #pragma omp begin assumes clauses[optseq] new-line
27861
27862 #pragma omp begin declare target clauses[optseq] new-line */
27863
27864#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \
27865 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \
27866 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INDIRECT))
27867
27868static void
27869c_parser_omp_begin (c_parser *parser)
27870{
27871 const char *p = "";
27872 c_parser_consume_pragma (parser);
27873 if (c_parser_next_token_is (parser, type: CPP_NAME))
27874 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27875 if (strcmp (s1: p, s2: "declare") == 0)
27876 {
27877 c_parser_consume_token (parser);
27878 p = "";
27879 if (c_parser_next_token_is (parser, type: CPP_NAME))
27880 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27881 if (strcmp (s1: p, s2: "target") == 0)
27882 {
27883 c_parser_consume_token (parser);
27884 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27885 tree clauses
27886 = c_parser_omp_all_clauses (parser,
27887 OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
27888 where: "#pragma omp begin declare target");
27889 int device_type = 0;
27890 int indirect = 0;
27891 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
27892 {
27893 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
27894 device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
27895 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INDIRECT)
27896 indirect |= !integer_zerop (OMP_CLAUSE_INDIRECT_EXPR (c));
27897 }
27898 c_omp_declare_target_attr attr = { .attr_syntax: attr_syntax, .device_type: device_type,
27899 .indirect: indirect };
27900 vec_safe_push (v&: current_omp_declare_target_attribute, obj: attr);
27901 }
27902 else
27903 {
27904 c_parser_error (parser, gmsgid: "expected %<target%>");
27905 c_parser_skip_to_pragma_eol (parser);
27906 }
27907 }
27908 else if (strcmp (s1: p, s2: "assumes") == 0)
27909 {
27910 c_parser_consume_token (parser);
27911 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27912 c_parser_omp_assumption_clauses (parser, false);
27913 struct c_omp_begin_assumes_data a = { .attr_syntax: attr_syntax };
27914 vec_safe_push (v&: current_omp_begin_assumes, obj: a);
27915 }
27916 else
27917 {
27918 c_parser_error (parser, gmsgid: "expected %<declare target%> or %<assumes%>");
27919 c_parser_skip_to_pragma_eol (parser);
27920 }
27921}
27922
27923/* OpenMP 4.0
27924 #pragma omp end declare target
27925
27926 OpenMP 5.1
27927 #pragma omp end assumes */
27928
27929static void
27930c_parser_omp_end (c_parser *parser)
27931{
27932 location_t loc = c_parser_peek_token (parser)->location;
27933 const char *p = "";
27934 c_parser_consume_pragma (parser);
27935 if (c_parser_next_token_is (parser, type: CPP_NAME))
27936 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
27937 if (strcmp (s1: p, s2: "declare") == 0)
27938 {
27939 c_parser_consume_token (parser);
27940 if (c_parser_next_token_is (parser, type: CPP_NAME)
27941 && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
27942 s2: "target") == 0)
27943 c_parser_consume_token (parser);
27944 else
27945 {
27946 c_parser_error (parser, gmsgid: "expected %<target%>");
27947 c_parser_skip_to_pragma_eol (parser);
27948 return;
27949 }
27950 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27951 c_parser_skip_to_pragma_eol (parser);
27952 if (!vec_safe_length (v: current_omp_declare_target_attribute))
27953 error_at (loc, "%<#pragma omp end declare target%> without "
27954 "corresponding %<#pragma omp declare target%> or "
27955 "%<#pragma omp begin declare target%>");
27956 else
27957 {
27958 c_omp_declare_target_attr
27959 a = current_omp_declare_target_attribute->pop ();
27960 if (a.attr_syntax != attr_syntax)
27961 {
27962 if (a.attr_syntax)
27963 error_at (loc,
27964 "%qs in attribute syntax terminated "
27965 "with %qs in pragma syntax",
27966 a.device_type >= 0 ? "begin declare target"
27967 : "declare target",
27968 "end declare target");
27969 else
27970 error_at (loc,
27971 "%qs in pragma syntax terminated "
27972 "with %qs in attribute syntax",
27973 a.device_type >= 0 ? "begin declare target"
27974 : "declare target",
27975 "end declare target");
27976 }
27977 }
27978 }
27979 else if (strcmp (s1: p, s2: "assumes") == 0)
27980 {
27981 c_parser_consume_token (parser);
27982 bool attr_syntax = parser->in_omp_attribute_pragma != NULL;
27983 c_parser_skip_to_pragma_eol (parser);
27984 if (!vec_safe_length (v: current_omp_begin_assumes))
27985 error_at (loc, "%qs without corresponding %qs",
27986 "#pragma omp end assumes", "#pragma omp begin assumes");
27987 else
27988 {
27989 c_omp_begin_assumes_data
27990 a = current_omp_begin_assumes->pop ();
27991 if (a.attr_syntax != attr_syntax)
27992 {
27993 if (a.attr_syntax)
27994 error_at (loc,
27995 "%qs in attribute syntax terminated "
27996 "with %qs in pragma syntax",
27997 "begin assumes", "end assumes");
27998 else
27999 error_at (loc,
28000 "%qs in pragma syntax terminated "
28001 "with %qs in attribute syntax",
28002 "begin assumes", "end assumes");
28003 }
28004 }
28005 }
28006 else
28007 {
28008 c_parser_error (parser, gmsgid: "expected %<declare%> or %<assumes%>");
28009 c_parser_skip_to_pragma_eol (parser);
28010 }
28011}
28012
28013/* OpenMP 5.0
28014 #pragma omp declare mapper ([mapper-identifier :] type var) \
28015 [clause [ [,] clause ] ... ] new-line */
28016
28017static void
28018c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
28019{
28020 tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
28021 tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
28022 c_token *token;
28023
28024 if (context == pragma_struct || context == pragma_param)
28025 {
28026 error ("%<#pragma omp declare mapper%> not at file or block scope");
28027 goto fail;
28028 }
28029
28030 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
28031 goto fail;
28032
28033 token = c_parser_peek_token (parser);
28034
28035 if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
28036 {
28037 switch (token->type)
28038 {
28039 case CPP_NAME:
28040 mapper_name = token->value;
28041 c_parser_consume_token (parser);
28042 break;
28043 case CPP_KEYWORD:
28044 if (token->keyword == RID_DEFAULT)
28045 {
28046 mapper_name = NULL_TREE;
28047 c_parser_consume_token (parser);
28048 break;
28049 }
28050 /* Fallthrough. */
28051 default:
28052 error_at (token->location, "expected identifier or %<default%>");
28053 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28054 return;
28055 }
28056
28057 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
28058 goto fail;
28059 }
28060
28061 mapper_id = c_omp_mapper_id (mapper_name);
28062 mapper_decl = c_omp_mapper_decl (mapper_id);
28063
28064 {
28065 location_t loc = c_parser_peek_token (parser)->location;
28066 struct c_type_name *ctype = c_parser_type_name (parser);
28067 type = groktypename (ctype, NULL, NULL);
28068 if (type == error_mark_node)
28069 goto fail;
28070 if (!RECORD_OR_UNION_TYPE_P (type))
28071 {
28072 error_at (loc, "%qT is not a struct or union type in "
28073 "%<#pragma omp declare mapper%>", type);
28074 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28075 return;
28076 }
28077 for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
28078 if (comptypes (TREE_PURPOSE (t), type))
28079 {
28080 error_at (loc, "redeclaration of %qs %<#pragma omp declare "
28081 "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
28082 + sizeof ("omp declare mapper ") - 1,
28083 type);
28084 tree prevmapper = TREE_VALUE (t);
28085 /* Hmm, this location might not be very accurate. */
28086 location_t ploc
28087 = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
28088 inform (ploc, "%<#pragma omp declare mapper%> "
28089 "previously declared here");
28090 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28091 return;
28092 }
28093 }
28094
28095 token = c_parser_peek_token (parser);
28096 if (token->type == CPP_NAME)
28097 {
28098 var = build_decl (token->location, VAR_DECL, token->value, type);
28099 c_parser_consume_token (parser);
28100 DECL_ARTIFICIAL (var) = 1;
28101 }
28102 else
28103 {
28104 error_at (token->location, "expected identifier");
28105 goto fail;
28106 }
28107
28108 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
28109 goto fail;
28110
28111 push_scope ();
28112 stmtlist = push_stmt_list ();
28113 pushdecl (var);
28114 DECL_CONTEXT (var) = current_function_decl;
28115
28116 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
28117 {
28118 location_t here;
28119 pragma_omp_clause c_kind;
28120 here = c_parser_peek_token (parser)->location;
28121 c_kind = c_parser_omp_clause_name (parser);
28122 if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
28123 {
28124 error_at (here, "unexpected clause");
28125 goto fail;
28126 }
28127 maplist = c_parser_omp_clause_map (parser, list: maplist, declare_mapper_p: true);
28128 }
28129
28130 if (maplist == NULL_TREE)
28131 {
28132 error_at (input_location, "missing %<map%> clause");
28133 goto fail;
28134 }
28135
28136 stmt = make_node (OMP_DECLARE_MAPPER);
28137 TREE_TYPE (stmt) = type;
28138 OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
28139 OMP_DECLARE_MAPPER_DECL (stmt) = var;
28140 OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
28141
28142 add_stmt (stmt);
28143
28144 pop_stmt_list (stmtlist);
28145 pop_scope ();
28146
28147 c_parser_skip_to_pragma_eol (parser);
28148
28149 t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
28150 DECL_INITIAL (mapper_decl) = t;
28151
28152 return;
28153
28154 fail:
28155 c_parser_skip_to_pragma_eol (parser);
28156}
28157
28158/* OpenMP 4.0
28159 #pragma omp declare reduction (reduction-id : typename-list : expression) \
28160 initializer-clause[opt] new-line
28161
28162 initializer-clause:
28163 initializer (omp_priv = initializer)
28164 initializer (function-name (argument-list)) */
28165
28166static void
28167c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
28168{
28169 unsigned int tokens_avail = 0, i;
28170 c_token *saved_tokens = NULL;
28171 vec<tree> types = vNULL;
28172 vec<c_token> clauses = vNULL;
28173 enum tree_code reduc_code = ERROR_MARK;
28174 tree reduc_id = NULL_TREE;
28175 tree type;
28176 location_t rloc = c_parser_peek_token (parser)->location;
28177
28178 if (context == pragma_struct || context == pragma_param)
28179 {
28180 error ("%<#pragma omp declare reduction%> not at file or block scope");
28181 goto fail;
28182 }
28183
28184 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
28185 goto fail;
28186
28187 switch (c_parser_peek_token (parser)->type)
28188 {
28189 case CPP_PLUS:
28190 reduc_code = PLUS_EXPR;
28191 break;
28192 case CPP_MULT:
28193 reduc_code = MULT_EXPR;
28194 break;
28195 case CPP_MINUS:
28196 reduc_code = MINUS_EXPR;
28197 break;
28198 case CPP_AND:
28199 reduc_code = BIT_AND_EXPR;
28200 break;
28201 case CPP_XOR:
28202 reduc_code = BIT_XOR_EXPR;
28203 break;
28204 case CPP_OR:
28205 reduc_code = BIT_IOR_EXPR;
28206 break;
28207 case CPP_AND_AND:
28208 reduc_code = TRUTH_ANDIF_EXPR;
28209 break;
28210 case CPP_OR_OR:
28211 reduc_code = TRUTH_ORIF_EXPR;
28212 break;
28213 case CPP_NAME:
28214 const char *p;
28215 p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28216 if (strcmp (s1: p, s2: "min") == 0)
28217 {
28218 reduc_code = MIN_EXPR;
28219 break;
28220 }
28221 if (strcmp (s1: p, s2: "max") == 0)
28222 {
28223 reduc_code = MAX_EXPR;
28224 break;
28225 }
28226 reduc_id = c_parser_peek_token (parser)->value;
28227 break;
28228 default:
28229 c_parser_error (parser,
28230 gmsgid: "expected %<+%>, %<*%>, %<-%>, %<&%>, "
28231 "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
28232 goto fail;
28233 }
28234
28235 tree orig_reduc_id, reduc_decl;
28236 orig_reduc_id = reduc_id;
28237 reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
28238 reduc_decl = c_omp_reduction_decl (reduc_id);
28239 c_parser_consume_token (parser);
28240
28241 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>"))
28242 goto fail;
28243
28244 while (true)
28245 {
28246 location_t loc = c_parser_peek_token (parser)->location;
28247 struct c_type_name *ctype = c_parser_type_name (parser);
28248 if (ctype != NULL)
28249 {
28250 type = groktypename (ctype, NULL, NULL);
28251 if (type == error_mark_node)
28252 ;
28253 else if ((INTEGRAL_TYPE_P (type)
28254 || SCALAR_FLOAT_TYPE_P (type)
28255 || TREE_CODE (type) == COMPLEX_TYPE)
28256 && orig_reduc_id == NULL_TREE)
28257 error_at (loc, "predeclared arithmetic type in "
28258 "%<#pragma omp declare reduction%>");
28259 else if (TREE_CODE (type) == FUNCTION_TYPE
28260 || TREE_CODE (type) == ARRAY_TYPE)
28261 error_at (loc, "function or array type in "
28262 "%<#pragma omp declare reduction%>");
28263 else if (TYPE_ATOMIC (type))
28264 error_at (loc, "%<_Atomic%> qualified type in "
28265 "%<#pragma omp declare reduction%>");
28266 else if (TYPE_QUALS_NO_ADDR_SPACE (type))
28267 error_at (loc, "const, volatile or restrict qualified type in "
28268 "%<#pragma omp declare reduction%>");
28269 else
28270 {
28271 tree t;
28272 for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
28273 if (comptypes (TREE_PURPOSE (t), type))
28274 {
28275 error_at (loc, "redeclaration of %qs "
28276 "%<#pragma omp declare reduction%> for "
28277 "type %qT",
28278 IDENTIFIER_POINTER (reduc_id)
28279 + sizeof ("omp declare reduction ") - 1,
28280 type);
28281 location_t ploc
28282 = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
28283 0));
28284 inform (ploc, "%<#pragma omp declare reduction%> "
28285 "previously declared here");
28286 break;
28287 }
28288 if (t == NULL_TREE)
28289 types.safe_push (obj: type);
28290 }
28291 if (c_parser_next_token_is (parser, type: CPP_COMMA))
28292 c_parser_consume_token (parser);
28293 else
28294 break;
28295 }
28296 else
28297 break;
28298 }
28299
28300 if (!c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>")
28301 || types.is_empty ())
28302 {
28303 fail:
28304 clauses.release ();
28305 types.release ();
28306 while (true)
28307 {
28308 c_token *token = c_parser_peek_token (parser);
28309 if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
28310 break;
28311 c_parser_consume_token (parser);
28312 }
28313 c_parser_skip_to_pragma_eol (parser);
28314 return;
28315 }
28316
28317 if (types.length () > 1)
28318 {
28319 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
28320 {
28321 c_token *token = c_parser_peek_token (parser);
28322 if (token->type == CPP_EOF)
28323 goto fail;
28324 clauses.safe_push (obj: *token);
28325 c_parser_consume_token (parser);
28326 }
28327 clauses.safe_push (obj: *c_parser_peek_token (parser));
28328 c_parser_skip_to_pragma_eol (parser);
28329
28330 /* Make sure nothing tries to read past the end of the tokens. */
28331 c_token eof_token;
28332 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
28333 eof_token.type = CPP_EOF;
28334 clauses.safe_push (obj: eof_token);
28335 clauses.safe_push (obj: eof_token);
28336 }
28337
28338 int errs = errorcount;
28339 FOR_EACH_VEC_ELT (types, i, type)
28340 {
28341 saved_tokens = parser->tokens;
28342 tokens_avail = parser->tokens_avail;
28343 if (!clauses.is_empty ())
28344 {
28345 parser->tokens = clauses.address ();
28346 parser->tokens_avail = clauses.length ();
28347 parser->in_pragma = true;
28348 }
28349
28350 bool nested = current_function_decl != NULL_TREE;
28351 if (nested)
28352 c_push_function_context ();
28353 tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
28354 reduc_id, default_function_type);
28355 current_function_decl = fndecl;
28356 allocate_struct_function (fndecl, true);
28357 push_scope ();
28358 tree stmt = push_stmt_list ();
28359 /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
28360 warn about these. */
28361 tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
28362 get_identifier ("omp_out"), type);
28363 DECL_ARTIFICIAL (omp_out) = 1;
28364 DECL_CONTEXT (omp_out) = fndecl;
28365 pushdecl (omp_out);
28366 tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
28367 get_identifier ("omp_in"), type);
28368 DECL_ARTIFICIAL (omp_in) = 1;
28369 DECL_CONTEXT (omp_in) = fndecl;
28370 pushdecl (omp_in);
28371 struct c_expr combiner = c_parser_expression (parser);
28372 struct c_expr initializer;
28373 tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
28374 bool bad = false;
28375 initializer.set_error ();
28376 if (!c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
28377 bad = true;
28378 else if (c_parser_next_token_is (parser, type: CPP_COMMA)
28379 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28380 c_parser_consume_token (parser);
28381 if (!bad
28382 && (c_parser_next_token_is (parser, type: CPP_NAME)
28383 && strcmp (IDENTIFIER_POINTER
28384 (c_parser_peek_token (parser)->value),
28385 s2: "initializer") == 0))
28386 {
28387 c_parser_consume_token (parser);
28388 pop_scope ();
28389 push_scope ();
28390 omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
28391 get_identifier ("omp_priv"), type);
28392 DECL_ARTIFICIAL (omp_priv) = 1;
28393 DECL_INITIAL (omp_priv) = error_mark_node;
28394 DECL_CONTEXT (omp_priv) = fndecl;
28395 pushdecl (omp_priv);
28396 omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
28397 get_identifier ("omp_orig"), type);
28398 DECL_ARTIFICIAL (omp_orig) = 1;
28399 DECL_CONTEXT (omp_orig) = fndecl;
28400 pushdecl (omp_orig);
28401 if (!c_parser_require (parser, type: CPP_OPEN_PAREN, msgid: "expected %<(%>"))
28402 bad = true;
28403 else if (!c_parser_next_token_is (parser, type: CPP_NAME))
28404 {
28405 c_parser_error (parser, gmsgid: "expected %<omp_priv%> or "
28406 "function-name");
28407 bad = true;
28408 }
28409 else if (strcmp (IDENTIFIER_POINTER
28410 (c_parser_peek_token (parser)->value),
28411 s2: "omp_priv") != 0)
28412 {
28413 if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
28414 || c_parser_peek_token (parser)->id_kind != C_ID_ID)
28415 {
28416 c_parser_error (parser, gmsgid: "expected function-name %<(%>");
28417 bad = true;
28418 }
28419 else
28420 initializer = c_parser_postfix_expression (parser);
28421 if (initializer.value
28422 && TREE_CODE (initializer.value) == CALL_EXPR)
28423 {
28424 int j;
28425 tree c = initializer.value;
28426 for (j = 0; j < call_expr_nargs (c); j++)
28427 {
28428 tree a = CALL_EXPR_ARG (c, j);
28429 STRIP_NOPS (a);
28430 if (TREE_CODE (a) == ADDR_EXPR
28431 && TREE_OPERAND (a, 0) == omp_priv)
28432 break;
28433 }
28434 if (j == call_expr_nargs (c))
28435 error ("one of the initializer call arguments should be "
28436 "%<&omp_priv%>");
28437 }
28438 }
28439 else
28440 {
28441 c_parser_consume_token (parser);
28442 if (!c_parser_require (parser, type: CPP_EQ, msgid: "expected %<=%>"))
28443 bad = true;
28444 else
28445 {
28446 tree st = push_stmt_list ();
28447 location_t loc = c_parser_peek_token (parser)->location;
28448 rich_location richloc (line_table, loc);
28449 start_init (omp_priv, NULL_TREE, false, false, &richloc);
28450 struct c_expr init = c_parser_initializer (parser, decl: omp_priv);
28451 finish_init ();
28452 finish_decl (omp_priv, loc, init.value,
28453 init.original_type, NULL_TREE);
28454 pop_stmt_list (st);
28455 }
28456 }
28457 if (!bad
28458 && !c_parser_require (parser, type: CPP_CLOSE_PAREN, msgid: "expected %<)%>"))
28459 bad = true;
28460 }
28461
28462 if (!bad)
28463 {
28464 c_parser_skip_to_pragma_eol (parser);
28465
28466 tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
28467 DECL_INITIAL (reduc_decl));
28468 DECL_INITIAL (reduc_decl) = t;
28469 DECL_SOURCE_LOCATION (omp_out) = rloc;
28470 TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
28471 TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
28472 TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
28473 walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
28474 &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
28475 if (omp_priv)
28476 {
28477 DECL_SOURCE_LOCATION (omp_priv) = rloc;
28478 TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
28479 TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
28480 TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
28481 walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
28482 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28483 walk_tree (&DECL_INITIAL (omp_priv),
28484 c_check_omp_declare_reduction_r,
28485 &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
28486 }
28487 }
28488
28489 pop_stmt_list (stmt);
28490 pop_scope ();
28491 if (cfun->language != NULL)
28492 {
28493 ggc_free (cfun->language);
28494 cfun->language = NULL;
28495 }
28496 set_cfun (NULL);
28497 current_function_decl = NULL_TREE;
28498 if (nested)
28499 c_pop_function_context ();
28500
28501 if (!clauses.is_empty ())
28502 {
28503 parser->tokens = saved_tokens;
28504 parser->tokens_avail = tokens_avail;
28505 }
28506 if (bad)
28507 goto fail;
28508 if (errs != errorcount)
28509 break;
28510 }
28511
28512 clauses.release ();
28513 types.release ();
28514}
28515
28516/* OpenMP 4.0
28517 #pragma omp declare simd declare-simd-clauses[optseq] new-line
28518 #pragma omp declare reduction (reduction-id : typename-list : expression) \
28519 initializer-clause[opt] new-line
28520 #pragma omp declare target new-line
28521
28522 OpenMP 5.0
28523 #pragma omp declare variant (identifier) match (context-selector)
28524
28525 OpenMP 5.1
28526 #pragma omp declare variant (identifier) match (context-selector) \
28527 adjust_args(adjust-op:argument-list) */
28528
28529static bool
28530c_parser_omp_declare (c_parser *parser, enum pragma_context context)
28531{
28532 c_parser_consume_pragma (parser);
28533 if (c_parser_next_token_is (parser, type: CPP_NAME))
28534 {
28535 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28536 if (strcmp (s1: p, s2: "simd") == 0)
28537 {
28538 /* c_parser_consume_token (parser); done in
28539 c_parser_omp_declare_simd. */
28540 c_parser_omp_declare_simd (parser, context);
28541 return true;
28542 }
28543 if (strcmp (s1: p, s2: "reduction") == 0)
28544 {
28545 c_parser_consume_token (parser);
28546 c_parser_omp_declare_reduction (parser, context);
28547 return false;
28548 }
28549 if (strcmp (s1: p, s2: "mapper") == 0)
28550 {
28551 c_parser_consume_token (parser);
28552 c_parser_omp_declare_mapper (parser, context);
28553 return false;
28554 }
28555 if (!flag_openmp) /* flag_openmp_simd */
28556 {
28557 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28558 return false;
28559 }
28560 if (strcmp (s1: p, s2: "target") == 0)
28561 {
28562 c_parser_consume_token (parser);
28563 c_parser_omp_declare_target (parser);
28564 return false;
28565 }
28566 if (strcmp (s1: p, s2: "variant") == 0)
28567 {
28568 /* c_parser_consume_token (parser); done in
28569 c_parser_omp_declare_simd. */
28570 c_parser_omp_declare_simd (parser, context);
28571 return true;
28572 }
28573 }
28574
28575 c_parser_error (parser, gmsgid: "expected %<simd%>, %<reduction%>, "
28576 "%<target%> or %<variant%>");
28577 c_parser_skip_to_pragma_eol (parser);
28578 return false;
28579}
28580
28581/* OpenMP 5.0
28582 #pragma omp requires clauses[optseq] new-line */
28583
28584static void
28585c_parser_omp_requires (c_parser *parser)
28586{
28587 enum omp_requires new_req = (enum omp_requires) 0;
28588
28589 c_parser_consume_pragma (parser);
28590
28591 location_t loc = c_parser_peek_token (parser)->location;
28592 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
28593 {
28594 if (c_parser_next_token_is (parser, type: CPP_COMMA)
28595 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28596 c_parser_consume_token (parser);
28597
28598 if (c_parser_next_token_is (parser, type: CPP_NAME))
28599 {
28600 const char *p
28601 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28602 location_t cloc = c_parser_peek_token (parser)->location;
28603 enum omp_requires this_req = (enum omp_requires) 0;
28604
28605 if (!strcmp (s1: p, s2: "unified_address"))
28606 this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
28607 else if (!strcmp (s1: p, s2: "unified_shared_memory"))
28608 this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
28609 else if (!strcmp (s1: p, s2: "self_maps"))
28610 this_req = OMP_REQUIRES_SELF_MAPS;
28611 else if (!strcmp (s1: p, s2: "dynamic_allocators"))
28612 this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
28613 else if (!strcmp (s1: p, s2: "reverse_offload"))
28614 this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
28615 else if (!strcmp (s1: p, s2: "atomic_default_mem_order"))
28616 {
28617 c_parser_consume_token (parser);
28618
28619 matching_parens parens;
28620 if (parens.require_open (parser))
28621 {
28622 if (c_parser_next_token_is (parser, type: CPP_NAME))
28623 {
28624 tree v = c_parser_peek_token (parser)->value;
28625 p = IDENTIFIER_POINTER (v);
28626
28627 if (!strcmp (s1: p, s2: "seq_cst"))
28628 this_req
28629 = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
28630 else if (!strcmp (s1: p, s2: "relaxed"))
28631 this_req
28632 = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
28633 else if (!strcmp (s1: p, s2: "release"))
28634 this_req
28635 = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE;
28636 else if (!strcmp (s1: p, s2: "acq_rel"))
28637 this_req
28638 = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
28639 else if (!strcmp (s1: p, s2: "acquire"))
28640 this_req
28641 = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE;
28642 }
28643 if (this_req == 0)
28644 {
28645 error_at (c_parser_peek_token (parser)->location,
28646 "expected %<acq_rel%>, %<acquire%>, "
28647 "%<relaxed%>, %<release%> or %<seq_cst%>");
28648 switch (c_parser_peek_token (parser)->type)
28649 {
28650 case CPP_EOF:
28651 case CPP_PRAGMA_EOL:
28652 case CPP_CLOSE_PAREN:
28653 break;
28654 default:
28655 if (c_parser_peek_2nd_token (parser)->type
28656 == CPP_CLOSE_PAREN)
28657 c_parser_consume_token (parser);
28658 break;
28659 }
28660 }
28661 else
28662 c_parser_consume_token (parser);
28663
28664 parens.skip_until_found_close (parser);
28665 if (this_req == 0)
28666 {
28667 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28668 return;
28669 }
28670 }
28671 p = NULL;
28672 }
28673 else
28674 {
28675 error_at (cloc, "expected %<unified_address%>, "
28676 "%<unified_shared_memory%>, "
28677 "%<self_maps%>, "
28678 "%<dynamic_allocators%>, "
28679 "%<reverse_offload%> "
28680 "or %<atomic_default_mem_order%> clause");
28681 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28682 return;
28683 }
28684 if (p)
28685 c_parser_consume_token (parser);
28686 if (this_req)
28687 {
28688 if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28689 {
28690 if ((this_req & new_req) != 0)
28691 error_at (cloc, "too many %qs clauses", p);
28692 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
28693 && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
28694 error_at (cloc, "%qs clause used lexically after first "
28695 "target construct or offloading API", p);
28696 }
28697 else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28698 {
28699 error_at (cloc, "too many %qs clauses",
28700 "atomic_default_mem_order");
28701 this_req = (enum omp_requires) 0;
28702 }
28703 else if ((omp_requires_mask
28704 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
28705 {
28706 error_at (cloc, "more than one %<atomic_default_mem_order%>"
28707 " clause in a single compilation unit");
28708 this_req
28709 = (enum omp_requires)
28710 (omp_requires_mask
28711 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
28712 }
28713 else if ((omp_requires_mask
28714 & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
28715 error_at (cloc, "%<atomic_default_mem_order%> clause used "
28716 "lexically after first %<atomic%> construct "
28717 "without memory order clause");
28718 new_req = (enum omp_requires) (new_req | this_req);
28719 omp_requires_mask
28720 = (enum omp_requires) (omp_requires_mask | this_req);
28721 continue;
28722 }
28723 }
28724 break;
28725 }
28726 c_parser_skip_to_pragma_eol (parser);
28727
28728 if (new_req == 0)
28729 error_at (loc, "%<pragma omp requires%> requires at least one clause");
28730}
28731
28732/* Helper function for c_parser_omp_taskloop.
28733 Disallow zero sized or potentially zero sized task reductions. */
28734
28735static tree
28736c_finish_taskloop_clauses (tree clauses)
28737{
28738 tree *pc = &clauses;
28739 for (tree c = clauses; c; c = *pc)
28740 {
28741 bool remove = false;
28742 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
28743 {
28744 tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
28745 if (integer_zerop (TYPE_SIZE_UNIT (type)))
28746 {
28747 error_at (OMP_CLAUSE_LOCATION (c),
28748 "zero sized type %qT in %<reduction%> clause", type);
28749 remove = true;
28750 }
28751 else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
28752 {
28753 error_at (OMP_CLAUSE_LOCATION (c),
28754 "variable sized type %qT in %<reduction%> clause",
28755 type);
28756 remove = true;
28757 }
28758 }
28759 if (remove)
28760 *pc = OMP_CLAUSE_CHAIN (c);
28761 else
28762 pc = &OMP_CLAUSE_CHAIN (c);
28763 }
28764 return clauses;
28765}
28766
28767/* OpenMP 4.5:
28768 #pragma omp taskloop taskloop-clause[optseq] new-line
28769 for-loop
28770
28771 #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
28772 for-loop */
28773
28774#define OMP_TASKLOOP_CLAUSE_MASK \
28775 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
28776 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
28777 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
28778 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
28779 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
28780 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
28781 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
28782 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
28783 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
28784 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
28785 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
28786 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
28787 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
28788 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
28789 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
28790 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
28791 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
28792
28793static tree
28794c_parser_omp_taskloop (location_t loc, c_parser *parser,
28795 char *p_name, omp_clause_mask mask, tree *cclauses,
28796 bool *if_p)
28797{
28798 tree clauses, block, ret;
28799
28800 strcat (dest: p_name, src: " taskloop");
28801 mask |= OMP_TASKLOOP_CLAUSE_MASK;
28802 /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
28803 clause. */
28804 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
28805 mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
28806
28807 if (c_parser_next_token_is (parser, type: CPP_NAME))
28808 {
28809 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28810
28811 if (strcmp (s1: p, s2: "simd") == 0)
28812 {
28813 tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
28814 if (cclauses == NULL)
28815 cclauses = cclauses_buf;
28816 c_parser_consume_token (parser);
28817 if (!flag_openmp) /* flag_openmp_simd */
28818 return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
28819 if_p);
28820 block = c_begin_compound_stmt (true);
28821 ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
28822 block = c_end_compound_stmt (loc, block, true);
28823 if (ret == NULL)
28824 return ret;
28825 ret = make_node (OMP_TASKLOOP);
28826 TREE_TYPE (ret) = void_type_node;
28827 OMP_FOR_BODY (ret) = block;
28828 OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
28829 OMP_FOR_CLAUSES (ret)
28830 = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
28831 SET_EXPR_LOCATION (ret, loc);
28832 add_stmt (ret);
28833 return ret;
28834 }
28835 }
28836 if (!flag_openmp) /* flag_openmp_simd */
28837 {
28838 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
28839 return NULL_TREE;
28840 }
28841
28842 clauses = c_parser_omp_all_clauses (parser, mask, where: p_name, finish_p: cclauses == NULL);
28843 if (cclauses)
28844 {
28845 omp_split_clauses (loc, code: OMP_TASKLOOP, mask, clauses, cclauses);
28846 clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
28847 }
28848
28849 clauses = c_finish_taskloop_clauses (clauses);
28850 block = c_begin_compound_stmt (true);
28851 ret = c_parser_omp_for_loop (loc, parser, code: OMP_TASKLOOP, clauses, NULL, if_p);
28852 block = c_end_compound_stmt (loc, block, true);
28853 add_stmt (block);
28854
28855 return ret;
28856}
28857
28858/* OpenMP 5.1: Parse sizes list for "omp tile sizes"
28859 sizes ( size-expr-list ) */
28860static tree
28861c_parser_omp_tile_sizes (c_parser *parser, location_t loc)
28862{
28863 tree sizes = NULL_TREE;
28864
28865 if (c_parser_next_token_is (parser, type: CPP_COMMA))
28866 c_parser_consume_token (parser);
28867
28868 c_token *tok = c_parser_peek_token (parser);
28869 if (tok->type != CPP_NAME
28870 || strcmp (s1: "sizes", IDENTIFIER_POINTER (tok->value)))
28871 {
28872 c_parser_error (parser, gmsgid: "expected %<sizes%>");
28873 return error_mark_node;
28874 }
28875 c_parser_consume_token (parser);
28876
28877 matching_parens parens;
28878 if (!parens.require_open (parser))
28879 return error_mark_node;
28880
28881 vec<tree, va_gc> *sizes_vec
28882 = c_parser_expr_list (parser, convert_p: true, fold_p: true, NULL, NULL, NULL, NULL);
28883 sizes = build_tree_list_vec (sizes_vec);
28884 release_tree_vector (sizes_vec);
28885
28886 for (tree s = sizes; s; s = TREE_CHAIN (s))
28887 {
28888 tree expr = TREE_VALUE (s);
28889 if (expr == error_mark_node)
28890 {
28891 parens.skip_until_found_close (parser);
28892 return error_mark_node;
28893 }
28894
28895 HOST_WIDE_INT n;
28896 if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
28897 || !tree_fits_shwi_p (expr)
28898 || (n = tree_to_shwi (expr)) <= 0
28899 || (int) n != n)
28900 {
28901 c_parser_error (parser, gmsgid: "%<sizes%> argument needs positive"
28902 " integral constant");
28903 TREE_VALUE (s) = integer_one_node;
28904 }
28905 }
28906 parens.require_close (parser);
28907
28908 gcc_assert (sizes);
28909 tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES);
28910 OMP_CLAUSE_SIZES_LIST (c) = sizes;
28911
28912 return c;
28913}
28914
28915/* OpenMP 5.1:
28916 #pragma omp tile sizes ( size-expr-list ) new-line
28917 for-loop
28918
28919 LOC is the location of the #pragma token. */
28920
28921static tree
28922c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p)
28923{
28924 tree clauses = c_parser_omp_tile_sizes (parser, loc);
28925 c_parser_skip_to_pragma_eol (parser);
28926
28927 if (!clauses || clauses == error_mark_node)
28928 return error_mark_node;
28929
28930 tree block = c_begin_compound_stmt (true);
28931 tree ret = c_parser_omp_for_loop (loc, parser, code: OMP_TILE, clauses,
28932 NULL, if_p);
28933 block = c_end_compound_stmt (loc, block, true);
28934 add_stmt (block);
28935
28936 return ret;
28937}
28938
28939#define OMP_UNROLL_CLAUSE_MASK \
28940 ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \
28941 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL))
28942
28943/* OpenMP 5.1
28944 #pragma omp unroll unroll-clause[optseq] new-line
28945 for-loop
28946
28947 LOC is the location of the #pragma token. */
28948
28949static tree
28950c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p)
28951{
28952 tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK,
28953 where: "#pragma omp unroll", finish_p: true);
28954
28955 tree block = c_begin_compound_stmt (true);
28956 tree ret = c_parser_omp_for_loop (loc, parser, code: OMP_UNROLL, clauses,
28957 NULL, if_p);
28958 block = c_end_compound_stmt (loc, block, true);
28959 add_stmt (block);
28960
28961 return ret;
28962}
28963
28964/* OpenMP 5.1
28965 #pragma omp nothing new-line */
28966
28967static void
28968c_parser_omp_nothing (c_parser *parser)
28969{
28970 c_parser_consume_pragma (parser);
28971 c_parser_skip_to_pragma_eol (parser);
28972}
28973
28974/* OpenMP 5.1
28975 #pragma omp error clauses[optseq] new-line */
28976
28977static bool
28978c_parser_omp_error (c_parser *parser, enum pragma_context context)
28979{
28980 int at_compilation = -1;
28981 int severity_fatal = -1;
28982 tree message = NULL_TREE;
28983 bool bad = false;
28984 location_t loc = c_parser_peek_token (parser)->location;
28985
28986 c_parser_consume_pragma (parser);
28987
28988 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
28989 {
28990 if (c_parser_next_token_is (parser, type: CPP_COMMA)
28991 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
28992 c_parser_consume_token (parser);
28993
28994 if (!c_parser_next_token_is (parser, type: CPP_NAME))
28995 break;
28996
28997 const char *p
28998 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
28999 location_t cloc = c_parser_peek_token (parser)->location;
29000 static const char *args[] = {
29001 "execution", "compilation", "warning", "fatal"
29002 };
29003 int *v = NULL;
29004 int idx = 0, n = -1;
29005 tree m = NULL_TREE;
29006
29007 if (!strcmp (s1: p, s2: "at"))
29008 v = &at_compilation;
29009 else if (!strcmp (s1: p, s2: "severity"))
29010 {
29011 v = &severity_fatal;
29012 idx += 2;
29013 }
29014 else if (strcmp (s1: p, s2: "message"))
29015 {
29016 error_at (cloc,
29017 "expected %<at%>, %<severity%> or %<message%> clause");
29018 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29019 return false;
29020 }
29021
29022 c_parser_consume_token (parser);
29023
29024 matching_parens parens;
29025 if (parens.require_open (parser))
29026 {
29027 if (v == NULL)
29028 {
29029 location_t expr_loc = c_parser_peek_token (parser)->location;
29030 c_expr expr = c_parser_expr_no_commas (parser, NULL);
29031 expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
29032 m = convert (const_string_type_node, expr.value);
29033 m = c_fully_fold (m, false, NULL);
29034 }
29035 else
29036 {
29037 if (c_parser_next_token_is (parser, type: CPP_NAME))
29038 {
29039 tree val = c_parser_peek_token (parser)->value;
29040 const char *q = IDENTIFIER_POINTER (val);
29041
29042 if (!strcmp (s1: q, s2: args[idx]))
29043 n = 0;
29044 else if (!strcmp (s1: q, s2: args[idx + 1]))
29045 n = 1;
29046 }
29047 if (n == -1)
29048 {
29049 error_at (c_parser_peek_token (parser)->location,
29050 "expected %qs or %qs", args[idx], args[idx + 1]);
29051 bad = true;
29052 switch (c_parser_peek_token (parser)->type)
29053 {
29054 case CPP_EOF:
29055 case CPP_PRAGMA_EOL:
29056 case CPP_CLOSE_PAREN:
29057 break;
29058 default:
29059 if (c_parser_peek_2nd_token (parser)->type
29060 == CPP_CLOSE_PAREN)
29061 c_parser_consume_token (parser);
29062 break;
29063 }
29064 }
29065 else
29066 c_parser_consume_token (parser);
29067 }
29068
29069 parens.skip_until_found_close (parser);
29070
29071 if (v == NULL)
29072 {
29073 if (message)
29074 {
29075 error_at (cloc, "too many %qs clauses", p);
29076 bad = true;
29077 }
29078 else
29079 message = m;
29080 }
29081 else if (n != -1)
29082 {
29083 if (*v != -1)
29084 {
29085 error_at (cloc, "too many %qs clauses", p);
29086 bad = true;
29087 }
29088 else
29089 *v = n;
29090 }
29091 }
29092 else
29093 bad = true;
29094 }
29095 c_parser_skip_to_pragma_eol (parser);
29096 if (bad)
29097 return true;
29098
29099 if (at_compilation == -1)
29100 at_compilation = 1;
29101 if (severity_fatal == -1)
29102 severity_fatal = 1;
29103 if (!at_compilation)
29104 {
29105 if (context != pragma_compound)
29106 {
29107 error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
29108 "may only be used in compound statements");
29109 return true;
29110 }
29111 tree fndecl
29112 = builtin_decl_explicit (fncode: severity_fatal ? BUILT_IN_GOMP_ERROR
29113 : BUILT_IN_GOMP_WARNING);
29114 if (!message)
29115 message = build_zero_cst (const_string_type_node);
29116 tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
29117 build_all_ones_cst (size_type_node));
29118 add_stmt (stmt);
29119 return true;
29120 }
29121 const char *msg = NULL;
29122 if (message)
29123 {
29124 msg = c_getstr (message);
29125 if (msg == NULL)
29126 msg = _("<message unknown at compile time>");
29127 }
29128 if (msg)
29129 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
29130 "%<pragma omp error%> encountered: %s", msg);
29131 else
29132 emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
29133 "%<pragma omp error%> encountered");
29134 return false;
29135}
29136
29137/* Assumption clauses:
29138 OpenMP 5.1
29139 absent (directive-name-list)
29140 contains (directive-name-list)
29141 holds (expression)
29142 no_openmp
29143 no_openmp_routines
29144 no_parallelism */
29145
29146static void
29147c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume)
29148{
29149 bool no_openmp = false;
29150 bool no_openmp_routines = false;
29151 bool no_parallelism = false;
29152 bitmap_head absent_head, contains_head;
29153
29154 bitmap_obstack_initialize (NULL);
29155 bitmap_initialize (head: &absent_head, obstack: &bitmap_default_obstack);
29156 bitmap_initialize (head: &contains_head, obstack: &bitmap_default_obstack);
29157
29158 if (c_parser_next_token_is (parser, type: CPP_PRAGMA_EOL))
29159 error_at (c_parser_peek_token (parser)->location,
29160 "expected at least one assumption clause");
29161
29162 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
29163 {
29164 if (c_parser_next_token_is (parser, type: CPP_COMMA)
29165 && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
29166 c_parser_consume_token (parser);
29167
29168 if (!c_parser_next_token_is (parser, type: CPP_NAME))
29169 break;
29170
29171 const char *p
29172 = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29173 location_t cloc = c_parser_peek_token (parser)->location;
29174
29175 if (!strcmp (s1: p, s2: "no_openmp"))
29176 {
29177 c_parser_consume_token (parser);
29178 if (no_openmp)
29179 error_at (cloc, "too many %qs clauses", "no_openmp");
29180 no_openmp = true;
29181 }
29182 else if (!strcmp (s1: p, s2: "no_openmp_routines"))
29183 {
29184 c_parser_consume_token (parser);
29185 if (no_openmp_routines)
29186 error_at (cloc, "too many %qs clauses", "no_openmp_routines");
29187 no_openmp_routines = true;
29188 }
29189 else if (!strcmp (s1: p, s2: "no_parallelism"))
29190 {
29191 c_parser_consume_token (parser);
29192 if (no_parallelism)
29193 error_at (cloc, "too many %qs clauses", "no_parallelism");
29194 no_parallelism = true;
29195 }
29196 else if (!strcmp (s1: p, s2: "holds"))
29197 {
29198 c_parser_consume_token (parser);
29199 matching_parens parens;
29200 if (parens.require_open (parser))
29201 {
29202 location_t eloc = c_parser_peek_token (parser)->location;
29203 c_expr expr = c_parser_expr_no_commas (parser, NULL);
29204 tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
29205 t = c_objc_common_truthvalue_conversion (eloc, t);
29206 t = c_fully_fold (t, false, NULL);
29207 if (is_assume && t != error_mark_node)
29208 {
29209 tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME,
29210 void_type_node, 1,
29211 t);
29212 add_stmt (fn);
29213 }
29214 parens.skip_until_found_close (parser);
29215 }
29216 }
29217 else if (!strcmp (s1: p, s2: "absent") || !strcmp (s1: p, s2: "contains"))
29218 {
29219 c_parser_consume_token (parser);
29220 matching_parens parens;
29221 if (parens.require_open (parser))
29222 {
29223 do
29224 {
29225 const char *directive[3] = {};
29226 int i;
29227 location_t dloc = c_parser_peek_token (parser)->location;
29228 for (i = 0; i < 3; i++)
29229 {
29230 tree id;
29231 if (c_parser_peek_nth_token (parser, n: i + 1)->type
29232 == CPP_NAME)
29233 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
29234 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
29235 != RID_MAX)
29236 {
29237 enum rid rid
29238 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
29239 id = ridpointers[rid];
29240 }
29241 else
29242 break;
29243 directive[i] = IDENTIFIER_POINTER (id);
29244 }
29245 if (i == 0)
29246 error_at (dloc, "expected directive name");
29247 else
29248 {
29249 const struct c_omp_directive *dir
29250 = c_omp_categorize_directive (directive[0],
29251 directive[1],
29252 directive[2]);
29253 if (dir
29254 && (dir->kind == C_OMP_DIR_DECLARATIVE
29255 || dir->kind == C_OMP_DIR_INFORMATIONAL
29256 || dir->kind == C_OMP_DIR_META))
29257 error_at (dloc, "invalid OpenMP directive name in "
29258 "%qs clause argument: declarative, "
29259 "informational, and meta directives "
29260 "not permitted", p);
29261 else if (dir == NULL
29262 || dir->id == PRAGMA_OMP_END
29263 || (!dir->second && directive[1])
29264 || (!dir->third && directive[2]))
29265 error_at (dloc, "unknown OpenMP directive name in "
29266 "%qs clause argument", p);
29267 else
29268 {
29269 int id = dir - c_omp_directives;
29270 if (bitmap_bit_p (p[0] == 'a' ? &contains_head
29271 : &absent_head, id))
29272 error_at (dloc, "%<%s%s%s%s%s%> directive "
29273 "mentioned in both %<absent%> and "
29274 "%<contains%> clauses",
29275 directive[0],
29276 directive[1] ? " " : "",
29277 directive[1] ? directive[1] : "",
29278 directive[2] ? " " : "",
29279 directive[2] ? directive[2] : "");
29280 else if (!bitmap_set_bit (p[0] == 'a'
29281 ? &absent_head
29282 : &contains_head, id))
29283 error_at (dloc, "%<%s%s%s%s%s%> directive "
29284 "mentioned multiple times in %qs "
29285 "clauses",
29286 directive[0],
29287 directive[1] ? " " : "",
29288 directive[1] ? directive[1] : "",
29289 directive[2] ? " " : "",
29290 directive[2] ? directive[2] : "", p);
29291 }
29292 for (; i; --i)
29293 c_parser_consume_token (parser);
29294 }
29295 if (c_parser_next_token_is (parser, type: CPP_COMMA))
29296 c_parser_consume_token (parser);
29297 else
29298 break;
29299 }
29300 while (1);
29301 parens.skip_until_found_close (parser);
29302 }
29303 }
29304 else if (startswith (str: p, prefix: "ext_"))
29305 {
29306 warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p);
29307 c_parser_consume_token (parser);
29308 if (c_parser_next_token_is (parser, type: CPP_OPEN_PAREN))
29309 {
29310 matching_parens parens;
29311 parens.consume_open (parser);
29312 c_parser_balanced_token_sequence (parser);
29313 parens.require_close (parser);
29314 }
29315 }
29316 else
29317 {
29318 c_parser_consume_token (parser);
29319 error_at (cloc, "expected assumption clause");
29320 break;
29321 }
29322 }
29323 c_parser_skip_to_pragma_eol (parser);
29324}
29325
29326/* OpenMP 5.1
29327 #pragma omp assume clauses[optseq] new-line */
29328
29329static void
29330c_parser_omp_assume (c_parser *parser, bool *if_p)
29331{
29332 c_parser_omp_assumption_clauses (parser, is_assume: true);
29333 add_stmt (c_parser_omp_structured_block (parser, if_p));
29334}
29335
29336/* OpenMP 5.1
29337 #pragma omp assumes clauses[optseq] new-line */
29338
29339static void
29340c_parser_omp_assumes (c_parser *parser)
29341{
29342 c_parser_consume_pragma (parser);
29343 c_parser_omp_assumption_clauses (parser, is_assume: false);
29344}
29345
29346/* Helper function for c_parser_omp_metadirective. */
29347
29348static void
29349analyze_metadirective_body (c_parser *parser,
29350 vec<c_token> &tokens,
29351 vec<tree> &labels)
29352{
29353 int nesting_depth = 0;
29354 int bracket_depth = 0;
29355 bool ignore_label = false;
29356
29357 /* Read in the body tokens to the tokens for each candidate directive. */
29358 while (1)
29359 {
29360 c_token *token = c_parser_peek_token (parser);
29361 bool stop = false;
29362
29363 if (c_parser_next_token_is_keyword (parser, keyword: RID_CASE))
29364 ignore_label = true;
29365
29366 switch (token->type)
29367 {
29368 case CPP_EOF:
29369 break;
29370 case CPP_NAME:
29371 if (!ignore_label
29372 && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
29373 labels.safe_push (obj: token->value);
29374 goto add;
29375 case CPP_OPEN_BRACE:
29376 ++nesting_depth;
29377 goto add;
29378 case CPP_CLOSE_BRACE:
29379 if (--nesting_depth == 0 && bracket_depth == 0)
29380 stop = true;
29381 goto add;
29382 case CPP_OPEN_PAREN:
29383 ++bracket_depth;
29384 goto add;
29385 case CPP_CLOSE_PAREN:
29386 --bracket_depth;
29387 goto add;
29388 case CPP_COLON:
29389 ignore_label = false;
29390 goto add;
29391 case CPP_SEMICOLON:
29392 if (nesting_depth == 0 && bracket_depth == 0)
29393 stop = true;
29394 goto add;
29395 default:
29396 add:
29397 tokens.safe_push (obj: *token);
29398 if (token->type == CPP_PRAGMA)
29399 c_parser_consume_pragma (parser);
29400 else if (token->type == CPP_PRAGMA_EOL)
29401 c_parser_skip_to_pragma_eol (parser);
29402 else
29403 c_parser_consume_token (parser);
29404 if (stop)
29405 break;
29406 continue;
29407 }
29408 break;
29409 }
29410}
29411
29412/* OpenMP 5.0:
29413
29414 # pragma omp metadirective [clause[, clause]]
29415*/
29416
29417static void
29418c_parser_omp_metadirective (c_parser *parser, bool *if_p)
29419{
29420 static unsigned int metadirective_region_count = 0;
29421
29422 tree ret;
29423 auto_vec<c_token> directive_tokens;
29424 auto_vec<c_token> body_tokens;
29425 auto_vec<tree> body_labels;
29426 auto_vec<const struct c_omp_directive *> directives;
29427 auto_vec<tree> ctxs;
29428 vec<struct omp_variant> candidates;
29429 bool default_seen = false;
29430 int directive_token_idx = 0;
29431 tree standalone_body = NULL_TREE;
29432 location_t pragma_loc = c_parser_peek_token (parser)->location;
29433 bool requires_body = false;
29434
29435 ret = make_node (OMP_METADIRECTIVE);
29436 SET_EXPR_LOCATION (ret, pragma_loc);
29437 TREE_TYPE (ret) = void_type_node;
29438 OMP_METADIRECTIVE_VARIANTS (ret) = NULL_TREE;
29439
29440 c_parser_consume_pragma (parser);
29441 while (c_parser_next_token_is_not (parser, type: CPP_PRAGMA_EOL))
29442 {
29443 if (c_parser_next_token_is (parser, type: CPP_COMMA))
29444 c_parser_consume_token (parser);
29445 if (c_parser_next_token_is_not (parser, type: CPP_NAME)
29446 && c_parser_next_token_is_not (parser, type: CPP_KEYWORD))
29447 {
29448 c_parser_error (parser, gmsgid: "expected %<when%>, "
29449 "%<otherwise%>, or %<default%> clause");
29450 goto error;
29451 }
29452
29453 location_t match_loc = c_parser_peek_token (parser)->location;
29454 const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
29455 c_parser_consume_token (parser);
29456 bool default_p
29457 = strcmp (s1: p, s2: "default") == 0 || strcmp (s1: p, s2: "otherwise") == 0;
29458 if (default_p)
29459 {
29460 if (default_seen)
29461 {
29462 error_at (match_loc, "too many %<otherwise%> or %<default%> "
29463 "clauses in %<metadirective%>");
29464 goto error;
29465 }
29466 default_seen = true;
29467 }
29468 else if (default_seen)
29469 {
29470 error_at (match_loc, "%<otherwise%> or %<default%> clause "
29471 "must appear last in %<metadirective%>");
29472 goto error;
29473 }
29474 if (!default_p && strcmp (s1: p, s2: "when") != 0)
29475 {
29476 error_at (match_loc, "%qs is not valid for %qs",
29477 p, "metadirective");
29478 goto error;
29479 }
29480
29481 matching_parens parens;
29482 tree ctx = NULL_TREE;
29483 bool skip = false;
29484
29485 if (!parens.require_open (parser))
29486 goto error;
29487
29488 if (!default_p)
29489 {
29490 ctx = c_parser_omp_context_selector_specification (parser,
29491 NULL_TREE);
29492 if (ctx == error_mark_node)
29493 goto error;
29494 ctx = omp_check_context_selector (loc: match_loc, ctx,
29495 directive: OMP_CTX_METADIRECTIVE);
29496 if (ctx == error_mark_node)
29497 goto error;
29498
29499 /* Remove the selector from further consideration if it can be
29500 evaluated as a non-match at this point. */
29501 skip = (omp_context_selector_matches (ctx, NULL_TREE, false) == 0);
29502
29503 if (c_parser_next_token_is_not (parser, type: CPP_COLON))
29504 {
29505 c_parser_require (parser, type: CPP_COLON, msgid: "expected %<:%>");
29506 goto error;
29507 }
29508 c_parser_consume_token (parser);
29509 }
29510
29511 /* Read in the directive type and create a dummy pragma token for
29512 it. */
29513 location_t loc = c_parser_peek_token (parser)->location;
29514
29515 const char *directive[3] = {};
29516 int i;
29517 for (i = 0; i < 3; i++)
29518 {
29519 tree id;
29520 if (c_parser_peek_nth_token (parser, n: i + 1)->type
29521 == CPP_CLOSE_PAREN)
29522 {
29523 if (i == 0)
29524 directive[i++] = "nothing";
29525 break;
29526 }
29527 else if (c_parser_peek_nth_token (parser, n: i + 1)->type
29528 == CPP_NAME)
29529 id = c_parser_peek_nth_token (parser, n: i + 1)->value;
29530 else if (c_parser_peek_nth_token (parser, n: i + 1)->keyword
29531 != RID_MAX)
29532 {
29533 enum rid rid
29534 = c_parser_peek_nth_token (parser, n: i + 1)->keyword;
29535 id = ridpointers[rid];
29536 }
29537 else
29538 break;
29539
29540 directive[i] = IDENTIFIER_POINTER (id);
29541 }
29542 if (i == 0)
29543 {
29544 error_at (loc, "expected directive name");
29545 goto error;
29546 }
29547
29548 const struct c_omp_directive *omp_directive
29549 = c_omp_categorize_directive (directive[0],
29550 directive[1],
29551 directive[2]);
29552
29553 if (omp_directive == NULL)
29554 {
29555 for (int j = 0; j < i; j++)
29556 c_parser_consume_token (parser);
29557 c_parser_error (parser, gmsgid: "unknown directive name");
29558 goto error;
29559 }
29560 else
29561 {
29562 int token_count = 0;
29563 if (omp_directive->first) token_count++;
29564 if (omp_directive->second) token_count++;
29565 if (omp_directive->third) token_count++;
29566 for (int j = 0; j < token_count; j++)
29567 c_parser_consume_token (parser);
29568 }
29569 if (omp_directive->id == PRAGMA_OMP_METADIRECTIVE)
29570 {
29571 c_parser_error (parser,
29572 gmsgid: "metadirectives cannot be used as variants of a "
29573 "%<metadirective%>");
29574 goto error;
29575 }
29576 if (omp_directive->kind == C_OMP_DIR_DECLARATIVE)
29577 {
29578 sorry_at (loc, "declarative directive variants of a "
29579 "%<metadirective%> are not supported");
29580 goto error;
29581 }
29582 if (omp_directive->kind == C_OMP_DIR_CONSTRUCT)
29583 requires_body = true;
29584
29585 if (!skip)
29586 {
29587 c_token pragma_token;
29588 pragma_token.type = CPP_PRAGMA;
29589 pragma_token.location = loc;
29590 pragma_token.pragma_kind = (enum pragma_kind) omp_directive->id;
29591
29592 directives.safe_push (obj: omp_directive);
29593 directive_tokens.safe_push (obj: pragma_token);
29594 ctxs.safe_push (obj: ctx);
29595 }
29596
29597 /* Read in tokens for the directive clauses. */
29598 int nesting_depth = 0;
29599 while (1)
29600 {
29601 c_token *token = c_parser_peek_token (parser);
29602 switch (token->type)
29603 {
29604 case CPP_EOF:
29605 case CPP_PRAGMA_EOL:
29606 break;
29607 case CPP_OPEN_PAREN:
29608 ++nesting_depth;
29609 goto add;
29610 case CPP_CLOSE_PAREN:
29611 if (nesting_depth-- == 0)
29612 {
29613 c_parser_consume_token (parser);
29614 break;
29615 }
29616 goto add;
29617 default:
29618 add:
29619 if (!skip)
29620 directive_tokens.safe_push (obj: *token);
29621 c_parser_consume_token (parser);
29622 continue;
29623 }
29624 break;
29625 }
29626
29627 if (!skip)
29628 {
29629 c_token eol_token;
29630 memset (s: &eol_token, c: 0, n: sizeof (eol_token));
29631 eol_token.type = CPP_PRAGMA_EOL;
29632 directive_tokens.safe_push (obj: eol_token);
29633 }
29634 }
29635 c_parser_skip_to_pragma_eol (parser);
29636
29637 if (!default_seen)
29638 {
29639 /* Add a default clause that evaluates to 'omp nothing'. */
29640 const struct c_omp_directive *omp_directive
29641 = c_omp_categorize_directive ("nothing", NULL, NULL);
29642
29643 c_token pragma_token;
29644 pragma_token.type = CPP_PRAGMA;
29645 pragma_token.location = UNKNOWN_LOCATION;
29646 pragma_token.pragma_kind = PRAGMA_OMP_NOTHING;
29647
29648 directives.safe_push (obj: omp_directive);
29649 directive_tokens.safe_push (obj: pragma_token);
29650 ctxs.safe_push (NULL_TREE);
29651
29652 c_token eol_token;
29653 memset (s: &eol_token, c: 0, n: sizeof (eol_token));
29654 eol_token.type = CPP_PRAGMA_EOL;
29655 directive_tokens.safe_push (obj: eol_token);
29656 }
29657
29658 if (requires_body)
29659 analyze_metadirective_body (parser, tokens&: body_tokens, labels&: body_labels);
29660
29661 /* Process each candidate directive. */
29662 unsigned i;
29663 tree ctx;
29664
29665 FOR_EACH_VEC_ELT (ctxs, i, ctx)
29666 {
29667 auto_vec<c_token> tokens;
29668
29669 /* Add the directive tokens. */
29670 do
29671 tokens.safe_push (obj: directive_tokens [directive_token_idx++]);
29672 while (tokens.last ().type != CPP_PRAGMA_EOL);
29673
29674 /* Add the body tokens. */
29675 gcc_assert (requires_body || body_tokens.is_empty ());
29676 for (unsigned j = 0; j < body_tokens.length (); j++)
29677 tokens.safe_push (obj: body_tokens[j]);
29678
29679 /* Make sure nothing tries to read past the end of the tokens. */
29680 c_token eof_token;
29681 memset (s: &eof_token, c: 0, n: sizeof (eof_token));
29682 eof_token.type = CPP_EOF;
29683 tokens.safe_push (obj: eof_token);
29684 tokens.safe_push (obj: eof_token);
29685
29686 unsigned int old_tokens_avail = parser->tokens_avail;
29687 c_token *old_tokens = parser->tokens;
29688 struct omp_attribute_pragma_state *old_in_omp_attribute_pragma
29689 = parser->in_omp_attribute_pragma;
29690 struct omp_metadirective_parse_data *old_state
29691 = parser->omp_metadirective_state;
29692
29693 struct omp_metadirective_parse_data new_state;
29694 new_state.body_labels = &body_labels;
29695 new_state.region_num = ++metadirective_region_count;
29696
29697 parser->tokens = tokens.address ();
29698 parser->tokens_avail = tokens.length ();
29699 parser->in_omp_attribute_pragma = NULL;
29700 parser->omp_metadirective_state = &new_state;
29701
29702 int prev_errorcount = errorcount;
29703 tree directive = c_begin_compound_stmt (true);
29704
29705 c_parser_pragma (parser, context: pragma_compound, if_p, NULL_TREE);
29706 directive = c_end_compound_stmt (pragma_loc, directive, true);
29707 bool standalone_p
29708 = directives[i]->kind == C_OMP_DIR_STANDALONE
29709 || directives[i]->kind == C_OMP_DIR_UTILITY;
29710 if (standalone_p && requires_body)
29711 {
29712 /* Parsing standalone directives will not consume the body
29713 tokens, so do that here. */
29714 if (standalone_body == NULL_TREE)
29715 {
29716 standalone_body = push_stmt_list ();
29717 c_parser_statement (parser, if_p);
29718 standalone_body = pop_stmt_list (standalone_body);
29719 }
29720 else
29721 c_parser_skip_to_end_of_block_or_statement (parser, metadirective_p: true);
29722 }
29723
29724 tree body = standalone_p ? standalone_body : NULL_TREE;
29725 tree variant = make_omp_metadirective_variant (ctx, directive, body);
29726 OMP_METADIRECTIVE_VARIANTS (ret)
29727 = chainon (OMP_METADIRECTIVE_VARIANTS (ret), variant);
29728
29729 /* Check that all valid tokens have been consumed if no parse errors
29730 encountered. */
29731 if (errorcount == prev_errorcount)
29732 {
29733 gcc_assert (parser->tokens_avail == 2);
29734 gcc_assert (c_parser_next_token_is (parser, CPP_EOF));
29735 gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF);
29736 }
29737
29738 parser->tokens = old_tokens;
29739 parser->tokens_avail = old_tokens_avail;
29740 parser->in_omp_attribute_pragma = old_in_omp_attribute_pragma;
29741 parser->omp_metadirective_state = old_state;
29742 }
29743
29744 /* Try to resolve the metadirective early. */
29745 candidates = omp_early_resolve_metadirective (ret);
29746 if (!candidates.is_empty ())
29747 ret = c_omp_expand_variant_construct (candidates);
29748
29749 add_stmt (ret);
29750 return;
29751
29752error:
29753 /* Skip the metadirective pragma. Do not skip the metadirective body. */
29754 if (parser->in_pragma)
29755 c_parser_skip_to_pragma_eol (parser, error_if_not_eol: false);
29756}
29757
29758/* Main entry point to parsing most OpenMP pragmas. */
29759
29760static void
29761c_parser_omp_construct (c_parser *parser, bool *if_p)
29762{
29763 enum pragma_kind p_kind;
29764 location_t loc;
29765 tree stmt;
29766 char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
29767 omp_clause_mask mask (0);
29768
29769 loc = c_parser_peek_token (parser)->location;
29770 p_kind = c_parser_peek_token (parser)->pragma_kind;
29771 c_parser_consume_pragma (parser);
29772
29773 switch (p_kind)
29774 {
29775 case PRAGMA_OACC_ATOMIC:
29776 c_parser_omp_atomic (loc, parser, openacc: true);
29777 return;
29778 case PRAGMA_OACC_CACHE:
29779 strcpy (dest: p_name, src: "#pragma acc");
29780 stmt = c_parser_oacc_cache (loc, parser);
29781 break;
29782 case PRAGMA_OACC_DATA:
29783 stmt = c_parser_oacc_data (loc, parser, if_p);
29784 break;
29785 case PRAGMA_OACC_HOST_DATA:
29786 stmt = c_parser_oacc_host_data (loc, parser, if_p);
29787 break;
29788 case PRAGMA_OACC_KERNELS:
29789 case PRAGMA_OACC_PARALLEL:
29790 case PRAGMA_OACC_SERIAL:
29791 strcpy (dest: p_name, src: "#pragma acc");
29792 stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
29793 break;
29794 case PRAGMA_OACC_LOOP:
29795 strcpy (dest: p_name, src: "#pragma acc");
29796 stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
29797 break;
29798 case PRAGMA_OACC_WAIT:
29799 strcpy (dest: p_name, src: "#pragma wait");
29800 stmt = c_parser_oacc_wait (loc, parser, p_name);
29801 break;
29802 case PRAGMA_OMP_ATOMIC:
29803 c_parser_omp_atomic (loc, parser, openacc: false);
29804 return;
29805 case PRAGMA_OMP_CRITICAL:
29806 stmt = c_parser_omp_critical (loc, parser, if_p);
29807 break;
29808 case PRAGMA_OMP_DISTRIBUTE:
29809 strcpy (dest: p_name, src: "#pragma omp");
29810 stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
29811 break;
29812 case PRAGMA_OMP_FOR:
29813 strcpy (dest: p_name, src: "#pragma omp");
29814 stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
29815 break;
29816 case PRAGMA_OMP_LOOP:
29817 strcpy (dest: p_name, src: "#pragma omp");
29818 stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
29819 break;
29820 case PRAGMA_OMP_MASKED:
29821 strcpy (dest: p_name, src: "#pragma omp");
29822 stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
29823 break;
29824 case PRAGMA_OMP_MASTER:
29825 strcpy (dest: p_name, src: "#pragma omp");
29826 stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
29827 break;
29828 case PRAGMA_OMP_PARALLEL:
29829 strcpy (dest: p_name, src: "#pragma omp");
29830 stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
29831 break;
29832 case PRAGMA_OMP_SCOPE:
29833 stmt = c_parser_omp_scope (loc, parser, if_p);
29834 break;
29835 case PRAGMA_OMP_SECTIONS:
29836 strcpy (dest: p_name, src: "#pragma omp");
29837 stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
29838 break;
29839 case PRAGMA_OMP_SIMD:
29840 strcpy (dest: p_name, src: "#pragma omp");
29841 stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
29842 break;
29843 case PRAGMA_OMP_SINGLE:
29844 stmt = c_parser_omp_single (loc, parser, if_p);
29845 break;
29846 case PRAGMA_OMP_TASK:
29847 stmt = c_parser_omp_task (loc, parser, if_p);
29848 break;
29849 case PRAGMA_OMP_TASKGROUP:
29850 stmt = c_parser_omp_taskgroup (loc, parser, if_p);
29851 break;
29852 case PRAGMA_OMP_TASKLOOP:
29853 strcpy (dest: p_name, src: "#pragma omp");
29854 stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
29855 break;
29856 case PRAGMA_OMP_TEAMS:
29857 strcpy (dest: p_name, src: "#pragma omp");
29858 stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
29859 break;
29860 case PRAGMA_OMP_ASSUME:
29861 c_parser_omp_assume (parser, if_p);
29862 return;
29863 case PRAGMA_OMP_TILE:
29864 stmt = c_parser_omp_tile (loc, parser, if_p);
29865 break;
29866 case PRAGMA_OMP_UNROLL:
29867 stmt = c_parser_omp_unroll (loc, parser, if_p);
29868 break;
29869 case PRAGMA_OMP_DISPATCH:
29870 stmt = c_parser_omp_dispatch (loc, parser);
29871 break;
29872 default:
29873 gcc_unreachable ();
29874 }
29875
29876 if (stmt && stmt != error_mark_node)
29877 gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
29878}
29879
29880
29881/* OpenMP 2.5:
29882 # pragma omp threadprivate (variable-list) */
29883
29884static void
29885c_parser_omp_threadprivate (c_parser *parser)
29886{
29887 tree vars, t;
29888 location_t loc;
29889
29890 c_parser_consume_pragma (parser);
29891 vars = c_parser_omp_var_list_parens (parser, kind: OMP_CLAUSE_ERROR, NULL);
29892
29893 /* Mark every variable in VARS to be assigned thread local storage. */
29894 for (t = vars; t; t = TREE_CHAIN (t))
29895 {
29896 tree v = TREE_PURPOSE (t);
29897 loc = EXPR_LOCATION (TREE_VALUE (t));
29898
29899 /* If V had already been marked threadprivate, it doesn't matter
29900 whether it had been used prior to this point. */
29901 if (!VAR_P (v))
29902 error_at (loc, "%qD is not a variable", v);
29903 else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
29904 error_at (loc, "%qE declared %<threadprivate%> after first use", v);
29905 else if (! is_global_var (t: v))
29906 error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
29907 else if (TREE_TYPE (v) == error_mark_node)
29908 ;
29909 else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
29910 error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
29911 else
29912 {
29913 if (! DECL_THREAD_LOCAL_P (v))
29914 {
29915 set_decl_tls_model (v, decl_default_tls_model (v));
29916 /* If rtl has been already set for this var, call
29917 make_decl_rtl once again, so that encode_section_info
29918 has a chance to look at the new decl flags. */
29919 if (DECL_RTL_SET_P (v))
29920 make_decl_rtl (v);
29921 }
29922 C_DECL_THREADPRIVATE_P (v) = 1;
29923 }
29924 }
29925
29926 c_parser_skip_to_pragma_eol (parser);
29927}
29928
29929/* Parse a transaction attribute (GCC Extension).
29930
29931 transaction-attribute:
29932 gnu-attributes
29933 attribute-specifier
29934*/
29935
29936static tree
29937c_parser_transaction_attributes (c_parser *parser)
29938{
29939 if (c_parser_next_token_is_keyword (parser, keyword: RID_ATTRIBUTE))
29940 return c_parser_gnu_attributes (parser);
29941
29942 if (!c_parser_next_token_is (parser, type: CPP_OPEN_SQUARE))
29943 return NULL_TREE;
29944 return c_parser_std_attribute_specifier (parser, for_tm: true);
29945}
29946
29947/* Parse a __transaction_atomic or __transaction_relaxed statement
29948 (GCC Extension).
29949
29950 transaction-statement:
29951 __transaction_atomic transaction-attribute[opt] compound-statement
29952 __transaction_relaxed compound-statement
29953
29954 Note that the only valid attribute is: "outer".
29955*/
29956
29957static tree
29958c_parser_transaction (c_parser *parser, enum rid keyword)
29959{
29960 unsigned int old_in = parser->in_transaction;
29961 unsigned int this_in = 1, new_in;
29962 location_t loc = c_parser_peek_token (parser)->location;
29963 tree stmt, attrs;
29964
29965 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
29966 || keyword == RID_TRANSACTION_RELAXED)
29967 && c_parser_next_token_is_keyword (parser, keyword));
29968 c_parser_consume_token (parser);
29969
29970 if (keyword == RID_TRANSACTION_RELAXED)
29971 this_in |= TM_STMT_ATTR_RELAXED;
29972 else
29973 {
29974 attrs = c_parser_transaction_attributes (parser);
29975 if (attrs)
29976 this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
29977 }
29978
29979 /* Keep track if we're in the lexical scope of an outer transaction. */
29980 new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
29981
29982 parser->in_transaction = new_in;
29983 stmt = c_parser_compound_statement (parser);
29984 parser->in_transaction = old_in;
29985
29986 if (flag_tm)
29987 stmt = c_finish_transaction (loc, stmt, this_in);
29988 else
29989 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
29990 "%<__transaction_atomic%> without transactional memory support enabled"
29991 : "%<__transaction_relaxed %> "
29992 "without transactional memory support enabled"));
29993
29994 return stmt;
29995}
29996
29997/* Parse a __transaction_atomic or __transaction_relaxed expression
29998 (GCC Extension).
29999
30000 transaction-expression:
30001 __transaction_atomic ( expression )
30002 __transaction_relaxed ( expression )
30003*/
30004
30005static struct c_expr
30006c_parser_transaction_expression (c_parser *parser, enum rid keyword)
30007{
30008 struct c_expr ret;
30009 unsigned int old_in = parser->in_transaction;
30010 unsigned int this_in = 1;
30011 location_t loc = c_parser_peek_token (parser)->location;
30012 tree attrs;
30013
30014 gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
30015 || keyword == RID_TRANSACTION_RELAXED)
30016 && c_parser_next_token_is_keyword (parser, keyword));
30017 c_parser_consume_token (parser);
30018
30019 if (keyword == RID_TRANSACTION_RELAXED)
30020 this_in |= TM_STMT_ATTR_RELAXED;
30021 else
30022 {
30023 attrs = c_parser_transaction_attributes (parser);
30024 if (attrs)
30025 this_in |= parse_tm_stmt_attr (attrs, 0);
30026 }
30027
30028 parser->in_transaction = this_in;
30029 matching_parens parens;
30030 if (parens.require_open (parser))
30031 {
30032 tree expr = c_parser_expression (parser).value;
30033 ret.original_type = TREE_TYPE (expr);
30034 ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
30035 if (this_in & TM_STMT_ATTR_RELAXED)
30036 TRANSACTION_EXPR_RELAXED (ret.value) = 1;
30037 SET_EXPR_LOCATION (ret.value, loc);
30038 ret.original_code = TRANSACTION_EXPR;
30039 ret.m_decimal = 0;
30040 if (!parens.require_close (parser))
30041 {
30042 c_parser_skip_until_found (parser, type: CPP_CLOSE_PAREN, NULL);
30043 goto error;
30044 }
30045 }
30046 else
30047 {
30048 error:
30049 ret.set_error ();
30050 ret.original_code = ERROR_MARK;
30051 ret.original_type = NULL;
30052 }
30053 parser->in_transaction = old_in;
30054
30055 if (!flag_tm)
30056 error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
30057 "%<__transaction_atomic%> without transactional memory support enabled"
30058 : "%<__transaction_relaxed %> "
30059 "without transactional memory support enabled"));
30060
30061 set_c_expr_source_range (expr: &ret, start: loc, finish: loc);
30062
30063 return ret;
30064}
30065
30066/* Parse a __transaction_cancel statement (GCC Extension).
30067
30068 transaction-cancel-statement:
30069 __transaction_cancel transaction-attribute[opt] ;
30070
30071 Note that the only valid attribute is "outer".
30072*/
30073
30074static tree
30075c_parser_transaction_cancel (c_parser *parser)
30076{
30077 location_t loc = c_parser_peek_token (parser)->location;
30078 tree attrs;
30079 bool is_outer = false;
30080
30081 gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
30082 c_parser_consume_token (parser);
30083
30084 attrs = c_parser_transaction_attributes (parser);
30085 if (attrs)
30086 is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
30087
30088 if (!flag_tm)
30089 {
30090 error_at (loc, "%<__transaction_cancel%> without "
30091 "transactional memory support enabled");
30092 goto ret_error;
30093 }
30094 else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
30095 {
30096 error_at (loc, "%<__transaction_cancel%> within a "
30097 "%<__transaction_relaxed%>");
30098 goto ret_error;
30099 }
30100 else if (is_outer)
30101 {
30102 if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
30103 && !is_tm_may_cancel_outer (current_function_decl))
30104 {
30105 error_at (loc, "outer %<__transaction_cancel%> not "
30106 "within outer %<__transaction_atomic%> or "
30107 "a %<transaction_may_cancel_outer%> function");
30108 goto ret_error;
30109 }
30110 }
30111 else if (parser->in_transaction == 0)
30112 {
30113 error_at (loc, "%<__transaction_cancel%> not within "
30114 "%<__transaction_atomic%>");
30115 goto ret_error;
30116 }
30117
30118 return add_stmt (build_tm_abort_call (loc, is_outer));
30119
30120 ret_error:
30121 return build1 (NOP_EXPR, void_type_node, error_mark_node);
30122}
30123
30124/* Parse a single source file. */
30125
30126void
30127c_parse_file (void)
30128{
30129 /* Use local storage to begin. If the first token is a pragma, parse it.
30130 If it is #pragma GCC pch_preprocess, then this will load a PCH file
30131 which will cause garbage collection. */
30132 c_parser tparser;
30133
30134 memset (s: &tparser, c: 0, n: sizeof tparser);
30135 tparser.translate_strings_p = true;
30136 tparser.tokens = &tparser.tokens_buf[0];
30137 the_parser = &tparser;
30138
30139 if (c_parser_peek_token (parser: &tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
30140 c_parser_pragma_pch_preprocess (parser: &tparser);
30141 else
30142 c_common_no_more_pch ();
30143
30144 the_parser = ggc_alloc<c_parser> ();
30145 *the_parser = tparser;
30146 if (tparser.tokens == &tparser.tokens_buf[0])
30147 the_parser->tokens = &the_parser->tokens_buf[0];
30148
30149 /* Initialize EH, if we've been told to do so. */
30150 if (flag_exceptions)
30151 using_eh_for_cleanups ();
30152
30153 c_parser_translation_unit (parser: the_parser);
30154 the_parser = NULL;
30155}
30156
30157void
30158c_init_preprocess (void)
30159{
30160 /* Create a parser for use by pragma_lex during preprocessing. */
30161 the_parser = ggc_alloc<c_parser> ();
30162 memset (s: the_parser, c: 0, n: sizeof (c_parser));
30163 the_parser->tokens = &the_parser->tokens_buf[0];
30164}
30165
30166/* Parse the body of a function declaration marked with "__RTL".
30167
30168 The RTL parser works on the level of characters read from a
30169 FILE *, whereas c_parser works at the level of tokens.
30170 Square this circle by consuming all of the tokens up to and
30171 including the closing brace, recording the start/end of the RTL
30172 fragment, and reopening the file and re-reading the relevant
30173 lines within the RTL parser.
30174
30175 This requires the opening and closing braces of the C function
30176 to be on separate lines from the RTL they wrap.
30177
30178 Take ownership of START_WITH_PASS, if non-NULL. */
30179
30180location_t
30181c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
30182{
30183 if (!c_parser_require (parser, type: CPP_OPEN_BRACE, msgid: "expected %<{%>"))
30184 {
30185 free (ptr: start_with_pass);
30186 return c_parser_peek_token (parser)->location;
30187 }
30188
30189 location_t start_loc = c_parser_peek_token (parser)->location;
30190
30191 /* Consume all tokens, up to the closing brace, handling
30192 matching pairs of braces in the rtl dump. */
30193 int num_open_braces = 1;
30194 while (1)
30195 {
30196 switch (c_parser_peek_token (parser)->type)
30197 {
30198 case CPP_OPEN_BRACE:
30199 num_open_braces++;
30200 break;
30201 case CPP_CLOSE_BRACE:
30202 if (--num_open_braces == 0)
30203 goto found_closing_brace;
30204 break;
30205 case CPP_EOF:
30206 error_at (start_loc, "no closing brace");
30207 free (ptr: start_with_pass);
30208 return c_parser_peek_token (parser)->location;
30209 default:
30210 break;
30211 }
30212 c_parser_consume_token (parser);
30213 }
30214
30215 found_closing_brace:
30216 /* At the closing brace; record its location. */
30217 location_t end_loc = c_parser_peek_token (parser)->location;
30218
30219 /* Consume the closing brace. */
30220 c_parser_consume_token (parser);
30221
30222 /* Invoke the RTL parser. */
30223 if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
30224 {
30225 free (ptr: start_with_pass);
30226 return end_loc;
30227 }
30228
30229 /* Run the backend on the cfun created above, transferring ownership of
30230 START_WITH_PASS. */
30231 run_rtl_passes (initial_pass_name: start_with_pass);
30232 return end_loc;
30233}
30234
30235#include "gt-c-c-parser.h"
30236

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of gcc/c/c-parser.cc